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 ((unsigned char)*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 long 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 decrement 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));
3446 if (IS_AOP_A (rightOp))
3448 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3449 accopWithAop (sub, leftOp, offset);
3450 accopWithMisc ("nega", "");
3451 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3457 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3458 accopWithAop (sub, rightOp, offset);
3459 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3464 // adjustArithmeticResult (ic);
3467 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3468 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3469 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3474 /*-----------------------------------------------------------------*/
3475 /* genMultOneByte : 8*8=8/16 bit multiplication */
3476 /*-----------------------------------------------------------------*/
3478 genMultOneByte (operand * left,
3482 /* sym_link *opetype = operandType (result); */
3483 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3484 int size=AOP_SIZE(result);
3485 bool negLiteral = FALSE;
3486 bool lUnsigned, rUnsigned;
3488 D(emitcode ("; genMultOneByte",""));
3490 if (size<1 || size>2) {
3491 // this should never happen
3492 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3493 AOP_SIZE(result), __FILE__, lineno);
3497 /* (if two literals: the value is computed before) */
3498 /* if one literal, literal on the right */
3499 if (AOP_TYPE (left) == AOP_LIT)
3505 /* if an operand is in A, make sure it is on the left */
3506 if (IS_AOP_A (AOP (right)))
3513 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3514 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3516 /* lUnsigned rUnsigned negLiteral negate case */
3517 /* false false false odd 3 */
3518 /* false false true even 3 */
3519 /* false true false odd 3 */
3520 /* false true true impossible */
3521 /* true false false odd 3 */
3522 /* true false true always 2 */
3523 /* true true false never 1 */
3524 /* true true true impossible */
3528 || (lUnsigned && rUnsigned))
3530 // just an unsigned 8*8=8/16 multiply
3531 //D(emitcode (";","unsigned"));
3533 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3534 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3535 emitcode ("mul", "");
3536 hc08_dirtyReg (hc08_reg_xa, FALSE);
3537 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3538 hc08_freeReg (hc08_reg_xa);
3543 // we have to do a signed multiply
3546 /* left unsigned, right signed literal -- literal determines sign handling */
3547 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3549 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3551 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3553 emitcode ("ldx", "#0x%02x", -val);
3555 emitcode ("ldx", "#0x%02x", val);
3557 emitcode ("mul", "");
3561 rmwWithReg ("neg", hc08_reg_a);
3562 tlbl4 = newiTempLabel (NULL);
3563 emitBranch ("bcc", tlbl4);
3564 rmwWithReg ("inc", hc08_reg_x);
3566 rmwWithReg ("neg", hc08_reg_x);
3569 hc08_dirtyReg (hc08_reg_xa, FALSE);
3570 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3571 hc08_freeReg (hc08_reg_xa);
3578 emitcode ("clr", "1,s");
3580 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3583 tlbl1 = newiTempLabel (NULL);
3584 emitcode ("tsta","");
3585 emitBranch ("bpl", tlbl1);
3586 emitcode ("inc", "1,s");
3587 rmwWithReg ("neg", hc08_reg_a);
3591 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3593 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3594 /* AND literal negative */
3596 emitcode ("ldx", "#0x%02x", -val);
3599 emitcode ("ldx", "#0x%02x", val);
3601 hc08_useReg (hc08_reg_x);
3605 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3608 tlbl2 = newiTempLabel (NULL);
3609 emitcode ("tstx", "");
3610 emitBranch ("bpl", tlbl2);
3611 emitcode ("inc", "1,s");
3612 rmwWithReg ("neg", hc08_reg_x);
3617 emitcode ("mul", "");
3618 hc08_dirtyReg (hc08_reg_xa, FALSE);
3620 tlbl3 = newiTempLabel (NULL);
3621 emitcode ("dec", "1,s");
3622 if (!lUnsigned && !rUnsigned && negLiteral)
3623 emitBranch ("beq", tlbl3);
3625 emitBranch ("bne", tlbl3);
3627 rmwWithReg ("neg", hc08_reg_a);
3628 tlbl4 = newiTempLabel (NULL);
3629 emitBranch ("bcc", tlbl4);
3630 rmwWithReg ("inc", hc08_reg_x);
3632 rmwWithReg ("neg", hc08_reg_x);
3636 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3637 hc08_freeReg (hc08_reg_xa);
3641 /*-----------------------------------------------------------------*/
3642 /* genMult - generates code for multiplication */
3643 /*-----------------------------------------------------------------*/
3645 genMult (iCode * ic)
3647 operand *left = IC_LEFT (ic);
3648 operand *right = IC_RIGHT (ic);
3649 operand *result = IC_RESULT (ic);
3651 D(emitcode ("; genMult",""));
3653 /* assign the amsops */
3654 aopOp (left, ic, FALSE);
3655 aopOp (right, ic, FALSE);
3656 aopOp (result, ic, TRUE);
3658 /* special cases first */
3659 /* if both are of size == 1 */
3660 // if (getSize(operandType(left)) == 1 &&
3661 // getSize(operandType(right)) == 1)
3662 if (AOP_SIZE (left) == 1 &&
3663 AOP_SIZE (right) == 1)
3665 genMultOneByte (left, right, result);
3669 /* should have been converted to function call */
3670 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3671 getSize(OP_SYMBOL(right)->type));
3672 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3677 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3678 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3679 freeAsmop (result, NULL, ic, TRUE);
3682 /*-----------------------------------------------------------------*/
3683 /* genDivOneByte : 8 bit division */
3684 /*-----------------------------------------------------------------*/
3686 genDivOneByte (operand * left,
3690 symbol *tlbl1, *tlbl2, *tlbl3;
3693 bool lUnsigned, rUnsigned;
3694 bool runtimeSign, compiletimeSign;
3696 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3697 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3699 D(emitcode ("; genDivOneByte",""));
3701 size = AOP_SIZE (result);
3702 /* signed or unsigned */
3703 if (lUnsigned && rUnsigned)
3705 /* unsigned is easy */
3706 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3707 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3708 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3709 emitcode ("div", "");
3710 hc08_dirtyReg (hc08_reg_a, FALSE);
3711 hc08_dirtyReg (hc08_reg_h, FALSE);
3712 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3713 hc08_freeReg (hc08_reg_a);
3714 hc08_freeReg (hc08_reg_x);
3715 hc08_freeReg (hc08_reg_h);
3719 /* signed is a little bit more difficult */
3721 /* now sign adjust for both left & right */
3723 /* let's see what's needed: */
3724 /* apply negative sign during runtime */
3725 runtimeSign = FALSE;
3726 /* negative sign from literals */
3727 compiletimeSign = FALSE;
3731 if (AOP_TYPE(left) == AOP_LIT)
3733 /* signed literal */
3734 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3736 compiletimeSign = TRUE;
3739 /* signed but not literal */
3745 if (AOP_TYPE(right) == AOP_LIT)
3747 /* signed literal */
3748 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3750 compiletimeSign ^= TRUE;
3753 /* signed but not literal */
3757 /* initialize the runtime sign */
3760 if (compiletimeSign)
3761 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3763 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3764 pushReg (hc08_reg_x, TRUE);
3767 /* save the signs of the operands */
3768 if (AOP_TYPE(right) == AOP_LIT)
3770 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3772 if (!rUnsigned && val < 0)
3773 emitcode ("ldx", "#0x%02x", -val);
3775 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3777 else /* ! literal */
3779 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3782 tlbl1 = newiTempLabel (NULL);
3783 emitcode ("tstx", "");
3784 emitBranch ("bpl", tlbl1);
3785 emitcode ("inc", "1,s");
3786 rmwWithReg ("neg", hc08_reg_x);
3791 if (AOP_TYPE(left) == AOP_LIT)
3793 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3795 if (!lUnsigned && val < 0)
3796 emitcode ("lda", "#0x%02x", -val);
3798 emitcode ("lda", "#0x%02x", (unsigned char) val);
3800 else /* ! literal */
3802 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3805 tlbl2 = newiTempLabel (NULL);
3806 emitcode ("tsta", "");
3807 emitBranch ("bpl", tlbl2);
3808 emitcode ("inc", "1,s");
3809 rmwWithReg ("neg", hc08_reg_a);
3814 loadRegFromConst (hc08_reg_h, zero);
3815 emitcode ("div", "");
3816 hc08_dirtyReg (hc08_reg_x, FALSE);
3817 hc08_dirtyReg (hc08_reg_a, FALSE);
3818 hc08_dirtyReg (hc08_reg_h, FALSE);
3820 if (runtimeSign || compiletimeSign)
3822 tlbl3 = newiTempLabel (NULL);
3825 pullReg (hc08_reg_x);
3826 rmwWithReg ("lsr", hc08_reg_x);
3827 rmwWithReg ("ror", hc08_reg_x);
3828 emitBranch ("bpl", tlbl3);
3831 rmwWithReg ("neg", hc08_reg_a);
3835 storeRegToAop (hc08_reg_a, AOP (result), 0);
3839 /* msb is 0x00 or 0xff depending on the sign */
3842 rmwWithReg ("lsl", hc08_reg_x);
3843 emitcode ("clra", "");
3844 emitcode ("sbc", "#0");
3846 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3848 else /* compiletimeSign */
3850 storeConstToAop ("#0xff", AOP (result), ++offset);
3855 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3858 hc08_freeReg (hc08_reg_a);
3859 hc08_freeReg (hc08_reg_x);
3860 hc08_freeReg (hc08_reg_h);
3863 /*-----------------------------------------------------------------*/
3864 /* genDiv - generates code for division */
3865 /*-----------------------------------------------------------------*/
3869 operand *left = IC_LEFT (ic);
3870 operand *right = IC_RIGHT (ic);
3871 operand *result = IC_RESULT (ic);
3873 D(emitcode ("; genDiv",""));
3875 /* assign the amsops */
3876 aopOp (left, ic, FALSE);
3877 aopOp (right, ic, FALSE);
3878 aopOp (result, ic, TRUE);
3880 /* special cases first */
3881 /* if both are of size == 1 */
3882 if (AOP_SIZE (left) <= 2 &&
3883 AOP_SIZE (right) == 1)
3885 genDivOneByte (left, right, result);
3889 /* should have been converted to function call */
3892 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3893 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3894 freeAsmop (result, NULL, ic, TRUE);
3897 /*-----------------------------------------------------------------*/
3898 /* genModOneByte : 8 bit modulus */
3899 /*-----------------------------------------------------------------*/
3901 genModOneByte (operand * left,
3905 symbol *tlbl1, *tlbl2, *tlbl3;
3908 bool lUnsigned, rUnsigned;
3909 bool runtimeSign, compiletimeSign;
3911 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3912 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3914 D(emitcode ("; genModOneByte",""));
3916 size = AOP_SIZE (result);
3918 if (lUnsigned && rUnsigned)
3920 /* unsigned is easy */
3921 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3922 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3923 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3924 emitcode ("div", "");
3925 hc08_freeReg (hc08_reg_a);
3926 hc08_freeReg (hc08_reg_x);
3927 hc08_dirtyReg (hc08_reg_h, FALSE);
3928 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3929 hc08_freeReg (hc08_reg_h);
3933 /* signed is a little bit more difficult */
3935 if (AOP_TYPE(right) == AOP_LIT)
3937 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3939 if (!rUnsigned && val < 0)
3940 emitcode ("ldx", "#0x%02x", -val);
3942 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3944 else /* ! literal */
3946 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3949 tlbl1 = newiTempLabel (NULL);
3950 emitcode ("tstx", "");
3951 emitBranch ("bpl", tlbl1);
3952 rmwWithReg ("neg", hc08_reg_x);
3957 /* let's see what's needed: */
3958 /* apply negative sign during runtime */
3959 runtimeSign = FALSE;
3960 /* negative sign from literals */
3961 compiletimeSign = FALSE;
3963 /* sign adjust left side */
3964 if (AOP_TYPE(left) == AOP_LIT)
3966 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3968 if (!lUnsigned && val < 0)
3970 compiletimeSign = TRUE; /* set sign flag */
3971 emitcode ("lda", "#0x%02x", -val);
3974 emitcode ("lda", "#0x%02x", (unsigned char) val);
3976 else /* ! literal */
3979 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3984 emitcode ("clr", "1,s");
3986 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3987 tlbl2 = newiTempLabel (NULL);
3988 emitcode ("tsta", "");
3989 emitBranch ("bpl", tlbl2);
3990 emitcode ("inc", "1,s");
3991 rmwWithReg ("neg", hc08_reg_a);
3996 loadRegFromConst (hc08_reg_h, zero);
3997 emitcode ("div", "");
3998 hc08_freeReg (hc08_reg_a);
3999 hc08_freeReg (hc08_reg_x);
4000 hc08_dirtyReg (hc08_reg_h, FALSE);
4002 if (runtimeSign || compiletimeSign)
4004 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4005 tlbl3 = newiTempLabel (NULL);
4008 pullReg (hc08_reg_x);
4009 rmwWithReg ("lsr", hc08_reg_x);
4010 rmwWithReg ("ror", hc08_reg_x);
4011 emitBranch ("bpl", tlbl3);
4014 rmwWithReg ("neg", hc08_reg_a);
4018 storeRegToAop (hc08_reg_a, AOP (result), 0);
4022 /* msb is 0x00 or 0xff depending on the sign */
4025 rmwWithReg ("lsl", hc08_reg_x);
4026 emitcode ("clra", "");
4027 emitcode ("sbc", "#0");
4029 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4031 else /* compiletimeSign */
4033 storeConstToAop ("#0xff", AOP (result), ++offset);
4038 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4041 hc08_freeReg (hc08_reg_a);
4042 hc08_freeReg (hc08_reg_x);
4043 hc08_freeReg (hc08_reg_h);
4046 /*-----------------------------------------------------------------*/
4047 /* genMod - generates code for division */
4048 /*-----------------------------------------------------------------*/
4052 operand *left = IC_LEFT (ic);
4053 operand *right = IC_RIGHT (ic);
4054 operand *result = IC_RESULT (ic);
4056 D(emitcode ("; genMod",""));
4058 /* assign the amsops */
4059 aopOp (left, ic, FALSE);
4060 aopOp (right, ic, FALSE);
4061 aopOp (result, ic, TRUE);
4063 /* special cases first */
4064 /* if both are of size == 1 */
4065 if (AOP_SIZE (left) <= 2 &&
4066 AOP_SIZE (right) == 1)
4068 genModOneByte (left, right, result);
4072 /* should have been converted to function call */
4076 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4077 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4078 freeAsmop (result, NULL, ic, TRUE);
4081 /*-----------------------------------------------------------------*/
4082 /* genIfxJump :- will create a jump depending on the ifx */
4083 /*-----------------------------------------------------------------*/
4085 genIfxJump (iCode * ic, char *jval)
4088 symbol *tlbl = newiTempLabel (NULL);
4091 D(emitcode ("; genIfxJump",""));
4093 /* if true label then we jump if condition
4097 jlbl = IC_TRUE (ic);
4098 if (!strcmp (jval, "a"))
4100 else if (!strcmp (jval, "c"))
4107 /* false label is present */
4108 jlbl = IC_FALSE (ic);
4109 if (!strcmp (jval, "a"))
4111 else if (!strcmp (jval, "c"))
4116 emitBranch (inst, tlbl);
4117 emitBranch ("jmp", jlbl);
4120 /* mark the icode as generated */
4125 /*-----------------------------------------------------------------*/
4126 /* exchangedCmp : returns the opcode need if the two operands are */
4127 /* exchanged in a comparison */
4128 /*-----------------------------------------------------------------*/
4130 exchangedCmp (int opcode)
4147 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4148 "opcode not a comparison");
4150 return EQ_OP; /* shouldn't happen, but need to return something */
4153 /*------------------------------------------------------------------*/
4154 /* negatedCmp : returns the equivalent opcode for when a comparison */
4156 /*------------------------------------------------------------------*/
4158 negatedCmp (int opcode)
4175 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4176 "opcode not a comparison");
4178 return EQ_OP; /* shouldn't happen, but need to return something */
4181 /* compile only if the debugging macro D is enabled */
4184 nameCmp (int opcode)
4206 /*------------------------------------------------------------------*/
4207 /* branchInstCmp : returns the conditional branch instruction that */
4208 /* will branch if the comparison is true */
4209 /*------------------------------------------------------------------*/
4211 branchInstCmp (int opcode, int sign)
4219 return "bcs"; /* same as blo */
4234 return "bcc"; /* same as bhs */
4240 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4241 "opcode not a comparison");
4247 /*------------------------------------------------------------------*/
4248 /* genCmp :- greater or less than (and maybe with equal) comparison */
4249 /*------------------------------------------------------------------*/
4251 genCmp (iCode * ic, iCode * ifx)
4253 operand *left, *right, *result;
4254 sym_link *letype, *retype;
4256 int size, offset = 0;
4257 unsigned long lit = 0L;
4259 symbol *jlbl = NULL;
4263 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4265 result = IC_RESULT (ic);
4266 left = IC_LEFT (ic);
4267 right = IC_RIGHT (ic);
4269 letype = getSpec (operandType (left));
4270 retype = getSpec (operandType (right));
4271 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4272 /* assign the amsops */
4273 aopOp (left, ic, FALSE);
4274 aopOp (right, ic, FALSE);
4275 aopOp (result, ic, TRUE);
4277 /* need register operand on left, prefer literal operand on right */
4278 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4280 operand *temp = left;
4283 opcode = exchangedCmp (opcode);
4290 jlbl = IC_TRUE (ifx);
4291 opcode = negatedCmp (opcode);
4295 /* false label is present */
4296 jlbl = IC_FALSE (ifx);
4300 size = max (AOP_SIZE (left), AOP_SIZE (right));
4303 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4304 && ((AOP_TYPE (right) == AOP_LIT) ||
4305 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4306 && hc08_reg_hx->isFree)
4308 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4309 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4310 hc08_freeReg (hc08_reg_hx);
4321 /* These conditions depend on the Z flag bit, but Z is */
4322 /* only valid for the last byte of the comparison, not */
4323 /* the whole value. So exchange the operands to get a */
4324 /* comparison that doesn't depend on Z. (This is safe */
4325 /* to do here since ralloc won't assign multi-byte */
4326 /* operands to registers for comparisons) */
4327 if ((opcode == '>') || (opcode == LE_OP))
4329 operand *temp = left;
4332 opcode = exchangedCmp (opcode);
4335 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4337 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4338 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4347 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4348 accopWithAop (sub, AOP (right), offset);
4349 hc08_freeReg (hc08_reg_a);
4354 freeAsmop (right, NULL, ic, FALSE);
4355 freeAsmop (left, NULL, ic, FALSE);
4359 symbol *tlbl = newiTempLabel (NULL);
4362 freeAsmop (result, NULL, ic, TRUE);
4364 inst = branchInstCmp (opcode, sign);
4365 emitBranch (inst, tlbl);
4366 emitBranch ("jmp", jlbl);
4369 /* mark the icode as generated */
4374 symbol *tlbl1 = newiTempLabel (NULL);
4375 symbol *tlbl2 = newiTempLabel (NULL);
4377 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4378 loadRegFromConst (hc08_reg_a, zero);
4379 emitBranch ("bra", tlbl2);
4381 loadRegFromConst (hc08_reg_a, one);
4383 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4384 freeAsmop (result, NULL, ic, TRUE);
4389 /*-----------------------------------------------------------------*/
4390 /* genCmpEQorNE - equal or not equal comparison */
4391 /*-----------------------------------------------------------------*/
4393 genCmpEQorNE (iCode * ic, iCode * ifx)
4395 operand *left, *right, *result;
4396 sym_link *letype, *retype;
4398 int size, offset = 0;
4400 symbol *jlbl = NULL;
4401 symbol *tlbl_NE = NULL;
4402 symbol *tlbl_EQ = NULL;
4406 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4408 result = IC_RESULT (ic);
4409 left = IC_LEFT (ic);
4410 right = IC_RIGHT (ic);
4412 letype = getSpec (operandType (left));
4413 retype = getSpec (operandType (right));
4414 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4415 /* assign the amsops */
4416 aopOp (left, ic, FALSE);
4417 aopOp (right, ic, FALSE);
4418 aopOp (result, ic, TRUE);
4420 /* need register operand on left, prefer literal operand on right */
4421 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4423 operand *temp = left;
4426 opcode = exchangedCmp (opcode);
4433 jlbl = IC_TRUE (ifx);
4434 opcode = negatedCmp (opcode);
4438 /* false label is present */
4439 jlbl = IC_FALSE (ifx);
4443 size = max (AOP_SIZE (left), AOP_SIZE (right));
4446 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4447 && ((AOP_TYPE (right) == AOP_LIT) ||
4448 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4449 && hc08_reg_hx->isFree)
4451 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4452 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4453 hc08_freeReg (hc08_reg_hx);
4461 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4462 accopWithAop (sub, AOP (right), offset);
4466 tlbl_NE = newiTempLabel (NULL);
4467 emitBranch ("bne", tlbl_NE);
4469 hc08_freeReg (hc08_reg_a);
4473 freeAsmop (right, NULL, ic, FALSE);
4474 freeAsmop (left, NULL, ic, FALSE);
4478 freeAsmop (result, NULL, ic, TRUE);
4480 if (opcode == EQ_OP)
4483 tlbl_EQ = newiTempLabel (NULL);
4484 emitBranch ("beq", tlbl_EQ);
4486 emitLabel (tlbl_NE);
4487 emitBranch ("jmp", jlbl);
4488 emitLabel (tlbl_EQ);
4493 tlbl_NE = newiTempLabel (NULL);
4494 emitBranch ("bne", tlbl_NE);
4495 emitBranch ("jmp", jlbl);
4496 emitLabel (tlbl_NE);
4499 /* mark the icode as generated */
4504 symbol *tlbl = newiTempLabel (NULL);
4506 if (opcode == EQ_OP)
4509 tlbl_EQ = newiTempLabel (NULL);
4510 emitBranch ("beq", tlbl_EQ);
4512 emitLabel (tlbl_NE);
4513 loadRegFromConst (hc08_reg_a, zero);
4514 emitBranch ("bra", tlbl);
4515 emitLabel (tlbl_EQ);
4516 loadRegFromConst (hc08_reg_a, one);
4521 tlbl_NE = newiTempLabel (NULL);
4522 emitBranch ("bne", tlbl_NE);
4523 loadRegFromConst (hc08_reg_a, zero);
4524 emitBranch ("bra", tlbl);
4525 emitLabel (tlbl_NE);
4526 loadRegFromConst (hc08_reg_a, one);
4530 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4531 freeAsmop (result, NULL, ic, TRUE);
4537 /*-----------------------------------------------------------------*/
4538 /* ifxForOp - returns the icode containing the ifx for operand */
4539 /*-----------------------------------------------------------------*/
4541 ifxForOp (operand * op, iCode * ic)
4543 /* if true symbol then needs to be assigned */
4544 if (IS_TRUE_SYMOP (op))
4547 /* if this has register type condition and
4548 the next instruction is ifx with the same operand
4549 and live to of the operand is upto the ifx only then */
4551 ic->next->op == IFX &&
4552 IC_COND (ic->next)->key == op->key &&
4553 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4560 genPointerGetSetOfs (iCode *ic)
4562 iCode *lic = ic->next;
4568 /* Make sure we have a next iCode */
4569 D(emitcode("","; checking lic"));
4573 /* Make sure the result of the addition is an iCode */
4574 D(emitcode("","; checking IS_ITEMP"));
4575 if (!IS_ITEMP (IC_RESULT (ic)))
4578 /* Make sure the next iCode is a pointer set or get */
4579 pset = POINTER_SET(lic);
4580 pget = POINTER_GET(lic);
4581 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4585 /* Make sure this is the only use of the pointer */
4586 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4589 D(emitcode("", "; checking pset operandsEqu"));
4590 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4593 D(emitcode("", "; checking pget operandsEqu"));
4594 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4597 D(emitcode("", "; checking IS_SYMOP"));
4598 if (!IS_SYMOP (IC_LEFT (ic)))
4601 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4602 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4605 sym = OP_SYMBOL (IC_LEFT (ic));
4607 D(emitcode("", "; checking remat"));
4614 D(emitcode ("; genPointerGetOfs",""));
4615 aopOp (IC_LEFT(ic), ic, FALSE);
4616 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4617 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4619 aopOp (IC_RIGHT(ic), ic, FALSE);
4620 aopOp (IC_RESULT(lic), lic, FALSE);
4622 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4624 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4626 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4627 loadRegFromConst (hc08_reg_h, zero);
4631 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4632 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4633 emitcode ("rola","");
4634 emitcode ("clra","");
4635 emitcode ("sbc", "#0");
4636 hc08_useReg (hc08_reg_a);
4637 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4641 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4642 size = AOP_SIZE (IC_RESULT(lic));
4643 derefaop->size = size;
4647 emitcode ("lda", "%s,x",
4648 aopAdrStr (derefaop, size, TRUE));
4649 hc08_useReg (hc08_reg_a);
4650 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4651 hc08_freeReg (hc08_reg_a);
4655 hc08_freeReg (hc08_reg_hx);
4657 freeAsmop (NULL, derefaop, ic, TRUE);
4658 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4659 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4666 D(emitcode ("; genPointerSetOfs",""));
4667 aopOp (IC_LEFT(ic), ic, FALSE);
4668 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4669 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4671 aopOp (IC_RIGHT(ic), ic, FALSE);
4672 aopOp (IC_RIGHT(lic), lic, FALSE);
4674 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4676 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4678 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4679 loadRegFromConst (hc08_reg_h, zero);
4683 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4684 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4685 emitcode ("rola","");
4686 emitcode ("clra","");
4687 emitcode ("sbc", "#0");
4688 hc08_useReg (hc08_reg_a);
4689 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4693 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4694 size = AOP_SIZE (IC_RIGHT(lic));
4695 derefaop->size = size;
4699 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4700 emitcode ("sta", "%s,x",
4701 aopAdrStr (derefaop, size, TRUE));
4702 hc08_freeReg (hc08_reg_a);
4706 hc08_freeReg (hc08_reg_hx);
4708 freeAsmop (NULL, derefaop, ic, TRUE);
4709 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4710 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4719 /*-----------------------------------------------------------------*/
4720 /* hasInc - operand is incremented before any other use */
4721 /*-----------------------------------------------------------------*/
4723 hasInc (operand *op, iCode *ic,int osize)
4725 sym_link *type = operandType(op);
4726 sym_link *retype = getSpec (type);
4727 iCode *lic = ic->next;
4730 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4731 if (!IS_SYMOP(op)) return NULL;
4733 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4734 if (IS_AGGREGATE(type->next)) return NULL;
4735 if (osize != (isize = getSize(type->next))) return NULL;
4738 /* if operand of the form op = op + <sizeof *op> */
4739 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4740 isOperandEqual(IC_RESULT(lic),op) &&
4741 isOperandLiteral(IC_RIGHT(lic)) &&
4742 operandLitValue(IC_RIGHT(lic)) == isize) {
4745 /* if the operand used or deffed */
4746 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4749 /* if GOTO or IFX */
4750 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4756 /*-----------------------------------------------------------------*/
4757 /* genAndOp - for && operation */
4758 /*-----------------------------------------------------------------*/
4760 genAndOp (iCode * ic)
4762 operand *left, *right, *result;
4763 symbol *tlbl, *tlbl0;
4765 D(emitcode ("; genAndOp",""));
4767 /* note here that && operations that are in an
4768 if statement are taken away by backPatchLabels
4769 only those used in arthmetic operations remain */
4770 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4771 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4772 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4774 tlbl = newiTempLabel (NULL);
4775 tlbl0 = newiTempLabel (NULL);
4777 asmopToBool (AOP (left), FALSE);
4778 emitBranch ("beq", tlbl0);
4779 asmopToBool (AOP (right), FALSE);
4780 emitBranch ("beq", tlbl0);
4781 loadRegFromConst (hc08_reg_a,one);
4782 emitBranch ("bra", tlbl);
4784 loadRegFromConst (hc08_reg_a,zero);
4787 hc08_useReg (hc08_reg_a);
4788 hc08_freeReg (hc08_reg_a);
4790 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4792 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4793 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4794 freeAsmop (result, NULL, ic, TRUE);
4798 /*-----------------------------------------------------------------*/
4799 /* genOrOp - for || operation */
4800 /*-----------------------------------------------------------------*/
4802 genOrOp (iCode * ic)
4804 operand *left, *right, *result;
4805 symbol *tlbl, *tlbl0;
4807 D(emitcode ("; genOrOp",""));
4809 /* note here that || operations that are in an
4810 if statement are taken away by backPatchLabels
4811 only those used in arthmetic operations remain */
4812 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4813 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4814 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4816 tlbl = newiTempLabel (NULL);
4817 tlbl0 = newiTempLabel (NULL);
4819 asmopToBool (AOP (left), FALSE);
4820 emitBranch ("bne", tlbl0);
4821 asmopToBool (AOP (right), FALSE);
4822 emitBranch ("bne", tlbl0);
4823 loadRegFromConst (hc08_reg_a,zero);
4824 emitBranch ("bra", tlbl);
4826 loadRegFromConst (hc08_reg_a,one);
4829 hc08_useReg (hc08_reg_a);
4830 hc08_freeReg (hc08_reg_a);
4832 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4835 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4836 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4837 freeAsmop (result, NULL, ic, TRUE);
4840 /*-----------------------------------------------------------------*/
4841 /* isLiteralBit - test if lit == 2^n */
4842 /*-----------------------------------------------------------------*/
4844 isLiteralBit (unsigned long lit)
4846 unsigned long pw[32] =
4847 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4848 0x100L, 0x200L, 0x400L, 0x800L,
4849 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4850 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4851 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4852 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4853 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4856 for (idx = 0; idx < 32; idx++)
4863 /*-----------------------------------------------------------------*/
4864 /* continueIfTrue - */
4865 /*-----------------------------------------------------------------*/
4867 continueIfTrue (iCode * ic)
4870 emitBranch ("jmp", IC_TRUE (ic));
4874 /*-----------------------------------------------------------------*/
4876 /*-----------------------------------------------------------------*/
4878 jumpIfTrue (iCode * ic)
4881 emitBranch ("jmp", IC_FALSE (ic));
4885 /*-----------------------------------------------------------------*/
4886 /* jmpTrueOrFalse - */
4887 /*-----------------------------------------------------------------*/
4889 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4891 // ugly but optimized by peephole
4894 symbol *nlbl = newiTempLabel (NULL);
4895 emitBranch ("bra", nlbl);
4897 emitBranch ("jmp", IC_TRUE (ic));
4902 emitBranch ("jmp", IC_FALSE (ic));
4909 /*-----------------------------------------------------------------*/
4910 /* genAnd - code for and */
4911 /*-----------------------------------------------------------------*/
4913 genAnd (iCode * ic, iCode * ifx)
4915 operand *left, *right, *result;
4916 int size, offset = 0;
4917 unsigned long lit = 0L;
4918 unsigned long litinv;
4919 unsigned char bytemask;
4925 D(emitcode ("; genAnd",""));
4927 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4928 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4929 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4932 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4934 AOP_TYPE (left), AOP_TYPE (right)));
4935 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4937 AOP_SIZE (left), AOP_SIZE (right)));
4940 /* if left is a literal & right is not then exchange them */
4941 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4943 operand *tmp = right;
4948 /* if right is accumulator & left is not then exchange them */
4949 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4951 operand *tmp = right;
4956 if (AOP_TYPE (right) == AOP_LIT)
4957 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4959 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4961 if (AOP_TYPE (result) == AOP_CRY
4963 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
4965 /* this generates ugly code, but meets volatility requirements */
4966 loadRegFromConst (hc08_reg_a, zero);
4967 pushReg (hc08_reg_a, TRUE);
4972 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4973 accopWithAop ("and", AOP (right), offset);
4974 emitcode ("ora", "1,s");
4975 emitcode ("sta", "1,s");
4979 pullReg (hc08_reg_a);
4980 emitcode ("tsta", "");
4981 genIfxJump (ifx, "a");
4985 if (AOP_TYPE (result) == AOP_CRY)
4987 symbol *tlbl = NULL;
4988 wassertl (ifx, "AOP_CRY result without ifx");
4993 bytemask = (lit >> (offset*8)) & 0xff;
4995 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
4999 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5001 rmwWithAop ("tst", AOP (left), offset);
5005 tlbl = newiTempLabel (NULL);
5006 emitBranch ("bne", tlbl);
5011 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5012 accopWithAop ("and", AOP (right), offset);
5013 hc08_freeReg( hc08_reg_a);
5017 tlbl = newiTempLabel (NULL);
5018 emitBranch ("bne", tlbl);
5025 genIfxJump (ifx, "a");
5029 size = AOP_SIZE (result);
5031 if (AOP_TYPE (right) == AOP_LIT)
5033 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5034 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5035 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5037 int bitpos = isLiteralBit(litinv)-1;
5038 emitcode ("bclr","#%d,%s",bitpos & 7,
5039 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5047 bytemask = (lit >> (offset*8)) & 0xff;
5049 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5051 if (isOperandVolatile (left, FALSE))
5053 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5054 hc08_freeReg( hc08_reg_a);
5056 storeConstToAop (zero, AOP (result), offset);
5058 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5060 transferAopAop (AOP (left), offset, AOP (result), offset);
5064 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5065 accopWithAop ("and", AOP (right), offset);
5066 storeRegToAop (hc08_reg_a, AOP (result), offset);
5067 hc08_freeReg (hc08_reg_a);
5073 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5074 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5075 freeAsmop (result, NULL, ic, TRUE);
5078 /*-----------------------------------------------------------------*/
5079 /* genOr - code for or */
5080 /*-----------------------------------------------------------------*/
5082 genOr (iCode * ic, iCode * ifx)
5084 operand *left, *right, *result;
5085 int size, offset = 0;
5086 unsigned long lit = 0L;
5087 unsigned char bytemask;
5089 D(emitcode ("; genOr",""));
5091 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5092 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5093 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5096 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5098 AOP_TYPE (left), AOP_TYPE (right)));
5099 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5101 AOP_SIZE (left), AOP_SIZE (right)));
5104 /* if left is a literal & right is not then exchange them */
5105 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5107 operand *tmp = right;
5112 /* if left is accumulator & right is not then exchange them */
5113 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5115 operand *tmp = right;
5120 if (AOP_TYPE (right) == AOP_LIT)
5121 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5123 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5125 if (AOP_TYPE (result) == AOP_CRY
5127 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5129 /* this generates ugly code, but meets volatility requirements */
5130 loadRegFromConst (hc08_reg_a, zero);
5131 pushReg (hc08_reg_a, TRUE);
5136 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5137 accopWithAop ("ora", AOP (right), offset);
5138 emitcode ("ora", "1,s");
5139 emitcode ("sta", "1,s");
5143 pullReg (hc08_reg_a);
5144 emitcode ("tsta", "");
5145 genIfxJump (ifx, "a");
5149 if (AOP_TYPE (result) == AOP_CRY)
5151 symbol *tlbl = NULL;
5152 wassertl (ifx, "AOP_CRY result without ifx");
5157 bytemask = (lit >> (offset*8)) & 0xff;
5159 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5161 rmwWithAop ("tst", AOP (left), offset);
5165 tlbl = newiTempLabel (NULL);
5166 emitBranch ("bne", tlbl);
5171 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5172 accopWithAop ("ora", AOP (right), offset);
5173 hc08_freeReg( hc08_reg_a);
5177 tlbl = newiTempLabel (NULL);
5178 emitBranch ("bne", tlbl);
5185 genIfxJump (ifx, "a");
5188 if (AOP_TYPE (right) == AOP_LIT)
5189 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5191 size = AOP_SIZE (result);
5193 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5194 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5195 (AOP_TYPE (left) == AOP_DIR))
5197 int bitpos = isLiteralBit(lit)-1;
5198 emitcode ("bset","#%d,%s",bitpos & 7,
5199 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5206 bytemask = (lit >> (offset*8)) & 0xff;
5208 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5210 if (isOperandVolatile (left, FALSE))
5212 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5213 hc08_freeReg( hc08_reg_a);
5215 transferAopAop (AOP (right), offset, AOP (result), offset);
5217 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5219 transferAopAop (AOP (left), offset, AOP (result), offset);
5223 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5224 accopWithAop ("ora", AOP (right), offset);
5225 storeRegToAop (hc08_reg_a, AOP (result), offset);
5226 hc08_freeReg (hc08_reg_a);
5233 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5234 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5235 freeAsmop (result, NULL, ic, TRUE);
5238 /*-----------------------------------------------------------------*/
5239 /* genXor - code for xclusive or */
5240 /*-----------------------------------------------------------------*/
5242 genXor (iCode * ic, iCode * ifx)
5244 operand *left, *right, *result;
5245 int size, offset = 0;
5246 unsigned long lit = 0L;
5248 D(emitcode ("; genXor",""));
5250 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5251 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5252 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5255 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5257 AOP_TYPE (left), AOP_TYPE (right)));
5258 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5260 AOP_SIZE (left), AOP_SIZE (right)));
5263 /* if left is a literal & right is not ||
5264 if left needs acc & right does not */
5265 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5267 operand *tmp = right;
5272 /* if left is accumulator & right is not then exchange them */
5273 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5275 operand *tmp = right;
5280 if (AOP_TYPE (result) == AOP_CRY)
5283 wassertl (ifx, "AOP_CPY result without ifx");
5285 tlbl = newiTempLabel (NULL);
5286 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5290 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5291 if ((AOP_TYPE (right) == AOP_LIT)
5292 && (((lit >> (offset*8)) & 0xff) == 0))
5293 emitcode ("tsta","");
5295 accopWithAop ("eor", AOP (right), offset);
5296 hc08_freeReg( hc08_reg_a);
5298 emitBranch ("bne", tlbl);
5302 genIfxJump (ifx, "a");
5308 if (AOP_TYPE (right) == AOP_LIT)
5309 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5311 size = AOP_SIZE (result);
5315 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5316 accopWithAop ("eor", AOP (right), offset);
5317 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5318 hc08_freeReg( hc08_reg_a);
5322 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5323 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5324 freeAsmop (result, NULL, ic, TRUE);
5328 emitinline (iCode * ic, char *inlin)
5334 symbol *sym, *tempsym;
5343 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5347 //printf("Found possible symbol '%s'\n",symname);
5348 tempsym = newSymbol (symname, ic->level);
5349 tempsym->block = ic->block;
5350 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5359 aop = aopForSym (ic, sym, FALSE);
5360 l = aopAdrStr (aop, aop->size - 1, TRUE);
5364 if (sym->level && !sym->allocreq && !sym->ismyparm)
5366 werror (E_ID_UNDEF, sym->name);
5368 " Add 'volatile' to the variable declaration so that it\n"
5369 " can be referenced within inline assembly");
5371 //printf("Replacing with '%s'\n",l);
5375 if ((2+bp-buffer)>sizeof(buffer))
5384 if ((2+bp-buffer)>sizeof(buffer))
5391 if ((2+bp-buffer)>sizeof(buffer))
5392 fprintf(stderr, "Inline assembly buffer overflow\n");
5394 //printf("%s\n",buffer);
5395 emitcode (buffer,"");
5399 /*-----------------------------------------------------------------*/
5400 /* genInline - write the inline code out */
5401 /*-----------------------------------------------------------------*/
5403 genInline (iCode * ic)
5405 char *buffer, *bp, *bp1;
5407 D(emitcode ("; genInline",""));
5409 _G.inLine += (!options.asmpeep);
5411 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5412 strcpy (buffer, IC_INLINE (ic));
5414 /* emit each line as a code */
5420 /* emitcode (bp1, ""); */
5421 emitinline (ic, bp1);
5440 /* emitcode (bp1, ""); */
5441 emitinline (ic, bp1);
5443 /* emitcode("",buffer); */
5444 _G.inLine -= (!options.asmpeep);
5447 /*-----------------------------------------------------------------*/
5448 /* genRRC - rotate right with carry */
5449 /*-----------------------------------------------------------------*/
5453 operand *left, *result;
5454 int size, offset = 0;
5455 bool needpula = FALSE;
5456 bool resultInA = FALSE;
5459 D(emitcode ("; genRRC",""));
5461 /* rotate right with carry */
5462 left = IC_LEFT (ic);
5463 result = IC_RESULT (ic);
5464 aopOp (left, ic, FALSE);
5465 aopOp (result, ic, FALSE);
5467 if ((AOP_TYPE (result) == AOP_REG)
5468 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5471 size = AOP_SIZE (result);
5475 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5479 rmwWithAop (shift, AOP (result), offset--);
5487 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5488 rmwWithReg (shift, hc08_reg_a);
5489 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5490 hc08_freeReg (hc08_reg_a);
5495 if ((!hc08_reg_a->isFree) || resultInA)
5497 pushReg (hc08_reg_a, TRUE);
5501 /* now we need to put the carry into the
5502 highest order byte of the result */
5503 offset = AOP_SIZE (result) - 1;
5504 emitcode ("clra","");
5505 emitcode ("rora","");
5506 hc08_dirtyReg (hc08_reg_a, FALSE);
5509 emitcode ("ora", "1,s");
5510 emitcode ("ais", "#1");
5511 hc08_dirtyReg (hc08_reg_a, FALSE);
5515 accopWithAop ("ora", AOP (result), offset);
5516 storeRegToAop (hc08_reg_a, AOP (result), offset);
5518 pullOrFreeReg (hc08_reg_a, needpula);
5520 freeAsmop (left, NULL, ic, TRUE);
5521 freeAsmop (result, NULL, ic, TRUE);
5524 /*-----------------------------------------------------------------*/
5525 /* genRLC - generate code for rotate left with carry */
5526 /*-----------------------------------------------------------------*/
5530 operand *left, *result;
5531 int size, offset = 0;
5533 bool resultInA = FALSE;
5534 bool needpula = FALSE;
5536 D(emitcode ("; genRLC",""));
5538 /* rotate right with carry */
5539 left = IC_LEFT (ic);
5540 result = IC_RESULT (ic);
5541 aopOp (left, ic, FALSE);
5542 aopOp (result, ic, FALSE);
5544 if ((AOP_TYPE (result) == AOP_REG)
5545 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5548 size = AOP_SIZE (result);
5552 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5556 rmwWithAop (shift, AOP (result), offset--);
5564 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5565 rmwWithReg (shift, hc08_reg_a);
5566 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5567 hc08_freeReg (hc08_reg_a);
5572 if ((!hc08_reg_a->isFree) || resultInA)
5574 pushReg (hc08_reg_a, TRUE);
5578 /* now we need to put the carry into the
5579 lowest order byte of the result */
5581 emitcode ("clra","");
5582 emitcode ("rola","");
5583 hc08_dirtyReg (hc08_reg_a, FALSE);
5586 emitcode ("ora", "1,s");
5587 emitcode ("ais", "#1");
5588 hc08_dirtyReg (hc08_reg_a, FALSE);
5592 accopWithAop ("ora", AOP (result), offset);
5593 storeRegToAop (hc08_reg_a, AOP (result), offset);
5595 pullOrFreeReg (hc08_reg_a, needpula);
5597 freeAsmop (left, NULL, ic, TRUE);
5598 freeAsmop (result, NULL, ic, TRUE);
5601 /*-----------------------------------------------------------------*/
5602 /* genGetHbit - generates code get highest order bit */
5603 /*-----------------------------------------------------------------*/
5605 genGetHbit (iCode * ic)
5607 operand *left, *result;
5609 D(emitcode ("; genGetHbit",""));
5611 left = IC_LEFT (ic);
5612 result = IC_RESULT (ic);
5613 aopOp (left, ic, FALSE);
5614 aopOp (result, ic, FALSE);
5616 /* get the highest order byte into a */
5617 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5618 emitcode ("rola", "");
5619 emitcode ("clra", "");
5620 emitcode ("rola", "");
5621 hc08_dirtyReg (hc08_reg_a, FALSE);
5622 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5623 hc08_freeReg (hc08_reg_a);
5625 freeAsmop (left, NULL, ic, TRUE);
5626 freeAsmop (result, NULL, ic, TRUE);
5629 /*-----------------------------------------------------------------*/
5630 /* genSwap - generates code to swap nibbles or bytes */
5631 /*-----------------------------------------------------------------*/
5633 genSwap (iCode * ic)
5635 operand *left, *result;
5637 D(emitcode ("; genSwap",""));
5639 left = IC_LEFT (ic);
5640 result = IC_RESULT (ic);
5641 aopOp (left, ic, FALSE);
5642 aopOp (result, ic, FALSE);
5644 switch (AOP_SIZE (left))
5646 case 1: /* swap nibbles in byte */
5647 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5648 emitcode ("nsa", "");
5649 hc08_dirtyReg (hc08_reg_a, FALSE);
5650 storeRegToAop (hc08_reg_a, AOP (result), 0);
5651 hc08_freeReg (hc08_reg_a);
5653 case 2: /* swap bytes in a word */
5654 if (operandsEqu (left, result))
5656 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5657 hc08_useReg (hc08_reg_a);
5658 transferAopAop (AOP (left), 1, AOP (result), 0);
5659 storeRegToAop (hc08_reg_a, AOP (result), 1);
5660 hc08_freeReg (hc08_reg_a);
5664 transferAopAop (AOP (left), 0, AOP (result), 1);
5665 transferAopAop (AOP (left), 1, AOP (result), 0);
5669 wassertl(FALSE, "unsupported SWAP operand size");
5672 freeAsmop (left, NULL, ic, TRUE);
5673 freeAsmop (result, NULL, ic, TRUE);
5677 /*-----------------------------------------------------------------*/
5678 /* AccRol - rotate left accumulator by known count */
5679 /*-----------------------------------------------------------------*/
5681 AccRol (int shCount)
5683 shCount &= 0x0007; // shCount : 0..7
5690 emitcode ("rola", ""); /* 1 cycle */
5693 emitcode ("rola", ""); /* 1 cycle */
5694 emitcode ("rola", ""); /* 1 cycle */
5697 emitcode ("nsa", "");
5698 emitcode ("rora", "");
5701 emitcode ("nsa", ""); /* 3 cycles */
5704 emitcode ("nsa", ""); /* 3 cycles */
5705 emitcode ("rola", ""); /* 1 cycle */
5708 emitcode ("nsa", ""); /* 3 cycles */
5709 emitcode ("rola", ""); /* 1 cycle */
5710 emitcode ("rola", ""); /* 1 cycle */
5713 emitcode ("nsa", ""); /* 3 cycles */
5714 emitcode ("rola", ""); /* 1 cycle */
5715 emitcode ("rola", ""); /* 1 cycle */
5716 emitcode ("rola", ""); /* 1 cycle */
5723 /*-----------------------------------------------------------------*/
5724 /* AccLsh - left shift accumulator by known count */
5725 /*-----------------------------------------------------------------*/
5727 AccLsh (int shCount)
5731 shCount &= 0x0007; // shCount : 0..7
5733 /* Shift counts of 4 and 5 are currently optimized for code size. */
5734 /* Falling through to the unrolled loop would be optimal for code speed. */
5735 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5739 if (optimize.codeSpeed)
5741 accopWithMisc ("nsa", "");
5742 accopWithMisc ("and", "#0xf0");
5743 /* total: 5 cycles, 3 bytes */
5746 if (optimize.codeSpeed)
5748 accopWithMisc ("nsa", "");
5749 accopWithMisc ("and", "#0xf0");
5750 accopWithMisc ("lsla", "");
5751 /* total: 6 cycles, 4 bytes */
5754 accopWithMisc ("rora", "");
5755 accopWithMisc ("rora", "");
5756 accopWithMisc ("rora", "");
5757 accopWithMisc ("and", "#0xc0");
5758 /* total: 5 cycles, 5 bytes */
5761 accopWithMisc ("rora", "");
5762 accopWithMisc ("clra", "");
5763 accopWithMisc ("rora", "");
5764 /* total: 3 cycles, 3 bytes */
5768 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5769 /* the fastest (shCount<6) and shortest (shCount<4). */
5770 for (i=0;i<shCount;i++)
5771 accopWithMisc ("lsla", "");
5775 /*-----------------------------------------------------------------*/
5776 /* AccSRsh - signed right shift accumulator by known count */
5777 /*-----------------------------------------------------------------*/
5779 AccSRsh (int shCount)
5783 shCount &= 0x0007; // shCount : 0..7
5787 accopWithMisc ("rola", "");
5788 accopWithMisc ("clra", "");
5789 accopWithMisc ("sbc", zero);
5790 /* total: 4 cycles, 4 bytes */
5794 for (i=0;i<shCount;i++)
5795 accopWithMisc ("asra", "");
5798 /*-----------------------------------------------------------------*/
5799 /* AccRsh - right shift accumulator by known count */
5800 /*-----------------------------------------------------------------*/
5802 AccRsh (int shCount, bool sign)
5812 shCount &= 0x0007; // shCount : 0..7
5814 /* Shift counts of 4 and 5 are currently optimized for code size. */
5815 /* Falling through to the unrolled loop would be optimal for code speed. */
5816 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5820 if (optimize.codeSpeed)
5822 accopWithMisc ("nsa", "");
5823 accopWithMisc ("and", "#0x0f");
5824 /* total: 5 cycles, 3 bytes */
5827 if (optimize.codeSpeed)
5829 accopWithMisc ("nsa", "");
5830 accopWithMisc ("and", "#0x0f");
5831 accopWithMisc ("lsra", "");
5832 /* total: 6 cycles, 4 bytes */
5835 accopWithMisc ("rola", "");
5836 accopWithMisc ("rola", "");
5837 accopWithMisc ("rola", "");
5838 accopWithMisc ("and", "#0x03");
5839 /* total: 5 cycles, 5 bytes */
5842 accopWithMisc ("rola", "");
5843 accopWithMisc ("clra", "");
5844 accopWithMisc ("rola", "");
5845 /* total: 3 cycles, 3 bytes */
5849 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5850 /* the fastest (shCount<6) and shortest (shCount<4). */
5851 for (i=0;i<shCount;i++)
5852 accopWithMisc ("lsra", "");
5856 /*-----------------------------------------------------------------*/
5857 /* XAccLsh - left shift register pair XA by known count */
5858 /*-----------------------------------------------------------------*/
5860 XAccLsh (int shCount)
5864 shCount &= 0x000f; // shCount : 0..15
5869 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5870 loadRegFromConst (hc08_reg_a, zero);
5874 /* if we can beat 2n cycles or bytes for some special case, do it here */
5878 /* bytes cycles reg x reg a carry
5879 ** abcd efgh ijkl mnop ?
5880 ** lsrx 1 1 0abc defg ijkl mnop h
5881 ** rora 1 1 0abc defg hijk lmno p
5882 ** tax 1 1 hijk lmno hijk lmno p
5883 ** clra 1 1 hijk lmno 0000 0000 p
5884 ** rora 1 1 hijk lmno p000 0000 0
5885 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5887 rmwWithReg ("lsr", hc08_reg_x);
5888 rmwWithReg ("ror", hc08_reg_a);
5889 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5890 loadRegFromConst (hc08_reg_a, zero);
5891 rmwWithReg ("ror", hc08_reg_a);
5898 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5899 /* the fastest and shortest. */
5900 for (i=0;i<shCount;i++)
5902 rmwWithReg ("lsl", hc08_reg_a);
5903 rmwWithReg ("rol", hc08_reg_x);
5907 /*-----------------------------------------------------------------*/
5908 /* XAccSRsh - signed right shift register pair XA by known count */
5909 /*-----------------------------------------------------------------*/
5911 XAccSRsh (int shCount)
5915 shCount &= 0x000f; // shCount : 0..7
5917 /* if we can beat 2n cycles or bytes for some special case, do it here */
5921 /* bytes cycles reg x reg a carry
5922 ** abcd efgh ijkl mnop ?
5923 ** lslx 1 1 bcde fgh0 ijkl mnop a
5924 ** clra 1 1 bcde fgh0 0000 0000 a
5925 ** rola 1 1 bcde fgh0 0000 000a 0
5926 ** nega 1 1 bcde fgh0 aaaa aaaa a
5927 ** tax 1 1 aaaa aaaa aaaa aaaa a
5928 ** total: 5 cycles, 5 bytes
5930 rmwWithReg ("lsl", hc08_reg_x);
5931 loadRegFromConst (hc08_reg_a, zero);
5932 rmwWithReg ("rol", hc08_reg_a);
5933 rmwWithReg ("neg", hc08_reg_a);
5934 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5944 /* bytes cycles reg x reg a carry
5945 ** abcd efgh ijkl mnop ?
5946 ** txa 1 1 abcd efgh abcd efgh ?
5947 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5948 ** lsla 1 1 abcd efgh ???? ???? a
5949 ** clrx 1 1 0000 0000 ???? ???? a
5950 ** rolx 1 1 0000 000a ???? ???? 0
5951 ** negx 1 1 aaaa aaaa ???? ???? a
5952 ** rora 1 1 aaaa aaaa LSBresult 0
5953 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5955 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5956 AccSRsh (shCount-8);
5957 rmwWithReg ("lsl", hc08_reg_a);
5958 loadRegFromConst (hc08_reg_x, zero);
5959 rmwWithReg ("rol", hc08_reg_x);
5960 rmwWithReg ("neg", hc08_reg_x);
5961 rmwWithReg ("ror", hc08_reg_a);
5968 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5969 /* the fastest and shortest. */
5970 for (i=0;i<shCount;i++)
5972 rmwWithReg ("asr", hc08_reg_x);
5973 rmwWithReg ("ror", hc08_reg_a);
5977 /*-----------------------------------------------------------------*/
5978 /* XAccRsh - right shift register pair XA by known count */
5979 /*-----------------------------------------------------------------*/
5981 XAccRsh (int shCount, bool sign)
5991 shCount &= 0x000f; // shCount : 0..f
5993 /* if we can beat 2n cycles or bytes for some special case, do it here */
5997 /* bytes cycles reg x reg a carry
5998 ** abcd efgh ijkl mnop ?
5999 ** clra 1 1 abcd efgh 0000 0000 a
6000 ** lslx 1 1 bcde fgh0 0000 0000 a
6001 ** rola 1 1 bcde fgh0 0000 000a 0
6002 ** clrx 1 1 0000 0000 0000 000a 0
6003 ** total: 4 cycles, 4 bytes
6005 loadRegFromConst (hc08_reg_x, zero);
6006 rmwWithReg ("lsl", hc08_reg_x);
6007 rmwWithReg ("rol", hc08_reg_a);
6008 loadRegFromConst (hc08_reg_a, zero);
6012 /* bytes cycles reg x reg a carry
6013 ** abcd efgh ijkl mnop ?
6014 ** clra 1 1 abcd efgh 0000 0000 a
6015 ** lslx 1 1 bcde fgh0 0000 0000 a
6016 ** rola 1 1 bcde fgh0 0000 000a 0
6017 ** lslx 1 1 cdef gh00 0000 000a b
6018 ** rola 1 1 cdef gh00 0000 00ab 0
6019 ** clrx 1 1 0000 0000 0000 00ab 0
6020 ** total: 6 cycles, 6 bytes
6022 loadRegFromConst (hc08_reg_x, zero);
6023 rmwWithReg ("lsl", hc08_reg_x);
6024 rmwWithReg ("rol", hc08_reg_a);
6025 rmwWithReg ("lsl", hc08_reg_x);
6026 rmwWithReg ("rol", hc08_reg_a);
6027 loadRegFromConst (hc08_reg_a, zero);
6036 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6037 AccRsh (shCount-8, FALSE);
6038 loadRegFromConst (hc08_reg_x, zero);
6042 /* bytes cycles reg x reg a carry
6043 ** abcd efgh ijkl mnop ?
6044 ** lsla 1 1 abcd efgh jklm nop0 i
6045 ** txa 1 1 abcd efgh abcd efgh i
6046 ** rola 1 1 abcd efgh bcde fghi a
6047 ** clrx 1 1 0000 0000 bcde fghi a
6048 ** rolx 1 1 0000 000a bcde fghi 0
6049 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6051 rmwWithReg ("lsl", hc08_reg_a);
6052 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6053 rmwWithReg ("rol", hc08_reg_a);
6054 loadRegFromConst (hc08_reg_x, zero);
6055 rmwWithReg ("rol", hc08_reg_x);
6058 /* bytes cycles reg x reg a carry
6059 ** abcd efgh ijkl mnop ?
6060 ** lsla 1 1 abcd efgh jklm nop0 i
6061 ** rolx 1 1 bcde fghi jklm nop0 a
6062 ** rola 1 1 bcde fghi klmn op0a j
6063 ** rolx 1 1 cdef ghij klmn op0a b
6064 ** rola 1 1 cdef ghij lmno p0ab k
6065 ** and #3 2 2 cdef ghij 0000 00ab k
6066 ** psha 1 2 cdef ghij 0000 00ab k
6067 ** txa 1 1 cdef ghij cdef ghij k
6068 ** pula 1 2 0000 00ab cdef ghij k
6069 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6075 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6076 /* the fastest and shortest. */
6077 for (i=0;i<shCount;i++)
6079 rmwWithReg ("lsr", hc08_reg_x);
6080 rmwWithReg ("ror", hc08_reg_a);
6087 /*-----------------------------------------------------------------*/
6088 /* shiftR1Left2Result - shift right one byte from left to result */
6089 /*-----------------------------------------------------------------*/
6091 shiftR1Left2Result (operand * left, int offl,
6092 operand * result, int offr,
6093 int shCount, int sign)
6095 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6096 /* shift right accumulator */
6097 AccRsh (shCount, sign);
6098 storeRegToAop (hc08_reg_a, AOP (result), offr);
6102 /*-----------------------------------------------------------------*/
6103 /* shiftL1Left2Result - shift left one byte from left to result */
6104 /*-----------------------------------------------------------------*/
6106 shiftL1Left2Result (operand * left, int offl,
6107 operand * result, int offr, int shCount)
6109 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6110 /* shift left accumulator */
6112 storeRegToAop (hc08_reg_a, AOP (result), offr);
6115 /*-----------------------------------------------------------------*/
6116 /* movLeft2Result - move byte from left to result */
6117 /*-----------------------------------------------------------------*/
6119 movLeft2Result (operand * left, int offl,
6120 operand * result, int offr, int sign)
6122 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6124 transferAopAop (AOP (left), offl, AOP (result), offr);
6129 /*-----------------------------------------------------------------*/
6130 /* shiftL2Left2Result - shift left two bytes from left to result */
6131 /*-----------------------------------------------------------------*/
6133 shiftL2Left2Result (operand * left, int offl,
6134 operand * result, int offr, int shCount)
6137 bool needpula = FALSE;
6138 bool needpulx = FALSE;
6140 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6141 needpula = pushRegIfUsed (hc08_reg_a);
6144 if (!IS_AOP_XA (AOP (left)))
6145 needpulx = pushRegIfUsed (hc08_reg_x);
6149 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6154 rmwWithReg ("lsr", hc08_reg_x);
6155 rmwWithReg ("ror", hc08_reg_a);
6156 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6157 rmwWithReg ("clr", hc08_reg_a);
6158 rmwWithReg ("ror", hc08_reg_a);
6161 for (i=0; i<shCount; i++)
6163 rmwWithReg ("lsl", hc08_reg_a);
6164 rmwWithReg ("rol", hc08_reg_x);
6167 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6169 pullOrFreeReg (hc08_reg_x, needpulx);
6170 pullOrFreeReg (hc08_reg_a, needpula);
6176 /*-----------------------------------------------------------------*/
6177 /* shiftR2Left2Result - shift right two bytes from left to result */
6178 /*-----------------------------------------------------------------*/
6180 shiftR2Left2Result (operand * left, int offl,
6181 operand * result, int offr,
6182 int shCount, int sign)
6185 bool needpula = FALSE;
6186 bool needpulx = FALSE;
6188 needpula = pushRegIfUsed (hc08_reg_a);
6189 needpulx = pushRegIfUsed (hc08_reg_x);
6191 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6192 for (i=0; i<shCount; i++)
6195 rmwWithReg ("asr", hc08_reg_x);
6197 rmwWithReg ("lsr", hc08_reg_x);
6198 rmwWithReg ("ror", hc08_reg_a);
6200 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6202 pullOrFreeReg (hc08_reg_x, needpulx);
6203 pullOrFreeReg (hc08_reg_a, needpula);
6208 /*-----------------------------------------------------------------*/
6209 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6210 /*-----------------------------------------------------------------*/
6212 shiftLLeftOrResult (operand * left, int offl,
6213 operand * result, int offr, int shCount)
6215 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6216 /* shift left accumulator */
6218 /* or with result */
6219 accopWithAop ("ora", AOP (result), offr);
6220 /* back to result */
6221 storeRegToAop (hc08_reg_a, AOP (result), offr);
6222 hc08_freeReg (hc08_reg_a);
6226 /*-----------------------------------------------------------------*/
6227 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6228 /*-----------------------------------------------------------------*/
6230 shiftRLeftOrResult (operand * left, int offl,
6231 operand * result, int offr, int shCount)
6233 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6234 /* shift left accumulator */
6235 AccRsh (shCount, FALSE);
6236 /* or with result */
6237 accopWithAop ("ora", AOP (result), offr);
6238 /* back to result */
6239 storeRegToAop (hc08_reg_a, AOP (result), offr);
6240 hc08_freeReg (hc08_reg_a);
6243 /*-----------------------------------------------------------------*/
6244 /* genlshOne - left shift a one byte quantity by known count */
6245 /*-----------------------------------------------------------------*/
6247 genlshOne (operand * result, operand * left, int shCount)
6249 D(emitcode ("; genlshOne",""));
6251 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6254 /*-----------------------------------------------------------------*/
6255 /* genlshTwo - left shift two bytes by known amount != 0 */
6256 /*-----------------------------------------------------------------*/
6258 genlshTwo (operand * result, operand * left, int shCount)
6262 D(emitcode ("; genlshTwo",""));
6265 size = getDataSize (result);
6267 /* if shCount >= 8 */
6274 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6276 storeRegToAop (hc08_reg_a, AOP (result), 1);
6278 storeConstToAop(zero, AOP (result), LSB);
6281 /* 1 <= shCount <= 7 */
6284 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6286 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6290 /*-----------------------------------------------------------------*/
6291 /* shiftLLong - shift left one long from left to result */
6292 /* offl = LSB or MSB16 */
6293 /*-----------------------------------------------------------------*/
6295 shiftLLong (operand * left, operand * result, int offr)
6298 // int size = AOP_SIZE (result);
6300 bool needpula = FALSE;
6301 bool needpulx = FALSE;
6303 needpula = pushRegIfUsed (hc08_reg_a);
6304 needpulx = pushRegIfUsed (hc08_reg_x);
6306 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6307 rmwWithReg ("lsl", hc08_reg_a);
6308 rmwWithReg ("rol", hc08_reg_x);
6309 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6313 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6314 rmwWithReg ("rol", hc08_reg_a);
6315 rmwWithReg ("rol", hc08_reg_x);
6316 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6318 else if (offr==MSB16)
6320 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6321 rmwWithReg ("rol", hc08_reg_a);
6322 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6323 storeConstToAop (zero, AOP (result), 0);
6326 pullOrFreeReg (hc08_reg_x, needpulx);
6327 pullOrFreeReg (hc08_reg_a, needpula);
6330 /*-----------------------------------------------------------------*/
6331 /* genlshFour - shift four byte by a known amount != 0 */
6332 /*-----------------------------------------------------------------*/
6334 genlshFour (operand * result, operand * left, int shCount)
6338 D(emitcode ("; genlshFour",""));
6340 size = AOP_SIZE (result);
6342 /* TODO: deal with the &result == &left case */
6344 /* if shifting more that 3 bytes */
6349 /* lowest order of left goes to the highest
6350 order of the destination */
6351 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6353 movLeft2Result (left, LSB, result, MSB32, 0);
6354 storeConstToAop (zero, AOP (result), LSB);
6355 storeConstToAop (zero, AOP (result), MSB16);
6356 storeConstToAop (zero, AOP (result), MSB24);
6360 /* more than two bytes */
6361 else if (shCount >= 16)
6363 /* lower order two bytes goes to higher order two bytes */
6365 /* if some more remaining */
6367 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6370 movLeft2Result (left, MSB16, result, MSB32, 0);
6371 movLeft2Result (left, LSB, result, MSB24, 0);
6373 storeConstToAop (zero, AOP (result), LSB);
6374 storeConstToAop (zero, AOP (result), MSB16);
6378 /* if more than 1 byte */
6379 else if (shCount >= 8)
6381 /* lower order three bytes goes to higher order three bytes */
6386 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6388 movLeft2Result (left, LSB, result, MSB16, 0);
6394 movLeft2Result (left, MSB24, result, MSB32, 0);
6395 movLeft2Result (left, MSB16, result, MSB24, 0);
6396 movLeft2Result (left, LSB, result, MSB16, 0);
6397 storeConstToAop (zero, AOP (result), LSB);
6399 else if (shCount == 1)
6400 shiftLLong (left, result, MSB16);
6403 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6404 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6405 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6406 storeConstToAop (zero, AOP (result), LSB);
6411 /* 1 <= shCount <= 7 */
6412 else if (shCount <= 2)
6414 shiftLLong (left, result, LSB);
6416 shiftLLong (result, result, LSB);
6418 /* 3 <= shCount <= 7, optimize */
6421 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6422 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6423 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6427 /*-----------------------------------------------------------------*/
6428 /* genLeftShiftLiteral - left shifting by known count */
6429 /*-----------------------------------------------------------------*/
6431 genLeftShiftLiteral (operand * left,
6436 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6439 D(emitcode ("; genLeftShiftLiteral",""));
6441 freeAsmop (right, NULL, ic, TRUE);
6443 aopOp (left, ic, FALSE);
6444 aopOp (result, ic, FALSE);
6446 // size = getSize (operandType (result));
6447 size = AOP_SIZE (result);
6450 D(emitcode ("; shift left ", "result %d, left %d", size,
6457 transferAopAop( AOP(left), size, AOP(result), size);
6459 else if (shCount >= (size * 8))
6462 storeConstToAop (zero, AOP (result), size);
6469 genlshOne (result, left, shCount);
6473 genlshTwo (result, left, shCount);
6477 genlshFour (result, left, shCount);
6480 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6481 "*** ack! mystery literal shift!\n");
6485 freeAsmop (left, NULL, ic, TRUE);
6486 freeAsmop (result, NULL, ic, TRUE);
6489 /*-----------------------------------------------------------------*/
6490 /* genLeftShift - generates code for left shifting */
6491 /*-----------------------------------------------------------------*/
6493 genLeftShift (iCode * ic)
6495 operand *left, *right, *result;
6497 symbol *tlbl, *tlbl1;
6502 D(emitcode ("; genLeftShift",""));
6504 right = IC_RIGHT (ic);
6505 left = IC_LEFT (ic);
6506 result = IC_RESULT (ic);
6508 aopOp (right, ic, FALSE);
6510 /* if the shift count is known then do it
6511 as efficiently as possible */
6512 if (AOP_TYPE (right) == AOP_LIT)
6514 genLeftShiftLiteral (left, right, result, ic);
6518 /* shift count is unknown then we have to form
6519 a loop get the loop count in A : Note: we take
6520 only the lower order byte since shifting
6521 more that 32 bits make no sense anyway, ( the
6522 largest size of an object can be only 32 bits ) */
6524 aopOp (left, ic, FALSE);
6525 aopOp (result, ic, FALSE);
6527 /* now move the left to the result if they are not the
6529 if (!sameRegs (AOP (left), AOP (result)))
6532 size = AOP_SIZE (result);
6536 transferAopAop (AOP (left), offset, AOP (result), offset);
6540 freeAsmop (left, NULL, ic, TRUE);
6542 tlbl = newiTempLabel (NULL);
6543 size = AOP_SIZE (result);
6545 tlbl1 = newiTempLabel (NULL);
6549 loadRegFromAop (reg, AOP (right), 0);
6550 freeAsmop (right, NULL, ic, TRUE);
6551 emitBranch ("beq", tlbl1);
6555 for (offset=0;offset<size;offset++)
6557 rmwWithAop (shift, AOP (result), offset);
6560 rmwWithReg ("dec", reg);
6561 emitBranch ("bne", tlbl);
6565 freeAsmop (result, NULL, ic, TRUE);
6568 /*-----------------------------------------------------------------*/
6569 /* genrshOne - right shift a one byte quantity by known count */
6570 /*-----------------------------------------------------------------*/
6572 genrshOne (operand * result, operand * left,
6573 int shCount, int sign)
6575 D(emitcode ("; genrshOne",""));
6577 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6578 AccRsh (shCount, sign);
6579 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6582 /*-----------------------------------------------------------------*/
6583 /* genrshTwo - right shift two bytes by known amount != 0 */
6584 /*-----------------------------------------------------------------*/
6586 genrshTwo (operand * result, operand * left,
6587 int shCount, int sign)
6589 D(emitcode ("; genrshTwo",""));
6591 /* if shCount >= 8 */
6594 if (shCount || sign)
6596 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6597 AccRsh (shCount-8, sign);
6598 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6602 transferAopAop (AOP (left), 1, AOP (result), 0);
6603 storeConstToAop (zero, AOP (result), 1);
6607 /* 1 <= shCount <= 7 */
6610 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6611 XAccRsh (shCount, sign);
6612 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6616 /*-----------------------------------------------------------------*/
6617 /* shiftRLong - shift right one long from left to result */
6618 /* offl = LSB or MSB16 */
6619 /*-----------------------------------------------------------------*/
6621 shiftRLong (operand * left, int offl,
6622 operand * result, int sign)
6625 // int size = AOP_SIZE (result);
6627 bool needpula = FALSE;
6628 bool needpulx = FALSE;
6630 needpula = pushRegIfUsed (hc08_reg_a);
6631 needpulx = pushRegIfUsed (hc08_reg_x);
6635 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6637 rmwWithReg ("asr", hc08_reg_x);
6639 rmwWithReg ("lsr", hc08_reg_x);
6640 rmwWithReg ("ror", hc08_reg_a);
6641 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6643 else if (offl==MSB16)
6645 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6647 rmwWithReg ("asr", hc08_reg_a);
6649 rmwWithReg ("lsr", hc08_reg_a);
6650 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6651 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6654 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6655 rmwWithReg ("ror", hc08_reg_x);
6656 rmwWithReg ("ror", hc08_reg_a);
6657 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6660 pullOrFreeReg (hc08_reg_x, needpulx);
6661 pullOrFreeReg (hc08_reg_a, needpula);
6664 /*-----------------------------------------------------------------*/
6665 /* genrshFour - shift four byte by a known amount != 0 */
6666 /*-----------------------------------------------------------------*/
6668 genrshFour (operand * result, operand * left,
6669 int shCount, int sign)
6671 /* TODO: handle cases where left == result */
6673 D(emitcode ("; genrshFour",""));
6675 /* if shifting more that 3 bytes */
6678 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6679 AccRsh (shCount-24, sign);
6680 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6683 else if (shCount >= 16)
6685 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6686 XAccRsh (shCount-16, sign);
6687 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6690 else if (shCount >= 8)
6693 shiftRLong (left, MSB16, result, sign);
6694 else if (shCount == 8)
6696 transferAopAop (AOP (left), 1, AOP (result), 0);
6697 transferAopAop (AOP (left), 2, AOP (result), 1);
6698 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6699 storeRegToAop (hc08_reg_a, AOP (result), 2);
6700 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6702 else if (shCount == 9)
6704 shiftRLong (left, MSB16, result, sign);
6708 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6709 XAccRsh (shCount-8, FALSE);
6710 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6711 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6712 loadRegFromConst (hc08_reg_a, zero);
6713 XAccRsh (shCount-8, sign);
6714 accopWithAop ("ora", AOP (result), 1);
6715 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6716 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6720 { /* 1 <= shCount <= 7 */
6723 shiftRLong (left, LSB, result, sign);
6727 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6728 XAccRsh (shCount, FALSE);
6729 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6730 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6732 accopWithAop ("ora", AOP (result), 1);
6733 storeRegToAop (hc08_reg_a, AOP (result), 1);
6734 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6735 XAccRsh (shCount, sign);
6736 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6741 /*-----------------------------------------------------------------*/
6742 /* genRightShiftLiteral - right shifting by known count */
6743 /*-----------------------------------------------------------------*/
6745 genRightShiftLiteral (operand * left,
6751 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6754 D(emitcode ("; genRightShiftLiteral",""));
6756 freeAsmop (right, NULL, ic, TRUE);
6758 aopOp (left, ic, FALSE);
6759 aopOp (result, ic, FALSE);
6762 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6766 size = getDataSize (left);
6767 /* test the LEFT size !!! */
6769 /* I suppose that the left size >= result size */
6772 size = getDataSize (result);
6774 transferAopAop (AOP (left), size, AOP(result), size);
6776 else if (shCount >= (size * 8))
6779 /* get sign in acc.7 */
6780 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6782 addSign (result, LSB, sign);
6789 genrshOne (result, left, shCount, sign);
6793 genrshTwo (result, left, shCount, sign);
6797 genrshFour (result, left, shCount, sign);
6803 freeAsmop (left, NULL, ic, TRUE);
6804 freeAsmop (result, NULL, ic, TRUE);
6808 /*-----------------------------------------------------------------*/
6809 /* genRightShift - generate code for right shifting */
6810 /*-----------------------------------------------------------------*/
6812 genRightShift (iCode * ic)
6814 operand *right, *left, *result;
6818 symbol *tlbl, *tlbl1;
6822 D(emitcode ("; genRightShift",""));
6824 /* if signed then we do it the hard way preserve the
6825 sign bit moving it inwards */
6826 retype = getSpec (operandType (IC_RESULT (ic)));
6827 sign = !SPEC_USIGN (retype);
6829 /* signed & unsigned types are treated the same : i.e. the
6830 signed is NOT propagated inwards : quoting from the
6831 ANSI - standard : "for E1 >> E2, is equivalent to division
6832 by 2**E2 if unsigned or if it has a non-negative value,
6833 otherwise the result is implementation defined ", MY definition
6834 is that the sign does not get propagated */
6836 right = IC_RIGHT (ic);
6837 left = IC_LEFT (ic);
6838 result = IC_RESULT (ic);
6840 aopOp (right, ic, FALSE);
6842 /* if the shift count is known then do it
6843 as efficiently as possible */
6844 if (AOP_TYPE (right) == AOP_LIT)
6846 genRightShiftLiteral (left, right, result, ic, sign);
6850 /* shift count is unknown then we have to form
6851 a loop get the loop count in X : Note: we take
6852 only the lower order byte since shifting
6853 more that 32 bits make no sense anyway, ( the
6854 largest size of an object can be only 32 bits ) */
6856 aopOp (left, ic, FALSE);
6857 aopOp (result, ic, FALSE);
6859 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6860 AOP (result) = forceStackedAop (AOP (result));
6862 size = AOP_SIZE (result);
6866 transferAopAop (AOP (left), offset, AOP (result), offset);
6870 tlbl = newiTempLabel (NULL);
6871 size = AOP_SIZE (result);
6873 tlbl1 = newiTempLabel (NULL);
6875 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6876 emitcode ("tstx", "");
6877 emitcode ("beq", "%05d$", tlbl1->key + 100);
6878 emitcode ("", "%05d$:", tlbl->key + 100);
6879 shift= sign ? "asr" : "lsr";
6880 for (offset=size-1;offset>=0;offset--)
6882 rmwWithAop (shift, AOP (result), offset);
6885 rmwWithReg ("dec", hc08_reg_x);
6886 emitcode ("bne","%05d$", tlbl->key + 100);
6887 emitcode ("", "%05d$:", tlbl1->key + 100);
6889 freeAsmop (result, NULL, ic, TRUE);
6890 freeAsmop (left, NULL, ic, TRUE);
6891 freeAsmop (right, NULL, ic, TRUE);
6895 /*-----------------------------------------------------------------*/
6896 /* genUnpackBits - generates code for unpacking bits */
6897 /*-----------------------------------------------------------------*/
6899 genUnpackBits (operand * result, iCode *ifx)
6901 int offset = 0; /* result byte offset */
6902 int rsize; /* result size */
6903 int rlen = 0; /* remaining bitfield length */
6904 sym_link *etype; /* bitfield type information */
6905 int blen; /* bitfield length */
6906 int bstr; /* bitfield starting bit within byte */
6908 D(emitcode ("; genUnpackBits",""));
6910 etype = getSpec (operandType (result));
6911 rsize = getSize (operandType (result));
6912 blen = SPEC_BLEN (etype);
6913 bstr = SPEC_BSTR (etype);
6915 if (ifx && blen <= 8)
6917 emitcode ("lda", ",x");
6918 hc08_dirtyReg (hc08_reg_a, FALSE);
6921 emitcode ("and", "#0x%02x",
6922 (((unsigned char) -1) >> (8 - blen)) << bstr);
6924 genIfxJump (ifx, "a");
6929 /* If the bitfield length is less than a byte */
6932 emitcode ("lda", ",x");
6933 hc08_dirtyReg (hc08_reg_a, FALSE);
6934 AccRsh (bstr, FALSE);
6935 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6936 if (!SPEC_USIGN (etype))
6938 /* signed bitfield */
6939 symbol *tlbl = newiTempLabel (NULL);
6941 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
6942 emitcode ("beq", "%05d$", tlbl->key + 100);
6943 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
6946 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6950 /* Bit field did not fit in a byte. Copy all
6951 but the partial byte at the end. */
6952 for (rlen=blen;rlen>=8;rlen-=8)
6954 emitcode ("lda", ",x");
6955 hc08_dirtyReg (hc08_reg_a, FALSE);
6956 storeRegToAop (hc08_reg_a, AOP (result), offset);
6959 emitcode ("aix", "#1");
6962 /* Handle the partial byte at the end */
6965 emitcode ("lda", ",x");
6966 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6967 if (!SPEC_USIGN (etype))
6969 /* signed bitfield */
6970 symbol *tlbl = newiTempLabel (NULL);
6972 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
6973 emitcode ("beq", "%05d$", tlbl->key + 100);
6974 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
6977 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6984 if (SPEC_USIGN (etype))
6987 storeConstToAop (zero, AOP (result), offset++);
6991 /* signed bitfield: sign extension with 0x00 or 0xff */
6992 emitcode ("rola", "");
6993 emitcode ("clra", "");
6994 emitcode ("sbc", zero);
6997 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7003 /*-----------------------------------------------------------------*/
7004 /* genUnpackBitsImmed - generates code for unpacking bits */
7005 /*-----------------------------------------------------------------*/
7007 genUnpackBitsImmed (operand * left,
7013 int offset = 0; /* result byte offset */
7014 int rsize; /* result size */
7015 int rlen = 0; /* remaining bitfield length */
7016 sym_link *etype; /* bitfield type information */
7017 int blen; /* bitfield length */
7018 int bstr; /* bitfield starting bit within byte */
7021 D(emitcode ("; genUnpackBitsImmed",""));
7023 aopOp (result, ic, TRUE);
7024 size = AOP_SIZE (result);
7026 derefaop = aopDerefAop (AOP (left));
7027 freeAsmop (left, NULL, ic, TRUE);
7028 derefaop->size = size;
7030 etype = getSpec (operandType (result));
7031 rsize = getSize (operandType (result));
7032 blen = SPEC_BLEN (etype);
7033 bstr = SPEC_BSTR (etype);
7035 /* if the bitfield is a single bit in the direct page */
7036 if (blen == 1 && derefaop->type == AOP_DIR)
7040 symbol *tlbl = newiTempLabel (NULL);
7042 loadRegFromConst (hc08_reg_a, zero);
7043 emitcode ("brclr", "#%d,%s,%05d$",
7044 bstr, aopAdrStr (derefaop, 0, FALSE),
7046 if (SPEC_USIGN (etype))
7047 rmwWithReg ("inc", hc08_reg_a);
7049 rmwWithReg ("dec", hc08_reg_a);
7051 storeRegToAop (hc08_reg_a, AOP (result), offset);
7052 hc08_freeReg (hc08_reg_a);
7058 symbol *tlbl = newiTempLabel (NULL);
7064 jlbl = IC_TRUE (ifx);
7069 jlbl = IC_FALSE (ifx);
7072 emitcode (inst, "#%d,%s,%05d$",
7073 bstr, aopAdrStr (derefaop, 0, FALSE),
7075 emitBranch ("jmp", jlbl);
7083 /* If the bitfield length is less than a byte */
7086 loadRegFromAop (hc08_reg_a, derefaop, 0);
7089 AccRsh (bstr, FALSE);
7090 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7091 hc08_dirtyReg (hc08_reg_a, FALSE);
7092 if (!SPEC_USIGN (etype))
7094 /* signed bitfield */
7095 symbol *tlbl = newiTempLabel (NULL);
7097 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7098 emitcode ("beq", "%05d$", tlbl->key + 100);
7099 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7102 storeRegToAop (hc08_reg_a, AOP (result), offset);
7106 emitcode ("and", "#0x%02x",
7107 (((unsigned char) -1) >> (8 - blen)) << bstr);
7108 hc08_dirtyReg (hc08_reg_a, FALSE);
7114 /* Bit field did not fit in a byte. Copy all
7115 but the partial byte at the end. */
7116 for (rlen=blen;rlen>=8;rlen-=8)
7118 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7120 storeRegToAop (hc08_reg_a, AOP (result), offset);
7122 emitcode ("tsta", "");
7126 /* Handle the partial byte at the end */
7129 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7130 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7131 if (!SPEC_USIGN (etype))
7133 /* signed bitfield */
7134 symbol *tlbl = newiTempLabel (NULL);
7136 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7137 emitcode ("beq", "%05d$", tlbl->key + 100);
7138 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7141 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7148 if (SPEC_USIGN (etype))
7151 storeConstToAop (zero, AOP (result), offset++);
7155 /* signed bitfield: sign extension with 0x00 or 0xff */
7156 emitcode ("rola", "");
7157 emitcode ("clra", "");
7158 emitcode ("sbc", zero);
7161 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7165 freeAsmop (NULL, derefaop, ic, TRUE);
7166 freeAsmop (result, NULL, ic, TRUE);
7168 if (ifx && !ifx->generated)
7170 genIfxJump (ifx, "a");
7175 /*-----------------------------------------------------------------*/
7176 /* genDataPointerGet - generates code when ptr offset is known */
7177 /*-----------------------------------------------------------------*/
7179 genDataPointerGet (operand * left,
7187 D(emitcode ("; genDataPointerGet",""));
7189 aopOp (result, ic, TRUE);
7190 size = AOP_SIZE (result);
7192 derefaop = aopDerefAop (AOP (left));
7193 freeAsmop (left, NULL, ic, TRUE);
7194 derefaop->size = size;
7199 transferAopAop (derefaop, size, AOP (result), size);
7201 loadRegFromAop (hc08_reg_a, derefaop, size);
7204 freeAsmop (NULL, derefaop, ic, TRUE);
7205 freeAsmop (result, NULL, ic, TRUE);
7207 if (ifx && !ifx->generated)
7209 genIfxJump (ifx, "a");
7214 /*-----------------------------------------------------------------*/
7215 /* genPointerGet - generate code for pointer get */
7216 /*-----------------------------------------------------------------*/
7218 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7220 operand *left = IC_LEFT (ic);
7221 operand *result = IC_RESULT (ic);
7223 sym_link *retype = getSpec (operandType (result));
7225 D(emitcode ("; genPointerGet",""));
7227 if (getSize (operandType (result))>1)
7230 aopOp (left, ic, FALSE);
7232 /* if left is rematerialisable and
7233 result is not bit variable type */
7234 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7236 if (!IS_BITVAR (retype))
7238 genDataPointerGet (left, result, ic, ifx);
7243 genUnpackBitsImmed (left, result, ic, ifx);
7248 /* if the operand is already in hx
7249 then we do nothing else we move the value to hx */
7250 if (AOP_TYPE (left) != AOP_STR)
7252 /* if this is remateriazable */
7253 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7256 /* so hx now contains the address */
7257 aopOp (result, ic, FALSE);
7259 /* if bit then unpack */
7260 if (IS_BITVAR (retype))
7261 genUnpackBits (result, ifx);
7264 size = AOP_SIZE (result);
7269 accopWithMisc ("lda", ",x");
7272 emitcode ("aix", "#1");
7273 hc08_dirtyReg (hc08_reg_hx, FALSE);
7276 storeRegToAop (hc08_reg_a, AOP (result), offset);
7278 hc08_freeReg (hc08_reg_a);
7282 freeAsmop (left, NULL, ic, TRUE);
7283 freeAsmop (result, NULL, ic, TRUE);
7286 aopOp (IC_RESULT (pi), pi, FALSE);
7287 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7288 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7292 if (ifx && !ifx->generated)
7294 genIfxJump (ifx, "a");
7297 hc08_freeReg (hc08_reg_hx);
7301 /*-----------------------------------------------------------------*/
7302 /* genPackBits - generates code for packed bit storage */
7303 /*-----------------------------------------------------------------*/
7305 genPackBits (sym_link * etype,
7308 int offset = 0; /* source byte offset */
7309 int rlen = 0; /* remaining bitfield length */
7310 int blen; /* bitfield length */
7311 int bstr; /* bitfield starting bit within byte */
7312 int litval; /* source literal value (if AOP_LIT) */
7313 unsigned char mask; /* bitmask within current byte */
7316 D(emitcode ("; genPackBits",""));
7318 blen = SPEC_BLEN (etype);
7319 bstr = SPEC_BSTR (etype);
7321 /* If the bitfield length is less than a byte */
7324 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7325 (unsigned char) (0xFF >> (8 - bstr)));
7327 if (AOP_TYPE (right) == AOP_LIT)
7329 /* Case with a bitfield length <8 and literal source
7331 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7333 litval &= (~mask) & 0xff;
7335 emitcode ("lda", ",x");
7336 if ((mask|litval)!=0xff)
7337 emitcode ("and","#0x%02x", mask);
7339 emitcode ("ora","#0x%02x", litval);
7340 hc08_dirtyReg (hc08_reg_a, FALSE);
7341 emitcode ("sta", ",x");
7343 hc08_freeReg (hc08_reg_a);
7347 /* Case with a bitfield length < 8 and arbitrary source
7349 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7350 /* shift and mask source value */
7352 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7353 hc08_dirtyReg (hc08_reg_a, FALSE);
7354 pushReg (hc08_reg_a, TRUE);
7356 emitcode ("lda", ",x");
7357 emitcode ("and", "#0x%02x", mask);
7358 emitcode ("ora", "1,s");
7359 emitcode ("sta", ",x");
7360 pullReg (hc08_reg_a);
7362 hc08_freeReg (hc08_reg_a);
7366 /* Bit length is greater than 7 bits. In this case, copy */
7367 /* all except the partial byte at the end */
7368 for (rlen=blen;rlen>=8;rlen-=8)
7370 if (AOP (right)->type == AOP_DIR)
7372 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7377 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7378 emitcode ("sta", "%d,x", offset);
7383 /* If there was a partial byte at the end */
7386 mask = (((unsigned char) -1 << rlen) & 0xff);
7388 if (AOP_TYPE (right) == AOP_LIT)
7390 /* Case with partial byte and literal source
7392 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7393 litval >>= (blen-rlen);
7394 litval &= (~mask) & 0xff;
7395 emitcode ("lda", "%d,x", offset - xoffset);
7396 hc08_dirtyReg (hc08_reg_a, FALSE);
7397 if ((mask|litval)!=0xff)
7398 emitcode ("and","#0x%02x", mask);
7400 emitcode ("ora","#0x%02x", litval);
7401 emitcode ("sta", "%d,x", offset - xoffset);
7402 hc08_dirtyReg (hc08_reg_a, FALSE);
7403 hc08_freeReg (hc08_reg_a);
7407 /* Case with partial byte and arbitrary source
7409 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7410 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7411 hc08_dirtyReg (hc08_reg_a, FALSE);
7412 pushReg (hc08_reg_a, TRUE);
7414 emitcode ("lda", "%d,x", offset - xoffset);
7415 emitcode ("and", "#0x%02x", mask);
7416 emitcode ("ora", "1,s");
7417 emitcode ("sta", "%d,x", offset - xoffset);
7418 pullReg (hc08_reg_a);
7421 hc08_freeReg (hc08_reg_a);
7424 /*-----------------------------------------------------------------*/
7425 /* genPackBitsImmed - generates code for packed bit storage */
7426 /*-----------------------------------------------------------------*/
7428 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7432 int offset = 0; /* source byte offset */
7433 int rlen = 0; /* remaining bitfield length */
7434 int blen; /* bitfield length */
7435 int bstr; /* bitfield starting bit within byte */
7436 int litval; /* source literal value (if AOP_LIT) */
7437 unsigned char mask; /* bitmask within current byte */
7439 D(emitcode ("; genPackBitsImmed",""));
7441 blen = SPEC_BLEN (etype);
7442 bstr = SPEC_BSTR (etype);
7444 aopOp (right, ic, FALSE);
7445 size = AOP_SIZE (right);
7447 derefaop = aopDerefAop (AOP (result));
7448 freeAsmop (result, NULL, ic, TRUE);
7449 derefaop->size = size;
7451 /* if the bitfield is a single bit in the direct page */
7452 if (blen == 1 && derefaop->type == AOP_DIR)
7454 if (AOP_TYPE (right) == AOP_LIT)
7456 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7458 emitcode ((litval & 1) ? "bset" : "bclr",
7459 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7463 symbol *tlbl1 = newiTempLabel (NULL);
7464 symbol *tlbl2 = newiTempLabel (NULL);
7466 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7467 emitcode ("bit", "#1");
7468 emitBranch ("bne", tlbl1);
7469 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7470 emitBranch ("bra", tlbl2);
7472 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7474 hc08_freeReg (hc08_reg_a);
7479 /* If the bitfield length is less than a byte */
7482 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7483 (unsigned char) (0xFF >> (8 - bstr)));
7485 if (AOP_TYPE (right) == AOP_LIT)
7487 /* Case with a bitfield length <8 and literal source
7489 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7491 litval &= (~mask) & 0xff;
7493 loadRegFromAop (hc08_reg_a, derefaop, 0);
7494 if ((mask|litval)!=0xff)
7495 emitcode ("and","#0x%02x", mask);
7497 emitcode ("ora","#0x%02x", litval);
7498 hc08_dirtyReg (hc08_reg_a, FALSE);
7499 storeRegToAop (hc08_reg_a, derefaop, 0);
7501 hc08_freeReg (hc08_reg_a);
7505 /* Case with a bitfield length < 8 and arbitrary source
7507 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7508 /* shift and mask source value */
7510 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7511 hc08_dirtyReg (hc08_reg_a, FALSE);
7512 pushReg (hc08_reg_a, TRUE);
7514 loadRegFromAop (hc08_reg_a, derefaop, 0);
7515 emitcode ("and", "#0x%02x", mask);
7516 emitcode ("ora", "1,s");
7517 storeRegToAop (hc08_reg_a, derefaop, 0);
7518 pullReg (hc08_reg_a);
7520 hc08_freeReg (hc08_reg_a);
7524 /* Bit length is greater than 7 bits. In this case, copy */
7525 /* all except the partial byte at the end */
7526 for (rlen=blen;rlen>=8;rlen-=8)
7528 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7532 /* If there was a partial byte at the end */
7535 mask = (((unsigned char) -1 << rlen) & 0xff);
7537 if (AOP_TYPE (right) == AOP_LIT)
7539 /* Case with partial byte and literal source
7541 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7542 litval >>= (blen-rlen);
7543 litval &= (~mask) & 0xff;
7544 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7545 if ((mask|litval)!=0xff)
7546 emitcode ("and","#0x%02x", mask);
7548 emitcode ("ora","#0x%02x", litval);
7549 hc08_dirtyReg (hc08_reg_a, FALSE);
7550 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7551 hc08_dirtyReg (hc08_reg_a, FALSE);
7552 hc08_freeReg (hc08_reg_a);
7556 /* Case with partial byte and arbitrary source
7558 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7559 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7560 hc08_dirtyReg (hc08_reg_a, FALSE);
7561 pushReg (hc08_reg_a, TRUE);
7563 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7564 emitcode ("and", "#0x%02x", mask);
7565 emitcode ("ora", "1,s");
7566 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7567 pullReg (hc08_reg_a);
7570 hc08_freeReg (hc08_reg_a);
7573 freeAsmop (right, NULL, ic, TRUE);
7574 freeAsmop (NULL, derefaop, ic, TRUE);
7577 /*-----------------------------------------------------------------*/
7578 /* genDataPointerSet - remat pointer to data space */
7579 /*-----------------------------------------------------------------*/
7581 genDataPointerSet (operand * right,
7588 D(emitcode ("; genDataPointerSet",""));
7590 aopOp (right, ic, FALSE);
7591 size = AOP_SIZE (right);
7593 derefaop = aopDerefAop (AOP (result));
7594 freeAsmop (result, NULL, ic, TRUE);
7595 derefaop->size = size;
7599 transferAopAop (AOP (right), size, derefaop, size);
7602 freeAsmop (right, NULL, ic, TRUE);
7603 freeAsmop (NULL, derefaop, ic, TRUE);
7607 /*-----------------------------------------------------------------*/
7608 /* genPointerSet - stores the value into a pointer location */
7609 /*-----------------------------------------------------------------*/
7611 genPointerSet (iCode * ic, iCode *pi)
7613 operand *right = IC_RIGHT (ic);
7614 operand *result = IC_RESULT (ic);
7615 sym_link *type, *etype;
7617 sym_link *retype = getSpec (operandType (right));
7618 sym_link *letype = getSpec (operandType (result));
7620 D(emitcode ("; genPointerSet",""));
7622 type = operandType (result);
7623 etype = getSpec (type);
7625 aopOp (result, ic, FALSE);
7627 /* if the result is rematerializable */
7628 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7630 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7632 genDataPointerSet (right, result, ic);
7637 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7642 /* if the operand is already in hx
7643 then we do nothing else we move the value to hx */
7644 if (AOP_TYPE (result) != AOP_STR)
7646 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7648 /* so hx now contains the address */
7649 aopOp (right, ic, FALSE);
7651 /* if bit then unpack */
7652 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7653 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7656 size = AOP_SIZE (right);
7661 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7662 accopWithMisc ("sta", ",x");
7665 emitcode ("aix", "#1");
7667 hc08_freeReg (hc08_reg_a);
7671 freeAsmop (result, NULL, ic, TRUE);
7672 freeAsmop (right, NULL, ic, TRUE);
7675 aopOp (IC_RESULT (pi), pi, FALSE);
7676 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7677 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7681 hc08_freeReg (hc08_reg_hx);
7685 /*-----------------------------------------------------------------*/
7686 /* genIfx - generate code for Ifx statement */
7687 /*-----------------------------------------------------------------*/
7689 genIfx (iCode * ic, iCode * popIc)
7691 operand *cond = IC_COND (ic);
7694 D(emitcode ("; genIfx",""));
7696 aopOp (cond, ic, FALSE);
7698 /* get the value into acc */
7699 if (AOP_TYPE (cond) != AOP_CRY)
7700 asmopToBool (AOP (cond), FALSE);
7703 /* the result is now in the accumulator */
7704 freeAsmop (cond, NULL, ic, TRUE);
7706 /* if there was something to be popped then do it */
7710 /* if the condition is a bit variable */
7711 if (isbit && IS_ITEMP (cond) &&
7713 genIfxJump (ic, SPIL_LOC (cond)->rname);
7714 else if (isbit && !IS_ITEMP (cond))
7715 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7717 genIfxJump (ic, "a");
7722 /*-----------------------------------------------------------------*/
7723 /* genAddrOf - generates code for address of */
7724 /*-----------------------------------------------------------------*/
7726 genAddrOf (iCode * ic)
7728 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7731 D(emitcode ("; genAddrOf",""));
7733 aopOp (IC_RESULT (ic), ic, FALSE);
7735 /* if the operand is on the stack then we
7736 need to get the stack offset of this
7740 /* if it has an offset then we need to compute
7742 hc08_useReg (hc08_reg_hx);
7743 emitcode ("tsx", "");
7744 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7745 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7746 hc08_freeReg (hc08_reg_hx);
7751 /* object not on stack then we need the name */
7752 size = AOP_SIZE (IC_RESULT (ic));
7757 char s[SDCC_NAME_MAX+10];
7760 sprintf (s, "#%s", sym->rname);
7763 sprintf (s, "#>%s", sym->rname);
7766 sprintf (s, "#(%s >> %d)",
7770 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7774 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7778 /*-----------------------------------------------------------------*/
7779 /* genAssign - generate code for assignment */
7780 /*-----------------------------------------------------------------*/
7782 genAssign (iCode * ic)
7784 operand *result, *right;
7786 // unsigned long lit = 0L;
7788 D(emitcode("; genAssign",""));
7790 result = IC_RESULT (ic);
7791 right = IC_RIGHT (ic);
7793 /* if they are the same */
7794 if (operandsEqu (result, right)) {
7798 aopOp (right, ic, FALSE);
7799 aopOp (result, ic, TRUE);
7801 /* if they are the same registers */
7802 if (sameRegs (AOP (right), AOP (result)))
7805 if ((AOP_TYPE (right) == AOP_LIT)
7806 && (IS_AOP_HX(AOP(result))))
7808 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7813 size = AOP_SIZE (result);
7816 transferAopAop (AOP (right), size, AOP (result), size);
7820 freeAsmop (right, NULL, ic, TRUE);
7821 freeAsmop (result, NULL, ic, TRUE);
7824 /*-----------------------------------------------------------------*/
7825 /* genJumpTab - generates code for jump table */
7826 /*-----------------------------------------------------------------*/
7828 genJumpTab (iCode * ic)
7831 symbol *jtablo = newiTempLabel (NULL);
7832 symbol *jtabhi = newiTempLabel (NULL);
7834 D(emitcode ("; genJumpTab",""));
7836 aopOp (IC_JTCOND (ic), ic, FALSE);
7838 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7840 /* get the condition into x */
7841 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7842 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7843 loadRegFromConst (hc08_reg_h, zero);
7845 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7846 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7847 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7848 emitcode ("jmp", ",x");
7850 hc08_dirtyReg (hc08_reg_a, TRUE);
7851 hc08_dirtyReg (hc08_reg_hx, TRUE);
7856 pushReg(hc08_reg_hx, TRUE);
7858 /* get the condition into x */
7859 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7860 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7861 loadRegFromConst (hc08_reg_h, zero);
7863 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7864 emitcode ("sta", "3,s");
7865 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7866 emitcode ("sta", "4,s");
7868 pullReg(hc08_reg_hx);
7869 emitcode ("rts", "");
7870 _G.stackPushes += 2;
7874 /* now generate the jump labels */
7876 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7877 jtab = setNextItem (IC_JTLABELS (ic)))
7878 emitcode (".db", "%05d$", jtab->key + 100);
7880 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7881 jtab = setNextItem (IC_JTLABELS (ic)))
7882 emitcode (".db", ">%05d$", jtab->key + 100);
7886 /*-----------------------------------------------------------------*/
7887 /* genCast - gen code for casting */
7888 /*-----------------------------------------------------------------*/
7890 genCast (iCode * ic)
7892 operand *result = IC_RESULT (ic);
7893 sym_link *ctype = operandType (IC_LEFT (ic));
7894 sym_link *rtype = operandType (IC_RIGHT (ic));
7895 operand *right = IC_RIGHT (ic);
7898 D(emitcode("; genCast",""));
7900 /* if they are equivalent then do nothing */
7901 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7904 aopOp (right, ic, FALSE);
7905 aopOp (result, ic, FALSE);
7908 /* if they are the same size : or less */
7909 if (AOP_SIZE (result) <= AOP_SIZE (right))
7912 /* if they are in the same place */
7914 if (sameRegs (AOP (right), AOP (result)))
7918 /* if they in different places then copy */
7919 size = AOP_SIZE (result);
7923 transferAopAop(AOP (right), offset, AOP (result), offset);
7930 /* if the result is of type pointer */
7935 sym_link *type = operandType (right);
7936 sym_link *etype = getSpec (type);
7938 /* pointer to generic pointer */
7939 if (IS_GENPTR (ctype))
7942 p_type = DCL_TYPE (type);
7945 if (SPEC_SCLS(etype)==S_REGISTER) {
7946 // let's assume it is a generic pointer
7949 /* we have to go by the storage class */
7950 p_type = PTR_TYPE (SPEC_OCLS (etype));
7954 /* the first two bytes are known */
7955 size = GPTRSIZE - 1;
7959 transferAopAop(AOP (right), offset, AOP (result), offset);
7962 /* the last byte depending on type */
7965 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7970 // pointerTypeToGPByte will have bitched.
7974 sprintf(gpValStr, "#0x%x", gpVal);
7975 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7981 /* just copy the pointers */
7982 size = AOP_SIZE (result);
7986 transferAopAop(AOP (right), offset, AOP (result), offset);
7992 /* so we now know that the size of destination is greater
7993 than the size of the source */
7994 /* we move to result for the size of source */
7995 size = AOP_SIZE (right);
7999 transferAopAop(AOP (right), offset, AOP (result), offset);
8003 /* now depending on the sign of the source && destination */
8004 size = AOP_SIZE (result) - AOP_SIZE (right);
8005 /* if unsigned or not an integral type */
8006 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8009 storeConstToAop (zero, AOP (result), offset++);
8013 /* we need to extend the sign :{ */
8014 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8015 accopWithMisc ("rola", "");
8016 accopWithMisc ("clra", "");
8017 accopWithMisc ("sbc", zero);
8019 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8022 /* we are done hurray !!!! */
8025 freeAsmop (right, NULL, ic, TRUE);
8026 freeAsmop (result, NULL, ic, TRUE);
8030 /*-----------------------------------------------------------------*/
8031 /* genDjnz - generate decrement & jump if not zero instrucion */
8032 /*-----------------------------------------------------------------*/
8034 genDjnz (iCode * ic, iCode * ifx)
8040 D(emitcode ("; genDjnz",""));
8042 /* if the if condition has a false label
8043 then we cannot save */
8047 /* if the minus is not of the form
8049 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8050 !IS_OP_LITERAL (IC_RIGHT (ic)))
8053 if (operandLitValue (IC_RIGHT (ic)) != 1)
8056 /* dbnz doesn't support extended mode */
8057 if (isOperandInFarSpace (IC_RESULT (ic)))
8060 /* if the size of this greater than one then no
8062 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8064 aopOp (IC_RESULT (ic), ic, FALSE);
8065 if (AOP_SIZE (IC_RESULT (ic))>1)
8067 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8071 /* otherwise we can save BIG */
8072 lbl = newiTempLabel (NULL);
8073 lbl1 = newiTempLabel (NULL);
8076 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8079 emitBranch ("bra", lbl1);
8081 emitBranch ("jmp", IC_TRUE (ifx));
8084 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8089 /*-----------------------------------------------------------------*/
8090 /* genReceive - generate code for a receive iCode */
8091 /*-----------------------------------------------------------------*/
8093 genReceive (iCode * ic)
8097 D(emitcode ("; genReceive",""));
8099 aopOp (IC_RESULT (ic), ic, FALSE);
8100 size = AOP_SIZE (IC_RESULT (ic));
8105 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8106 AOP (IC_RESULT (ic)), offset);
8107 if (hc08_aop_pass[offset]->type == AOP_REG)
8108 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8113 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8116 /*-----------------------------------------------------------------*/
8117 /* genDummyRead - generate code for dummy read of volatiles */
8118 /*-----------------------------------------------------------------*/
8120 genDummyRead (iCode * ic)
8125 D(emitcode("; genDummyRead",""));
8128 if (op && IS_SYMOP (op))
8131 aopOp (op, ic, FALSE);
8133 size = AOP_SIZE (op);
8138 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8139 hc08_freeReg (hc08_reg_a);
8143 freeAsmop (op, NULL, ic, TRUE);
8146 if (op && IS_SYMOP (op))
8149 aopOp (op, ic, FALSE);
8151 size = AOP_SIZE (op);
8156 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8157 hc08_freeReg (hc08_reg_a);
8161 freeAsmop (op, NULL, ic, TRUE);
8165 /*-----------------------------------------------------------------*/
8166 /* genCritical - generate code for start of a critical sequence */
8167 /*-----------------------------------------------------------------*/
8169 genCritical (iCode *ic)
8171 D(emitcode("; genCritical",""));
8174 aopOp (IC_RESULT (ic), ic, TRUE);
8176 emitcode ("tpa", "");
8177 hc08_dirtyReg (hc08_reg_a, FALSE);
8178 emitcode ("sei", "");
8181 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8183 pushReg (hc08_reg_a, FALSE);
8185 hc08_freeReg (hc08_reg_a);
8187 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8190 /*-----------------------------------------------------------------*/
8191 /* genEndCritical - generate code for end of a critical sequence */
8192 /*-----------------------------------------------------------------*/
8194 genEndCritical (iCode *ic)
8196 D(emitcode("; genEndCritical",""));
8200 aopOp (IC_RIGHT (ic), ic, FALSE);
8201 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8202 emitcode ("tap", "");
8203 hc08_freeReg (hc08_reg_a);
8204 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8208 pullReg (hc08_reg_a);
8209 emitcode ("tap", "");
8215 /*-----------------------------------------------------------------*/
8216 /* genhc08Code - generate code for HC08 based controllers */
8217 /*-----------------------------------------------------------------*/
8219 genhc08Code (iCode * lic)
8226 lineHead = lineCurr = NULL;
8228 /* print the allocation information */
8229 if (allocInfo && currFunc)
8230 printAllocInfo (currFunc, codeOutFile);
8231 /* if debug information required */
8232 if (options.debug && currFunc)
8234 debugFile->writeFunction (currFunc, lic);
8237 if (IS_STATIC (currFunc->etype))
8238 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8240 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8244 /* stack pointer name */
8245 if (options.useXstack)
8250 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8252 hc08_aop_pass[0] = newAsmop (AOP_REG);
8253 hc08_aop_pass[0]->size=1;
8254 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8255 hc08_aop_pass[1] = newAsmop (AOP_REG);
8256 hc08_aop_pass[1]->size=1;
8257 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8258 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8259 hc08_aop_pass[2]->size=1;
8260 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8261 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8262 hc08_aop_pass[3]->size=1;
8263 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8265 for (ic = lic; ic; ic = ic->next)
8268 _G.current_iCode = ic;
8270 if (ic->level != clevel || ic->block != cblock)
8274 debugFile->writeScope(ic);
8280 if (ic->lineno && cln != ic->lineno)
8284 debugFile->writeCLine(ic);
8287 emitcode ("", "C$%s$%d$%d$%d ==.",
8288 FileBaseName (ic->filename), ic->lineno,
8289 ic->level, ic->block);
8293 if (!options.noCcodeInAsm) {
8294 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8295 printCLine(ic->filename, ic->lineno));
8299 if (options.iCodeInAsm) {
8303 for (i=0; i<6; i++) {
8304 sprintf (®sInUse[i],
8305 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8308 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8310 /* if the result is marked as
8311 spilt and rematerializable or code for
8312 this has already been generated then
8314 if (resultRemat (ic) || ic->generated)
8322 for (i=A_IDX;i<=XA_IDX;i++)
8324 reg = hc08_regWithIdx(i);
8326 emitcode("","; %s = %s offset %d", reg->name,
8327 aopName(reg->aop), reg->aopofs);
8330 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8332 sym = OP_SYMBOL (IC_LEFT (ic));
8333 if (sym->accuse == ACCUSE_HX)
8335 hc08_reg_h->isFree = FALSE;
8336 hc08_reg_x->isFree = FALSE;
8338 else if (sym->accuse == ACCUSE_XA)
8340 hc08_reg_a->isFree = FALSE;
8342 hc08_reg_x->isFree = FALSE;
8345 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8347 sym = OP_SYMBOL (IC_RIGHT (ic));
8348 if (sym->accuse == ACCUSE_HX)
8350 hc08_reg_h->isFree = FALSE;
8351 hc08_reg_x->isFree = FALSE;
8353 else if (sym->accuse == ACCUSE_XA)
8355 hc08_reg_a->isFree = FALSE;
8357 hc08_reg_x->isFree = FALSE;
8362 /* depending on the operation */
8382 /* IPOP happens only when trying to restore a
8383 spilt live range, if there is an ifx statement
8384 following this pop then the if statement might
8385 be using some of the registers being popped which
8386 would destory the contents of the register so
8387 we need to check for this condition and handle it */
8389 ic->next->op == IFX &&
8390 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8391 genIfx (ic->next, ic);
8409 genEndFunction (ic);
8425 if (!genPointerGetSetOfs (ic))
8430 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8450 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8455 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8467 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8471 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8475 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8502 case GET_VALUE_AT_ADDRESS:
8504 hasInc (IC_LEFT (ic), ic,
8505 getSize (operandType (IC_RESULT (ic)))),
8506 ifxForOp (IC_RESULT (ic), ic) );
8510 if (POINTER_SET (ic))
8511 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8537 addSet (&_G.sendSet, ic);
8540 case DUMMY_READ_VOLATILE:
8549 genEndCritical (ic);
8560 if (!hc08_reg_a->isFree)
8561 D(emitcode("","; forgot to free a"));
8562 if (!hc08_reg_x->isFree)
8563 D(emitcode("","; forgot to free x"));
8564 if (!hc08_reg_h->isFree)
8565 D(emitcode("","; forgot to free h"));
8566 if (!hc08_reg_hx->isFree)
8567 D(emitcode("","; forgot to free hx"));
8568 if (!hc08_reg_xa->isFree)
8569 D(emitcode("","; forgot to free xa"));
8572 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8575 /* now we are ready to call the
8576 peep hole optimizer */
8577 if (!options.nopeep)
8578 peepHole (&lineHead);
8580 /* now do the actual printing */
8581 printLine (lineHead, codeOutFile);