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);
2089 /*-----------------------------------------------------------------*/
2090 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2091 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2092 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2093 /*-----------------------------------------------------------------*/
2095 asmopToBool (asmop *aop, bool resultInA)
2097 symbol *tlbl, *tlbl1;
2098 int size = aop->size;
2099 bool needpula = FALSE;
2100 bool flagsonly = TRUE;
2105 hc08_freeReg(hc08_reg_a);
2112 emitcode ("tsta", "");
2115 else if (IS_AOP_X(aop))
2116 emitcode ("tstx", "");
2117 else if (IS_AOP_H(aop))
2119 if (hc08_reg_a->isFree)
2121 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2122 emitcode ("tsta", "");
2124 hc08_freeReg(hc08_reg_a);
2126 else if (hc08_reg_x->isFree)
2128 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2129 emitcode ("tstx", "");
2130 hc08_freeReg(hc08_reg_x);
2134 emitcode ("pshh", "");
2135 emitcode ("tst", "1,s");
2136 emitcode ("ais", "#1");
2139 else if (IS_AOP_HX(aop))
2140 emitcode ("cphx", zero);
2141 else if (IS_AOP_XA(aop))
2143 symbol *tlbl = newiTempLabel (NULL);
2144 emitcode ("tsta", "");
2145 emitcode ("bne", "%05d$", (tlbl->key + 100));
2146 emitcode ("tstx", "");
2147 emitcode ("", "%05d$:", (tlbl->key + 100));
2151 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2152 "Bad rIdx in asmToBool");
2160 needpula = pushRegIfUsed (hc08_reg_a);
2161 loadRegFromAop (hc08_reg_a, aop, 0);
2162 for (offset=1; offset<size; offset++)
2163 accopWithAop ("ora", aop, offset);
2165 pullReg (hc08_reg_a);
2168 hc08_freeReg (hc08_reg_a);
2177 loadRegFromAop (hc08_reg_a, aop, 0);
2178 hc08_freeReg (hc08_reg_a);
2182 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2187 if (hc08_reg_a->isFree)
2189 loadRegFromAop (hc08_reg_a, aop, 0);
2190 accopWithAop ("ora", aop, 1);
2191 hc08_freeReg (hc08_reg_a);
2196 tlbl = newiTempLabel (NULL);
2197 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2198 emitcode ("bne", "%05d$", (tlbl->key + 100));
2199 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2200 emitcode ("", "%05d$:", (tlbl->key + 100));
2206 needpula = pushRegIfUsed (hc08_reg_a);
2207 loadRegFromAop (hc08_reg_a, aop, 0);
2208 for (offset=1; offset<size; offset++)
2209 accopWithAop ("ora", aop, offset);
2211 pullReg (hc08_reg_a);
2214 hc08_freeReg (hc08_reg_a);
2222 tlbl = newiTempLabel (NULL);
2226 tlbl1 = newiTempLabel (NULL);
2227 emitBranch ("bne", tlbl1);
2228 loadRegFromConst (hc08_reg_a, zero);
2229 emitBranch ("bra", tlbl);
2231 loadRegFromConst (hc08_reg_a, one);
2235 emitBranch ("beq", tlbl);
2236 loadRegFromConst (hc08_reg_a, one);
2239 hc08_useReg (hc08_reg_a);
2245 /*-----------------------------------------------------------------*/
2246 /* genNot - generate code for ! operation */
2247 /*-----------------------------------------------------------------*/
2251 D(emitcode ("; genNot",""));
2253 /* assign asmOps to operand & result */
2254 aopOp (IC_LEFT (ic), ic, FALSE);
2255 aopOp (IC_RESULT (ic), ic, TRUE);
2257 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2258 emitcode ("eor", one);
2259 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2261 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2262 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2266 /*-----------------------------------------------------------------*/
2267 /* genCpl - generate code for complement */
2268 /*-----------------------------------------------------------------*/
2274 regs* reg = hc08_reg_a;
2278 D(emitcode ("; genCpl",""));
2280 /* assign asmOps to operand & result */
2281 aopOp (IC_LEFT (ic), ic, FALSE);
2282 aopOp (IC_RESULT (ic), ic, TRUE);
2284 size = AOP_SIZE (IC_RESULT (ic));
2287 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2288 rmwWithReg ("com", reg);
2290 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2295 /* release the aops */
2296 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2297 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2300 /*-----------------------------------------------------------------*/
2301 /* genUminusFloat - unary minus for floating points */
2302 /*-----------------------------------------------------------------*/
2304 genUminusFloat (operand * op, operand * result)
2306 int size, offset = 0;
2309 D(emitcode ("; genUminusFloat",""));
2311 /* for this we just copy and then flip the bit */
2313 size = AOP_SIZE (op) - 1;
2317 transferAopAop (AOP (op), offset, AOP (result), offset);
2321 needpula = pushRegIfUsed (hc08_reg_a);
2322 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2323 emitcode ("eor", "#0x80");
2324 hc08_useReg (hc08_reg_a);
2325 storeRegToAop (hc08_reg_a, AOP (result), offset);
2326 pullOrFreeReg (hc08_reg_a, needpula);
2329 /*-----------------------------------------------------------------*/
2330 /* genUminus - unary minus code generation */
2331 /*-----------------------------------------------------------------*/
2333 genUminus (iCode * ic)
2336 sym_link *optype, *rtype;
2341 D(emitcode ("; genUminus",""));
2344 aopOp (IC_LEFT (ic), ic, FALSE);
2345 aopOp (IC_RESULT (ic), ic, TRUE);
2347 optype = operandType (IC_LEFT (ic));
2348 rtype = operandType (IC_RESULT (ic));
2350 /* if float then do float stuff */
2351 if (IS_FLOAT (optype))
2353 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2357 /* otherwise subtract from zero */
2358 size = AOP_SIZE (IC_LEFT (ic));
2363 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2364 needpula = pushRegIfUsed (hc08_reg_a);
2367 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2368 emitcode ("nega", "");
2369 hc08_freeReg (hc08_reg_a);
2370 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2371 SPEC_USIGN (operandType (IC_LEFT (ic))));
2372 pullOrFreeReg (hc08_reg_a, needpula);
2376 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2377 result = forceStackedAop (AOP (IC_RESULT (ic)));
2379 result = AOP (IC_RESULT (ic));
2381 needpula = pushRegIfUsed (hc08_reg_a);
2385 loadRegFromConst (hc08_reg_a, zero);
2386 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2387 storeRegToAop (hc08_reg_a, result, offset++);
2390 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2391 SPEC_USIGN (operandType (IC_LEFT (ic))));
2392 pullOrFreeReg (hc08_reg_a, needpula);
2394 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2395 freeAsmop (NULL, result, ic, TRUE);
2401 /* release the aops */
2402 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2403 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2406 /*-----------------------------------------------------------------*/
2407 /* saveRegisters - will look for a call and save the registers */
2408 /*-----------------------------------------------------------------*/
2410 saveRegisters (iCode * lic)
2417 for (ic = lic; ic; ic = ic->next)
2418 if (ic->op == CALL || ic->op == PCALL)
2423 fprintf (stderr, "found parameter push with no function call\n");
2427 /* if the registers have been saved already or don't need to be then
2431 if (IS_SYMOP(IC_LEFT(ic)) &&
2432 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2433 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2436 /* safe the registers in use at this time but skip the
2437 ones for the result */
2438 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2439 hc08_rUmaskForOp (IC_RESULT(ic)));
2442 for (i = 0; i < hc08_nRegs; i++)
2444 if (bitVectBitValue (rsave, i))
2445 pushReg ( hc08_regWithIdx (i), FALSE);
2449 /*-----------------------------------------------------------------*/
2450 /* unsaveRegisters - pop the pushed registers */
2451 /*-----------------------------------------------------------------*/
2453 unsaveRegisters (iCode * ic)
2458 /* restore the registers in use at this time but skip the
2459 ones for the result */
2460 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2461 hc08_rUmaskForOp (IC_RESULT(ic)));
2463 for (i = hc08_nRegs; i >= 0; i--)
2465 if (bitVectBitValue (rsave, i))
2466 pullReg ( hc08_regWithIdx (i));
2472 /*-----------------------------------------------------------------*/
2474 /*-----------------------------------------------------------------*/
2476 pushSide (operand * oper, int size)
2481 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2482 pushReg ( hc08_reg_a, TRUE);
2486 /*-----------------------------------------------------------------*/
2487 /* assignResultValue - */
2488 /*-----------------------------------------------------------------*/
2490 assignResultValue (operand * oper)
2492 int size = AOP_SIZE (oper);
2496 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2497 if (hc08_aop_pass[offset]->type == AOP_REG)
2498 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2505 /*-----------------------------------------------------------------*/
2506 /* genIpush - genrate code for pushing this gets a little complex */
2507 /*-----------------------------------------------------------------*/
2509 genIpush (iCode * ic)
2511 int size, offset = 0;
2514 D(emitcode ("; genIpush",""));
2516 /* if this is not a parm push : ie. it is spill push
2517 and spill push is always done on the local stack */
2521 /* and the item is spilt then do nothing */
2522 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2525 aopOp (IC_LEFT (ic), ic, FALSE);
2526 size = AOP_SIZE (IC_LEFT (ic));
2528 /* push it on the stack */
2531 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2532 pushReg ( hc08_reg_a, TRUE);
2538 /* this is a paramter push: in this case we call
2539 the routine to find the call and save those
2540 registers that need to be saved */
2543 /* then do the push */
2544 aopOp (IC_LEFT (ic), ic, FALSE);
2547 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2548 size = AOP_SIZE (IC_LEFT (ic));
2551 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2552 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2554 if ((size==2) && hc08_reg_hx->isFree)
2556 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2557 pushReg (hc08_reg_hx, TRUE);
2564 // printf("loading %d\n", offset);
2565 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2566 // printf("pushing \n");
2567 pushReg (hc08_reg_a, TRUE);
2571 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2574 /*-----------------------------------------------------------------*/
2575 /* genIpop - recover the registers: can happen only for spilling */
2576 /*-----------------------------------------------------------------*/
2578 genIpop (iCode * ic)
2582 D(emitcode ("; genIpop",""));
2584 /* if the temp was not pushed then */
2585 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2588 aopOp (IC_LEFT (ic), ic, FALSE);
2589 size = AOP_SIZE (IC_LEFT (ic));
2593 pullReg (hc08_reg_a);
2594 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2596 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2600 /*-----------------------------------------------------------------*/
2601 /* genSend - gen code for SEND */
2602 /*-----------------------------------------------------------------*/
2603 static void genSend(set *sendSet)
2607 for (sic = setFirstItem (sendSet); sic;
2608 sic = setNextItem (sendSet)) {
2609 int size, offset = 0;
2610 aopOp (IC_LEFT (sic), sic, FALSE);
2611 size = AOP_SIZE (IC_LEFT (sic));
2616 transferAopAop( AOP (IC_LEFT (sic)), offset,
2617 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2621 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2625 /*-----------------------------------------------------------------*/
2626 /* genCall - generates a call statement */
2627 /*-----------------------------------------------------------------*/
2629 genCall (iCode * ic)
2632 // bool restoreBank = FALSE;
2633 // bool swapBanks = FALSE;
2635 D(emitcode("; genCall",""));
2637 dtype = operandType (IC_LEFT (ic));
2638 /* if send set is not empty then assign */
2641 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2642 genSend(reverseSet(_G.sendSet));
2644 genSend(_G.sendSet);
2650 /* if caller saves & we have not saved then */
2656 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2657 OP_SYMBOL (IC_LEFT (ic))->rname :
2658 OP_SYMBOL (IC_LEFT (ic))->name));
2661 /* if we need assign a result value */
2662 if ((IS_ITEMP (IC_RESULT (ic)) &&
2663 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2664 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2665 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2666 IS_TRUE_SYMOP (IC_RESULT (ic)))
2670 aopOp (IC_RESULT (ic), ic, FALSE);
2673 assignResultValue (IC_RESULT (ic));
2675 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2678 /* adjust the stack for parameters if
2682 pullNull (ic->parmBytes);
2685 /* if we had saved some registers then unsave them */
2686 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2687 unsaveRegisters (ic);
2691 /*-----------------------------------------------------------------*/
2692 /* -10l - generates a call by pointer statement */
2693 /*-----------------------------------------------------------------*/
2695 genPcall (iCode * ic)
2698 symbol *rlbl = newiTempLabel (NULL);
2699 symbol *tlbl = newiTempLabel (NULL);
2700 // bool restoreBank=FALSE;
2701 // bool swapBanks = FALSE;
2703 D(emitcode("; genPCall",""));
2705 /* if caller saves & we have not saved then */
2709 /* if we are calling a not _naked function that is not using
2710 the same register bank then we need to save the
2711 destination registers on the stack */
2712 dtype = operandType (IC_LEFT (ic))->next;
2714 /* now push the calling address */
2715 emitBranch ("bsr", tlbl);
2716 emitBranch ("bra", rlbl);
2719 /* Push the function's address */
2720 aopOp (IC_LEFT (ic), ic, FALSE);
2721 pushSide (IC_LEFT (ic), FPTRSIZE);
2722 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2724 /* if send set is not empty the assign */
2727 genSend(reverseSet(_G.sendSet));
2733 emitcode ("rts", "");
2738 /* if we need assign a result value */
2739 if ((IS_ITEMP (IC_RESULT (ic)) &&
2740 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2741 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2742 IS_TRUE_SYMOP (IC_RESULT (ic)))
2746 aopOp (IC_RESULT (ic), ic, FALSE);
2749 assignResultValue (IC_RESULT (ic));
2751 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2754 /* adjust the stack for parameters if
2758 pullNull (ic->parmBytes);
2761 /* if we hade saved some registers then
2763 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2764 unsaveRegisters (ic);
2767 /*-----------------------------------------------------------------*/
2768 /* resultRemat - result is rematerializable */
2769 /*-----------------------------------------------------------------*/
2771 resultRemat (iCode * ic)
2773 if (SKIP_IC (ic) || ic->op == IFX)
2776 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2778 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2779 if (sym->remat && !POINTER_SET (ic))
2786 #if defined(__BORLANDC__) || defined(_MSC_VER)
2787 #define STRCASECMP stricmp
2789 #define STRCASECMP strcasecmp
2792 /*-----------------------------------------------------------------*/
2793 /* inExcludeList - return 1 if the string is in exclude Reg list */
2794 /*-----------------------------------------------------------------*/
2796 regsCmp(void *p1, void *p2)
2798 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2802 inExcludeList (char *s)
2804 const char *p = setFirstItem(options.excludeRegsSet);
2806 if (p == NULL || STRCASECMP(p, "none") == 0)
2810 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2813 /*-----------------------------------------------------------------*/
2814 /* genFunction - generated code for function entry */
2815 /*-----------------------------------------------------------------*/
2817 genFunction (iCode * ic)
2819 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2821 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2822 int stackAdjust = sym->stack;
2823 int accIsFree = sym->recvSize == 0;
2827 /* create the function header */
2828 emitcode (";", "-----------------------------------------");
2829 emitcode (";", " function %s", sym->name);
2830 emitcode (";", "-----------------------------------------");
2832 emitcode ("", "%s:", sym->rname);
2833 ftype = operandType (IC_LEFT (ic));
2837 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2839 if (IFFUNC_ISNAKED(ftype))
2841 emitcode(";", "naked function: no prologue.");
2845 /* if this is an interrupt service routine then
2847 if (IFFUNC_ISISR (sym->type))
2850 if (!inExcludeList ("h"))
2851 pushReg (hc08_reg_h, FALSE);
2854 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2855 /* before setting up the stack frame completely. */
2856 while (ric && ric->next && ric->next->op == RECEIVE)
2858 while (ric && IC_RESULT (ric))
2860 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2861 int rsymSize = rsym ? getSize(rsym->type) : 0;
2865 if (rsym && rsym->regType == REG_CND)
2867 if (rsym && (rsym->accuse || rsym->ruonly))
2869 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2870 rsym = rsym->usl.spillLoc;
2873 /* If the RECEIVE operand immediately spills to the first entry on the */
2874 /* stack, we can push it directly rather than use an sp relative store. */
2875 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2879 _G.current_iCode = ric;
2880 D(emitcode ("; genReceive",""));
2881 for (ofs=0; ofs < rsymSize; ofs++)
2883 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2884 pushReg (reg, TRUE);
2885 if (reg->rIdx == A_IDX)
2889 _G.current_iCode = ic;
2892 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2895 /* adjust the stack for the function */
2898 adjustStack (-stackAdjust);
2900 _G.stackOfs = sym->stack;
2903 /* if critical function then turn interrupts off */
2904 if (IFFUNC_ISCRITICAL (ftype))
2908 /* Function was passed parameters, so make sure A is preserved */
2909 pushReg (hc08_reg_a, FALSE);
2910 pushReg (hc08_reg_a, FALSE);
2911 emitcode ("tpa", "");
2912 emitcode ("sta", "2,s");
2913 emitcode ("sei", "");
2914 pullReg (hc08_reg_a);
2918 /* No passed parameters, so A can be freely modified */
2919 emitcode ("tpa", "");
2920 pushReg (hc08_reg_a, TRUE);
2921 emitcode ("sei", "");
2927 /*-----------------------------------------------------------------*/
2928 /* genEndFunction - generates epilogue for functions */
2929 /*-----------------------------------------------------------------*/
2931 genEndFunction (iCode * ic)
2933 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2935 if (IFFUNC_ISNAKED(sym->type))
2937 emitcode(";", "naked function: no epilogue.");
2938 if (options.debug && currFunc)
2939 debugFile->writeEndFunction (currFunc, ic, 0);
2943 if (IFFUNC_ISCRITICAL (sym->type))
2945 if (!IS_VOID(sym->type->next))
2947 /* Function has return value, so make sure A is preserved */
2948 pushReg (hc08_reg_a, FALSE);
2949 emitcode ("lda", "2,s");
2950 emitcode ("tap", "");
2951 pullReg (hc08_reg_a);
2956 /* Function returns void, so A can be freely modified */
2957 pullReg (hc08_reg_a);
2958 emitcode ("tap", "");
2962 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2968 _G.stackPushes += sym->stack;
2969 adjustStack (sym->stack);
2973 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2977 if (IFFUNC_ISISR (sym->type))
2980 if (!inExcludeList ("h"))
2981 pullReg (hc08_reg_h);
2984 /* if debug then send end of function */
2985 if (options.debug && currFunc)
2987 debugFile->writeEndFunction (currFunc, ic, 1);
2990 emitcode ("rti", "");
2994 if (IFFUNC_CALLEESAVES(sym->type))
2998 /* if any registers used */
3001 /* save the registers used */
3002 for (i = sym->regsUsed->size; i >= 0; i--)
3004 if (bitVectBitValue (sym->regsUsed, i) ||
3005 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3006 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3012 /* if debug then send end of function */
3013 if (options.debug && currFunc)
3015 debugFile->writeEndFunction (currFunc, ic, 1);
3018 emitcode ("rts", "");
3023 /*-----------------------------------------------------------------*/
3024 /* genRet - generate code for return statement */
3025 /*-----------------------------------------------------------------*/
3029 int size, offset = 0;
3032 D(emitcode ("; genRet",""));
3034 /* if we have no return value then
3035 just generate the "ret" */
3039 /* we have something to return then
3040 move the return value into place */
3041 aopOp (IC_LEFT (ic), ic, FALSE);
3042 size = AOP_SIZE (IC_LEFT (ic));
3048 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3055 /* 4 byte return: store value in the global return variable */
3059 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3060 STA (fReturn2[offset--], FALSE);
3061 hc08_freeReg (hc08_reg_a);
3065 /* 2 byte return: store value in x:a */
3066 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3067 hc08_freeReg (hc08_reg_xa);
3070 /* 1 byte return: store value in a */
3071 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3072 hc08_freeReg (hc08_reg_a);
3077 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3080 /* generate a jump to the return label
3081 if the next is not the return statement */
3082 if (!(ic->next && ic->next->op == LABEL &&
3083 IC_LABEL (ic->next) == returnLabel))
3085 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3089 /*-----------------------------------------------------------------*/
3090 /* genLabel - generates a label */
3091 /*-----------------------------------------------------------------*/
3093 genLabel (iCode * ic)
3098 /* For the high level labels we cannot depend on any */
3099 /* register's contents. Amnesia time. */
3100 for (i=A_IDX;i<=XA_IDX;i++)
3102 reg = hc08_regWithIdx(i);
3107 /* special case never generate */
3108 if (IC_LABEL (ic) == entryLabel)
3111 debugFile->writeLabel(IC_LABEL (ic), ic);
3113 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3117 /*-----------------------------------------------------------------*/
3118 /* genGoto - generates a jmp */
3119 /*-----------------------------------------------------------------*/
3121 genGoto (iCode * ic)
3123 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3127 /*-----------------------------------------------------------------*/
3128 /* findLabelBackwards: walks back through the iCode chain looking */
3129 /* for the given label. Returns number of iCode instructions */
3130 /* between that label and given ic. */
3131 /* Returns zero if label not found. */
3132 /*-----------------------------------------------------------------*/
3134 findLabelBackwards (iCode * ic, int key)
3143 /* If we have any pushes or pops, we cannot predict the distance.
3144 I don't like this at all, this should be dealt with in the
3146 if (ic->op == IPUSH || ic->op == IPOP) {
3150 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3160 /*-----------------------------------------------------------------*/
3161 /* genPlusIncr :- does addition with increment if possible */
3162 /*-----------------------------------------------------------------*/
3164 genPlusIncr (iCode * ic)
3172 unsigned int size = getDataSize (IC_RESULT (ic));
3173 unsigned int offset;
3174 symbol *tlbl = NULL;
3176 left = IC_LEFT (ic);
3177 result = IC_RESULT (ic);
3179 /* will try to generate an increment */
3180 /* if the right side is not a literal
3182 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3185 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3187 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3189 if ((IS_AOP_HX (AOP (left)) ||
3190 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3192 && (icount>=-128) && (icount<=127) && (size==2))
3194 if (!IS_AOP_HX (AOP (left)))
3196 needpulx = pushRegIfUsed (hc08_reg_x);
3197 needpulh = pushRegIfUsed (hc08_reg_h);
3204 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3205 emitcode ("aix","#%d", icount);
3206 hc08_dirtyReg (hc08_reg_hx, FALSE);
3207 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3208 pullOrFreeReg (hc08_reg_h, needpulh);
3209 pullOrFreeReg (hc08_reg_x, needpulx);
3213 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3214 sameRegs (AOP (left), AOP (result))));
3216 if ((icount > 255) || (icount<0))
3219 if (!sameRegs (AOP (left), AOP (result)))
3222 D(emitcode ("; genPlusIncr",""));
3225 tlbl = newiTempLabel (NULL);
3230 rmwWithAop ("inc", AOP (result), 0);
3232 emitBranch ("bne", tlbl);
3236 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3237 needpula = pushRegIfUsed (hc08_reg_a);
3240 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3241 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3242 hc08_useReg (hc08_reg_a);
3243 storeRegToAop (hc08_reg_a, AOP (result), 0);
3244 hc08_freeReg (hc08_reg_a);
3246 emitBranch ("bcc", tlbl);
3248 for (offset=1; offset<size; offset++)
3250 rmwWithAop ("inc", AOP (result), offset);
3251 if ((offset+1)<size)
3252 emitBranch ("bne", tlbl);
3258 pullOrFreeReg (hc08_reg_a, needpula);
3265 /*-----------------------------------------------------------------*/
3266 /* genPlus - generates code for addition */
3267 /*-----------------------------------------------------------------*/
3269 genPlus (iCode * ic)
3271 int size, offset = 0;
3273 asmop *leftOp, *rightOp;
3275 /* special cases :- */
3277 D(emitcode ("; genPlus",""));
3279 aopOp (IC_LEFT (ic), ic, FALSE);
3280 aopOp (IC_RIGHT (ic), ic, FALSE);
3281 aopOp (IC_RESULT (ic), ic, TRUE);
3283 /* we want registers on the left and literals on the right */
3284 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3285 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3287 operand *t = IC_RIGHT (ic);
3288 IC_RIGHT (ic) = IC_LEFT (ic);
3293 /* if I can do an increment instead
3294 of add then GOOD for ME */
3295 if (genPlusIncr (ic) == TRUE)
3298 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3299 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3300 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3302 size = getDataSize (IC_RESULT (ic));
3304 leftOp = AOP(IC_LEFT(ic));
3305 rightOp = AOP(IC_RIGHT(ic));
3311 loadRegFromAop (hc08_reg_a, leftOp, offset);
3312 accopWithAop(add, rightOp, offset);
3313 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3314 hc08_freeReg (hc08_reg_a);
3315 add = "adc"; /* further adds must propagate carry */
3319 // adjustArithmeticResult (ic);
3322 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3323 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3324 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3327 /*-----------------------------------------------------------------*/
3328 /* genMinusDec :- does subtraction with deccrement if possible */
3329 /*-----------------------------------------------------------------*/
3331 genMinusDec (iCode * ic)
3333 unsigned int icount;
3338 unsigned int size = getDataSize (IC_RESULT (ic));
3342 left = IC_LEFT (ic);
3343 result = IC_RESULT (ic);
3345 /* will try to generate an increment */
3346 /* if the right side is not a literal
3348 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3351 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3353 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3354 && (icount>=-127) && (icount<=128) && (size==2))
3356 if (!IS_AOP_HX (AOP (left)))
3358 needpulx = pushRegIfUsed (hc08_reg_x);
3359 needpulh = pushRegIfUsed (hc08_reg_h);
3366 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3367 emitcode ("aix","#%d", -icount);
3368 hc08_dirtyReg (hc08_reg_hx, FALSE);
3369 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3370 pullOrFreeReg (hc08_reg_h, needpulh);
3371 pullOrFreeReg (hc08_reg_x, needpulx);
3375 if ((icount > 1) || (icount<0))
3378 if (!sameRegs (AOP (left), AOP (result)))
3384 D(emitcode ("; genMinusDec",""));
3386 rmwWithAop ("dec", AOP (result), 0);
3391 /*-----------------------------------------------------------------*/
3392 /* addSign - complete with sign */
3393 /*-----------------------------------------------------------------*/
3395 addSign (operand * result, int offset, int sign)
3397 int size = (getDataSize (result) - offset);
3402 emitcode ("rola", "");
3403 emitcode ("clra", "");
3404 emitcode ("sbc", zero);
3406 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3410 storeConstToAop (zero, AOP (result), offset++);
3415 /*-----------------------------------------------------------------*/
3416 /* genMinus - generates code for subtraction */
3417 /*-----------------------------------------------------------------*/
3419 genMinus (iCode * ic)
3422 int size, offset = 0;
3424 asmop *leftOp, *rightOp;
3426 D(emitcode ("; genMinus",""));
3428 aopOp (IC_LEFT (ic), ic, FALSE);
3429 aopOp (IC_RIGHT (ic), ic, FALSE);
3430 aopOp (IC_RESULT (ic), ic, TRUE);
3432 /* special cases :- */
3433 /* if I can do an decrement instead
3434 of subtract then GOOD for ME */
3435 if (genMinusDec (ic) == TRUE)
3438 size = getDataSize (IC_RESULT (ic));
3441 leftOp = AOP(IC_LEFT(ic));
3442 rightOp = AOP(IC_RIGHT(ic));
3448 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3449 accopWithAop(sub, rightOp, offset);
3450 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3455 // adjustArithmeticResult (ic);
3458 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3459 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3460 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3465 /*-----------------------------------------------------------------*/
3466 /* genMultOneByte : 8*8=8/16 bit multiplication */
3467 /*-----------------------------------------------------------------*/
3469 genMultOneByte (operand * left,
3473 /* sym_link *opetype = operandType (result); */
3474 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3475 int size=AOP_SIZE(result);
3476 bool negLiteral = FALSE;
3477 bool lUnsigned, rUnsigned;
3479 D(emitcode ("; genMultOneByte",""));
3481 if (size<1 || size>2) {
3482 // this should never happen
3483 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3484 AOP_SIZE(result), __FILE__, lineno);
3488 /* (if two literals: the value is computed before) */
3489 /* if one literal, literal on the right */
3490 if (AOP_TYPE (left) == AOP_LIT)
3496 /* if an operand is in A, make sure it is on the left */
3497 if (IS_AOP_A (AOP (right)))
3504 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3505 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3507 /* lUnsigned rUnsigned negLiteral negate case */
3508 /* false false false odd 3 */
3509 /* false false true even 3 */
3510 /* false true false odd 3 */
3511 /* false true true impossible */
3512 /* true false false odd 3 */
3513 /* true false true always 2 */
3514 /* true true false never 1 */
3515 /* true true true impossible */
3519 || (lUnsigned && rUnsigned))
3521 // just an unsigned 8*8=8/16 multiply
3522 //D(emitcode (";","unsigned"));
3524 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3525 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3526 emitcode ("mul", "");
3527 hc08_dirtyReg (hc08_reg_xa, FALSE);
3528 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3529 hc08_freeReg (hc08_reg_xa);
3534 // we have to do a signed multiply
3537 /* left unsigned, right signed literal -- literal determines sign handling */
3538 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3540 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3542 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3544 emitcode ("ldx", "#0x%02x", -val);
3546 emitcode ("ldx", "#0x%02x", val);
3548 emitcode ("mul", "");
3552 rmwWithReg ("neg", hc08_reg_a);
3553 tlbl4 = newiTempLabel (NULL);
3554 emitBranch ("bcc", tlbl4);
3555 rmwWithReg ("inc", hc08_reg_x);
3557 rmwWithReg ("neg", hc08_reg_x);
3560 hc08_dirtyReg (hc08_reg_xa, FALSE);
3561 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3562 hc08_freeReg (hc08_reg_xa);
3569 emitcode ("clr", "1,s");
3571 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3574 tlbl1 = newiTempLabel (NULL);
3575 emitcode ("tsta","");
3576 emitBranch ("bpl", tlbl1);
3577 emitcode ("inc", "1,s");
3578 rmwWithReg ("neg", hc08_reg_a);
3582 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3584 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3585 /* AND literal negative */
3587 emitcode ("ldx", "#0x%02x", -val);
3590 emitcode ("ldx", "#0x%02x", val);
3592 hc08_useReg (hc08_reg_x);
3596 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3599 tlbl2 = newiTempLabel (NULL);
3600 emitcode ("tstx", "");
3601 emitBranch ("bpl", tlbl2);
3602 emitcode ("inc", "1,s");
3603 rmwWithReg ("neg", hc08_reg_x);
3608 emitcode ("mul", "");
3609 hc08_dirtyReg (hc08_reg_xa, FALSE);
3611 tlbl3 = newiTempLabel (NULL);
3612 emitcode ("dec", "1,s");
3613 if (!lUnsigned && !rUnsigned && negLiteral)
3614 emitBranch ("beq", tlbl3);
3616 emitBranch ("bne", tlbl3);
3618 rmwWithReg ("neg", hc08_reg_a);
3619 tlbl4 = newiTempLabel (NULL);
3620 emitBranch ("bcc", tlbl4);
3621 rmwWithReg ("inc", hc08_reg_x);
3623 rmwWithReg ("neg", hc08_reg_x);
3627 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3628 hc08_freeReg (hc08_reg_xa);
3632 /*-----------------------------------------------------------------*/
3633 /* genMult - generates code for multiplication */
3634 /*-----------------------------------------------------------------*/
3636 genMult (iCode * ic)
3638 operand *left = IC_LEFT (ic);
3639 operand *right = IC_RIGHT (ic);
3640 operand *result = IC_RESULT (ic);
3642 D(emitcode ("; genMult",""));
3644 /* assign the amsops */
3645 aopOp (left, ic, FALSE);
3646 aopOp (right, ic, FALSE);
3647 aopOp (result, ic, TRUE);
3649 /* special cases first */
3650 /* if both are of size == 1 */
3651 // if (getSize(operandType(left)) == 1 &&
3652 // getSize(operandType(right)) == 1)
3653 if (AOP_SIZE (left) == 1 &&
3654 AOP_SIZE (right) == 1)
3656 genMultOneByte (left, right, result);
3660 /* should have been converted to function call */
3661 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3662 getSize(OP_SYMBOL(right)->type));
3663 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3668 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3669 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3670 freeAsmop (result, NULL, ic, TRUE);
3673 /*-----------------------------------------------------------------*/
3674 /* genDivOneByte : 8 bit division */
3675 /*-----------------------------------------------------------------*/
3677 genDivOneByte (operand * left,
3681 symbol *tlbl1, *tlbl2, *tlbl3;
3684 bool lUnsigned, rUnsigned;
3685 bool runtimeSign, compiletimeSign;
3687 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3688 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3690 D(emitcode ("; genDivOneByte",""));
3692 size = AOP_SIZE (result);
3693 /* signed or unsigned */
3694 if (lUnsigned && rUnsigned)
3696 /* unsigned is easy */
3697 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3698 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3699 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3700 emitcode ("div", "");
3701 hc08_dirtyReg (hc08_reg_a, FALSE);
3702 hc08_dirtyReg (hc08_reg_h, FALSE);
3703 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3704 hc08_freeReg (hc08_reg_a);
3705 hc08_freeReg (hc08_reg_x);
3706 hc08_freeReg (hc08_reg_h);
3710 /* signed is a little bit more difficult */
3712 /* now sign adjust for both left & right */
3714 /* let's see what's needed: */
3715 /* apply negative sign during runtime */
3716 runtimeSign = FALSE;
3717 /* negative sign from literals */
3718 compiletimeSign = FALSE;
3722 if (AOP_TYPE(left) == AOP_LIT)
3724 /* signed literal */
3725 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3727 compiletimeSign = TRUE;
3730 /* signed but not literal */
3736 if (AOP_TYPE(right) == AOP_LIT)
3738 /* signed literal */
3739 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3741 compiletimeSign ^= TRUE;
3744 /* signed but not literal */
3748 /* initialize the runtime sign */
3751 if (compiletimeSign)
3752 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3754 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3755 pushReg (hc08_reg_x, TRUE);
3758 /* save the signs of the operands */
3759 if (AOP_TYPE(right) == AOP_LIT)
3761 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3763 if (!rUnsigned && val < 0)
3764 emitcode ("ldx", "#0x%02x", -val);
3766 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3768 else /* ! literal */
3770 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3773 tlbl1 = newiTempLabel (NULL);
3774 emitcode ("tstx", "");
3775 emitBranch ("bpl", tlbl1);
3776 emitcode ("inc", "1,s");
3777 rmwWithReg ("neg", hc08_reg_x);
3782 if (AOP_TYPE(left) == AOP_LIT)
3784 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3786 if (!lUnsigned && val < 0)
3787 emitcode ("lda", "#0x%02x", -val);
3789 emitcode ("lda", "#0x%02x", (unsigned char) val);
3791 else /* ! literal */
3793 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3796 tlbl2 = newiTempLabel (NULL);
3797 emitcode ("tsta", "");
3798 emitBranch ("bpl", tlbl2);
3799 emitcode ("inc", "1,s");
3800 rmwWithReg ("neg", hc08_reg_a);
3805 loadRegFromConst (hc08_reg_h, zero);
3806 emitcode ("div", "");
3807 hc08_dirtyReg (hc08_reg_x, FALSE);
3808 hc08_dirtyReg (hc08_reg_a, FALSE);
3809 hc08_dirtyReg (hc08_reg_h, FALSE);
3811 if (runtimeSign || compiletimeSign)
3813 tlbl3 = newiTempLabel (NULL);
3816 pullReg (hc08_reg_x);
3817 rmwWithReg ("lsr", hc08_reg_x);
3818 rmwWithReg ("ror", hc08_reg_x);
3819 emitBranch ("bpl", tlbl3);
3822 rmwWithReg ("neg", hc08_reg_a);
3826 storeRegToAop (hc08_reg_a, AOP (result), 0);
3830 /* msb is 0x00 or 0xff depending on the sign */
3833 rmwWithReg ("lsl", hc08_reg_x);
3834 emitcode ("clra", "");
3835 emitcode ("sbc", "#0");
3837 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3839 else /* compiletimeSign */
3841 storeConstToAop ("#0xff", AOP (result), ++offset);
3846 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3849 hc08_freeReg (hc08_reg_a);
3850 hc08_freeReg (hc08_reg_x);
3851 hc08_freeReg (hc08_reg_h);
3854 /*-----------------------------------------------------------------*/
3855 /* genDiv - generates code for division */
3856 /*-----------------------------------------------------------------*/
3860 operand *left = IC_LEFT (ic);
3861 operand *right = IC_RIGHT (ic);
3862 operand *result = IC_RESULT (ic);
3864 D(emitcode ("; genDiv",""));
3866 /* assign the amsops */
3867 aopOp (left, ic, FALSE);
3868 aopOp (right, ic, FALSE);
3869 aopOp (result, ic, TRUE);
3871 /* special cases first */
3872 /* if both are of size == 1 */
3873 if (AOP_SIZE (left) <= 2 &&
3874 AOP_SIZE (right) == 1)
3876 genDivOneByte (left, right, result);
3880 /* should have been converted to function call */
3883 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3884 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3885 freeAsmop (result, NULL, ic, TRUE);
3888 /*-----------------------------------------------------------------*/
3889 /* genModOneByte : 8 bit modulus */
3890 /*-----------------------------------------------------------------*/
3892 genModOneByte (operand * left,
3896 symbol *tlbl1, *tlbl2, *tlbl3;
3899 bool lUnsigned, rUnsigned;
3900 bool runtimeSign, compiletimeSign;
3902 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3903 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3905 D(emitcode ("; genModOneByte",""));
3907 size = AOP_SIZE (result);
3909 if (lUnsigned && rUnsigned)
3911 /* unsigned is easy */
3912 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3913 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3914 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3915 emitcode ("div", "");
3916 hc08_dirtyReg (hc08_reg_a, FALSE);
3917 hc08_dirtyReg (hc08_reg_h, FALSE);
3918 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3919 hc08_freeReg (hc08_reg_a);
3920 hc08_freeReg (hc08_reg_x);
3921 hc08_freeReg (hc08_reg_h);
3925 /* signed is a little bit more difficult */
3927 if (AOP_TYPE(right) == AOP_LIT)
3929 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3931 if (!rUnsigned && val < 0)
3932 emitcode ("ldx", "#0x%02x", -val);
3934 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3936 else /* ! literal */
3938 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3941 tlbl1 = newiTempLabel (NULL);
3942 emitcode ("tstx", "");
3943 emitBranch ("bpl", tlbl1);
3944 rmwWithReg ("neg", hc08_reg_x);
3949 /* let's see what's needed: */
3950 /* apply negative sign during runtime */
3951 runtimeSign = FALSE;
3952 /* negative sign from literals */
3953 compiletimeSign = FALSE;
3955 /* sign adjust left side */
3956 if (AOP_TYPE(left) == AOP_LIT)
3958 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3960 if (!lUnsigned && val < 0)
3962 compiletimeSign = TRUE; /* set sign flag */
3963 emitcode ("lda", "#0x%02x", -val);
3966 emitcode ("lda", "#0x%02x", (unsigned char) val);
3968 else /* ! literal */
3971 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3976 emitcode ("clr", "1,s");
3978 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3979 tlbl2 = newiTempLabel (NULL);
3980 emitcode ("tsta", "");
3981 emitBranch ("bpl", tlbl2);
3982 emitcode ("inc", "1,s");
3983 rmwWithReg ("neg", hc08_reg_a);
3988 loadRegFromConst (hc08_reg_h, zero);
3989 emitcode ("div", "");
3990 hc08_dirtyReg (hc08_reg_x, FALSE);
3991 hc08_dirtyReg (hc08_reg_a, FALSE);
3992 hc08_dirtyReg (hc08_reg_h, FALSE);
3994 if (runtimeSign || compiletimeSign)
3996 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3997 tlbl3 = newiTempLabel (NULL);
4000 pullReg (hc08_reg_x);
4001 rmwWithReg ("lsr", hc08_reg_x);
4002 rmwWithReg ("ror", hc08_reg_x);
4003 emitBranch ("bpl", tlbl3);
4006 rmwWithReg ("neg", hc08_reg_a);
4010 storeRegToAop (hc08_reg_a, AOP (result), 0);
4014 /* msb is 0x00 or 0xff depending on the sign */
4017 rmwWithReg ("lsl", hc08_reg_x);
4018 emitcode ("clra", "");
4019 emitcode ("sbc", "#0");
4021 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4023 else /* compiletimeSign */
4025 storeConstToAop ("#0xff", AOP (result), ++offset);
4030 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4033 hc08_freeReg (hc08_reg_a);
4034 hc08_freeReg (hc08_reg_x);
4035 hc08_freeReg (hc08_reg_h);
4038 /*-----------------------------------------------------------------*/
4039 /* genMod - generates code for division */
4040 /*-----------------------------------------------------------------*/
4044 operand *left = IC_LEFT (ic);
4045 operand *right = IC_RIGHT (ic);
4046 operand *result = IC_RESULT (ic);
4048 D(emitcode ("; genMod",""));
4050 /* assign the amsops */
4051 aopOp (left, ic, FALSE);
4052 aopOp (right, ic, FALSE);
4053 aopOp (result, ic, TRUE);
4055 /* special cases first */
4056 /* if both are of size == 1 */
4057 if (AOP_SIZE (left) <= 2 &&
4058 AOP_SIZE (right) == 1)
4060 genModOneByte (left, right, result);
4064 /* should have been converted to function call */
4068 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4069 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4070 freeAsmop (result, NULL, ic, TRUE);
4073 /*-----------------------------------------------------------------*/
4074 /* genIfxJump :- will create a jump depending on the ifx */
4075 /*-----------------------------------------------------------------*/
4077 genIfxJump (iCode * ic, char *jval)
4080 symbol *tlbl = newiTempLabel (NULL);
4083 D(emitcode ("; genIfxJump",""));
4085 /* if true label then we jump if condition
4089 jlbl = IC_TRUE (ic);
4090 if (!strcmp (jval, "a"))
4092 else if (!strcmp (jval, "c"))
4099 /* false label is present */
4100 jlbl = IC_FALSE (ic);
4101 if (!strcmp (jval, "a"))
4103 else if (!strcmp (jval, "c"))
4108 emitBranch (inst, tlbl);
4109 emitBranch ("jmp", jlbl);
4112 /* mark the icode as generated */
4117 /*-----------------------------------------------------------------*/
4118 /* exchangedCmp : returns the opcode need if the two operands are */
4119 /* exchanged in a comparison */
4120 /*-----------------------------------------------------------------*/
4122 exchangedCmp (int opcode)
4139 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4140 "opcode not a comparison");
4142 return EQ_OP; /* shouldn't happen, but need to return something */
4145 /*------------------------------------------------------------------*/
4146 /* negatedCmp : returns the equivalent opcode for when a comparison */
4148 /*------------------------------------------------------------------*/
4150 negatedCmp (int opcode)
4167 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4168 "opcode not a comparison");
4170 return EQ_OP; /* shouldn't happen, but need to return something */
4173 /* compile only if the debugging macro D is enabled */
4176 nameCmp (int opcode)
4198 /*------------------------------------------------------------------*/
4199 /* branchInstCmp : returns the conditional branch instruction that */
4200 /* will branch if the comparison is true */
4201 /*------------------------------------------------------------------*/
4203 branchInstCmp (int opcode, int sign)
4211 return "bcs"; /* same as blo */
4226 return "bcc"; /* same as bhs */
4232 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4233 "opcode not a comparison");
4239 /*------------------------------------------------------------------*/
4240 /* genCmp :- greater or less than (and maybe with equal) comparison */
4241 /*------------------------------------------------------------------*/
4243 genCmp (iCode * ic, iCode * ifx)
4245 operand *left, *right, *result;
4246 sym_link *letype, *retype;
4248 int size, offset = 0;
4249 unsigned long lit = 0L;
4251 symbol *jlbl = NULL;
4255 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4257 result = IC_RESULT (ic);
4258 left = IC_LEFT (ic);
4259 right = IC_RIGHT (ic);
4261 letype = getSpec (operandType (left));
4262 retype = getSpec (operandType (right));
4263 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4264 /* assign the amsops */
4265 aopOp (left, ic, FALSE);
4266 aopOp (right, ic, FALSE);
4267 aopOp (result, ic, TRUE);
4269 /* need register operand on left, prefer literal operand on right */
4270 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4272 operand *temp = left;
4275 opcode = exchangedCmp (opcode);
4282 jlbl = IC_TRUE (ifx);
4283 opcode = negatedCmp (opcode);
4287 /* false label is present */
4288 jlbl = IC_FALSE (ifx);
4292 size = max (AOP_SIZE (left), AOP_SIZE (right));
4295 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4296 && ((AOP_TYPE (right) == AOP_LIT) ||
4297 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4298 && hc08_reg_hx->isFree)
4300 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4301 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4302 hc08_freeReg (hc08_reg_hx);
4313 /* These conditions depend on the Z flag bit, but Z is */
4314 /* only valid for the last byte of the comparison, not */
4315 /* the whole value. So exchange the operands to get a */
4316 /* comparison that doesn't depend on Z. (This is safe */
4317 /* to do here since ralloc won't assign multi-byte */
4318 /* operands to registers for comparisons) */
4319 if ((opcode == '>') || (opcode == LE_OP))
4321 operand *temp = left;
4324 opcode = exchangedCmp (opcode);
4327 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4329 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4330 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4339 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4340 accopWithAop (sub, AOP (right), offset);
4341 hc08_freeReg (hc08_reg_a);
4346 freeAsmop (right, NULL, ic, FALSE);
4347 freeAsmop (left, NULL, ic, FALSE);
4351 symbol *tlbl = newiTempLabel (NULL);
4354 freeAsmop (result, NULL, ic, TRUE);
4356 inst = branchInstCmp (opcode, sign);
4357 emitBranch (inst, tlbl);
4358 emitBranch ("jmp", jlbl);
4361 /* mark the icode as generated */
4366 symbol *tlbl1 = newiTempLabel (NULL);
4367 symbol *tlbl2 = newiTempLabel (NULL);
4369 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4370 loadRegFromConst (hc08_reg_a, zero);
4371 emitBranch ("bra", tlbl2);
4373 loadRegFromConst (hc08_reg_a, one);
4375 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4376 freeAsmop (result, NULL, ic, TRUE);
4381 /*-----------------------------------------------------------------*/
4382 /* genCmpEQorNE - equal or not equal comparison */
4383 /*-----------------------------------------------------------------*/
4385 genCmpEQorNE (iCode * ic, iCode * ifx)
4387 operand *left, *right, *result;
4388 sym_link *letype, *retype;
4390 int size, offset = 0;
4392 symbol *jlbl = NULL;
4393 symbol *tlbl_NE = NULL;
4394 symbol *tlbl_EQ = NULL;
4398 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4400 result = IC_RESULT (ic);
4401 left = IC_LEFT (ic);
4402 right = IC_RIGHT (ic);
4404 letype = getSpec (operandType (left));
4405 retype = getSpec (operandType (right));
4406 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4407 /* assign the amsops */
4408 aopOp (left, ic, FALSE);
4409 aopOp (right, ic, FALSE);
4410 aopOp (result, ic, TRUE);
4412 /* need register operand on left, prefer literal operand on right */
4413 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4415 operand *temp = left;
4418 opcode = exchangedCmp (opcode);
4425 jlbl = IC_TRUE (ifx);
4426 opcode = negatedCmp (opcode);
4430 /* false label is present */
4431 jlbl = IC_FALSE (ifx);
4435 size = max (AOP_SIZE (left), AOP_SIZE (right));
4438 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4439 && ((AOP_TYPE (right) == AOP_LIT) ||
4440 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4441 && hc08_reg_hx->isFree)
4443 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4444 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4445 hc08_freeReg (hc08_reg_hx);
4453 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4454 accopWithAop (sub, AOP (right), offset);
4458 tlbl_NE = newiTempLabel (NULL);
4459 emitBranch ("bne", tlbl_NE);
4461 hc08_freeReg (hc08_reg_a);
4465 freeAsmop (right, NULL, ic, FALSE);
4466 freeAsmop (left, NULL, ic, FALSE);
4470 freeAsmop (result, NULL, ic, TRUE);
4472 if (opcode == EQ_OP)
4475 tlbl_EQ = newiTempLabel (NULL);
4476 emitBranch ("beq", tlbl_EQ);
4478 emitLabel (tlbl_NE);
4479 emitBranch ("jmp", jlbl);
4480 emitLabel (tlbl_EQ);
4485 tlbl_NE = newiTempLabel (NULL);
4486 emitBranch ("bne", tlbl_NE);
4487 emitBranch ("jmp", jlbl);
4488 emitLabel (tlbl_NE);
4491 /* mark the icode as generated */
4496 symbol *tlbl = newiTempLabel (NULL);
4498 if (opcode == EQ_OP)
4501 tlbl_EQ = newiTempLabel (NULL);
4502 emitBranch ("beq", tlbl_EQ);
4504 emitLabel (tlbl_NE);
4505 loadRegFromConst (hc08_reg_a, zero);
4506 emitBranch ("bra", tlbl);
4507 emitLabel (tlbl_EQ);
4508 loadRegFromConst (hc08_reg_a, one);
4513 tlbl_NE = newiTempLabel (NULL);
4514 emitBranch ("bne", tlbl_NE);
4515 loadRegFromConst (hc08_reg_a, zero);
4516 emitBranch ("bra", tlbl);
4517 emitLabel (tlbl_NE);
4518 loadRegFromConst (hc08_reg_a, one);
4522 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4523 freeAsmop (result, NULL, ic, TRUE);
4529 /*-----------------------------------------------------------------*/
4530 /* ifxForOp - returns the icode containing the ifx for operand */
4531 /*-----------------------------------------------------------------*/
4533 ifxForOp (operand * op, iCode * ic)
4535 /* if true symbol then needs to be assigned */
4536 if (IS_TRUE_SYMOP (op))
4539 /* if this has register type condition and
4540 the next instruction is ifx with the same operand
4541 and live to of the operand is upto the ifx only then */
4543 ic->next->op == IFX &&
4544 IC_COND (ic->next)->key == op->key &&
4545 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4552 genPointerGetSetOfs (iCode *ic)
4554 iCode *lic = ic->next;
4560 /* Make sure we have a next iCode */
4561 D(emitcode("","; checking lic"));
4565 /* Make sure the result of the addition is an iCode */
4566 D(emitcode("","; checking IS_ITEMP"));
4567 if (!IS_ITEMP (IC_RESULT (ic)))
4570 /* Make sure the next iCode is a pointer set or get */
4571 pset = POINTER_SET(lic);
4572 pget = POINTER_GET(lic);
4573 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4577 /* Make sure this is the only use of the pointer */
4578 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4581 D(emitcode("", "; checking pset operandsEqu"));
4582 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4585 D(emitcode("", "; checking pget operandsEqu"));
4586 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4589 D(emitcode("", "; checking IS_SYMOP"));
4590 if (!IS_SYMOP (IC_LEFT (ic)))
4593 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4594 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4597 sym = OP_SYMBOL (IC_LEFT (ic));
4599 D(emitcode("", "; checking remat"));
4606 D(emitcode ("; genPointerGetOfs",""));
4607 aopOp (IC_LEFT(ic), ic, FALSE);
4608 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4609 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4611 aopOp (IC_RIGHT(ic), ic, FALSE);
4612 aopOp (IC_RESULT(lic), lic, FALSE);
4614 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4616 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4618 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4619 loadRegFromConst (hc08_reg_h, zero);
4623 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4624 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4625 emitcode ("rola","");
4626 emitcode ("clra","");
4627 emitcode ("sbc", "#0");
4628 hc08_useReg (hc08_reg_a);
4629 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4633 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4634 size = AOP_SIZE (IC_RESULT(lic));
4635 derefaop->size = size;
4639 emitcode ("lda", "%s,x",
4640 aopAdrStr (derefaop, size, TRUE));
4641 hc08_useReg (hc08_reg_a);
4642 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4643 hc08_freeReg (hc08_reg_a);
4647 hc08_freeReg (hc08_reg_hx);
4649 freeAsmop (NULL, derefaop, ic, TRUE);
4650 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4651 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4658 D(emitcode ("; genPointerSetOfs",""));
4659 aopOp (IC_LEFT(ic), ic, FALSE);
4660 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4661 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4663 aopOp (IC_RIGHT(ic), ic, FALSE);
4664 aopOp (IC_RIGHT(lic), lic, FALSE);
4666 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4668 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4670 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4671 loadRegFromConst (hc08_reg_h, zero);
4675 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4676 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4677 emitcode ("rola","");
4678 emitcode ("clra","");
4679 emitcode ("sbc", "#0");
4680 hc08_useReg (hc08_reg_a);
4681 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4685 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4686 size = AOP_SIZE (IC_RIGHT(lic));
4687 derefaop->size = size;
4691 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4692 emitcode ("sta", "%s,x",
4693 aopAdrStr (derefaop, size, TRUE));
4694 hc08_freeReg (hc08_reg_a);
4698 hc08_freeReg (hc08_reg_hx);
4700 freeAsmop (NULL, derefaop, ic, TRUE);
4701 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4702 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4711 /*-----------------------------------------------------------------*/
4712 /* hasInc - operand is incremented before any other use */
4713 /*-----------------------------------------------------------------*/
4715 hasInc (operand *op, iCode *ic,int osize)
4717 sym_link *type = operandType(op);
4718 sym_link *retype = getSpec (type);
4719 iCode *lic = ic->next;
4722 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4723 if (!IS_SYMOP(op)) return NULL;
4725 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4726 if (IS_AGGREGATE(type->next)) return NULL;
4727 if (osize != (isize = getSize(type->next))) return NULL;
4730 /* if operand of the form op = op + <sizeof *op> */
4731 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4732 isOperandEqual(IC_RESULT(lic),op) &&
4733 isOperandLiteral(IC_RIGHT(lic)) &&
4734 operandLitValue(IC_RIGHT(lic)) == isize) {
4737 /* if the operand used or deffed */
4738 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4741 /* if GOTO or IFX */
4742 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4748 /*-----------------------------------------------------------------*/
4749 /* genAndOp - for && operation */
4750 /*-----------------------------------------------------------------*/
4752 genAndOp (iCode * ic)
4754 operand *left, *right, *result;
4755 symbol *tlbl, *tlbl0;
4757 D(emitcode ("; genAndOp",""));
4759 /* note here that && operations that are in an
4760 if statement are taken away by backPatchLabels
4761 only those used in arthmetic operations remain */
4762 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4763 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4764 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4766 tlbl = newiTempLabel (NULL);
4767 tlbl0 = newiTempLabel (NULL);
4769 asmopToBool (AOP (left), FALSE);
4770 emitBranch ("beq", tlbl0);
4771 asmopToBool (AOP (right), FALSE);
4772 emitBranch ("beq", tlbl0);
4773 loadRegFromConst (hc08_reg_a,one);
4774 emitBranch ("bra", tlbl);
4776 loadRegFromConst (hc08_reg_a,zero);
4779 hc08_useReg (hc08_reg_a);
4780 hc08_freeReg (hc08_reg_a);
4782 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4784 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4785 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4786 freeAsmop (result, NULL, ic, TRUE);
4790 /*-----------------------------------------------------------------*/
4791 /* genOrOp - for || operation */
4792 /*-----------------------------------------------------------------*/
4794 genOrOp (iCode * ic)
4796 operand *left, *right, *result;
4797 symbol *tlbl, *tlbl0;
4799 D(emitcode ("; genOrOp",""));
4801 /* note here that || operations that are in an
4802 if statement are taken away by backPatchLabels
4803 only those used in arthmetic operations remain */
4804 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4805 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4806 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4808 tlbl = newiTempLabel (NULL);
4809 tlbl0 = newiTempLabel (NULL);
4811 asmopToBool (AOP (left), FALSE);
4812 emitBranch ("bne", tlbl0);
4813 asmopToBool (AOP (right), FALSE);
4814 emitBranch ("bne", tlbl0);
4815 loadRegFromConst (hc08_reg_a,zero);
4816 emitBranch ("bra", tlbl);
4818 loadRegFromConst (hc08_reg_a,one);
4821 hc08_useReg (hc08_reg_a);
4822 hc08_freeReg (hc08_reg_a);
4824 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4827 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4828 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4829 freeAsmop (result, NULL, ic, TRUE);
4832 /*-----------------------------------------------------------------*/
4833 /* isLiteralBit - test if lit == 2^n */
4834 /*-----------------------------------------------------------------*/
4836 isLiteralBit (unsigned long lit)
4838 unsigned long pw[32] =
4839 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4840 0x100L, 0x200L, 0x400L, 0x800L,
4841 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4842 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4843 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4844 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4845 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4848 for (idx = 0; idx < 32; idx++)
4855 /*-----------------------------------------------------------------*/
4856 /* continueIfTrue - */
4857 /*-----------------------------------------------------------------*/
4859 continueIfTrue (iCode * ic)
4862 emitBranch ("jmp", IC_TRUE (ic));
4866 /*-----------------------------------------------------------------*/
4868 /*-----------------------------------------------------------------*/
4870 jumpIfTrue (iCode * ic)
4873 emitBranch ("jmp", IC_FALSE (ic));
4877 /*-----------------------------------------------------------------*/
4878 /* jmpTrueOrFalse - */
4879 /*-----------------------------------------------------------------*/
4881 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4883 // ugly but optimized by peephole
4886 symbol *nlbl = newiTempLabel (NULL);
4887 emitBranch ("bra", nlbl);
4889 emitBranch ("jmp", IC_TRUE (ic));
4894 emitBranch ("jmp", IC_FALSE (ic));
4901 /*-----------------------------------------------------------------*/
4902 /* genAnd - code for and */
4903 /*-----------------------------------------------------------------*/
4905 genAnd (iCode * ic, iCode * ifx)
4907 operand *left, *right, *result;
4908 int size, offset = 0;
4909 unsigned long lit = 0L;
4910 unsigned long litinv;
4911 unsigned char bytemask;
4917 D(emitcode ("; genAnd",""));
4919 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4920 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4921 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4924 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4926 AOP_TYPE (left), AOP_TYPE (right)));
4927 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4929 AOP_SIZE (left), AOP_SIZE (right)));
4932 /* if left is a literal & right is not then exchange them */
4933 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4935 operand *tmp = right;
4940 /* if right is accumulator & left is not then exchange them */
4941 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4943 operand *tmp = right;
4948 if (AOP_TYPE (right) == AOP_LIT)
4949 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4951 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4953 if (AOP_TYPE (result) == AOP_CRY
4955 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
4957 /* this generates ugly code, but meets volatility requirements */
4958 loadRegFromConst (hc08_reg_a, zero);
4959 pushReg (hc08_reg_a, TRUE);
4964 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4965 accopWithAop ("and", AOP (right), offset);
4966 emitcode ("ora", "1,s");
4967 emitcode ("sta", "1,s");
4971 pullReg (hc08_reg_a);
4972 emitcode ("tsta", "");
4973 genIfxJump (ifx, "a");
4977 if (AOP_TYPE (result) == AOP_CRY)
4979 symbol *tlbl = NULL;
4980 wassertl (ifx, "AOP_CRY result without ifx");
4985 bytemask = (lit >> (offset*8)) & 0xff;
4987 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
4991 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
4993 rmwWithAop ("tst", AOP (left), offset);
4997 tlbl = newiTempLabel (NULL);
4998 emitBranch ("bne", tlbl);
5003 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5004 accopWithAop ("and", AOP (right), offset);
5005 hc08_freeReg( hc08_reg_a);
5009 tlbl = newiTempLabel (NULL);
5010 emitBranch ("bne", tlbl);
5017 genIfxJump (ifx, "a");
5021 size = AOP_SIZE (result);
5023 if (AOP_TYPE (right) == AOP_LIT)
5025 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5026 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5027 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5029 int bitpos = isLiteralBit(litinv)-1;
5030 emitcode ("bclr","#%d,%s",bitpos & 7,
5031 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5039 bytemask = (lit >> (offset*8)) & 0xff;
5041 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5043 if (isOperandVolatile (left, FALSE))
5045 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5046 hc08_freeReg( hc08_reg_a);
5048 storeConstToAop (zero, AOP (result), offset);
5050 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5052 transferAopAop (AOP (left), offset, AOP (result), offset);
5056 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5057 accopWithAop ("and", AOP (right), offset);
5058 storeRegToAop (hc08_reg_a, AOP (result), offset);
5059 hc08_freeReg (hc08_reg_a);
5065 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5066 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5067 freeAsmop (result, NULL, ic, TRUE);
5070 /*-----------------------------------------------------------------*/
5071 /* genOr - code for or */
5072 /*-----------------------------------------------------------------*/
5074 genOr (iCode * ic, iCode * ifx)
5076 operand *left, *right, *result;
5077 int size, offset = 0;
5078 unsigned long lit = 0L;
5079 unsigned char bytemask;
5081 D(emitcode ("; genOr",""));
5083 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5084 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5085 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5088 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5090 AOP_TYPE (left), AOP_TYPE (right)));
5091 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5093 AOP_SIZE (left), AOP_SIZE (right)));
5096 /* if left is a literal & right is not then exchange them */
5097 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5099 operand *tmp = right;
5104 /* if left is accumulator & right is not then exchange them */
5105 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5107 operand *tmp = right;
5112 if (AOP_TYPE (right) == AOP_LIT)
5113 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5115 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5117 if (AOP_TYPE (result) == AOP_CRY
5119 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5121 /* this generates ugly code, but meets volatility requirements */
5122 loadRegFromConst (hc08_reg_a, zero);
5123 pushReg (hc08_reg_a, TRUE);
5128 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5129 accopWithAop ("ora", AOP (right), offset);
5130 emitcode ("ora", "1,s");
5131 emitcode ("sta", "1,s");
5135 pullReg (hc08_reg_a);
5136 emitcode ("tsta", "");
5137 genIfxJump (ifx, "a");
5141 if (AOP_TYPE (result) == AOP_CRY)
5143 symbol *tlbl = NULL;
5144 wassertl (ifx, "AOP_CRY result without ifx");
5149 bytemask = (lit >> (offset*8)) & 0xff;
5151 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5153 rmwWithAop ("tst", AOP (left), offset);
5157 tlbl = newiTempLabel (NULL);
5158 emitBranch ("bne", tlbl);
5163 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5164 accopWithAop ("ora", AOP (right), offset);
5165 hc08_freeReg( hc08_reg_a);
5169 tlbl = newiTempLabel (NULL);
5170 emitBranch ("bne", tlbl);
5177 genIfxJump (ifx, "a");
5180 if (AOP_TYPE (right) == AOP_LIT)
5181 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5183 size = AOP_SIZE (result);
5185 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5186 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5187 (AOP_TYPE (left) == AOP_DIR))
5189 int bitpos = isLiteralBit(lit)-1;
5190 emitcode ("bset","#%d,%s",bitpos & 7,
5191 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5198 bytemask = (lit >> (offset*8)) & 0xff;
5200 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5202 if (isOperandVolatile (left, FALSE))
5204 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5205 hc08_freeReg( hc08_reg_a);
5207 transferAopAop (AOP (right), offset, AOP (result), offset);
5209 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5211 transferAopAop (AOP (left), offset, AOP (result), offset);
5215 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5216 accopWithAop ("ora", AOP (right), offset);
5217 storeRegToAop (hc08_reg_a, AOP (result), offset);
5218 hc08_freeReg (hc08_reg_a);
5225 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5226 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5227 freeAsmop (result, NULL, ic, TRUE);
5230 /*-----------------------------------------------------------------*/
5231 /* genXor - code for xclusive or */
5232 /*-----------------------------------------------------------------*/
5234 genXor (iCode * ic, iCode * ifx)
5236 operand *left, *right, *result;
5237 int size, offset = 0;
5238 unsigned long lit = 0L;
5240 D(emitcode ("; genXor",""));
5242 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5243 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5244 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5247 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5249 AOP_TYPE (left), AOP_TYPE (right)));
5250 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5252 AOP_SIZE (left), AOP_SIZE (right)));
5255 /* if left is a literal & right is not ||
5256 if left needs acc & right does not */
5257 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5259 operand *tmp = right;
5264 /* if left is accumulator & right is not then exchange them */
5265 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5267 operand *tmp = right;
5272 if (AOP_TYPE (result) == AOP_CRY)
5275 wassertl (ifx, "AOP_CPY result without ifx");
5277 tlbl = newiTempLabel (NULL);
5278 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5282 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5283 if ((AOP_TYPE (right) == AOP_LIT)
5284 && (((lit >> (offset*8)) & 0xff) == 0))
5285 emitcode ("tsta","");
5287 accopWithAop ("eor", AOP (right), offset);
5288 hc08_freeReg( hc08_reg_a);
5290 emitBranch ("bne", tlbl);
5294 genIfxJump (ifx, "a");
5300 if (AOP_TYPE (right) == AOP_LIT)
5301 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5303 size = AOP_SIZE (result);
5307 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5308 accopWithAop ("eor", AOP (right), offset);
5309 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5310 hc08_freeReg( hc08_reg_a);
5314 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5315 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5316 freeAsmop (result, NULL, ic, TRUE);
5320 emitinline (iCode * ic, char *inlin)
5326 symbol *sym, *tempsym;
5335 while (isalnum(*inlin) || (*inlin == '_'))
5339 //printf("Found possible symbol '%s'\n",symname);
5340 tempsym = newSymbol (symname, ic->level);
5341 tempsym->block = ic->block;
5342 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5351 aop = aopForSym (ic, sym, FALSE);
5352 l = aopAdrStr (aop, aop->size - 1, TRUE);
5356 if (sym->level && !sym->allocreq && !sym->ismyparm)
5358 werror (E_ID_UNDEF, sym->name);
5360 " Add 'volatile' to the variable declaration so that it\n"
5361 " can be referenced within inline assembly");
5363 //printf("Replacing with '%s'\n",l);
5367 if ((2+bp-buffer)>sizeof(buffer))
5376 if ((2+bp-buffer)>sizeof(buffer))
5383 if ((2+bp-buffer)>sizeof(buffer))
5384 fprintf(stderr, "Inline assembly buffer overflow\n");
5386 //printf("%s\n",buffer);
5387 emitcode (buffer,"");
5391 /*-----------------------------------------------------------------*/
5392 /* genInline - write the inline code out */
5393 /*-----------------------------------------------------------------*/
5395 genInline (iCode * ic)
5397 char *buffer, *bp, *bp1;
5399 D(emitcode ("; genInline",""));
5401 _G.inLine += (!options.asmpeep);
5403 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5404 strcpy (buffer, IC_INLINE (ic));
5406 /* emit each line as a code */
5412 /* emitcode (bp1, ""); */
5413 emitinline (ic, bp1);
5432 /* emitcode (bp1, ""); */
5433 emitinline (ic, bp1);
5435 /* emitcode("",buffer); */
5436 _G.inLine -= (!options.asmpeep);
5439 /*-----------------------------------------------------------------*/
5440 /* genRRC - rotate right with carry */
5441 /*-----------------------------------------------------------------*/
5445 operand *left, *result;
5446 int size, offset = 0;
5447 bool needpula = FALSE;
5448 bool resultInA = FALSE;
5451 D(emitcode ("; genRRC",""));
5453 /* rotate right with carry */
5454 left = IC_LEFT (ic);
5455 result = IC_RESULT (ic);
5456 aopOp (left, ic, FALSE);
5457 aopOp (result, ic, FALSE);
5459 if ((AOP_TYPE (result) == AOP_REG)
5460 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5463 size = AOP_SIZE (result);
5467 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5471 rmwWithAop (shift, AOP (result), offset--);
5479 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5480 rmwWithReg (shift, hc08_reg_a);
5481 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5482 hc08_freeReg (hc08_reg_a);
5487 if ((!hc08_reg_a->isFree) || resultInA)
5489 pushReg (hc08_reg_a, TRUE);
5493 /* now we need to put the carry into the
5494 highest order byte of the result */
5495 offset = AOP_SIZE (result) - 1;
5496 emitcode ("clra","");
5497 emitcode ("rora","");
5498 hc08_dirtyReg (hc08_reg_a, FALSE);
5501 emitcode ("ora", "1,s");
5502 emitcode ("ais", "#1");
5503 hc08_dirtyReg (hc08_reg_a, FALSE);
5507 accopWithAop ("ora", AOP (result), offset);
5508 storeRegToAop (hc08_reg_a, AOP (result), offset);
5510 pullOrFreeReg (hc08_reg_a, needpula);
5512 freeAsmop (left, NULL, ic, TRUE);
5513 freeAsmop (result, NULL, ic, TRUE);
5516 /*-----------------------------------------------------------------*/
5517 /* genRLC - generate code for rotate left with carry */
5518 /*-----------------------------------------------------------------*/
5522 operand *left, *result;
5523 int size, offset = 0;
5525 bool resultInA = FALSE;
5526 bool needpula = FALSE;
5528 D(emitcode ("; genRLC",""));
5530 /* rotate right with carry */
5531 left = IC_LEFT (ic);
5532 result = IC_RESULT (ic);
5533 aopOp (left, ic, FALSE);
5534 aopOp (result, ic, FALSE);
5536 if ((AOP_TYPE (result) == AOP_REG)
5537 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5540 size = AOP_SIZE (result);
5544 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5548 rmwWithAop (shift, AOP (result), offset--);
5556 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5557 rmwWithReg (shift, hc08_reg_a);
5558 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5559 hc08_freeReg (hc08_reg_a);
5564 if ((!hc08_reg_a->isFree) || resultInA)
5566 pushReg (hc08_reg_a, TRUE);
5570 /* now we need to put the carry into the
5571 lowest order byte of the result */
5573 emitcode ("clra","");
5574 emitcode ("rola","");
5575 hc08_dirtyReg (hc08_reg_a, FALSE);
5578 emitcode ("ora", "1,s");
5579 emitcode ("ais", "#1");
5580 hc08_dirtyReg (hc08_reg_a, FALSE);
5584 accopWithAop ("ora", AOP (result), offset);
5585 storeRegToAop (hc08_reg_a, AOP (result), offset);
5587 pullOrFreeReg (hc08_reg_a, needpula);
5589 freeAsmop (left, NULL, ic, TRUE);
5590 freeAsmop (result, NULL, ic, TRUE);
5593 /*-----------------------------------------------------------------*/
5594 /* genGetHbit - generates code get highest order bit */
5595 /*-----------------------------------------------------------------*/
5597 genGetHbit (iCode * ic)
5599 operand *left, *result;
5601 D(emitcode ("; genGetHbit",""));
5603 left = IC_LEFT (ic);
5604 result = IC_RESULT (ic);
5605 aopOp (left, ic, FALSE);
5606 aopOp (result, ic, FALSE);
5608 /* get the highest order byte into a */
5609 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5610 emitcode ("rola", "");
5611 emitcode ("clra", "");
5612 emitcode ("rola", "");
5613 hc08_dirtyReg (hc08_reg_a, FALSE);
5614 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5615 hc08_freeReg (hc08_reg_a);
5617 freeAsmop (left, NULL, ic, TRUE);
5618 freeAsmop (result, NULL, ic, TRUE);
5621 /*-----------------------------------------------------------------*/
5622 /* genSwap - generates code to swap nibbles or bytes */
5623 /*-----------------------------------------------------------------*/
5625 genSwap (iCode * ic)
5627 operand *left, *result;
5629 D(emitcode ("; genSwap",""));
5631 left = IC_LEFT (ic);
5632 result = IC_RESULT (ic);
5633 aopOp (left, ic, FALSE);
5634 aopOp (result, ic, FALSE);
5636 switch (AOP_SIZE (left))
5638 case 1: /* swap nibbles in byte */
5639 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5640 emitcode ("nsa", "");
5641 hc08_dirtyReg (hc08_reg_a, FALSE);
5642 storeRegToAop (hc08_reg_a, AOP (result), 0);
5643 hc08_freeReg (hc08_reg_a);
5645 case 2: /* swap bytes in a word */
5646 if (operandsEqu (left, result))
5648 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5649 hc08_useReg (hc08_reg_a);
5650 transferAopAop (AOP (left), 1, AOP (result), 0);
5651 storeRegToAop (hc08_reg_a, AOP (result), 1);
5652 hc08_freeReg (hc08_reg_a);
5656 transferAopAop (AOP (left), 0, AOP (result), 1);
5657 transferAopAop (AOP (left), 1, AOP (result), 0);
5661 wassertl(FALSE, "unsupported SWAP operand size");
5664 freeAsmop (left, NULL, ic, TRUE);
5665 freeAsmop (result, NULL, ic, TRUE);
5669 /*-----------------------------------------------------------------*/
5670 /* AccRol - rotate left accumulator by known count */
5671 /*-----------------------------------------------------------------*/
5673 AccRol (int shCount)
5675 shCount &= 0x0007; // shCount : 0..7
5682 emitcode ("rola", ""); /* 1 cycle */
5685 emitcode ("rola", ""); /* 1 cycle */
5686 emitcode ("rola", ""); /* 1 cycle */
5689 emitcode ("nsa", "");
5690 emitcode ("rora", "");
5693 emitcode ("nsa", ""); /* 3 cycles */
5696 emitcode ("nsa", ""); /* 3 cycles */
5697 emitcode ("rola", ""); /* 1 cycle */
5700 emitcode ("nsa", ""); /* 3 cycles */
5701 emitcode ("rola", ""); /* 1 cycle */
5702 emitcode ("rola", ""); /* 1 cycle */
5705 emitcode ("nsa", ""); /* 3 cycles */
5706 emitcode ("rola", ""); /* 1 cycle */
5707 emitcode ("rola", ""); /* 1 cycle */
5708 emitcode ("rola", ""); /* 1 cycle */
5715 /*-----------------------------------------------------------------*/
5716 /* AccLsh - left shift accumulator by known count */
5717 /*-----------------------------------------------------------------*/
5719 AccLsh (int shCount)
5723 shCount &= 0x0007; // shCount : 0..7
5725 /* Shift counts of 4 and 5 are currently optimized for code size. */
5726 /* Falling through to the unrolled loop would be optimal for code speed. */
5727 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5731 if (optimize.codeSpeed)
5733 accopWithMisc ("nsa", "");
5734 accopWithMisc ("and", "#0xf0");
5735 /* total: 5 cycles, 3 bytes */
5738 if (optimize.codeSpeed)
5740 accopWithMisc ("nsa", "");
5741 accopWithMisc ("and", "#0xf0");
5742 accopWithMisc ("lsla", "");
5743 /* total: 6 cycles, 4 bytes */
5746 accopWithMisc ("rora", "");
5747 accopWithMisc ("rora", "");
5748 accopWithMisc ("rora", "");
5749 accopWithMisc ("and", "#0xc0");
5750 /* total: 5 cycles, 5 bytes */
5753 accopWithMisc ("rora", "");
5754 accopWithMisc ("clra", "");
5755 accopWithMisc ("rora", "");
5756 /* total: 3 cycles, 3 bytes */
5760 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5761 /* the fastest (shCount<6) and shortest (shCount<4). */
5762 for (i=0;i<shCount;i++)
5763 accopWithMisc ("lsla", "");
5767 /*-----------------------------------------------------------------*/
5768 /* AccSRsh - signed right shift accumulator by known count */
5769 /*-----------------------------------------------------------------*/
5771 AccSRsh (int shCount)
5775 shCount &= 0x0007; // shCount : 0..7
5779 accopWithMisc ("rola", "");
5780 accopWithMisc ("clra", "");
5781 accopWithMisc ("sbc", zero);
5782 /* total: 4 cycles, 4 bytes */
5786 for (i=0;i<shCount;i++)
5787 accopWithMisc ("asra", "");
5790 /*-----------------------------------------------------------------*/
5791 /* AccRsh - right shift accumulator by known count */
5792 /*-----------------------------------------------------------------*/
5794 AccRsh (int shCount, bool sign)
5804 shCount &= 0x0007; // shCount : 0..7
5806 /* Shift counts of 4 and 5 are currently optimized for code size. */
5807 /* Falling through to the unrolled loop would be optimal for code speed. */
5808 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5812 if (optimize.codeSpeed)
5814 accopWithMisc ("nsa", "");
5815 accopWithMisc ("and", "#0x0f");
5816 /* total: 5 cycles, 3 bytes */
5819 if (optimize.codeSpeed)
5821 accopWithMisc ("nsa", "");
5822 accopWithMisc ("and", "#0x0f");
5823 accopWithMisc ("lsra", "");
5824 /* total: 6 cycles, 4 bytes */
5827 accopWithMisc ("rola", "");
5828 accopWithMisc ("rola", "");
5829 accopWithMisc ("rola", "");
5830 accopWithMisc ("and", "#0x03");
5831 /* total: 5 cycles, 5 bytes */
5834 accopWithMisc ("rola", "");
5835 accopWithMisc ("clra", "");
5836 accopWithMisc ("rola", "");
5837 /* total: 3 cycles, 3 bytes */
5841 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5842 /* the fastest (shCount<6) and shortest (shCount<4). */
5843 for (i=0;i<shCount;i++)
5844 accopWithMisc ("lsra", "");
5848 /*-----------------------------------------------------------------*/
5849 /* XAccLsh - left shift register pair XA by known count */
5850 /*-----------------------------------------------------------------*/
5852 XAccLsh (int shCount)
5856 shCount &= 0x000f; // shCount : 0..15
5861 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5862 loadRegFromConst (hc08_reg_a, zero);
5866 /* if we can beat 2n cycles or bytes for some special case, do it here */
5870 /* bytes cycles reg x reg a carry
5871 ** abcd efgh ijkl mnop ?
5872 ** lsrx 1 1 0abc defg ijkl mnop h
5873 ** rora 1 1 0abc defg hijk lmno p
5874 ** tax 1 1 hijk lmno hijk lmno p
5875 ** clra 1 1 hijk lmno 0000 0000 p
5876 ** rora 1 1 hijk lmno p000 0000 0
5877 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5879 rmwWithReg ("lsr", hc08_reg_x);
5880 rmwWithReg ("ror", hc08_reg_a);
5881 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5882 loadRegFromConst (hc08_reg_a, zero);
5883 rmwWithReg ("ror", hc08_reg_a);
5890 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5891 /* the fastest and shortest. */
5892 for (i=0;i<shCount;i++)
5894 rmwWithReg ("lsl", hc08_reg_a);
5895 rmwWithReg ("rol", hc08_reg_x);
5899 /*-----------------------------------------------------------------*/
5900 /* XAccSRsh - signed right shift register pair XA by known count */
5901 /*-----------------------------------------------------------------*/
5903 XAccSRsh (int shCount)
5907 shCount &= 0x000f; // shCount : 0..7
5909 /* if we can beat 2n cycles or bytes for some special case, do it here */
5913 /* bytes cycles reg x reg a carry
5914 ** abcd efgh ijkl mnop ?
5915 ** lslx 1 1 bcde fgh0 ijkl mnop a
5916 ** clra 1 1 bcde fgh0 0000 0000 a
5917 ** rola 1 1 bcde fgh0 0000 000a 0
5918 ** nega 1 1 bcde fgh0 aaaa aaaa a
5919 ** tax 1 1 aaaa aaaa aaaa aaaa a
5920 ** total: 5 cycles, 5 bytes
5922 rmwWithReg ("lsl", hc08_reg_x);
5923 loadRegFromConst (hc08_reg_a, zero);
5924 rmwWithReg ("rol", hc08_reg_a);
5925 rmwWithReg ("neg", hc08_reg_a);
5926 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5936 /* bytes cycles reg x reg a carry
5937 ** abcd efgh ijkl mnop ?
5938 ** txa 1 1 abcd efgh abcd efgh ?
5939 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5940 ** lsla 1 1 abcd efgh ???? ???? a
5941 ** clrx 1 1 0000 0000 ???? ???? a
5942 ** rolx 1 1 0000 000a ???? ???? 0
5943 ** negx 1 1 aaaa aaaa ???? ???? a
5944 ** rora 1 1 aaaa aaaa LSBresult 0
5945 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5947 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5948 AccSRsh (shCount-8);
5949 rmwWithReg ("lsl", hc08_reg_a);
5950 loadRegFromConst (hc08_reg_x, zero);
5951 rmwWithReg ("rol", hc08_reg_x);
5952 rmwWithReg ("neg", hc08_reg_x);
5953 rmwWithReg ("ror", hc08_reg_a);
5960 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5961 /* the fastest and shortest. */
5962 for (i=0;i<shCount;i++)
5964 rmwWithReg ("asr", hc08_reg_x);
5965 rmwWithReg ("ror", hc08_reg_a);
5969 /*-----------------------------------------------------------------*/
5970 /* XAccRsh - right shift register pair XA by known count */
5971 /*-----------------------------------------------------------------*/
5973 XAccRsh (int shCount, bool sign)
5983 shCount &= 0x000f; // shCount : 0..f
5985 /* if we can beat 2n cycles or bytes for some special case, do it here */
5989 /* bytes cycles reg x reg a carry
5990 ** abcd efgh ijkl mnop ?
5991 ** clra 1 1 abcd efgh 0000 0000 a
5992 ** lslx 1 1 bcde fgh0 0000 0000 a
5993 ** rola 1 1 bcde fgh0 0000 000a 0
5994 ** clrx 1 1 0000 0000 0000 000a 0
5995 ** total: 4 cycles, 4 bytes
5997 loadRegFromConst (hc08_reg_x, zero);
5998 rmwWithReg ("lsl", hc08_reg_x);
5999 rmwWithReg ("rol", hc08_reg_a);
6000 loadRegFromConst (hc08_reg_a, zero);
6004 /* bytes cycles reg x reg a carry
6005 ** abcd efgh ijkl mnop ?
6006 ** clra 1 1 abcd efgh 0000 0000 a
6007 ** lslx 1 1 bcde fgh0 0000 0000 a
6008 ** rola 1 1 bcde fgh0 0000 000a 0
6009 ** lslx 1 1 cdef gh00 0000 000a b
6010 ** rola 1 1 cdef gh00 0000 00ab 0
6011 ** clrx 1 1 0000 0000 0000 00ab 0
6012 ** total: 6 cycles, 6 bytes
6014 loadRegFromConst (hc08_reg_x, zero);
6015 rmwWithReg ("lsl", hc08_reg_x);
6016 rmwWithReg ("rol", hc08_reg_a);
6017 rmwWithReg ("lsl", hc08_reg_x);
6018 rmwWithReg ("rol", hc08_reg_a);
6019 loadRegFromConst (hc08_reg_a, zero);
6028 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6029 AccRsh (shCount-8, FALSE);
6030 loadRegFromConst (hc08_reg_x, zero);
6034 /* bytes cycles reg x reg a carry
6035 ** abcd efgh ijkl mnop ?
6036 ** lsla 1 1 abcd efgh jklm nop0 i
6037 ** txa 1 1 abcd efgh abcd efgh i
6038 ** rola 1 1 abcd efgh bcde fghi a
6039 ** clrx 1 1 0000 0000 bcde fghi a
6040 ** rolx 1 1 0000 000a bcde fghi 0
6041 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6043 rmwWithReg ("lsl", hc08_reg_a);
6044 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6045 rmwWithReg ("rol", hc08_reg_a);
6046 loadRegFromConst (hc08_reg_x, zero);
6047 rmwWithReg ("rol", hc08_reg_x);
6050 /* bytes cycles reg x reg a carry
6051 ** abcd efgh ijkl mnop ?
6052 ** lsla 1 1 abcd efgh jklm nop0 i
6053 ** rolx 1 1 bcde fghi jklm nop0 a
6054 ** rola 1 1 bcde fghi klmn op0a j
6055 ** rolx 1 1 cdef ghij klmn op0a b
6056 ** rola 1 1 cdef ghij lmno p0ab k
6057 ** and #3 2 2 cdef ghij 0000 00ab k
6058 ** psha 1 2 cdef ghij 0000 00ab k
6059 ** txa 1 1 cdef ghij cdef ghij k
6060 ** pula 1 2 0000 00ab cdef ghij k
6061 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6067 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6068 /* the fastest and shortest. */
6069 for (i=0;i<shCount;i++)
6071 rmwWithReg ("lsr", hc08_reg_x);
6072 rmwWithReg ("ror", hc08_reg_a);
6079 /*-----------------------------------------------------------------*/
6080 /* shiftR1Left2Result - shift right one byte from left to result */
6081 /*-----------------------------------------------------------------*/
6083 shiftR1Left2Result (operand * left, int offl,
6084 operand * result, int offr,
6085 int shCount, int sign)
6087 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6088 /* shift right accumulator */
6089 AccRsh (shCount, sign);
6090 storeRegToAop (hc08_reg_a, AOP (result), offr);
6094 /*-----------------------------------------------------------------*/
6095 /* shiftL1Left2Result - shift left one byte from left to result */
6096 /*-----------------------------------------------------------------*/
6098 shiftL1Left2Result (operand * left, int offl,
6099 operand * result, int offr, int shCount)
6101 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6102 /* shift left accumulator */
6104 storeRegToAop (hc08_reg_a, AOP (result), offr);
6107 /*-----------------------------------------------------------------*/
6108 /* movLeft2Result - move byte from left to result */
6109 /*-----------------------------------------------------------------*/
6111 movLeft2Result (operand * left, int offl,
6112 operand * result, int offr, int sign)
6114 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6116 transferAopAop (AOP (left), offl, AOP (result), offr);
6121 /*-----------------------------------------------------------------*/
6122 /* shiftL2Left2Result - shift left two bytes from left to result */
6123 /*-----------------------------------------------------------------*/
6125 shiftL2Left2Result (operand * left, int offl,
6126 operand * result, int offr, int shCount)
6129 bool needpula = FALSE;
6130 bool needpulx = FALSE;
6132 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6133 needpula = pushRegIfUsed (hc08_reg_a);
6136 if (!IS_AOP_XA (AOP (left)))
6137 needpulx = pushRegIfUsed (hc08_reg_x);
6141 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6146 rmwWithReg ("lsr", hc08_reg_x);
6147 rmwWithReg ("ror", hc08_reg_a);
6148 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6149 rmwWithReg ("clr", hc08_reg_a);
6150 rmwWithReg ("ror", hc08_reg_a);
6153 for (i=0; i<shCount; i++)
6155 rmwWithReg ("lsl", hc08_reg_a);
6156 rmwWithReg ("rol", hc08_reg_x);
6159 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6161 pullOrFreeReg (hc08_reg_x, needpulx);
6162 pullOrFreeReg (hc08_reg_a, needpula);
6168 /*-----------------------------------------------------------------*/
6169 /* shiftR2Left2Result - shift right two bytes from left to result */
6170 /*-----------------------------------------------------------------*/
6172 shiftR2Left2Result (operand * left, int offl,
6173 operand * result, int offr,
6174 int shCount, int sign)
6177 bool needpula = FALSE;
6178 bool needpulx = FALSE;
6180 needpula = pushRegIfUsed (hc08_reg_a);
6181 needpulx = pushRegIfUsed (hc08_reg_x);
6183 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6184 for (i=0; i<shCount; i++)
6187 rmwWithReg ("asr", hc08_reg_x);
6189 rmwWithReg ("lsr", hc08_reg_x);
6190 rmwWithReg ("ror", hc08_reg_a);
6192 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6194 pullOrFreeReg (hc08_reg_x, needpulx);
6195 pullOrFreeReg (hc08_reg_a, needpula);
6200 /*-----------------------------------------------------------------*/
6201 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6202 /*-----------------------------------------------------------------*/
6204 shiftLLeftOrResult (operand * left, int offl,
6205 operand * result, int offr, int shCount)
6207 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6208 /* shift left accumulator */
6210 /* or with result */
6211 accopWithAop ("ora", AOP (result), offr);
6212 /* back to result */
6213 storeRegToAop (hc08_reg_a, AOP (result), offr);
6214 hc08_freeReg (hc08_reg_a);
6218 /*-----------------------------------------------------------------*/
6219 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6220 /*-----------------------------------------------------------------*/
6222 shiftRLeftOrResult (operand * left, int offl,
6223 operand * result, int offr, int shCount)
6225 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6226 /* shift left accumulator */
6227 AccRsh (shCount, FALSE);
6228 /* or with result */
6229 accopWithAop ("ora", AOP (result), offr);
6230 /* back to result */
6231 storeRegToAop (hc08_reg_a, AOP (result), offr);
6232 hc08_freeReg (hc08_reg_a);
6235 /*-----------------------------------------------------------------*/
6236 /* genlshOne - left shift a one byte quantity by known count */
6237 /*-----------------------------------------------------------------*/
6239 genlshOne (operand * result, operand * left, int shCount)
6241 D(emitcode ("; genlshOne",""));
6243 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6246 /*-----------------------------------------------------------------*/
6247 /* genlshTwo - left shift two bytes by known amount != 0 */
6248 /*-----------------------------------------------------------------*/
6250 genlshTwo (operand * result, operand * left, int shCount)
6254 D(emitcode ("; genlshTwo",""));
6257 size = getDataSize (result);
6259 /* if shCount >= 8 */
6266 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6268 storeRegToAop (hc08_reg_a, AOP (result), 1);
6270 storeConstToAop(zero, AOP (result), LSB);
6273 /* 1 <= shCount <= 7 */
6276 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6278 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6282 /*-----------------------------------------------------------------*/
6283 /* shiftLLong - shift left one long from left to result */
6284 /* offl = LSB or MSB16 */
6285 /*-----------------------------------------------------------------*/
6287 shiftLLong (operand * left, operand * result, int offr)
6290 // int size = AOP_SIZE (result);
6292 bool needpula = FALSE;
6293 bool needpulx = FALSE;
6295 needpula = pushRegIfUsed (hc08_reg_a);
6296 needpulx = pushRegIfUsed (hc08_reg_x);
6298 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6299 rmwWithReg ("lsl", hc08_reg_a);
6300 rmwWithReg ("rol", hc08_reg_x);
6301 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6305 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6306 rmwWithReg ("rol", hc08_reg_a);
6307 rmwWithReg ("rol", hc08_reg_x);
6308 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6310 else if (offr==MSB16)
6312 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6313 rmwWithReg ("rol", hc08_reg_a);
6314 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6315 storeConstToAop (zero, AOP (result), 0);
6318 pullOrFreeReg (hc08_reg_x, needpulx);
6319 pullOrFreeReg (hc08_reg_a, needpula);
6322 /*-----------------------------------------------------------------*/
6323 /* genlshFour - shift four byte by a known amount != 0 */
6324 /*-----------------------------------------------------------------*/
6326 genlshFour (operand * result, operand * left, int shCount)
6330 D(emitcode ("; genlshFour",""));
6332 size = AOP_SIZE (result);
6334 /* TODO: deal with the &result == &left case */
6336 /* if shifting more that 3 bytes */
6341 /* lowest order of left goes to the highest
6342 order of the destination */
6343 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6345 movLeft2Result (left, LSB, result, MSB32, 0);
6346 storeConstToAop (zero, AOP (result), LSB);
6347 storeConstToAop (zero, AOP (result), MSB16);
6348 storeConstToAop (zero, AOP (result), MSB24);
6352 /* more than two bytes */
6353 else if (shCount >= 16)
6355 /* lower order two bytes goes to higher order two bytes */
6357 /* if some more remaining */
6359 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6362 movLeft2Result (left, MSB16, result, MSB32, 0);
6363 movLeft2Result (left, LSB, result, MSB24, 0);
6365 storeConstToAop (zero, AOP (result), LSB);
6366 storeConstToAop (zero, AOP (result), MSB16);
6370 /* if more than 1 byte */
6371 else if (shCount >= 8)
6373 /* lower order three bytes goes to higher order three bytes */
6378 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6380 movLeft2Result (left, LSB, result, MSB16, 0);
6386 movLeft2Result (left, MSB24, result, MSB32, 0);
6387 movLeft2Result (left, MSB16, result, MSB24, 0);
6388 movLeft2Result (left, LSB, result, MSB16, 0);
6389 storeConstToAop (zero, AOP (result), LSB);
6391 else if (shCount == 1)
6392 shiftLLong (left, result, MSB16);
6395 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6396 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6397 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6398 storeConstToAop (zero, AOP (result), LSB);
6403 /* 1 <= shCount <= 7 */
6404 else if (shCount <= 2)
6406 shiftLLong (left, result, LSB);
6408 shiftLLong (result, result, LSB);
6410 /* 3 <= shCount <= 7, optimize */
6413 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6414 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6415 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6419 /*-----------------------------------------------------------------*/
6420 /* genLeftShiftLiteral - left shifting by known count */
6421 /*-----------------------------------------------------------------*/
6423 genLeftShiftLiteral (operand * left,
6428 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6431 D(emitcode ("; genLeftShiftLiteral",""));
6433 freeAsmop (right, NULL, ic, TRUE);
6435 aopOp (left, ic, FALSE);
6436 aopOp (result, ic, FALSE);
6438 // size = getSize (operandType (result));
6439 size = AOP_SIZE (result);
6442 D(emitcode ("; shift left ", "result %d, left %d", size,
6449 transferAopAop( AOP(left), size, AOP(result), size);
6451 else if (shCount >= (size * 8))
6454 storeConstToAop (zero, AOP (result), size);
6461 genlshOne (result, left, shCount);
6465 genlshTwo (result, left, shCount);
6469 genlshFour (result, left, shCount);
6472 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6473 "*** ack! mystery literal shift!\n");
6477 freeAsmop (left, NULL, ic, TRUE);
6478 freeAsmop (result, NULL, ic, TRUE);
6481 /*-----------------------------------------------------------------*/
6482 /* genLeftShift - generates code for left shifting */
6483 /*-----------------------------------------------------------------*/
6485 genLeftShift (iCode * ic)
6487 operand *left, *right, *result;
6489 symbol *tlbl, *tlbl1;
6494 D(emitcode ("; genLeftShift",""));
6496 right = IC_RIGHT (ic);
6497 left = IC_LEFT (ic);
6498 result = IC_RESULT (ic);
6500 aopOp (right, ic, FALSE);
6502 /* if the shift count is known then do it
6503 as efficiently as possible */
6504 if (AOP_TYPE (right) == AOP_LIT)
6506 genLeftShiftLiteral (left, right, result, ic);
6510 /* shift count is unknown then we have to form
6511 a loop get the loop count in A : Note: we take
6512 only the lower order byte since shifting
6513 more that 32 bits make no sense anyway, ( the
6514 largest size of an object can be only 32 bits ) */
6516 aopOp (left, ic, FALSE);
6517 aopOp (result, ic, FALSE);
6519 /* now move the left to the result if they are not the
6521 if (!sameRegs (AOP (left), AOP (result)))
6524 size = AOP_SIZE (result);
6528 transferAopAop (AOP (left), offset, AOP (result), offset);
6532 freeAsmop (left, NULL, ic, TRUE);
6534 tlbl = newiTempLabel (NULL);
6535 size = AOP_SIZE (result);
6537 tlbl1 = newiTempLabel (NULL);
6541 loadRegFromAop (reg, AOP (right), 0);
6542 freeAsmop (right, NULL, ic, TRUE);
6543 emitBranch ("beq", tlbl1);
6547 for (offset=0;offset<size;offset++)
6549 rmwWithAop (shift, AOP (result), offset);
6552 rmwWithReg ("dec", reg);
6553 emitBranch ("bne", tlbl);
6557 freeAsmop (result, NULL, ic, TRUE);
6560 /*-----------------------------------------------------------------*/
6561 /* genrshOne - right shift a one byte quantity by known count */
6562 /*-----------------------------------------------------------------*/
6564 genrshOne (operand * result, operand * left,
6565 int shCount, int sign)
6567 D(emitcode ("; genrshOne",""));
6569 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6570 AccRsh (shCount, sign);
6571 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6574 /*-----------------------------------------------------------------*/
6575 /* genrshTwo - right shift two bytes by known amount != 0 */
6576 /*-----------------------------------------------------------------*/
6578 genrshTwo (operand * result, operand * left,
6579 int shCount, int sign)
6581 D(emitcode ("; genrshTwo",""));
6583 /* if shCount >= 8 */
6586 if (shCount || sign)
6588 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6589 AccRsh (shCount-8, sign);
6590 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6594 transferAopAop (AOP (left), 1, AOP (result), 0);
6595 storeConstToAop (zero, AOP (result), 1);
6599 /* 1 <= shCount <= 7 */
6602 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6603 XAccRsh (shCount, sign);
6604 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6608 /*-----------------------------------------------------------------*/
6609 /* shiftRLong - shift right one long from left to result */
6610 /* offl = LSB or MSB16 */
6611 /*-----------------------------------------------------------------*/
6613 shiftRLong (operand * left, int offl,
6614 operand * result, int sign)
6617 // int size = AOP_SIZE (result);
6619 bool needpula = FALSE;
6620 bool needpulx = FALSE;
6622 needpula = pushRegIfUsed (hc08_reg_a);
6623 needpulx = pushRegIfUsed (hc08_reg_x);
6627 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6629 rmwWithReg ("asr", hc08_reg_x);
6631 rmwWithReg ("lsr", hc08_reg_x);
6632 rmwWithReg ("ror", hc08_reg_a);
6633 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6635 else if (offl==MSB16)
6637 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6639 rmwWithReg ("asr", hc08_reg_a);
6641 rmwWithReg ("lsr", hc08_reg_a);
6642 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6643 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6646 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6647 rmwWithReg ("ror", hc08_reg_x);
6648 rmwWithReg ("ror", hc08_reg_a);
6649 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6652 pullOrFreeReg (hc08_reg_x, needpulx);
6653 pullOrFreeReg (hc08_reg_a, needpula);
6656 /*-----------------------------------------------------------------*/
6657 /* genrshFour - shift four byte by a known amount != 0 */
6658 /*-----------------------------------------------------------------*/
6660 genrshFour (operand * result, operand * left,
6661 int shCount, int sign)
6663 /* TODO: handle cases where left == result */
6665 D(emitcode ("; genrshFour",""));
6667 /* if shifting more that 3 bytes */
6670 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6671 AccRsh (shCount-24, sign);
6672 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6675 else if (shCount >= 16)
6677 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6678 XAccRsh (shCount-16, sign);
6679 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6682 else if (shCount >= 8)
6685 shiftRLong (left, MSB16, result, sign);
6686 else if (shCount == 8)
6688 transferAopAop (AOP (left), 1, AOP (result), 0);
6689 transferAopAop (AOP (left), 2, AOP (result), 1);
6690 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6691 storeRegToAop (hc08_reg_a, AOP (result), 2);
6692 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6694 else if (shCount == 9)
6696 shiftRLong (left, MSB16, result, sign);
6700 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6701 XAccRsh (shCount-8, FALSE);
6702 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6703 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6704 loadRegFromConst (hc08_reg_a, zero);
6705 XAccRsh (shCount-8, sign);
6706 accopWithAop ("ora", AOP (result), 1);
6707 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6708 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6712 { /* 1 <= shCount <= 7 */
6715 shiftRLong (left, LSB, result, sign);
6719 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6720 XAccRsh (shCount, FALSE);
6721 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6722 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6724 accopWithAop ("ora", AOP (result), 1);
6725 storeRegToAop (hc08_reg_a, AOP (result), 1);
6726 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6727 XAccRsh (shCount, sign);
6728 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6733 /*-----------------------------------------------------------------*/
6734 /* genRightShiftLiteral - right shifting by known count */
6735 /*-----------------------------------------------------------------*/
6737 genRightShiftLiteral (operand * left,
6743 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6746 D(emitcode ("; genRightShiftLiteral",""));
6748 freeAsmop (right, NULL, ic, TRUE);
6750 aopOp (left, ic, FALSE);
6751 aopOp (result, ic, FALSE);
6754 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6758 size = getDataSize (left);
6759 /* test the LEFT size !!! */
6761 /* I suppose that the left size >= result size */
6764 size = getDataSize (result);
6766 transferAopAop (AOP (left), size, AOP(result), size);
6768 else if (shCount >= (size * 8))
6771 /* get sign in acc.7 */
6772 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6774 addSign (result, LSB, sign);
6781 genrshOne (result, left, shCount, sign);
6785 genrshTwo (result, left, shCount, sign);
6789 genrshFour (result, left, shCount, sign);
6795 freeAsmop (left, NULL, ic, TRUE);
6796 freeAsmop (result, NULL, ic, TRUE);
6800 /*-----------------------------------------------------------------*/
6801 /* genRightShift - generate code for right shifting */
6802 /*-----------------------------------------------------------------*/
6804 genRightShift (iCode * ic)
6806 operand *right, *left, *result;
6810 symbol *tlbl, *tlbl1;
6814 D(emitcode ("; genRightShift",""));
6816 /* if signed then we do it the hard way preserve the
6817 sign bit moving it inwards */
6818 retype = getSpec (operandType (IC_RESULT (ic)));
6819 sign = !SPEC_USIGN (retype);
6821 /* signed & unsigned types are treated the same : i.e. the
6822 signed is NOT propagated inwards : quoting from the
6823 ANSI - standard : "for E1 >> E2, is equivalent to division
6824 by 2**E2 if unsigned or if it has a non-negative value,
6825 otherwise the result is implementation defined ", MY definition
6826 is that the sign does not get propagated */
6828 right = IC_RIGHT (ic);
6829 left = IC_LEFT (ic);
6830 result = IC_RESULT (ic);
6832 aopOp (right, ic, FALSE);
6834 /* if the shift count is known then do it
6835 as efficiently as possible */
6836 if (AOP_TYPE (right) == AOP_LIT)
6838 genRightShiftLiteral (left, right, result, ic, sign);
6842 /* shift count is unknown then we have to form
6843 a loop get the loop count in X : Note: we take
6844 only the lower order byte since shifting
6845 more that 32 bits make no sense anyway, ( the
6846 largest size of an object can be only 32 bits ) */
6848 aopOp (left, ic, FALSE);
6849 aopOp (result, ic, FALSE);
6851 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6852 AOP (result) = forceStackedAop (AOP (result));
6854 size = AOP_SIZE (result);
6858 transferAopAop (AOP (left), offset, AOP (result), offset);
6862 tlbl = newiTempLabel (NULL);
6863 size = AOP_SIZE (result);
6865 tlbl1 = newiTempLabel (NULL);
6867 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6868 emitcode ("tstx", "");
6869 emitcode ("beq", "%05d$", tlbl1->key + 100);
6870 emitcode ("", "%05d$:", tlbl->key + 100);
6871 shift= sign ? "asr" : "lsr";
6872 for (offset=size-1;offset>=0;offset--)
6874 rmwWithAop (shift, AOP (result), offset);
6877 rmwWithReg ("dec", hc08_reg_x);
6878 emitcode ("bne","%05d$", tlbl->key + 100);
6879 emitcode ("", "%05d$:", tlbl1->key + 100);
6881 freeAsmop (result, NULL, ic, TRUE);
6882 freeAsmop (left, NULL, ic, TRUE);
6883 freeAsmop (right, NULL, ic, TRUE);
6887 /*-----------------------------------------------------------------*/
6888 /* genUnpackBits - generates code for unpacking bits */
6889 /*-----------------------------------------------------------------*/
6891 genUnpackBits (operand * result, iCode *ifx)
6893 int offset = 0; /* result byte offset */
6894 int rsize; /* result size */
6895 int rlen = 0; /* remaining bitfield length */
6896 sym_link *etype; /* bitfield type information */
6897 int blen; /* bitfield length */
6898 int bstr; /* bitfield starting bit within byte */
6900 D(emitcode ("; genUnpackBits",""));
6902 etype = getSpec (operandType (result));
6903 rsize = getSize (operandType (result));
6904 blen = SPEC_BLEN (etype);
6905 bstr = SPEC_BSTR (etype);
6907 /* If the bitfield length is less than a byte */
6910 emitcode ("lda", ",x");
6911 hc08_dirtyReg (hc08_reg_a, FALSE);
6914 AccRsh (bstr, FALSE);
6915 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6916 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6920 emitcode ("and", "#0x%02x",
6921 (((unsigned char) -1) >> (8 - blen)) << bstr);
6926 /* Bit field did not fit in a byte. Copy all
6927 but the partial byte at the end. */
6928 for (rlen=blen;rlen>=8;rlen-=8)
6930 emitcode ("lda", ",x");
6931 hc08_dirtyReg (hc08_reg_a, FALSE);
6933 storeRegToAop (hc08_reg_a, AOP (result), offset);
6936 emitcode ("aix", "#1");
6939 /* Handle the partial byte at the end */
6942 emitcode ("lda", ",x");
6943 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6944 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6952 storeConstToAop (zero, AOP (result), offset++);
6955 if (ifx && !ifx->generated)
6957 genIfxJump (ifx, "a");
6962 /*-----------------------------------------------------------------*/
6963 /* genUnpackBitsImmed - generates code for unpacking bits */
6964 /*-----------------------------------------------------------------*/
6966 genUnpackBitsImmed (operand * left,
6972 int offset = 0; /* result byte offset */
6973 int rsize; /* result size */
6974 int rlen = 0; /* remaining bitfield length */
6975 sym_link *etype; /* bitfield type information */
6976 int blen; /* bitfield length */
6977 int bstr; /* bitfield starting bit within byte */
6980 D(emitcode ("; genUnpackBitsImmed",""));
6982 aopOp (result, ic, TRUE);
6983 size = AOP_SIZE (result);
6985 derefaop = aopDerefAop (AOP (left));
6986 freeAsmop (left, NULL, ic, TRUE);
6987 derefaop->size = size;
6989 etype = getSpec (operandType (result));
6990 rsize = getSize (operandType (result));
6991 blen = SPEC_BLEN (etype);
6992 bstr = SPEC_BSTR (etype);
6994 /* if the bitfield is a single bit in the direct page */
6995 if (blen == 1 && derefaop->type == AOP_DIR)
6999 symbol *tlbl = newiTempLabel (NULL);
7001 loadRegFromConst (hc08_reg_a, zero);
7002 emitcode ("brclr", "#%d,%s,%05d$",
7003 bstr, aopAdrStr (derefaop, 0, FALSE),
7005 rmwWithReg ("inc", hc08_reg_a);
7007 storeRegToAop (hc08_reg_a, AOP (result), offset);
7008 hc08_freeReg (hc08_reg_a);
7014 symbol *tlbl = newiTempLabel (NULL);
7020 jlbl = IC_TRUE (ifx);
7025 jlbl = IC_FALSE (ifx);
7028 emitcode (inst, "#%d,%s,%05d$",
7029 bstr, aopAdrStr (derefaop, 0, FALSE),
7031 emitBranch ("jmp", jlbl);
7039 /* If the bitfield length is less than a byte */
7042 loadRegFromAop (hc08_reg_a, derefaop, 0);
7045 AccRsh (bstr, FALSE);
7046 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7047 hc08_dirtyReg (hc08_reg_a, FALSE);
7048 storeRegToAop (hc08_reg_a, AOP (result), offset);
7052 emitcode ("and", "#0x%02x",
7053 (((unsigned char) -1) >> (8 - blen)) << bstr);
7054 hc08_dirtyReg (hc08_reg_a, FALSE);
7060 /* Bit field did not fit in a byte. Copy all
7061 but the partial byte at the end. */
7062 for (rlen=blen;rlen>=8;rlen-=8)
7064 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7066 storeRegToAop (hc08_reg_a, AOP (result), offset);
7068 emitcode ("tsta", "");
7072 /* Handle the partial byte at the end */
7075 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7076 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7077 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7085 storeConstToAop (zero, AOP (result), offset++);
7088 freeAsmop (NULL, derefaop, ic, TRUE);
7089 freeAsmop (result, NULL, ic, TRUE);
7091 if (ifx && !ifx->generated)
7093 genIfxJump (ifx, "a");
7098 /*-----------------------------------------------------------------*/
7099 /* genDataPointerGet - generates code when ptr offset is known */
7100 /*-----------------------------------------------------------------*/
7102 genDataPointerGet (operand * left,
7110 D(emitcode ("; genDataPointerGet",""));
7112 aopOp (result, ic, TRUE);
7113 size = AOP_SIZE (result);
7115 derefaop = aopDerefAop (AOP (left));
7116 freeAsmop (left, NULL, ic, TRUE);
7117 derefaop->size = size;
7122 transferAopAop (derefaop, size, AOP (result), size);
7124 loadRegFromAop (hc08_reg_a, derefaop, size);
7127 freeAsmop (NULL, derefaop, ic, TRUE);
7128 freeAsmop (result, NULL, ic, TRUE);
7130 if (ifx && !ifx->generated)
7132 genIfxJump (ifx, "a");
7137 /*-----------------------------------------------------------------*/
7138 /* genPointerGet - generate code for pointer get */
7139 /*-----------------------------------------------------------------*/
7141 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7143 operand *left = IC_LEFT (ic);
7144 operand *result = IC_RESULT (ic);
7146 sym_link *retype = getSpec (operandType (result));
7148 D(emitcode ("; genPointerGet",""));
7150 if (getSize (operandType (result))>1)
7153 aopOp (left, ic, FALSE);
7155 /* if left is rematerialisable and
7156 result is not bit variable type */
7157 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7159 if (!IS_BITVAR (retype))
7161 genDataPointerGet (left, result, ic, ifx);
7166 genUnpackBitsImmed (left, result, ic, ifx);
7171 /* if the operand is already in hx
7172 then we do nothing else we move the value to hx */
7173 if (AOP_TYPE (left) != AOP_STR)
7175 /* if this is remateriazable */
7176 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7179 /* so hx now contains the address */
7180 aopOp (result, ic, FALSE);
7182 /* if bit then unpack */
7183 if (IS_BITVAR (retype))
7184 genUnpackBits (result, ifx);
7187 size = AOP_SIZE (result);
7192 accopWithMisc ("lda", ",x");
7195 emitcode ("aix", "#1");
7196 hc08_dirtyReg (hc08_reg_hx, FALSE);
7199 storeRegToAop (hc08_reg_a, AOP (result), offset);
7201 hc08_freeReg (hc08_reg_a);
7205 freeAsmop (left, NULL, ic, TRUE);
7206 freeAsmop (result, NULL, ic, TRUE);
7209 aopOp (IC_RESULT (pi), pi, FALSE);
7210 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7211 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7215 if (ifx && !ifx->generated)
7217 genIfxJump (ifx, "a");
7220 hc08_freeReg (hc08_reg_hx);
7224 /*-----------------------------------------------------------------*/
7225 /* genPackBits - generates code for packed bit storage */
7226 /*-----------------------------------------------------------------*/
7228 genPackBits (sym_link * etype,
7231 int offset = 0; /* source byte offset */
7232 int rlen = 0; /* remaining bitfield length */
7233 int blen; /* bitfield length */
7234 int bstr; /* bitfield starting bit within byte */
7235 int litval; /* source literal value (if AOP_LIT) */
7236 unsigned char mask; /* bitmask within current byte */
7239 D(emitcode ("; genPackBits",""));
7241 blen = SPEC_BLEN (etype);
7242 bstr = SPEC_BSTR (etype);
7244 /* If the bitfield length is less than a byte */
7247 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7248 (unsigned char) (0xFF >> (8 - bstr)));
7250 if (AOP_TYPE (right) == AOP_LIT)
7252 /* Case with a bitfield length <8 and literal source
7254 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7256 litval &= (~mask) & 0xff;
7258 emitcode ("lda", ",x");
7259 if ((mask|litval)!=0xff)
7260 emitcode ("and","#0x%02x", mask);
7262 emitcode ("ora","#0x%02x", litval);
7263 hc08_dirtyReg (hc08_reg_a, FALSE);
7264 emitcode ("sta", ",x");
7266 hc08_freeReg (hc08_reg_a);
7270 /* Case with a bitfield length < 8 and arbitrary source
7272 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7273 /* shift and mask source value */
7275 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7276 hc08_dirtyReg (hc08_reg_a, FALSE);
7277 pushReg (hc08_reg_a, TRUE);
7279 emitcode ("lda", ",x");
7280 emitcode ("and", "#0x%02x", mask);
7281 emitcode ("ora", "1,s");
7282 emitcode ("sta", ",x");
7283 pullReg (hc08_reg_a);
7285 hc08_freeReg (hc08_reg_a);
7289 /* Bit length is greater than 7 bits. In this case, copy */
7290 /* all except the partial byte at the end */
7291 for (rlen=blen;rlen>=8;rlen-=8)
7293 if (AOP (right)->type == AOP_DIR)
7295 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7300 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7301 emitcode ("sta", "%d,x", offset);
7306 /* If there was a partial byte at the end */
7309 mask = (((unsigned char) -1 << rlen) & 0xff);
7311 if (AOP_TYPE (right) == AOP_LIT)
7313 /* Case with partial byte and literal source
7315 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7316 litval >>= (blen-rlen);
7317 litval &= (~mask) & 0xff;
7318 emitcode ("lda", "%d,x", offset - xoffset);
7319 hc08_dirtyReg (hc08_reg_a, FALSE);
7320 if ((mask|litval)!=0xff)
7321 emitcode ("and","#0x%02x", mask);
7323 emitcode ("ora","#0x%02x", litval);
7324 emitcode ("sta", "%d,x", offset - xoffset);
7325 hc08_dirtyReg (hc08_reg_a, FALSE);
7326 hc08_freeReg (hc08_reg_a);
7330 /* Case with partial byte and arbitrary source
7332 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7333 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7334 hc08_dirtyReg (hc08_reg_a, FALSE);
7335 pushReg (hc08_reg_a, TRUE);
7337 emitcode ("lda", "%d,x", offset - xoffset);
7338 emitcode ("and", "#0x%02x", mask);
7339 emitcode ("ora", "1,s");
7340 emitcode ("sta", "%d,x", offset - xoffset);
7341 pullReg (hc08_reg_a);
7344 hc08_freeReg (hc08_reg_a);
7347 /*-----------------------------------------------------------------*/
7348 /* genPackBitsImmed - generates code for packed bit storage */
7349 /*-----------------------------------------------------------------*/
7351 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7355 int offset = 0; /* source byte offset */
7356 int rlen = 0; /* remaining bitfield length */
7357 int blen; /* bitfield length */
7358 int bstr; /* bitfield starting bit within byte */
7359 int litval; /* source literal value (if AOP_LIT) */
7360 unsigned char mask; /* bitmask within current byte */
7362 D(emitcode ("; genPackBitsImmed",""));
7364 blen = SPEC_BLEN (etype);
7365 bstr = SPEC_BSTR (etype);
7367 aopOp (right, ic, FALSE);
7368 size = AOP_SIZE (right);
7370 derefaop = aopDerefAop (AOP (result));
7371 freeAsmop (result, NULL, ic, TRUE);
7372 derefaop->size = size;
7374 /* if the bitfield is a single bit in the direct page */
7375 if (blen == 1 && derefaop->type == AOP_DIR)
7377 if (AOP_TYPE (right) == AOP_LIT)
7379 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7381 emitcode ((litval & 1) ? "bset" : "bclr",
7382 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7386 symbol *tlbl1 = newiTempLabel (NULL);
7387 symbol *tlbl2 = newiTempLabel (NULL);
7389 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7390 emitcode ("bit", "#1");
7391 emitBranch ("bne", tlbl1);
7392 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7393 emitBranch ("bra", tlbl2);
7395 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7397 hc08_freeReg (hc08_reg_a);
7402 /* If the bitfield length is less than a byte */
7405 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7406 (unsigned char) (0xFF >> (8 - bstr)));
7408 if (AOP_TYPE (right) == AOP_LIT)
7410 /* Case with a bitfield length <8 and literal source
7412 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7414 litval &= (~mask) & 0xff;
7416 loadRegFromAop (hc08_reg_a, derefaop, 0);
7417 if ((mask|litval)!=0xff)
7418 emitcode ("and","#0x%02x", mask);
7420 emitcode ("ora","#0x%02x", litval);
7421 hc08_dirtyReg (hc08_reg_a, FALSE);
7422 storeRegToAop (hc08_reg_a, derefaop, 0);
7424 hc08_freeReg (hc08_reg_a);
7428 /* Case with a bitfield length < 8 and arbitrary source
7430 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7431 /* shift and mask source value */
7433 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7434 hc08_dirtyReg (hc08_reg_a, FALSE);
7435 pushReg (hc08_reg_a, TRUE);
7437 loadRegFromAop (hc08_reg_a, derefaop, 0);
7438 emitcode ("and", "#0x%02x", mask);
7439 emitcode ("ora", "1,s");
7440 storeRegToAop (hc08_reg_a, derefaop, 0);
7441 pullReg (hc08_reg_a);
7443 hc08_freeReg (hc08_reg_a);
7447 /* Bit length is greater than 7 bits. In this case, copy */
7448 /* all except the partial byte at the end */
7449 for (rlen=blen;rlen>=8;rlen-=8)
7451 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7455 /* If there was a partial byte at the end */
7458 mask = (((unsigned char) -1 << rlen) & 0xff);
7460 if (AOP_TYPE (right) == AOP_LIT)
7462 /* Case with partial byte and literal source
7464 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7465 litval >>= (blen-rlen);
7466 litval &= (~mask) & 0xff;
7467 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7468 if ((mask|litval)!=0xff)
7469 emitcode ("and","#0x%02x", mask);
7471 emitcode ("ora","#0x%02x", litval);
7472 hc08_dirtyReg (hc08_reg_a, FALSE);
7473 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7474 hc08_dirtyReg (hc08_reg_a, FALSE);
7475 hc08_freeReg (hc08_reg_a);
7479 /* Case with partial byte and arbitrary source
7481 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7482 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7483 hc08_dirtyReg (hc08_reg_a, FALSE);
7484 pushReg (hc08_reg_a, TRUE);
7486 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7487 emitcode ("and", "#0x%02x", mask);
7488 emitcode ("ora", "1,s");
7489 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7490 pullReg (hc08_reg_a);
7493 hc08_freeReg (hc08_reg_a);
7496 freeAsmop (right, NULL, ic, TRUE);
7497 freeAsmop (NULL, derefaop, ic, TRUE);
7500 /*-----------------------------------------------------------------*/
7501 /* genDataPointerSet - remat pointer to data space */
7502 /*-----------------------------------------------------------------*/
7504 genDataPointerSet (operand * right,
7511 D(emitcode ("; genDataPointerSet",""));
7513 aopOp (right, ic, FALSE);
7514 size = AOP_SIZE (right);
7516 derefaop = aopDerefAop (AOP (result));
7517 freeAsmop (result, NULL, ic, TRUE);
7518 derefaop->size = size;
7522 transferAopAop (AOP (right), size, derefaop, size);
7525 freeAsmop (right, NULL, ic, TRUE);
7526 freeAsmop (NULL, derefaop, ic, TRUE);
7530 /*-----------------------------------------------------------------*/
7531 /* genPointerSet - stores the value into a pointer location */
7532 /*-----------------------------------------------------------------*/
7534 genPointerSet (iCode * ic, iCode *pi)
7536 operand *right = IC_RIGHT (ic);
7537 operand *result = IC_RESULT (ic);
7538 sym_link *type, *etype;
7540 sym_link *retype = getSpec (operandType (right));
7541 sym_link *letype = getSpec (operandType (result));
7543 D(emitcode ("; genPointerSet",""));
7545 type = operandType (result);
7546 etype = getSpec (type);
7548 aopOp (result, ic, FALSE);
7550 /* if the result is rematerializable */
7551 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7553 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7555 genDataPointerSet (right, result, ic);
7560 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7565 /* if the operand is already in hx
7566 then we do nothing else we move the value to hx */
7567 if (AOP_TYPE (result) != AOP_STR)
7569 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7571 /* so hx now contains the address */
7572 aopOp (right, ic, FALSE);
7574 /* if bit then unpack */
7575 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7576 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7579 size = AOP_SIZE (right);
7584 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7585 accopWithMisc ("sta", ",x");
7588 emitcode ("aix", "#1");
7590 hc08_freeReg (hc08_reg_a);
7594 freeAsmop (result, NULL, ic, TRUE);
7595 freeAsmop (right, NULL, ic, TRUE);
7598 aopOp (IC_RESULT (pi), pi, FALSE);
7599 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7600 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7604 hc08_freeReg (hc08_reg_hx);
7608 /*-----------------------------------------------------------------*/
7609 /* genIfx - generate code for Ifx statement */
7610 /*-----------------------------------------------------------------*/
7612 genIfx (iCode * ic, iCode * popIc)
7614 operand *cond = IC_COND (ic);
7617 D(emitcode ("; genIfx",""));
7619 aopOp (cond, ic, FALSE);
7621 /* get the value into acc */
7622 if (AOP_TYPE (cond) != AOP_CRY)
7623 asmopToBool (AOP (cond), FALSE);
7626 /* the result is now in the accumulator */
7627 freeAsmop (cond, NULL, ic, TRUE);
7629 /* if there was something to be popped then do it */
7633 /* if the condition is a bit variable */
7634 if (isbit && IS_ITEMP (cond) &&
7636 genIfxJump (ic, SPIL_LOC (cond)->rname);
7637 else if (isbit && !IS_ITEMP (cond))
7638 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7640 genIfxJump (ic, "a");
7645 /*-----------------------------------------------------------------*/
7646 /* genAddrOf - generates code for address of */
7647 /*-----------------------------------------------------------------*/
7649 genAddrOf (iCode * ic)
7651 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7654 D(emitcode ("; genAddrOf",""));
7656 aopOp (IC_RESULT (ic), ic, FALSE);
7658 /* if the operand is on the stack then we
7659 need to get the stack offset of this
7663 /* if it has an offset then we need to compute
7665 hc08_useReg (hc08_reg_hx);
7666 emitcode ("tsx", "");
7667 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7668 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7669 hc08_freeReg (hc08_reg_hx);
7674 /* object not on stack then we need the name */
7675 size = AOP_SIZE (IC_RESULT (ic));
7680 char s[SDCC_NAME_MAX+10];
7683 sprintf (s, "#%s", sym->rname);
7686 sprintf (s, "#>%s", sym->rname);
7689 sprintf (s, "#(%s >> %d)",
7693 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7697 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7701 /*-----------------------------------------------------------------*/
7702 /* genAssign - generate code for assignment */
7703 /*-----------------------------------------------------------------*/
7705 genAssign (iCode * ic)
7707 operand *result, *right;
7709 // unsigned long lit = 0L;
7711 D(emitcode("; genAssign",""));
7713 result = IC_RESULT (ic);
7714 right = IC_RIGHT (ic);
7716 /* if they are the same */
7717 if (operandsEqu (result, right)) {
7721 aopOp (right, ic, FALSE);
7722 aopOp (result, ic, TRUE);
7724 /* if they are the same registers */
7725 if (sameRegs (AOP (right), AOP (result)))
7728 if ((AOP_TYPE (right) == AOP_LIT)
7729 && (IS_AOP_HX(AOP(result))))
7731 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7736 size = AOP_SIZE (result);
7739 transferAopAop (AOP (right), size, AOP (result), size);
7743 freeAsmop (right, NULL, ic, TRUE);
7744 freeAsmop (result, NULL, ic, TRUE);
7747 /*-----------------------------------------------------------------*/
7748 /* genJumpTab - generates code for jump table */
7749 /*-----------------------------------------------------------------*/
7751 genJumpTab (iCode * ic)
7754 symbol *jtablo = newiTempLabel (NULL);
7755 symbol *jtabhi = newiTempLabel (NULL);
7757 D(emitcode ("; genJumpTab",""));
7759 aopOp (IC_JTCOND (ic), ic, FALSE);
7761 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7763 /* get the condition into x */
7764 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7765 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7766 loadRegFromConst (hc08_reg_h, zero);
7768 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7769 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7770 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7771 emitcode ("jmp", ",x");
7773 hc08_dirtyReg (hc08_reg_a, TRUE);
7774 hc08_dirtyReg (hc08_reg_hx, TRUE);
7779 pushReg(hc08_reg_hx, TRUE);
7781 /* get the condition into x */
7782 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7783 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7784 loadRegFromConst (hc08_reg_h, zero);
7786 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7787 emitcode ("sta", "3,s");
7788 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7789 emitcode ("sta", "4,s");
7791 pullReg(hc08_reg_hx);
7792 emitcode ("rts", "");
7793 _G.stackPushes += 2;
7797 /* now generate the jump labels */
7799 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7800 jtab = setNextItem (IC_JTLABELS (ic)))
7801 emitcode (".db", "%05d$", jtab->key + 100);
7803 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7804 jtab = setNextItem (IC_JTLABELS (ic)))
7805 emitcode (".db", ">%05d$", jtab->key + 100);
7809 /*-----------------------------------------------------------------*/
7810 /* genCast - gen code for casting */
7811 /*-----------------------------------------------------------------*/
7813 genCast (iCode * ic)
7815 operand *result = IC_RESULT (ic);
7816 sym_link *ctype = operandType (IC_LEFT (ic));
7817 sym_link *rtype = operandType (IC_RIGHT (ic));
7818 operand *right = IC_RIGHT (ic);
7821 D(emitcode("; genCast",""));
7823 /* if they are equivalent then do nothing */
7824 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7827 aopOp (right, ic, FALSE);
7828 aopOp (result, ic, FALSE);
7831 /* if they are the same size : or less */
7832 if (AOP_SIZE (result) <= AOP_SIZE (right))
7835 /* if they are in the same place */
7837 if (sameRegs (AOP (right), AOP (result)))
7841 /* if they in different places then copy */
7842 size = AOP_SIZE (result);
7846 transferAopAop(AOP (right), offset, AOP (result), offset);
7853 /* if the result is of type pointer */
7858 sym_link *type = operandType (right);
7859 sym_link *etype = getSpec (type);
7861 /* pointer to generic pointer */
7862 if (IS_GENPTR (ctype))
7865 p_type = DCL_TYPE (type);
7868 if (SPEC_SCLS(etype)==S_REGISTER) {
7869 // let's assume it is a generic pointer
7872 /* we have to go by the storage class */
7873 p_type = PTR_TYPE (SPEC_OCLS (etype));
7877 /* the first two bytes are known */
7878 size = GPTRSIZE - 1;
7882 transferAopAop(AOP (right), offset, AOP (result), offset);
7885 /* the last byte depending on type */
7888 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7893 // pointerTypeToGPByte will have bitched.
7897 sprintf(gpValStr, "#0x%d", gpVal);
7898 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7904 /* just copy the pointers */
7905 size = AOP_SIZE (result);
7909 transferAopAop(AOP (right), offset, AOP (result), offset);
7915 /* so we now know that the size of destination is greater
7916 than the size of the source */
7917 /* we move to result for the size of source */
7918 size = AOP_SIZE (right);
7922 transferAopAop(AOP (right), offset, AOP (result), offset);
7926 /* now depending on the sign of the source && destination */
7927 size = AOP_SIZE (result) - AOP_SIZE (right);
7928 /* if unsigned or not an integral type */
7929 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7932 storeConstToAop (zero, AOP (result), offset++);
7936 /* we need to extend the sign :{ */
7937 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7938 accopWithMisc ("rola", "");
7939 accopWithMisc ("clra", "");
7940 accopWithMisc ("sbc", zero);
7942 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7945 /* we are done hurray !!!! */
7948 freeAsmop (right, NULL, ic, TRUE);
7949 freeAsmop (result, NULL, ic, TRUE);
7953 /*-----------------------------------------------------------------*/
7954 /* genDjnz - generate decrement & jump if not zero instrucion */
7955 /*-----------------------------------------------------------------*/
7957 genDjnz (iCode * ic, iCode * ifx)
7963 D(emitcode ("; genDjnz",""));
7965 /* if the if condition has a false label
7966 then we cannot save */
7970 /* if the minus is not of the form
7972 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7973 !IS_OP_LITERAL (IC_RIGHT (ic)))
7976 if (operandLitValue (IC_RIGHT (ic)) != 1)
7979 /* dbnz doesn't support extended mode */
7980 if (isOperandInFarSpace (IC_RESULT (ic)))
7983 /* if the size of this greater than one then no
7985 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7987 aopOp (IC_RESULT (ic), ic, FALSE);
7988 if (AOP_SIZE (IC_RESULT (ic))>1)
7990 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7994 /* otherwise we can save BIG */
7995 lbl = newiTempLabel (NULL);
7996 lbl1 = newiTempLabel (NULL);
7999 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8002 emitBranch ("bra", lbl1);
8004 emitBranch ("jmp", IC_TRUE (ifx));
8007 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8012 /*-----------------------------------------------------------------*/
8013 /* genReceive - generate code for a receive iCode */
8014 /*-----------------------------------------------------------------*/
8016 genReceive (iCode * ic)
8020 D(emitcode ("; genReceive",""));
8022 aopOp (IC_RESULT (ic), ic, FALSE);
8023 size = AOP_SIZE (IC_RESULT (ic));
8028 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8029 AOP (IC_RESULT (ic)), offset);
8030 if (hc08_aop_pass[offset]->type == AOP_REG)
8031 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8036 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8039 /*-----------------------------------------------------------------*/
8040 /* genDummyRead - generate code for dummy read of volatiles */
8041 /*-----------------------------------------------------------------*/
8043 genDummyRead (iCode * ic)
8048 D(emitcode("; genDummyRead",""));
8051 if (op && IS_SYMOP (op))
8054 aopOp (op, ic, FALSE);
8056 size = AOP_SIZE (op);
8061 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8062 hc08_freeReg (hc08_reg_a);
8066 freeAsmop (op, NULL, ic, TRUE);
8069 if (op && IS_SYMOP (op))
8072 aopOp (op, ic, FALSE);
8074 size = AOP_SIZE (op);
8079 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8080 hc08_freeReg (hc08_reg_a);
8084 freeAsmop (op, NULL, ic, TRUE);
8088 /*-----------------------------------------------------------------*/
8089 /* genCritical - generate code for start of a critical sequence */
8090 /*-----------------------------------------------------------------*/
8092 genCritical (iCode *ic)
8094 D(emitcode("; genCritical",""));
8097 aopOp (IC_RESULT (ic), ic, TRUE);
8099 emitcode ("tpa", "");
8100 hc08_dirtyReg (hc08_reg_a, FALSE);
8101 emitcode ("sei", "");
8104 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8106 pushReg (hc08_reg_a, FALSE);
8108 hc08_freeReg (hc08_reg_a);
8110 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8113 /*-----------------------------------------------------------------*/
8114 /* genEndCritical - generate code for end of a critical sequence */
8115 /*-----------------------------------------------------------------*/
8117 genEndCritical (iCode *ic)
8119 D(emitcode("; genEndCritical",""));
8123 aopOp (IC_RIGHT (ic), ic, FALSE);
8124 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8125 emitcode ("tap", "");
8126 hc08_freeReg (hc08_reg_a);
8127 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8131 pullReg (hc08_reg_a);
8132 emitcode ("tap", "");
8138 /*-----------------------------------------------------------------*/
8139 /* genhc08Code - generate code for HC08 based controllers */
8140 /*-----------------------------------------------------------------*/
8142 genhc08Code (iCode * lic)
8149 lineHead = lineCurr = NULL;
8151 /* print the allocation information */
8152 if (allocInfo && currFunc)
8153 printAllocInfo (currFunc, codeOutFile);
8154 /* if debug information required */
8155 if (options.debug && currFunc)
8157 debugFile->writeFunction (currFunc, lic);
8160 if (IS_STATIC (currFunc->etype))
8161 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8163 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8167 /* stack pointer name */
8168 if (options.useXstack)
8173 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8175 hc08_aop_pass[0] = newAsmop (AOP_REG);
8176 hc08_aop_pass[0]->size=1;
8177 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8178 hc08_aop_pass[1] = newAsmop (AOP_REG);
8179 hc08_aop_pass[1]->size=1;
8180 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8181 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8182 hc08_aop_pass[2]->size=1;
8183 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8184 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8185 hc08_aop_pass[3]->size=1;
8186 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8188 for (ic = lic; ic; ic = ic->next)
8191 _G.current_iCode = ic;
8193 if (ic->level != clevel || ic->block != cblock)
8197 debugFile->writeScope(ic);
8203 if (ic->lineno && cln != ic->lineno)
8207 debugFile->writeCLine(ic);
8210 emitcode ("", "C$%s$%d$%d$%d ==.",
8211 FileBaseName (ic->filename), ic->lineno,
8212 ic->level, ic->block);
8216 if (!options.noCcodeInAsm) {
8217 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8218 printCLine(ic->filename, ic->lineno));
8222 if (options.iCodeInAsm) {
8226 for (i=0; i<6; i++) {
8227 sprintf (®sInUse[i],
8228 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8231 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8233 /* if the result is marked as
8234 spilt and rematerializable or code for
8235 this has already been generated then
8237 if (resultRemat (ic) || ic->generated)
8245 for (i=A_IDX;i<=XA_IDX;i++)
8247 reg = hc08_regWithIdx(i);
8249 emitcode("","; %s = %s offset %d", reg->name,
8250 aopName(reg->aop), reg->aopofs);
8253 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8255 sym = OP_SYMBOL (IC_LEFT (ic));
8256 if (sym->accuse == ACCUSE_HX)
8258 hc08_reg_h->isFree = FALSE;
8259 hc08_reg_x->isFree = FALSE;
8261 else if (sym->accuse == ACCUSE_XA)
8263 hc08_reg_a->isFree = FALSE;
8265 hc08_reg_x->isFree = FALSE;
8268 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8270 sym = OP_SYMBOL (IC_RIGHT (ic));
8271 if (sym->accuse == ACCUSE_HX)
8273 hc08_reg_h->isFree = FALSE;
8274 hc08_reg_x->isFree = FALSE;
8276 else if (sym->accuse == ACCUSE_XA)
8278 hc08_reg_a->isFree = FALSE;
8280 hc08_reg_x->isFree = FALSE;
8285 /* depending on the operation */
8305 /* IPOP happens only when trying to restore a
8306 spilt live range, if there is an ifx statement
8307 following this pop then the if statement might
8308 be using some of the registers being popped which
8309 would destory the contents of the register so
8310 we need to check for this condition and handle it */
8312 ic->next->op == IFX &&
8313 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8314 genIfx (ic->next, ic);
8332 genEndFunction (ic);
8348 if (!genPointerGetSetOfs (ic))
8353 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8373 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8378 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8390 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8394 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8398 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8425 case GET_VALUE_AT_ADDRESS:
8427 hasInc (IC_LEFT (ic), ic,
8428 getSize (operandType (IC_RESULT (ic)))),
8429 ifxForOp (IC_RESULT (ic), ic) );
8433 if (POINTER_SET (ic))
8434 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8460 addSet (&_G.sendSet, ic);
8463 case DUMMY_READ_VOLATILE:
8472 genEndCritical (ic);
8483 if (!hc08_reg_a->isFree)
8484 D(emitcode("","; forgot to free a"));
8485 if (!hc08_reg_x->isFree)
8486 D(emitcode("","; forgot to free x"));
8487 if (!hc08_reg_h->isFree)
8488 D(emitcode("","; forgot to free h"));
8489 if (!hc08_reg_hx->isFree)
8490 D(emitcode("","; forgot to free hx"));
8491 if (!hc08_reg_xa->isFree)
8492 D(emitcode("","; forgot to free xa"));
8495 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8498 /* now we are ready to call the
8499 peep hole optimizer */
8500 if (!options.nopeep)
8501 peepHole (&lineHead);
8503 /* now do the actual printing */
8504 printLine (lineHead, codeOutFile);