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)
843 if (aop->type == AOP_CRY) /* This can only happen if IFX was optimized */
844 return; /* away, so just toss the result */
849 if ((aop->type == AOP_REG) && (loffset < aop->size))
850 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
852 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
855 if ((aop->type == AOP_REG) && (loffset < aop->size))
856 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
858 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
861 if (hc08_reg_a->isFree)
863 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
864 storeRegToAop (hc08_reg_a, aop, loffset);
865 hc08_freeReg (hc08_reg_a);
867 else if (hc08_reg_x->isFree)
869 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
870 storeRegToAop (hc08_reg_x, aop, loffset);
871 hc08_freeReg (hc08_reg_x);
875 pushReg (hc08_reg_a, TRUE);
876 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
877 storeRegToAop (hc08_reg_a, aop, loffset);
878 pullReg (hc08_reg_a);
882 if ((aop->type == AOP_DIR) )
884 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
886 else if (IS_AOP_XA(aop))
887 transferRegReg(reg, hc08_reg_xa, FALSE);
888 else if (IS_AOP_HX(aop))
893 needpula = pushRegIfUsed (hc08_reg_a);
894 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
895 storeRegToAop (hc08_reg_a, aop, loffset+1);
896 storeRegToAop (hc08_reg_x, aop, loffset);
897 pullOrFreeReg (hc08_reg_a, needpula);
902 transferRegReg(reg, hc08_reg_hx, FALSE);
903 else if (IS_AOP_XA(aop))
907 storeRegToAop (hc08_reg_a, aop, loffset);
908 storeRegToAop (hc08_reg_x, aop, loffset+1);
913 /* Disable the register tracking for now */
915 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
918 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
920 otherreg=hc08_regWithIdx(otheridx);
921 if (otherreg && otherreg->aop
922 && otherreg->aop->op && aop->op
923 && operandsEqu(otherreg->aop->op,aop->op)
924 && (otherreg->aopofs == loffset))
926 D(emitcode("","; marking %s stale", otherreg->name));
930 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
932 hc08_reg_hx->aop = NULL;
933 D(emitcode("","; marking hx stale"));
935 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
937 hc08_reg_xa->aop = NULL;
938 D(emitcode("","; marking xa stale"));
942 reg->aopofs = loffset;
947 /*--------------------------------------------------------------------------*/
948 /* loadRegFromConst - Load register reg from constant c. */
949 /*--------------------------------------------------------------------------*/
951 loadRegFromConst (regs *reg, char *c)
957 emitcode ("clra", "");
959 emitcode ("lda", "%s", c);
963 emitcode ("clrx", "");
965 emitcode ("ldx", "%s", c);
969 emitcode ("clrh", "");
970 else if (hc08_reg_a->isFree)
972 loadRegFromConst (hc08_reg_a, c);
973 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
975 else if (hc08_reg_x->isFree)
977 loadRegFromConst (hc08_reg_x, c);
978 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
982 pushReg (hc08_reg_a, TRUE);
983 loadRegFromConst (hc08_reg_a, c);
984 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
985 pullReg (hc08_reg_a);
989 emitcode ("ldhx", "%s", c);
992 emitcode ("lda", "%s", c);
993 emitcode ("ldx", "%s >> 8", c);
996 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
997 "Bad rIdx in loadRegFromConst");
1004 /*--------------------------------------------------------------------------*/
1005 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
1006 /*--------------------------------------------------------------------------*/
1008 storeConstToAop (char *c, asmop *aop, int loffset)
1010 if (aop->stacked && aop->stk_aop[loffset])
1012 storeConstToAop (c, aop->stk_aop[loffset], 0);
1019 if (!strcmp(c,zero))
1020 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
1022 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
1025 if (loffset>(aop->size-1))
1027 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
1032 if (hc08_reg_a->isFree)
1034 loadRegFromConst (hc08_reg_a, c);
1035 storeRegToAop( hc08_reg_a, aop, loffset);
1036 hc08_freeReg (hc08_reg_a);
1038 else if (hc08_reg_x->isFree)
1040 loadRegFromConst (hc08_reg_x, c);
1041 storeRegToAop( hc08_reg_x, aop, loffset);
1042 hc08_freeReg (hc08_reg_x);
1046 pushReg (hc08_reg_a, TRUE);
1047 loadRegFromConst (hc08_reg_a, c);
1048 storeRegToAop( hc08_reg_a, aop, loffset);
1049 pullReg (hc08_reg_a);
1055 /*--------------------------------------------------------------------------*/
1056 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
1057 /* reg is extended to fill logical offsets loffset */
1058 /* and above of asmop aop. Otherwise, logical */
1059 /* offsets loffset and above of asmop aop are */
1060 /* zeroed. reg must be an 8-bit register. */
1061 /*--------------------------------------------------------------------------*/
1063 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
1065 // int regidx = reg->rIdx;
1066 int size = aop->size;
1074 while (loffset<size)
1075 storeConstToAop(zero, aop, loffset++);
1080 transferRegReg (reg, hc08_reg_a, FALSE);
1081 emitcode ("rola","");
1082 emitcode ("clra","");
1083 emitcode ("sbc", "#0");
1084 hc08_useReg (hc08_reg_a);
1085 while (loffset<size)
1086 storeRegToAop (hc08_reg_a, aop, loffset++);
1087 hc08_freeReg (hc08_reg_a);
1091 /*--------------------------------------------------------------------------*/
1092 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1093 /* padding and/or truncation as needed. If isSigned is */
1094 /* true, sign extension will take place in the padding. */
1095 /*--------------------------------------------------------------------------*/
1097 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1099 int regidx = reg->rIdx;
1100 int size = aop->size;
1107 storeRegToAop (reg, aop, 0);
1108 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1113 storeRegToAop (hc08_reg_x, aop, 0);
1117 storeRegToAop (reg, aop, 0);
1118 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1124 storeRegToAop (hc08_reg_a, aop, 0);
1128 storeRegToAop (reg, aop, 0);
1129 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1135 /*--------------------------------------------------------------------------*/
1136 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1137 /* srcaop to logical offset dstofs of asmop dstaop. */
1138 /*--------------------------------------------------------------------------*/
1140 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1142 bool needpula = FALSE;
1145 bool keepreg = FALSE;
1147 /* ignore transfers at the same byte, unless its volatile */
1148 if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
1149 && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
1150 && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs
1151 && dstaop->type == srcaop->type)
1154 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1156 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1160 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1162 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1166 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1167 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1168 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1169 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1171 if (dstofs >= dstaop->size)
1174 if ((dstaop->type == AOP_DIR)
1175 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1177 if (srcaop->type == AOP_LIT)
1180 unsigned long bytemask;
1182 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1183 bytemask = (lit >> (srcofs*8)) & 0xff;
1187 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1192 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1193 aopAdrStr(dstaop, dstofs, FALSE));
1197 if (dstaop->type == AOP_REG)
1199 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1200 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1202 reg = dstaop->aopu.aop_reg[dstofs];
1207 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1209 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1210 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1212 reg = srcaop->aopu.aop_reg[srcofs];
1219 if (hc08_reg_a->isFree)
1221 else if (hc08_reg_x->isFree)
1225 pushReg (hc08_reg_a, TRUE);
1231 loadRegFromAop (reg, srcaop, srcofs);
1232 storeRegToAop (reg, dstaop, dstofs);
1235 pullOrFreeReg (hc08_reg_a, needpula);
1239 /*--------------------------------------------------------------------------*/
1240 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1241 /* parameter param. */
1242 /*--------------------------------------------------------------------------*/
1244 accopWithMisc (char *accop, char *param)
1246 emitcode (accop, "%s", param);
1247 hc08_dirtyReg (hc08_reg_a, FALSE);
1250 /*--------------------------------------------------------------------------*/
1251 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1252 /* byte at logical offset loffset of asmop aop. */
1253 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1254 /*--------------------------------------------------------------------------*/
1256 accopWithAop (char *accop, asmop *aop, int loffset)
1258 if (aop->stacked && aop->stk_aop[loffset])
1260 accopWithAop (accop, aop->stk_aop[loffset], 0);
1264 if (aop->type == AOP_DUMMY)
1267 if (aop->type == AOP_REG)
1269 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1270 emitcode (accop, "1,s");
1274 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1276 hc08_dirtyReg (hc08_reg_a, FALSE);
1280 /*--------------------------------------------------------------------------*/
1281 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1282 /* byte at logical offset loffset of asmop aop. Register reg */
1283 /* must be 8-bit. */
1284 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1285 /*--------------------------------------------------------------------------*/
1287 rmwWithReg (char *rmwop, regs *reg)
1290 char *rmwaop = rmwbuf;
1292 if (reg->rIdx == A_IDX)
1294 sprintf(rmwaop,"%sa", rmwop);
1295 emitcode (rmwaop, "");
1296 hc08_dirtyReg (hc08_reg_a, FALSE);
1298 else if (reg->rIdx == X_IDX)
1300 sprintf(rmwaop,"%sx", rmwop);
1301 emitcode (rmwaop, "");
1302 hc08_dirtyReg (hc08_reg_a, FALSE);
1304 else if (hc08_reg_a->isFree)
1306 transferRegReg(reg, hc08_reg_a, FALSE);
1307 sprintf(rmwaop,"%sa", rmwop);
1308 emitcode (rmwaop, "");
1309 hc08_dirtyReg (hc08_reg_a, FALSE);
1310 transferRegReg(hc08_reg_a, reg, TRUE);
1314 pushReg (reg, FALSE);
1315 emitcode (rmwop, "1,s");
1317 hc08_dirtyReg (reg, FALSE);
1321 /*--------------------------------------------------------------------------*/
1322 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1323 /* logical offset loffset of asmop aop. */
1324 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1325 /*--------------------------------------------------------------------------*/
1327 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1329 bool needpula = FALSE;
1331 if (aop->stacked && aop->stk_aop[loffset])
1333 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1340 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1343 needpula = pushRegIfUsed (hc08_reg_a);
1344 loadRegFromAop (hc08_reg_a, aop, loffset);
1345 rmwWithReg (rmwop, hc08_reg_a);
1346 if (strcmp ("tst", rmwop))
1347 storeRegToAop (hc08_reg_a, aop, loffset);
1348 pullOrFreeReg (hc08_reg_a, needpula);
1353 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1359 /*-----------------------------------------------------------------*/
1360 /* newAsmop - creates a new asmOp */
1361 /*-----------------------------------------------------------------*/
1363 newAsmop (short type)
1367 aop = Safe_calloc (1, sizeof (asmop));
1374 /*-----------------------------------------------------------------*/
1375 /* pointerCode - returns the code for a pointer type */
1376 /*-----------------------------------------------------------------*/
1378 pointerCode (sym_link * etype)
1381 return PTR_TYPE (SPEC_OCLS (etype));
1386 /*-----------------------------------------------------------------*/
1387 /* aopForSym - for a true symbol */
1388 /*-----------------------------------------------------------------*/
1390 aopForSym (iCode * ic, symbol * sym, bool result)
1395 wassertl (ic != NULL, "Got a null iCode");
1396 wassertl (sym != NULL, "Got a null symbol");
1398 // printf("in aopForSym for symbol %s\n", sym->name);
1400 space = SPEC_OCLS (sym->etype);
1402 /* if already has one */
1408 /* special case for a function */
1409 if (IS_FUNC (sym->type))
1411 sym->aop = aop = newAsmop (AOP_IMMD);
1412 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1413 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1414 aop->size = FPTRSIZE;
1418 /* if it is in direct space */
1419 if (IN_DIRSPACE (space))
1421 sym->aop = aop = newAsmop (AOP_DIR);
1422 aop->aopu.aop_dir = sym->rname;
1423 aop->size = getSize (sym->type);
1427 /* if it is in far space */
1428 if (IN_FARSPACE (space))
1430 sym->aop = aop = newAsmop (AOP_EXT);
1431 aop->aopu.aop_dir = sym->rname;
1432 aop->size = getSize (sym->type);
1436 if (IN_STACK (sym->etype))
1438 sym->aop = aop = newAsmop (AOP_SOF);
1439 aop->aopu.aop_dir = sym->rname;
1440 aop->size = getSize (sym->type);
1441 aop->aopu.aop_stk = sym->stack;
1447 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1448 "aopForSym should never reach here");
1452 /* if it is in code space */
1453 if (IN_CODESPACE (space))
1459 /*-----------------------------------------------------------------*/
1460 /* aopForRemat - rematerialzes an object */
1461 /*-----------------------------------------------------------------*/
1463 aopForRemat (symbol * sym)
1465 iCode *ic = sym->rematiCode;
1473 val += (int) operandLitValue (IC_RIGHT (ic));
1474 else if (ic->op == '-')
1475 val -= (int) operandLitValue (IC_RIGHT (ic));
1476 else if (IS_CAST_ICODE(ic)) {
1477 sym_link *from_type = operandType(IC_RIGHT(ic));
1478 aop->aopu.aop_immd.from_cast_remat = 1;
1479 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1480 ptr_type = DCL_TYPE(from_type);
1481 if (ptr_type == IPOINTER) {
1488 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1491 if (ic->op == ADDRESS_OF)
1494 sprintf (buffer, "(%s %c 0x%04x)",
1495 OP_SYMBOL (IC_LEFT (ic))->rname,
1496 val >= 0 ? '+' : '-',
1497 abs (val) & 0xffff);
1499 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1501 aop = newAsmop (AOP_IMMD);
1502 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1503 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1504 /* set immd2 field if required */
1505 if (aop->aopu.aop_immd.from_cast_remat)
1507 sprintf(buffer,"#0x%02x",ptr_type);
1508 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1509 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1512 else if (ic->op == '=')
1514 val += (int) operandLitValue (IC_RIGHT (ic));
1516 sprintf (buffer, "0x%04x", val);
1517 aop = newAsmop (AOP_LIT);
1518 aop->aopu.aop_lit = constVal (buffer);
1521 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1522 "unexpected rematerialization");
1529 /*-----------------------------------------------------------------*/
1530 /* regsInCommon - two operands have some registers in common */
1531 /*-----------------------------------------------------------------*/
1533 regsInCommon (operand * op1, operand * op2)
1535 symbol *sym1, *sym2;
1538 /* if they have registers in common */
1539 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1542 sym1 = OP_SYMBOL (op1);
1543 sym2 = OP_SYMBOL (op2);
1545 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1548 for (i = 0; i < sym1->nRegs; i++)
1554 for (j = 0; j < sym2->nRegs; j++)
1559 if (sym2->regs[j] == sym1->regs[i])
1567 /*-----------------------------------------------------------------*/
1568 /* operandsEqu - equivalent */
1569 /*-----------------------------------------------------------------*/
1571 operandsEqu (operand * op1, operand * op2)
1573 symbol *sym1, *sym2;
1575 /* if they not symbols */
1576 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1579 sym1 = OP_SYMBOL (op1);
1580 sym2 = OP_SYMBOL (op2);
1582 /* if both are itemps & one is spilt
1583 and the other is not then false */
1584 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1585 sym1->isspilt != sym2->isspilt)
1588 /* if they are the same */
1592 if (sym1->rname[0] && sym2->rname[0]
1593 && strcmp (sym1->rname, sym2->rname) == 0)
1596 /* if left is a tmp & right is not */
1597 if (IS_ITEMP (op1) &&
1600 (sym1->usl.spillLoc == sym2))
1603 if (IS_ITEMP (op2) &&
1607 (sym2->usl.spillLoc == sym1))
1613 /*-----------------------------------------------------------------*/
1614 /* sameRegs - two asmops have the same registers */
1615 /*-----------------------------------------------------------------*/
1617 sameRegs (asmop * aop1, asmop * aop2)
1624 // if (aop1->size != aop2->size)
1627 if (aop1->type == aop2->type)
1632 for (i = 0; i < aop1->size; i++)
1633 if (aop1->aopu.aop_reg[i] !=
1634 aop2->aopu.aop_reg[i])
1638 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1641 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1648 /*-----------------------------------------------------------------*/
1649 /* aopOp - allocates an asmop for an operand : */
1650 /*-----------------------------------------------------------------*/
1652 aopOp (operand * op, iCode * ic, bool result)
1661 // Is this a pointer set result?
1663 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1667 // printf("checking literal\n");
1668 /* if this a literal */
1669 if (IS_OP_LITERAL (op))
1671 op->aop = aop = newAsmop (AOP_LIT);
1672 aop->aopu.aop_lit = op->operand.valOperand;
1673 aop->size = getSize (operandType (op));
1675 aop->isaddr = op->isaddr;
1679 // printf("checking pre-existing\n");
1680 /* if already has a asmop then continue */
1684 op->aop->isaddr = op->isaddr;
1688 // printf("checking underlying sym\n");
1689 /* if the underlying symbol has a aop */
1690 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1692 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1693 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1694 //op->aop = aop = OP_SYMBOL (op)->aop;
1695 aop->size = getSize( operandType (op));
1696 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1697 //printf (" with size = %d\n", aop->size);
1700 aop->isaddr = op->isaddr;
1701 /* if (aop->isaddr & IS_ITEMP (op))
1703 aop->psize=aop->size;
1704 aop->size = getSize( operandType (op)->next);
1709 // printf("checking true sym\n");
1710 /* if this is a true symbol */
1711 if (IS_TRUE_SYMOP (op))
1713 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1715 aop->isaddr = op->isaddr;
1716 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1717 //printf (" with size = %d\n", aop->size);
1721 /* this is a temporary : this has
1727 e) can be a return use only */
1729 sym = OP_SYMBOL (op);
1731 // printf("checking conditional\n");
1732 /* if the type is a conditional */
1733 if (sym->regType == REG_CND)
1735 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1738 aop->isaddr = op->isaddr;
1742 // printf("checking spilt\n");
1743 /* if it is spilt then two situations
1745 b) has a spill location */
1746 if (sym->isspilt || sym->nRegs == 0)
1749 // printf("checking remat\n");
1750 /* rematerialize it NOW */
1753 sym->aop = op->aop = aop =
1755 aop->size = getSize (sym->type);
1757 aop->isaddr = op->isaddr;
1758 /* if (aop->isaddr & IS_ITEMP (op))
1760 aop->psize=aop->size;
1761 aop->size = getSize( operandType (op)->next);
1766 // printf("checking accuse\n");
1769 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1770 aop->size = getSize (sym->type);
1771 switch (sym->accuse)
1774 aop->aopu.aop_reg[0] = hc08_reg_a;
1775 aop->aopu.aop_reg[1] = hc08_reg_x;
1778 aop->aopu.aop_reg[0] = hc08_reg_x;
1779 aop->aopu.aop_reg[1] = hc08_reg_h;
1783 aop->isaddr = op->isaddr;
1787 // printf("checking ruonly\n");
1793 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1794 aop->size = getSize (sym->type);
1795 for (i = 0; i < fReturnSizeHC08; i++)
1796 aop->aopu.aop_str[i] = fReturn2[i];
1798 aop->isaddr = op->isaddr;
1802 /* else spill location */
1803 if (sym->usl.spillLoc)
1805 asmop *oldAsmOp = NULL;
1807 if (sym->usl.spillLoc->aop
1808 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1810 /* force a new aop if sizes differ */
1811 oldAsmOp = sym->usl.spillLoc->aop;
1812 sym->usl.spillLoc->aop = NULL;
1813 //printf ("forcing new aop\n");
1815 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1816 if (sym->usl.spillLoc->aop->size != getSize (sym->type))
1818 /* Don't reuse the new aop, go with the last one */
1819 sym->usl.spillLoc->aop = oldAsmOp;
1821 aop->size = getSize (sym->type);
1823 aop->isaddr = op->isaddr;
1824 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1825 //printf (" with size = %d\n", aop->size);
1829 /* else must be a dummy iTemp */
1830 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1831 aop->size = getSize (sym->type);
1835 // printf("assuming register\n");
1836 /* must be in a register */
1837 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1838 aop->size = sym->nRegs;
1839 for (i = 0; i < sym->nRegs; i++)
1840 aop->aopu.aop_reg[i] = sym->regs[i];
1842 aop->isaddr = op->isaddr;
1846 /*-----------------------------------------------------------------*/
1847 /* freeAsmop - free up the asmop given to an operand */
1848 /*----------------------------------------------------------------*/
1850 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1872 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1875 for (loffset=0; loffset<aop->size; loffset++)
1876 if (aop->stk_aop[loffset])
1878 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1881 pullNull (stackAdjust);
1885 /* all other cases just dealloc */
1891 OP_SYMBOL (op)->aop = NULL;
1892 /* if the symbol has a spill */
1894 SPIL_LOC (op)->aop = NULL;
1900 /*-----------------------------------------------------------------*/
1901 /* aopDerefAop - treating the aop parameter as a pointer, return */
1902 /* an asmop for the object it references */
1903 /*-----------------------------------------------------------------*/
1905 aopDerefAop (asmop *aop)
1910 asmop *newaop = NULL;
1911 sym_link *type, *etype;
1914 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1918 type = operandType (aop->op);
1919 etype = getSpec (type);
1920 /* if op is of type of pointer then it is simple */
1921 if (IS_PTR (type) && !IS_FUNC (type->next))
1922 p_type = DCL_TYPE (type);
1925 /* we have to go by the storage class */
1926 p_type = PTR_TYPE (SPEC_OCLS (etype));
1935 if (p_type == POINTER)
1936 newaop = newAsmop (AOP_DIR);
1938 newaop = newAsmop (AOP_EXT);
1939 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1942 adr = (int) floatFromVal (aop->aopu.aop_lit);
1943 if (p_type == POINTER)
1948 newaop = newAsmop (AOP_DIR);
1949 sprintf (s, "0x%02x",adr);
1953 newaop = newAsmop (AOP_EXT);
1954 sprintf (s, "0x%04x",adr);
1956 rs = Safe_calloc (1, strlen (s) + 1);
1958 newaop->aopu.aop_dir = rs;
1961 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1962 "unsupported asmop");
1972 /*-----------------------------------------------------------------*/
1973 /* aopAdrStr - for referencing the address of the aop */
1974 /*-----------------------------------------------------------------*/
1976 aopAdrStr (asmop * aop, int loffset, bool bit16)
1980 int offset = aop->size - 1 - loffset;
1983 /* offset is greater than
1985 if (loffset > (aop->size - 1) &&
1986 aop->type != AOP_LIT)
1989 /* depending on type */
1997 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1998 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
2000 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
2004 sprintf (s, "#(%s >> %d)",
2005 aop->aopu.aop_immd.aop_immd1,
2009 aop->aopu.aop_immd.aop_immd1);
2013 aop->aopu.aop_immd.aop_immd1);
2014 rs = Safe_calloc (1, strlen (s) + 1);
2020 sprintf (s, "*(%s + %d)",
2024 sprintf (s, "*%s", aop->aopu.aop_dir);
2025 rs = Safe_calloc (1, strlen (s) + 1);
2031 sprintf (s, "(%s + %d)",
2035 sprintf (s, "%s", aop->aopu.aop_dir);
2036 rs = Safe_calloc (1, strlen (s) + 1);
2041 return aop->aopu.aop_reg[loffset]->name;
2045 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2047 return aopLiteral (aop->aopu.aop_lit, loffset);
2051 return aop->aopu.aop_str[loffset];
2054 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2056 rs = Safe_calloc (1, strlen (s) + 1);
2062 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2063 "aopAdrStr got unsupported aop->type");
2072 /*-----------------------------------------------------------------*/
2073 /* opIsGptr: returns non-zero if the passed operand is */
2074 /* a generic pointer type. */
2075 /*-----------------------------------------------------------------*/
2077 opIsGptr (operand * op)
2079 sym_link *type = operandType (op);
2081 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2089 /*-----------------------------------------------------------------*/
2090 /* getDataSize - get the operand data size */
2091 /*-----------------------------------------------------------------*/
2093 getDataSize (operand * op)
2096 size = AOP_SIZE (op);
2101 /*-----------------------------------------------------------------*/
2102 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2103 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2104 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2105 /*-----------------------------------------------------------------*/
2107 asmopToBool (asmop *aop, bool resultInA)
2109 symbol *tlbl, *tlbl1;
2110 int size = aop->size;
2111 bool needpula = FALSE;
2112 bool flagsonly = TRUE;
2117 hc08_freeReg(hc08_reg_a);
2124 emitcode ("tsta", "");
2127 else if (IS_AOP_X(aop))
2128 emitcode ("tstx", "");
2129 else if (IS_AOP_H(aop))
2131 if (hc08_reg_a->isFree)
2133 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2134 emitcode ("tsta", "");
2136 hc08_freeReg(hc08_reg_a);
2138 else if (hc08_reg_x->isFree)
2140 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2141 emitcode ("tstx", "");
2142 hc08_freeReg(hc08_reg_x);
2146 emitcode ("pshh", "");
2147 emitcode ("tst", "1,s");
2148 emitcode ("ais", "#1");
2151 else if (IS_AOP_HX(aop))
2152 emitcode ("cphx", zero);
2153 else if (IS_AOP_XA(aop))
2155 symbol *tlbl = newiTempLabel (NULL);
2156 emitcode ("tsta", "");
2157 emitcode ("bne", "%05d$", (tlbl->key + 100));
2158 emitcode ("tstx", "");
2159 emitcode ("", "%05d$:", (tlbl->key + 100));
2163 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2164 "Bad rIdx in asmToBool");
2172 needpula = pushRegIfUsed (hc08_reg_a);
2173 loadRegFromAop (hc08_reg_a, aop, 0);
2174 for (offset=1; offset<size; offset++)
2175 accopWithAop ("ora", aop, offset);
2177 pullReg (hc08_reg_a);
2180 hc08_freeReg (hc08_reg_a);
2185 /* Higher levels should optimize this case away but let's be safe */
2186 if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
2187 loadRegFromConst (hc08_reg_a, one);
2189 loadRegFromConst (hc08_reg_a, zero);
2190 hc08_freeReg(hc08_reg_a);
2197 loadRegFromAop (hc08_reg_a, aop, 0);
2198 hc08_freeReg (hc08_reg_a);
2202 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2207 if (hc08_reg_a->isFree)
2209 loadRegFromAop (hc08_reg_a, aop, 0);
2210 accopWithAop ("ora", aop, 1);
2211 hc08_freeReg (hc08_reg_a);
2216 tlbl = newiTempLabel (NULL);
2217 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2218 emitcode ("bne", "%05d$", (tlbl->key + 100));
2219 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2220 emitcode ("", "%05d$:", (tlbl->key + 100));
2226 needpula = pushRegIfUsed (hc08_reg_a);
2227 loadRegFromAop (hc08_reg_a, aop, 0);
2228 for (offset=1; offset<size; offset++)
2229 accopWithAop ("ora", aop, offset);
2231 pullReg (hc08_reg_a);
2234 hc08_freeReg (hc08_reg_a);
2242 tlbl = newiTempLabel (NULL);
2246 tlbl1 = newiTempLabel (NULL);
2247 emitBranch ("bne", tlbl1);
2248 loadRegFromConst (hc08_reg_a, zero);
2249 emitBranch ("bra", tlbl);
2251 loadRegFromConst (hc08_reg_a, one);
2255 emitBranch ("beq", tlbl);
2256 loadRegFromConst (hc08_reg_a, one);
2259 hc08_useReg (hc08_reg_a);
2265 /*-----------------------------------------------------------------*/
2266 /* genNot - generate code for ! operation */
2267 /*-----------------------------------------------------------------*/
2271 D(emitcode ("; genNot",""));
2273 /* assign asmOps to operand & result */
2274 aopOp (IC_LEFT (ic), ic, FALSE);
2275 aopOp (IC_RESULT (ic), ic, TRUE);
2277 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2278 emitcode ("eor", one);
2279 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2281 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2282 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2286 /*-----------------------------------------------------------------*/
2287 /* genCpl - generate code for complement */
2288 /*-----------------------------------------------------------------*/
2294 regs* reg = hc08_reg_a;
2298 D(emitcode ("; genCpl",""));
2300 /* assign asmOps to operand & result */
2301 aopOp (IC_LEFT (ic), ic, FALSE);
2302 aopOp (IC_RESULT (ic), ic, TRUE);
2304 size = AOP_SIZE (IC_RESULT (ic));
2307 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2308 rmwWithReg ("com", reg);
2310 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2315 /* release the aops */
2316 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2317 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2320 /*-----------------------------------------------------------------*/
2321 /* genUminusFloat - unary minus for floating points */
2322 /*-----------------------------------------------------------------*/
2324 genUminusFloat (operand * op, operand * result)
2326 int size, offset = 0;
2329 D(emitcode ("; genUminusFloat",""));
2331 /* for this we just copy and then flip the bit */
2333 size = AOP_SIZE (op) - 1;
2337 transferAopAop (AOP (op), offset, AOP (result), offset);
2341 needpula = pushRegIfUsed (hc08_reg_a);
2342 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2343 emitcode ("eor", "#0x80");
2344 hc08_useReg (hc08_reg_a);
2345 storeRegToAop (hc08_reg_a, AOP (result), offset);
2346 pullOrFreeReg (hc08_reg_a, needpula);
2349 /*-----------------------------------------------------------------*/
2350 /* genUminus - unary minus code generation */
2351 /*-----------------------------------------------------------------*/
2353 genUminus (iCode * ic)
2356 sym_link *optype, *rtype;
2361 D(emitcode ("; genUminus",""));
2364 aopOp (IC_LEFT (ic), ic, FALSE);
2365 aopOp (IC_RESULT (ic), ic, TRUE);
2367 optype = operandType (IC_LEFT (ic));
2368 rtype = operandType (IC_RESULT (ic));
2370 /* if float then do float stuff */
2371 if (IS_FLOAT (optype))
2373 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2377 /* otherwise subtract from zero */
2378 size = AOP_SIZE (IC_LEFT (ic));
2383 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2384 needpula = pushRegIfUsed (hc08_reg_a);
2387 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2388 emitcode ("nega", "");
2389 hc08_freeReg (hc08_reg_a);
2390 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2391 SPEC_USIGN (operandType (IC_LEFT (ic))));
2392 pullOrFreeReg (hc08_reg_a, needpula);
2396 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2397 result = forceStackedAop (AOP (IC_RESULT (ic)));
2399 result = AOP (IC_RESULT (ic));
2401 needpula = pushRegIfUsed (hc08_reg_a);
2405 loadRegFromConst (hc08_reg_a, zero);
2406 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2407 storeRegToAop (hc08_reg_a, result, offset++);
2410 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2411 SPEC_USIGN (operandType (IC_LEFT (ic))));
2412 pullOrFreeReg (hc08_reg_a, needpula);
2414 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2415 freeAsmop (NULL, result, ic, TRUE);
2421 /* release the aops */
2422 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2423 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2426 /*-----------------------------------------------------------------*/
2427 /* saveRegisters - will look for a call and save the registers */
2428 /*-----------------------------------------------------------------*/
2430 saveRegisters (iCode * lic)
2437 for (ic = lic; ic; ic = ic->next)
2438 if (ic->op == CALL || ic->op == PCALL)
2443 fprintf (stderr, "found parameter push with no function call\n");
2447 /* if the registers have been saved already or don't need to be then
2451 if (IS_SYMOP(IC_LEFT(ic)) &&
2452 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2453 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2456 /* safe the registers in use at this time but skip the
2457 ones for the result */
2458 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2459 hc08_rUmaskForOp (IC_RESULT(ic)));
2462 for (i = 0; i < hc08_nRegs; i++)
2464 if (bitVectBitValue (rsave, i))
2465 pushReg ( hc08_regWithIdx (i), FALSE);
2469 /*-----------------------------------------------------------------*/
2470 /* unsaveRegisters - pop the pushed registers */
2471 /*-----------------------------------------------------------------*/
2473 unsaveRegisters (iCode * ic)
2478 /* restore the registers in use at this time but skip the
2479 ones for the result */
2480 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2481 hc08_rUmaskForOp (IC_RESULT(ic)));
2483 for (i = hc08_nRegs; i >= 0; i--)
2485 if (bitVectBitValue (rsave, i))
2486 pullReg ( hc08_regWithIdx (i));
2492 /*-----------------------------------------------------------------*/
2494 /*-----------------------------------------------------------------*/
2496 pushSide (operand * oper, int size)
2501 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2502 pushReg ( hc08_reg_a, TRUE);
2506 /*-----------------------------------------------------------------*/
2507 /* assignResultValue - */
2508 /*-----------------------------------------------------------------*/
2510 assignResultValue (operand * oper)
2512 int size = AOP_SIZE (oper);
2516 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2517 if (hc08_aop_pass[offset]->type == AOP_REG)
2518 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2525 /*-----------------------------------------------------------------*/
2526 /* genIpush - genrate code for pushing this gets a little complex */
2527 /*-----------------------------------------------------------------*/
2529 genIpush (iCode * ic)
2531 int size, offset = 0;
2534 D(emitcode ("; genIpush",""));
2536 /* if this is not a parm push : ie. it is spill push
2537 and spill push is always done on the local stack */
2541 /* and the item is spilt then do nothing */
2542 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2545 aopOp (IC_LEFT (ic), ic, FALSE);
2546 size = AOP_SIZE (IC_LEFT (ic));
2548 /* push it on the stack */
2551 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2552 pushReg ( hc08_reg_a, TRUE);
2558 /* this is a paramter push: in this case we call
2559 the routine to find the call and save those
2560 registers that need to be saved */
2563 /* then do the push */
2564 aopOp (IC_LEFT (ic), ic, FALSE);
2567 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2568 size = AOP_SIZE (IC_LEFT (ic));
2571 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2572 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2574 if ((size==2) && hc08_reg_hx->isFree)
2576 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2577 pushReg (hc08_reg_hx, TRUE);
2584 // printf("loading %d\n", offset);
2585 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2586 // printf("pushing \n");
2587 pushReg (hc08_reg_a, TRUE);
2591 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2594 /*-----------------------------------------------------------------*/
2595 /* genIpop - recover the registers: can happen only for spilling */
2596 /*-----------------------------------------------------------------*/
2598 genIpop (iCode * ic)
2602 D(emitcode ("; genIpop",""));
2604 /* if the temp was not pushed then */
2605 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2608 aopOp (IC_LEFT (ic), ic, FALSE);
2609 size = AOP_SIZE (IC_LEFT (ic));
2613 pullReg (hc08_reg_a);
2614 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2616 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2620 /*-----------------------------------------------------------------*/
2621 /* genSend - gen code for SEND */
2622 /*-----------------------------------------------------------------*/
2623 static void genSend(set *sendSet)
2627 for (sic = setFirstItem (sendSet); sic;
2628 sic = setNextItem (sendSet)) {
2629 int size, offset = 0;
2630 aopOp (IC_LEFT (sic), sic, FALSE);
2631 size = AOP_SIZE (IC_LEFT (sic));
2636 transferAopAop( AOP (IC_LEFT (sic)), offset,
2637 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2641 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2645 /*-----------------------------------------------------------------*/
2646 /* genCall - generates a call statement */
2647 /*-----------------------------------------------------------------*/
2649 genCall (iCode * ic)
2652 // bool restoreBank = FALSE;
2653 // bool swapBanks = FALSE;
2655 D(emitcode("; genCall",""));
2657 dtype = operandType (IC_LEFT (ic));
2658 /* if send set is not empty then assign */
2661 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2662 genSend(reverseSet(_G.sendSet));
2664 genSend(_G.sendSet);
2670 /* if caller saves & we have not saved then */
2676 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2677 OP_SYMBOL (IC_LEFT (ic))->rname :
2678 OP_SYMBOL (IC_LEFT (ic))->name));
2681 /* if we need assign a result value */
2682 if ((IS_ITEMP (IC_RESULT (ic)) &&
2683 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2684 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2685 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2686 IS_TRUE_SYMOP (IC_RESULT (ic)))
2690 aopOp (IC_RESULT (ic), ic, FALSE);
2693 assignResultValue (IC_RESULT (ic));
2695 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2698 /* adjust the stack for parameters if
2702 pullNull (ic->parmBytes);
2705 /* if we had saved some registers then unsave them */
2706 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2707 unsaveRegisters (ic);
2711 /*-----------------------------------------------------------------*/
2712 /* -10l - generates a call by pointer statement */
2713 /*-----------------------------------------------------------------*/
2715 genPcall (iCode * ic)
2718 symbol *rlbl = newiTempLabel (NULL);
2719 symbol *tlbl = newiTempLabel (NULL);
2720 // bool restoreBank=FALSE;
2721 // bool swapBanks = FALSE;
2723 D(emitcode("; genPCall",""));
2725 /* if caller saves & we have not saved then */
2729 /* if we are calling a not _naked function that is not using
2730 the same register bank then we need to save the
2731 destination registers on the stack */
2732 dtype = operandType (IC_LEFT (ic))->next;
2734 /* now push the calling address */
2735 emitBranch ("bsr", tlbl);
2736 emitBranch ("bra", rlbl);
2738 _G.stackPushes += 2; /* account for the bsr return address now on stack */
2741 /* Push the function's address */
2742 aopOp (IC_LEFT (ic), ic, FALSE);
2743 pushSide (IC_LEFT (ic), FPTRSIZE);
2744 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2746 /* if send set is not empty the assign */
2749 genSend(reverseSet(_G.sendSet));
2755 emitcode ("rts", "");
2758 _G.stackPushes -= 4; /* account for rts here & in called function */
2762 /* if we need assign a result value */
2763 if ((IS_ITEMP (IC_RESULT (ic)) &&
2764 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2765 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2766 IS_TRUE_SYMOP (IC_RESULT (ic)))
2770 aopOp (IC_RESULT (ic), ic, FALSE);
2773 assignResultValue (IC_RESULT (ic));
2775 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2778 /* adjust the stack for parameters if
2782 pullNull (ic->parmBytes);
2785 /* if we hade saved some registers then
2787 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2788 unsaveRegisters (ic);
2791 /*-----------------------------------------------------------------*/
2792 /* resultRemat - result is rematerializable */
2793 /*-----------------------------------------------------------------*/
2795 resultRemat (iCode * ic)
2797 if (SKIP_IC (ic) || ic->op == IFX)
2800 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2802 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2803 if (sym->remat && !POINTER_SET (ic))
2810 #if defined(__BORLANDC__) || defined(_MSC_VER)
2811 #define STRCASECMP stricmp
2813 #define STRCASECMP strcasecmp
2816 /*-----------------------------------------------------------------*/
2817 /* inExcludeList - return 1 if the string is in exclude Reg list */
2818 /*-----------------------------------------------------------------*/
2820 regsCmp(void *p1, void *p2)
2822 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2826 inExcludeList (char *s)
2828 const char *p = setFirstItem(options.excludeRegsSet);
2830 if (p == NULL || STRCASECMP(p, "none") == 0)
2834 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2837 /*-----------------------------------------------------------------*/
2838 /* genFunction - generated code for function entry */
2839 /*-----------------------------------------------------------------*/
2841 genFunction (iCode * ic)
2843 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2845 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2846 int stackAdjust = sym->stack;
2847 int accIsFree = sym->recvSize == 0;
2851 /* create the function header */
2852 emitcode (";", "-----------------------------------------");
2853 emitcode (";", " function %s", sym->name);
2854 emitcode (";", "-----------------------------------------");
2856 emitcode ("", "%s:", sym->rname);
2857 ftype = operandType (IC_LEFT (ic));
2861 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2863 if (IFFUNC_ISNAKED(ftype))
2865 emitcode(";", "naked function: no prologue.");
2869 /* if this is an interrupt service routine then
2871 if (IFFUNC_ISISR (sym->type))
2874 if (!inExcludeList ("h"))
2875 pushReg (hc08_reg_h, FALSE);
2878 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2879 /* before setting up the stack frame completely. */
2880 while (ric && ric->next && ric->next->op == RECEIVE)
2882 while (ric && IC_RESULT (ric))
2884 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2885 int rsymSize = rsym ? getSize(rsym->type) : 0;
2889 if (rsym && rsym->regType == REG_CND)
2891 if (rsym && (rsym->accuse || rsym->ruonly))
2893 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2894 rsym = rsym->usl.spillLoc;
2897 /* If the RECEIVE operand immediately spills to the first entry on the */
2898 /* stack, we can push it directly rather than use an sp relative store. */
2899 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2903 _G.current_iCode = ric;
2904 D(emitcode ("; genReceive",""));
2905 for (ofs=0; ofs < rsymSize; ofs++)
2907 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2908 pushReg (reg, TRUE);
2909 if (reg->rIdx == A_IDX)
2913 _G.current_iCode = ic;
2916 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2919 /* adjust the stack for the function */
2922 adjustStack (-stackAdjust);
2924 _G.stackOfs = sym->stack;
2927 /* if critical function then turn interrupts off */
2928 if (IFFUNC_ISCRITICAL (ftype))
2932 /* Function was passed parameters, so make sure A is preserved */
2933 pushReg (hc08_reg_a, FALSE);
2934 pushReg (hc08_reg_a, FALSE);
2935 emitcode ("tpa", "");
2936 emitcode ("sta", "2,s");
2937 emitcode ("sei", "");
2938 pullReg (hc08_reg_a);
2942 /* No passed parameters, so A can be freely modified */
2943 emitcode ("tpa", "");
2944 pushReg (hc08_reg_a, TRUE);
2945 emitcode ("sei", "");
2951 /*-----------------------------------------------------------------*/
2952 /* genEndFunction - generates epilogue for functions */
2953 /*-----------------------------------------------------------------*/
2955 genEndFunction (iCode * ic)
2957 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2959 if (IFFUNC_ISNAKED(sym->type))
2961 emitcode(";", "naked function: no epilogue.");
2962 if (options.debug && currFunc)
2963 debugFile->writeEndFunction (currFunc, ic, 0);
2967 if (IFFUNC_ISCRITICAL (sym->type))
2969 if (!IS_VOID(sym->type->next))
2971 /* Function has return value, so make sure A is preserved */
2972 pushReg (hc08_reg_a, FALSE);
2973 emitcode ("lda", "2,s");
2974 emitcode ("tap", "");
2975 pullReg (hc08_reg_a);
2980 /* Function returns void, so A can be freely modified */
2981 pullReg (hc08_reg_a);
2982 emitcode ("tap", "");
2986 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2992 _G.stackPushes += sym->stack;
2993 adjustStack (sym->stack);
2997 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
3001 if (IFFUNC_ISISR (sym->type))
3004 if (!inExcludeList ("h"))
3005 pullReg (hc08_reg_h);
3008 /* if debug then send end of function */
3009 if (options.debug && currFunc)
3011 debugFile->writeEndFunction (currFunc, ic, 1);
3014 emitcode ("rti", "");
3018 if (IFFUNC_CALLEESAVES(sym->type))
3022 /* if any registers used */
3025 /* save the registers used */
3026 for (i = sym->regsUsed->size; i >= 0; i--)
3028 if (bitVectBitValue (sym->regsUsed, i) ||
3029 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3030 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3036 /* if debug then send end of function */
3037 if (options.debug && currFunc)
3039 debugFile->writeEndFunction (currFunc, ic, 1);
3042 emitcode ("rts", "");
3047 /*-----------------------------------------------------------------*/
3048 /* genRet - generate code for return statement */
3049 /*-----------------------------------------------------------------*/
3053 int size, offset = 0;
3056 D(emitcode ("; genRet",""));
3058 /* if we have no return value then
3059 just generate the "ret" */
3063 /* we have something to return then
3064 move the return value into place */
3065 aopOp (IC_LEFT (ic), ic, FALSE);
3066 size = AOP_SIZE (IC_LEFT (ic));
3072 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3079 /* 4 byte return: store value in the global return variable */
3083 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3084 STA (fReturn2[offset--], FALSE);
3085 hc08_freeReg (hc08_reg_a);
3089 /* 2 byte return: store value in x:a */
3090 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3091 hc08_freeReg (hc08_reg_xa);
3094 /* 1 byte return: store value in a */
3095 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3096 hc08_freeReg (hc08_reg_a);
3101 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3104 /* generate a jump to the return label
3105 if the next is not the return statement */
3106 if (!(ic->next && ic->next->op == LABEL &&
3107 IC_LABEL (ic->next) == returnLabel))
3109 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3113 /*-----------------------------------------------------------------*/
3114 /* genLabel - generates a label */
3115 /*-----------------------------------------------------------------*/
3117 genLabel (iCode * ic)
3122 /* For the high level labels we cannot depend on any */
3123 /* register's contents. Amnesia time. */
3124 for (i=A_IDX;i<=XA_IDX;i++)
3126 reg = hc08_regWithIdx(i);
3131 /* special case never generate */
3132 if (IC_LABEL (ic) == entryLabel)
3135 debugFile->writeLabel(IC_LABEL (ic), ic);
3137 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3141 /*-----------------------------------------------------------------*/
3142 /* genGoto - generates a jmp */
3143 /*-----------------------------------------------------------------*/
3145 genGoto (iCode * ic)
3147 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3151 /*-----------------------------------------------------------------*/
3152 /* findLabelBackwards: walks back through the iCode chain looking */
3153 /* for the given label. Returns number of iCode instructions */
3154 /* between that label and given ic. */
3155 /* Returns zero if label not found. */
3156 /*-----------------------------------------------------------------*/
3158 findLabelBackwards (iCode * ic, int key)
3167 /* If we have any pushes or pops, we cannot predict the distance.
3168 I don't like this at all, this should be dealt with in the
3170 if (ic->op == IPUSH || ic->op == IPOP) {
3174 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3184 /*-----------------------------------------------------------------*/
3185 /* genPlusIncr :- does addition with increment if possible */
3186 /*-----------------------------------------------------------------*/
3188 genPlusIncr (iCode * ic)
3196 unsigned int size = getDataSize (IC_RESULT (ic));
3197 unsigned int offset;
3198 symbol *tlbl = NULL;
3200 left = IC_LEFT (ic);
3201 result = IC_RESULT (ic);
3203 /* will try to generate an increment */
3204 /* if the right side is not a literal
3206 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3209 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3211 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3213 if ((IS_AOP_HX (AOP (left)) ||
3214 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3216 && (icount>=-128) && (icount<=127) && (size==2))
3218 if (!IS_AOP_HX (AOP (left)))
3220 needpulx = pushRegIfUsed (hc08_reg_x);
3221 needpulh = pushRegIfUsed (hc08_reg_h);
3228 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3229 emitcode ("aix","#%d", icount);
3230 hc08_dirtyReg (hc08_reg_hx, FALSE);
3231 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3232 pullOrFreeReg (hc08_reg_h, needpulh);
3233 pullOrFreeReg (hc08_reg_x, needpulx);
3237 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3238 sameRegs (AOP (left), AOP (result))));
3240 if ((icount > 255) || (icount<0))
3243 if (!sameRegs (AOP (left), AOP (result)))
3246 D(emitcode ("; genPlusIncr",""));
3249 tlbl = newiTempLabel (NULL);
3254 rmwWithAop ("inc", AOP (result), 0);
3256 emitBranch ("bne", tlbl);
3260 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3261 needpula = pushRegIfUsed (hc08_reg_a);
3264 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3265 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3266 hc08_useReg (hc08_reg_a);
3267 storeRegToAop (hc08_reg_a, AOP (result), 0);
3268 hc08_freeReg (hc08_reg_a);
3270 emitBranch ("bcc", tlbl);
3272 for (offset=1; offset<size; offset++)
3274 rmwWithAop ("inc", AOP (result), offset);
3275 if ((offset+1)<size)
3276 emitBranch ("bne", tlbl);
3282 pullOrFreeReg (hc08_reg_a, needpula);
3289 /*-----------------------------------------------------------------*/
3290 /* genPlus - generates code for addition */
3291 /*-----------------------------------------------------------------*/
3293 genPlus (iCode * ic)
3295 int size, offset = 0;
3297 asmop *leftOp, *rightOp;
3299 /* special cases :- */
3301 D(emitcode ("; genPlus",""));
3303 aopOp (IC_LEFT (ic), ic, FALSE);
3304 aopOp (IC_RIGHT (ic), ic, FALSE);
3305 aopOp (IC_RESULT (ic), ic, TRUE);
3307 /* we want registers on the left and literals on the right */
3308 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3309 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3311 operand *t = IC_RIGHT (ic);
3312 IC_RIGHT (ic) = IC_LEFT (ic);
3317 /* if I can do an increment instead
3318 of add then GOOD for ME */
3319 if (genPlusIncr (ic) == TRUE)
3322 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3323 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3324 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3326 size = getDataSize (IC_RESULT (ic));
3328 leftOp = AOP(IC_LEFT(ic));
3329 rightOp = AOP(IC_RIGHT(ic));
3335 loadRegFromAop (hc08_reg_a, leftOp, offset);
3336 accopWithAop(add, rightOp, offset);
3337 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3338 hc08_freeReg (hc08_reg_a);
3339 add = "adc"; /* further adds must propagate carry */
3343 // adjustArithmeticResult (ic);
3346 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3347 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3348 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3351 /*-----------------------------------------------------------------*/
3352 /* genMinusDec :- does subtraction with decrement if possible */
3353 /*-----------------------------------------------------------------*/
3355 genMinusDec (iCode * ic)
3357 unsigned int icount;
3362 unsigned int size = getDataSize (IC_RESULT (ic));
3366 left = IC_LEFT (ic);
3367 result = IC_RESULT (ic);
3369 /* will try to generate an increment */
3370 /* if the right side is not a literal
3372 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3375 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3377 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3378 && (icount>=-127) && (icount<=128) && (size==2))
3380 if (!IS_AOP_HX (AOP (left)))
3382 needpulx = pushRegIfUsed (hc08_reg_x);
3383 needpulh = pushRegIfUsed (hc08_reg_h);
3390 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3391 emitcode ("aix","#%d", -icount);
3392 hc08_dirtyReg (hc08_reg_hx, FALSE);
3393 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3394 pullOrFreeReg (hc08_reg_h, needpulh);
3395 pullOrFreeReg (hc08_reg_x, needpulx);
3399 if ((icount > 1) || (icount<0))
3402 if (!sameRegs (AOP (left), AOP (result)))
3408 D(emitcode ("; genMinusDec",""));
3410 rmwWithAop ("dec", AOP (result), 0);
3415 /*-----------------------------------------------------------------*/
3416 /* addSign - complete with sign */
3417 /*-----------------------------------------------------------------*/
3419 addSign (operand * result, int offset, int sign)
3421 int size = (getDataSize (result) - offset);
3426 emitcode ("rola", "");
3427 emitcode ("clra", "");
3428 emitcode ("sbc", zero);
3430 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3434 storeConstToAop (zero, AOP (result), offset++);
3439 /*-----------------------------------------------------------------*/
3440 /* genMinus - generates code for subtraction */
3441 /*-----------------------------------------------------------------*/
3443 genMinus (iCode * ic)
3446 int size, offset = 0;
3448 asmop *leftOp, *rightOp;
3450 D(emitcode ("; genMinus",""));
3452 aopOp (IC_LEFT (ic), ic, FALSE);
3453 aopOp (IC_RIGHT (ic), ic, FALSE);
3454 aopOp (IC_RESULT (ic), ic, TRUE);
3456 /* special cases :- */
3457 /* if I can do an decrement instead
3458 of subtract then GOOD for ME */
3459 if (genMinusDec (ic) == TRUE)
3462 size = getDataSize (IC_RESULT (ic));
3465 leftOp = AOP(IC_LEFT(ic));
3466 rightOp = AOP(IC_RIGHT(ic));
3470 if (IS_AOP_A (rightOp))
3472 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3473 accopWithAop (sub, leftOp, offset);
3474 accopWithMisc ("nega", "");
3475 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3481 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3482 accopWithAop (sub, rightOp, offset);
3483 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3488 // adjustArithmeticResult (ic);
3491 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3492 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3493 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3498 /*-----------------------------------------------------------------*/
3499 /* genMultOneByte : 8*8=8/16 bit multiplication */
3500 /*-----------------------------------------------------------------*/
3502 genMultOneByte (operand * left,
3506 /* sym_link *opetype = operandType (result); */
3507 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3508 int size=AOP_SIZE(result);
3509 bool negLiteral = FALSE;
3510 bool lUnsigned, rUnsigned;
3512 D(emitcode ("; genMultOneByte",""));
3514 if (size<1 || size>2) {
3515 // this should never happen
3516 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3517 AOP_SIZE(result), __FILE__, lineno);
3521 /* (if two literals: the value is computed before) */
3522 /* if one literal, literal on the right */
3523 if (AOP_TYPE (left) == AOP_LIT)
3529 /* if an operand is in A, make sure it is on the left */
3530 if (IS_AOP_A (AOP (right)))
3537 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3538 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3540 /* lUnsigned rUnsigned negLiteral negate case */
3541 /* false false false odd 3 */
3542 /* false false true even 3 */
3543 /* false true false odd 3 */
3544 /* false true true impossible */
3545 /* true false false odd 3 */
3546 /* true false true always 2 */
3547 /* true true false never 1 */
3548 /* true true true impossible */
3552 || (lUnsigned && rUnsigned))
3554 // just an unsigned 8*8=8/16 multiply
3555 //D(emitcode (";","unsigned"));
3557 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3558 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3559 emitcode ("mul", "");
3560 hc08_dirtyReg (hc08_reg_xa, FALSE);
3561 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3562 hc08_freeReg (hc08_reg_xa);
3567 // we have to do a signed multiply
3570 /* left unsigned, right signed literal -- literal determines sign handling */
3571 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3573 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3575 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3577 emitcode ("ldx", "#0x%02x", -val);
3579 emitcode ("ldx", "#0x%02x", val);
3581 emitcode ("mul", "");
3585 rmwWithReg ("neg", hc08_reg_a);
3586 tlbl4 = newiTempLabel (NULL);
3587 emitBranch ("bcc", tlbl4);
3588 rmwWithReg ("inc", hc08_reg_x);
3590 rmwWithReg ("neg", hc08_reg_x);
3593 hc08_dirtyReg (hc08_reg_xa, FALSE);
3594 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3595 hc08_freeReg (hc08_reg_xa);
3602 emitcode ("clr", "1,s");
3604 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3607 tlbl1 = newiTempLabel (NULL);
3608 emitcode ("tsta","");
3609 emitBranch ("bpl", tlbl1);
3610 emitcode ("inc", "1,s");
3611 rmwWithReg ("neg", hc08_reg_a);
3615 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3617 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3618 /* AND literal negative */
3620 emitcode ("ldx", "#0x%02x", -val);
3623 emitcode ("ldx", "#0x%02x", val);
3625 hc08_useReg (hc08_reg_x);
3629 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3632 tlbl2 = newiTempLabel (NULL);
3633 emitcode ("tstx", "");
3634 emitBranch ("bpl", tlbl2);
3635 emitcode ("inc", "1,s");
3636 rmwWithReg ("neg", hc08_reg_x);
3641 emitcode ("mul", "");
3642 hc08_dirtyReg (hc08_reg_xa, FALSE);
3644 tlbl3 = newiTempLabel (NULL);
3645 emitcode ("dec", "1,s");
3646 if (!lUnsigned && !rUnsigned && negLiteral)
3647 emitBranch ("beq", tlbl3);
3649 emitBranch ("bne", tlbl3);
3651 rmwWithReg ("neg", hc08_reg_a);
3652 tlbl4 = newiTempLabel (NULL);
3653 emitBranch ("bcc", tlbl4);
3654 rmwWithReg ("inc", hc08_reg_x);
3656 rmwWithReg ("neg", hc08_reg_x);
3660 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3661 hc08_freeReg (hc08_reg_xa);
3665 /*-----------------------------------------------------------------*/
3666 /* genMult - generates code for multiplication */
3667 /*-----------------------------------------------------------------*/
3669 genMult (iCode * ic)
3671 operand *left = IC_LEFT (ic);
3672 operand *right = IC_RIGHT (ic);
3673 operand *result = IC_RESULT (ic);
3675 D(emitcode ("; genMult",""));
3677 /* assign the amsops */
3678 aopOp (left, ic, FALSE);
3679 aopOp (right, ic, FALSE);
3680 aopOp (result, ic, TRUE);
3682 /* special cases first */
3683 /* if both are of size == 1 */
3684 // if (getSize(operandType(left)) == 1 &&
3685 // getSize(operandType(right)) == 1)
3686 if (AOP_SIZE (left) == 1 &&
3687 AOP_SIZE (right) == 1)
3689 genMultOneByte (left, right, result);
3693 /* should have been converted to function call */
3694 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3695 getSize(OP_SYMBOL(right)->type));
3696 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3701 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3702 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3703 freeAsmop (result, NULL, ic, TRUE);
3706 /*-----------------------------------------------------------------*/
3707 /* genDivOneByte : 8 bit division */
3708 /*-----------------------------------------------------------------*/
3710 genDivOneByte (operand * left,
3714 symbol *tlbl1, *tlbl2, *tlbl3;
3717 bool lUnsigned, rUnsigned;
3718 bool runtimeSign, compiletimeSign;
3720 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3721 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3723 D(emitcode ("; genDivOneByte",""));
3725 size = AOP_SIZE (result);
3726 /* signed or unsigned */
3727 if (lUnsigned && rUnsigned)
3729 /* unsigned is easy */
3730 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3731 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3732 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3733 emitcode ("div", "");
3734 hc08_dirtyReg (hc08_reg_a, FALSE);
3735 hc08_dirtyReg (hc08_reg_h, FALSE);
3736 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3737 hc08_freeReg (hc08_reg_a);
3738 hc08_freeReg (hc08_reg_x);
3739 hc08_freeReg (hc08_reg_h);
3743 /* signed is a little bit more difficult */
3745 /* now sign adjust for both left & right */
3747 /* let's see what's needed: */
3748 /* apply negative sign during runtime */
3749 runtimeSign = FALSE;
3750 /* negative sign from literals */
3751 compiletimeSign = FALSE;
3755 if (AOP_TYPE(left) == AOP_LIT)
3757 /* signed literal */
3758 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3760 compiletimeSign = TRUE;
3763 /* signed but not literal */
3769 if (AOP_TYPE(right) == AOP_LIT)
3771 /* signed literal */
3772 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3774 compiletimeSign ^= TRUE;
3777 /* signed but not literal */
3781 /* initialize the runtime sign */
3784 if (compiletimeSign)
3785 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3787 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3788 pushReg (hc08_reg_x, TRUE);
3791 /* save the signs of the operands */
3792 if (AOP_TYPE(right) == AOP_LIT)
3794 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3796 if (!rUnsigned && val < 0)
3797 emitcode ("ldx", "#0x%02x", -val);
3799 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3801 else /* ! literal */
3803 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3806 tlbl1 = newiTempLabel (NULL);
3807 emitcode ("tstx", "");
3808 emitBranch ("bpl", tlbl1);
3809 emitcode ("inc", "1,s");
3810 rmwWithReg ("neg", hc08_reg_x);
3815 if (AOP_TYPE(left) == AOP_LIT)
3817 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3819 if (!lUnsigned && val < 0)
3820 emitcode ("lda", "#0x%02x", -val);
3822 emitcode ("lda", "#0x%02x", (unsigned char) val);
3824 else /* ! literal */
3826 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3829 tlbl2 = newiTempLabel (NULL);
3830 emitcode ("tsta", "");
3831 emitBranch ("bpl", tlbl2);
3832 emitcode ("inc", "1,s");
3833 rmwWithReg ("neg", hc08_reg_a);
3838 loadRegFromConst (hc08_reg_h, zero);
3839 emitcode ("div", "");
3840 hc08_dirtyReg (hc08_reg_x, FALSE);
3841 hc08_dirtyReg (hc08_reg_a, FALSE);
3842 hc08_dirtyReg (hc08_reg_h, FALSE);
3844 if (runtimeSign || compiletimeSign)
3846 tlbl3 = newiTempLabel (NULL);
3849 pullReg (hc08_reg_x);
3850 rmwWithReg ("lsr", hc08_reg_x);
3851 rmwWithReg ("ror", hc08_reg_x);
3852 emitBranch ("bpl", tlbl3);
3855 rmwWithReg ("neg", hc08_reg_a);
3859 storeRegToAop (hc08_reg_a, AOP (result), 0);
3863 /* msb is 0x00 or 0xff depending on the sign */
3866 rmwWithReg ("lsl", hc08_reg_x);
3867 emitcode ("clra", "");
3868 emitcode ("sbc", "#0");
3870 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3872 else /* compiletimeSign */
3874 storeConstToAop ("#0xff", AOP (result), ++offset);
3879 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3882 hc08_freeReg (hc08_reg_a);
3883 hc08_freeReg (hc08_reg_x);
3884 hc08_freeReg (hc08_reg_h);
3887 /*-----------------------------------------------------------------*/
3888 /* genDiv - generates code for division */
3889 /*-----------------------------------------------------------------*/
3893 operand *left = IC_LEFT (ic);
3894 operand *right = IC_RIGHT (ic);
3895 operand *result = IC_RESULT (ic);
3897 D(emitcode ("; genDiv",""));
3899 /* assign the amsops */
3900 aopOp (left, ic, FALSE);
3901 aopOp (right, ic, FALSE);
3902 aopOp (result, ic, TRUE);
3904 /* special cases first */
3905 /* if both are of size == 1 */
3906 if (AOP_SIZE (left) <= 2 &&
3907 AOP_SIZE (right) == 1)
3909 genDivOneByte (left, right, result);
3913 /* should have been converted to function call */
3916 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3917 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3918 freeAsmop (result, NULL, ic, TRUE);
3921 /*-----------------------------------------------------------------*/
3922 /* genModOneByte : 8 bit modulus */
3923 /*-----------------------------------------------------------------*/
3925 genModOneByte (operand * left,
3929 symbol *tlbl1, *tlbl2, *tlbl3;
3932 bool lUnsigned, rUnsigned;
3933 bool runtimeSign, compiletimeSign;
3935 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3936 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3938 D(emitcode ("; genModOneByte",""));
3940 size = AOP_SIZE (result);
3942 if (lUnsigned && rUnsigned)
3944 /* unsigned is easy */
3945 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3946 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3947 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3948 emitcode ("div", "");
3949 hc08_freeReg (hc08_reg_a);
3950 hc08_freeReg (hc08_reg_x);
3951 hc08_dirtyReg (hc08_reg_h, FALSE);
3952 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3953 hc08_freeReg (hc08_reg_h);
3957 /* signed is a little bit more difficult */
3959 if (AOP_TYPE(right) == AOP_LIT)
3961 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3963 if (!rUnsigned && val < 0)
3964 emitcode ("ldx", "#0x%02x", -val);
3966 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3968 else /* ! literal */
3970 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3973 tlbl1 = newiTempLabel (NULL);
3974 emitcode ("tstx", "");
3975 emitBranch ("bpl", tlbl1);
3976 rmwWithReg ("neg", hc08_reg_x);
3981 /* let's see what's needed: */
3982 /* apply negative sign during runtime */
3983 runtimeSign = FALSE;
3984 /* negative sign from literals */
3985 compiletimeSign = FALSE;
3987 /* sign adjust left side */
3988 if (AOP_TYPE(left) == AOP_LIT)
3990 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3992 if (!lUnsigned && val < 0)
3994 compiletimeSign = TRUE; /* set sign flag */
3995 emitcode ("lda", "#0x%02x", -val);
3998 emitcode ("lda", "#0x%02x", (unsigned char) val);
4000 else /* ! literal */
4003 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4008 emitcode ("clr", "1,s");
4010 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4011 tlbl2 = newiTempLabel (NULL);
4012 emitcode ("tsta", "");
4013 emitBranch ("bpl", tlbl2);
4014 emitcode ("inc", "1,s");
4015 rmwWithReg ("neg", hc08_reg_a);
4020 loadRegFromConst (hc08_reg_h, zero);
4021 emitcode ("div", "");
4022 hc08_freeReg (hc08_reg_a);
4023 hc08_freeReg (hc08_reg_x);
4024 hc08_dirtyReg (hc08_reg_h, FALSE);
4026 if (runtimeSign || compiletimeSign)
4028 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4029 tlbl3 = newiTempLabel (NULL);
4032 pullReg (hc08_reg_x);
4033 rmwWithReg ("lsr", hc08_reg_x);
4034 rmwWithReg ("ror", hc08_reg_x);
4035 emitBranch ("bpl", tlbl3);
4038 rmwWithReg ("neg", hc08_reg_a);
4042 storeRegToAop (hc08_reg_a, AOP (result), 0);
4046 /* msb is 0x00 or 0xff depending on the sign */
4049 rmwWithReg ("lsl", hc08_reg_x);
4050 emitcode ("clra", "");
4051 emitcode ("sbc", "#0");
4053 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4055 else /* compiletimeSign */
4057 storeConstToAop ("#0xff", AOP (result), ++offset);
4062 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4065 hc08_freeReg (hc08_reg_a);
4066 hc08_freeReg (hc08_reg_x);
4067 hc08_freeReg (hc08_reg_h);
4070 /*-----------------------------------------------------------------*/
4071 /* genMod - generates code for division */
4072 /*-----------------------------------------------------------------*/
4076 operand *left = IC_LEFT (ic);
4077 operand *right = IC_RIGHT (ic);
4078 operand *result = IC_RESULT (ic);
4080 D(emitcode ("; genMod",""));
4082 /* assign the amsops */
4083 aopOp (left, ic, FALSE);
4084 aopOp (right, ic, FALSE);
4085 aopOp (result, ic, TRUE);
4087 /* special cases first */
4088 /* if both are of size == 1 */
4089 if (AOP_SIZE (left) <= 2 &&
4090 AOP_SIZE (right) == 1)
4092 genModOneByte (left, right, result);
4096 /* should have been converted to function call */
4100 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4101 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4102 freeAsmop (result, NULL, ic, TRUE);
4105 /*-----------------------------------------------------------------*/
4106 /* genIfxJump :- will create a jump depending on the ifx */
4107 /*-----------------------------------------------------------------*/
4109 genIfxJump (iCode * ic, char *jval)
4112 symbol *tlbl = newiTempLabel (NULL);
4115 D(emitcode ("; genIfxJump",""));
4117 /* if true label then we jump if condition
4121 jlbl = IC_TRUE (ic);
4122 if (!strcmp (jval, "a"))
4124 else if (!strcmp (jval, "c"))
4131 /* false label is present */
4132 jlbl = IC_FALSE (ic);
4133 if (!strcmp (jval, "a"))
4135 else if (!strcmp (jval, "c"))
4140 emitBranch (inst, tlbl);
4141 emitBranch ("jmp", jlbl);
4144 /* mark the icode as generated */
4149 /*-----------------------------------------------------------------*/
4150 /* exchangedCmp : returns the opcode need if the two operands are */
4151 /* exchanged in a comparison */
4152 /*-----------------------------------------------------------------*/
4154 exchangedCmp (int opcode)
4171 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4172 "opcode not a comparison");
4174 return EQ_OP; /* shouldn't happen, but need to return something */
4177 /*------------------------------------------------------------------*/
4178 /* negatedCmp : returns the equivalent opcode for when a comparison */
4180 /*------------------------------------------------------------------*/
4182 negatedCmp (int opcode)
4199 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4200 "opcode not a comparison");
4202 return EQ_OP; /* shouldn't happen, but need to return something */
4205 /* compile only if the debugging macro D is enabled */
4208 nameCmp (int opcode)
4230 /*------------------------------------------------------------------*/
4231 /* branchInstCmp : returns the conditional branch instruction that */
4232 /* will branch if the comparison is true */
4233 /*------------------------------------------------------------------*/
4235 branchInstCmp (int opcode, int sign)
4243 return "bcs"; /* same as blo */
4258 return "bcc"; /* same as bhs */
4264 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4265 "opcode not a comparison");
4271 /*------------------------------------------------------------------*/
4272 /* genCmp :- greater or less than (and maybe with equal) comparison */
4273 /*------------------------------------------------------------------*/
4275 genCmp (iCode * ic, iCode * ifx)
4277 operand *left, *right, *result;
4278 sym_link *letype, *retype;
4280 int size, offset = 0;
4281 unsigned long lit = 0L;
4283 symbol *jlbl = NULL;
4287 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4289 result = IC_RESULT (ic);
4290 left = IC_LEFT (ic);
4291 right = IC_RIGHT (ic);
4293 letype = getSpec (operandType (left));
4294 retype = getSpec (operandType (right));
4295 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4296 /* assign the amsops */
4297 aopOp (left, ic, FALSE);
4298 aopOp (right, ic, FALSE);
4299 aopOp (result, ic, TRUE);
4301 /* need register operand on left, prefer literal operand on right */
4302 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4304 operand *temp = left;
4307 opcode = exchangedCmp (opcode);
4314 jlbl = IC_TRUE (ifx);
4315 opcode = negatedCmp (opcode);
4319 /* false label is present */
4320 jlbl = IC_FALSE (ifx);
4324 size = max (AOP_SIZE (left), AOP_SIZE (right));
4327 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4328 && ((AOP_TYPE (right) == AOP_LIT) ||
4329 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4330 && hc08_reg_hx->isFree)
4332 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4333 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4334 hc08_freeReg (hc08_reg_hx);
4345 /* These conditions depend on the Z flag bit, but Z is */
4346 /* only valid for the last byte of the comparison, not */
4347 /* the whole value. So exchange the operands to get a */
4348 /* comparison that doesn't depend on Z. (This is safe */
4349 /* to do here since ralloc won't assign multi-byte */
4350 /* operands to registers for comparisons) */
4351 if ((opcode == '>') || (opcode == LE_OP))
4353 operand *temp = left;
4356 opcode = exchangedCmp (opcode);
4359 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4361 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4362 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4371 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4372 accopWithAop (sub, AOP (right), offset);
4373 hc08_freeReg (hc08_reg_a);
4378 freeAsmop (right, NULL, ic, FALSE);
4379 freeAsmop (left, NULL, ic, FALSE);
4383 symbol *tlbl = newiTempLabel (NULL);
4386 freeAsmop (result, NULL, ic, TRUE);
4388 inst = branchInstCmp (opcode, sign);
4389 emitBranch (inst, tlbl);
4390 emitBranch ("jmp", jlbl);
4393 /* mark the icode as generated */
4398 symbol *tlbl1 = newiTempLabel (NULL);
4399 symbol *tlbl2 = newiTempLabel (NULL);
4401 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4402 loadRegFromConst (hc08_reg_a, zero);
4403 emitBranch ("bra", tlbl2);
4405 loadRegFromConst (hc08_reg_a, one);
4407 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4408 freeAsmop (result, NULL, ic, TRUE);
4413 /*-----------------------------------------------------------------*/
4414 /* genCmpEQorNE - equal or not equal comparison */
4415 /*-----------------------------------------------------------------*/
4417 genCmpEQorNE (iCode * ic, iCode * ifx)
4419 operand *left, *right, *result;
4420 sym_link *letype, *retype;
4422 int size, offset = 0;
4424 symbol *jlbl = NULL;
4425 symbol *tlbl_NE = NULL;
4426 symbol *tlbl_EQ = NULL;
4430 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4432 result = IC_RESULT (ic);
4433 left = IC_LEFT (ic);
4434 right = IC_RIGHT (ic);
4436 letype = getSpec (operandType (left));
4437 retype = getSpec (operandType (right));
4438 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4439 /* assign the amsops */
4440 aopOp (left, ic, FALSE);
4441 aopOp (right, ic, FALSE);
4442 aopOp (result, ic, TRUE);
4444 /* need register operand on left, prefer literal operand on right */
4445 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4447 operand *temp = left;
4450 opcode = exchangedCmp (opcode);
4457 jlbl = IC_TRUE (ifx);
4458 opcode = negatedCmp (opcode);
4462 /* false label is present */
4463 jlbl = IC_FALSE (ifx);
4467 size = max (AOP_SIZE (left), AOP_SIZE (right));
4470 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4471 && ((AOP_TYPE (right) == AOP_LIT) ||
4472 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4473 && hc08_reg_hx->isFree)
4475 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4476 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4477 hc08_freeReg (hc08_reg_hx);
4485 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4486 accopWithAop (sub, AOP (right), offset);
4490 tlbl_NE = newiTempLabel (NULL);
4491 emitBranch ("bne", tlbl_NE);
4493 hc08_freeReg (hc08_reg_a);
4497 freeAsmop (right, NULL, ic, FALSE);
4498 freeAsmop (left, NULL, ic, FALSE);
4502 freeAsmop (result, NULL, ic, TRUE);
4504 if (opcode == EQ_OP)
4507 tlbl_EQ = newiTempLabel (NULL);
4508 emitBranch ("beq", tlbl_EQ);
4510 emitLabel (tlbl_NE);
4511 emitBranch ("jmp", jlbl);
4512 emitLabel (tlbl_EQ);
4517 tlbl_NE = newiTempLabel (NULL);
4518 emitBranch ("bne", tlbl_NE);
4519 emitBranch ("jmp", jlbl);
4520 emitLabel (tlbl_NE);
4523 /* mark the icode as generated */
4528 symbol *tlbl = newiTempLabel (NULL);
4530 if (opcode == EQ_OP)
4533 tlbl_EQ = newiTempLabel (NULL);
4534 emitBranch ("beq", tlbl_EQ);
4536 emitLabel (tlbl_NE);
4537 loadRegFromConst (hc08_reg_a, zero);
4538 emitBranch ("bra", tlbl);
4539 emitLabel (tlbl_EQ);
4540 loadRegFromConst (hc08_reg_a, one);
4545 tlbl_NE = newiTempLabel (NULL);
4546 emitBranch ("bne", tlbl_NE);
4547 loadRegFromConst (hc08_reg_a, zero);
4548 emitBranch ("bra", tlbl);
4549 emitLabel (tlbl_NE);
4550 loadRegFromConst (hc08_reg_a, one);
4554 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4555 freeAsmop (result, NULL, ic, TRUE);
4561 /*-----------------------------------------------------------------*/
4562 /* ifxForOp - returns the icode containing the ifx for operand */
4563 /*-----------------------------------------------------------------*/
4565 ifxForOp (operand * op, iCode * ic)
4567 /* if true symbol then needs to be assigned */
4568 if (IS_TRUE_SYMOP (op))
4571 /* if this has register type condition and
4572 the next instruction is ifx with the same operand
4573 and live to of the operand is upto the ifx only then */
4575 ic->next->op == IFX &&
4576 IC_COND (ic->next)->key == op->key &&
4577 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4584 genPointerGetSetOfs (iCode *ic)
4586 iCode *lic = ic->next;
4592 /* Make sure we have a next iCode */
4593 D(emitcode("","; checking lic"));
4597 /* Make sure the result of the addition is an iCode */
4598 D(emitcode("","; checking IS_ITEMP"));
4599 if (!IS_ITEMP (IC_RESULT (ic)))
4602 /* Make sure the next iCode is a pointer set or get */
4603 pset = POINTER_SET(lic);
4604 pget = POINTER_GET(lic);
4605 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4609 /* Make sure this is the only use of the pointer */
4610 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4613 D(emitcode("", "; checking pset operandsEqu"));
4614 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4617 D(emitcode("", "; checking pget operandsEqu"));
4618 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4621 D(emitcode("", "; checking IS_SYMOP"));
4622 if (!IS_SYMOP (IC_LEFT (ic)))
4625 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4626 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4629 sym = OP_SYMBOL (IC_LEFT (ic));
4631 D(emitcode("", "; checking remat"));
4638 D(emitcode ("; genPointerGetOfs",""));
4639 aopOp (IC_LEFT(ic), ic, FALSE);
4640 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4641 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4643 aopOp (IC_RIGHT(ic), ic, FALSE);
4644 aopOp (IC_RESULT(lic), lic, FALSE);
4646 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4648 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4650 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4651 loadRegFromConst (hc08_reg_h, zero);
4655 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4656 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4657 emitcode ("rola","");
4658 emitcode ("clra","");
4659 emitcode ("sbc", "#0");
4660 hc08_useReg (hc08_reg_a);
4661 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4665 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4666 size = AOP_SIZE (IC_RESULT(lic));
4667 derefaop->size = size;
4671 emitcode ("lda", "%s,x",
4672 aopAdrStr (derefaop, size, TRUE));
4673 hc08_useReg (hc08_reg_a);
4674 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4675 hc08_freeReg (hc08_reg_a);
4679 hc08_freeReg (hc08_reg_hx);
4681 freeAsmop (NULL, derefaop, ic, TRUE);
4682 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4683 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4690 D(emitcode ("; genPointerSetOfs",""));
4691 aopOp (IC_LEFT(ic), ic, FALSE);
4692 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4693 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4695 aopOp (IC_RIGHT(ic), ic, FALSE);
4696 aopOp (IC_RIGHT(lic), lic, FALSE);
4698 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4700 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4702 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4703 loadRegFromConst (hc08_reg_h, zero);
4707 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4708 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4709 emitcode ("rola","");
4710 emitcode ("clra","");
4711 emitcode ("sbc", "#0");
4712 hc08_useReg (hc08_reg_a);
4713 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4717 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4718 size = AOP_SIZE (IC_RIGHT(lic));
4719 derefaop->size = size;
4723 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4724 emitcode ("sta", "%s,x",
4725 aopAdrStr (derefaop, size, TRUE));
4726 hc08_freeReg (hc08_reg_a);
4730 hc08_freeReg (hc08_reg_hx);
4732 freeAsmop (NULL, derefaop, ic, TRUE);
4733 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4734 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4743 /*-----------------------------------------------------------------*/
4744 /* hasInc - operand is incremented before any other use */
4745 /*-----------------------------------------------------------------*/
4747 hasInc (operand *op, iCode *ic,int osize)
4749 sym_link *type = operandType(op);
4750 sym_link *retype = getSpec (type);
4751 iCode *lic = ic->next;
4754 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4755 if (!IS_SYMOP(op)) return NULL;
4757 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4758 if (IS_AGGREGATE(type->next)) return NULL;
4759 if (osize != (isize = getSize(type->next))) return NULL;
4762 /* if operand of the form op = op + <sizeof *op> */
4763 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4764 isOperandEqual(IC_RESULT(lic),op) &&
4765 isOperandLiteral(IC_RIGHT(lic)) &&
4766 operandLitValue(IC_RIGHT(lic)) == isize) {
4769 /* if the operand used or deffed */
4770 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4773 /* if GOTO or IFX */
4774 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4780 /*-----------------------------------------------------------------*/
4781 /* genAndOp - for && operation */
4782 /*-----------------------------------------------------------------*/
4784 genAndOp (iCode * ic)
4786 operand *left, *right, *result;
4787 symbol *tlbl, *tlbl0;
4789 D(emitcode ("; genAndOp",""));
4791 /* note here that && operations that are in an
4792 if statement are taken away by backPatchLabels
4793 only those used in arthmetic operations remain */
4794 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4795 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4796 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4798 tlbl = newiTempLabel (NULL);
4799 tlbl0 = newiTempLabel (NULL);
4801 asmopToBool (AOP (left), FALSE);
4802 emitBranch ("beq", tlbl0);
4803 asmopToBool (AOP (right), FALSE);
4804 emitBranch ("beq", tlbl0);
4805 loadRegFromConst (hc08_reg_a,one);
4806 emitBranch ("bra", tlbl);
4808 loadRegFromConst (hc08_reg_a,zero);
4811 hc08_useReg (hc08_reg_a);
4812 hc08_freeReg (hc08_reg_a);
4814 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4816 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4817 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4818 freeAsmop (result, NULL, ic, TRUE);
4822 /*-----------------------------------------------------------------*/
4823 /* genOrOp - for || operation */
4824 /*-----------------------------------------------------------------*/
4826 genOrOp (iCode * ic)
4828 operand *left, *right, *result;
4829 symbol *tlbl, *tlbl0;
4831 D(emitcode ("; genOrOp",""));
4833 /* note here that || operations that are in an
4834 if statement are taken away by backPatchLabels
4835 only those used in arthmetic operations remain */
4836 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4837 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4838 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4840 tlbl = newiTempLabel (NULL);
4841 tlbl0 = newiTempLabel (NULL);
4843 asmopToBool (AOP (left), FALSE);
4844 emitBranch ("bne", tlbl0);
4845 asmopToBool (AOP (right), FALSE);
4846 emitBranch ("bne", tlbl0);
4847 loadRegFromConst (hc08_reg_a,zero);
4848 emitBranch ("bra", tlbl);
4850 loadRegFromConst (hc08_reg_a,one);
4853 hc08_useReg (hc08_reg_a);
4854 hc08_freeReg (hc08_reg_a);
4856 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4859 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4860 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4861 freeAsmop (result, NULL, ic, TRUE);
4864 /*-----------------------------------------------------------------*/
4865 /* isLiteralBit - test if lit == 2^n */
4866 /*-----------------------------------------------------------------*/
4868 isLiteralBit (unsigned long lit)
4870 unsigned long pw[32] =
4871 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4872 0x100L, 0x200L, 0x400L, 0x800L,
4873 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4874 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4875 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4876 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4877 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4880 for (idx = 0; idx < 32; idx++)
4887 /*-----------------------------------------------------------------*/
4888 /* continueIfTrue - */
4889 /*-----------------------------------------------------------------*/
4891 continueIfTrue (iCode * ic)
4894 emitBranch ("jmp", IC_TRUE (ic));
4898 /*-----------------------------------------------------------------*/
4900 /*-----------------------------------------------------------------*/
4902 jumpIfTrue (iCode * ic)
4905 emitBranch ("jmp", IC_FALSE (ic));
4909 /*-----------------------------------------------------------------*/
4910 /* jmpTrueOrFalse - */
4911 /*-----------------------------------------------------------------*/
4913 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4915 // ugly but optimized by peephole
4918 symbol *nlbl = newiTempLabel (NULL);
4919 emitBranch ("bra", nlbl);
4921 emitBranch ("jmp", IC_TRUE (ic));
4926 emitBranch ("jmp", IC_FALSE (ic));
4933 /*-----------------------------------------------------------------*/
4934 /* genAnd - code for and */
4935 /*-----------------------------------------------------------------*/
4937 genAnd (iCode * ic, iCode * ifx)
4939 operand *left, *right, *result;
4940 int size, offset = 0;
4941 unsigned long lit = 0L;
4942 unsigned long litinv;
4943 unsigned char bytemask;
4949 D(emitcode ("; genAnd",""));
4951 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4952 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4953 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4956 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4958 AOP_TYPE (left), AOP_TYPE (right)));
4959 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4961 AOP_SIZE (left), AOP_SIZE (right)));
4964 /* if left is a literal & right is not then exchange them */
4965 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4967 operand *tmp = right;
4972 /* if right is accumulator & left is not then exchange them */
4973 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4975 operand *tmp = right;
4980 if (AOP_TYPE (right) == AOP_LIT)
4981 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4983 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4985 if (AOP_TYPE (result) == AOP_CRY
4987 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
4989 /* this generates ugly code, but meets volatility requirements */
4990 loadRegFromConst (hc08_reg_a, zero);
4991 pushReg (hc08_reg_a, TRUE);
4996 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4997 accopWithAop ("and", AOP (right), offset);
4998 emitcode ("ora", "1,s");
4999 emitcode ("sta", "1,s");
5003 pullReg (hc08_reg_a);
5004 emitcode ("tsta", "");
5005 genIfxJump (ifx, "a");
5009 if (AOP_TYPE (result) == AOP_CRY)
5011 symbol *tlbl = NULL;
5012 wassertl (ifx, "AOP_CRY result without ifx");
5017 bytemask = (lit >> (offset*8)) & 0xff;
5019 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5023 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5025 rmwWithAop ("tst", AOP (left), offset);
5029 tlbl = newiTempLabel (NULL);
5030 emitBranch ("bne", tlbl);
5035 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5036 accopWithAop ("and", AOP (right), offset);
5037 hc08_freeReg( hc08_reg_a);
5041 tlbl = newiTempLabel (NULL);
5042 emitBranch ("bne", tlbl);
5049 genIfxJump (ifx, "a");
5053 size = AOP_SIZE (result);
5055 if (AOP_TYPE (right) == AOP_LIT)
5057 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5058 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5059 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5061 int bitpos = isLiteralBit(litinv)-1;
5062 emitcode ("bclr","#%d,%s",bitpos & 7,
5063 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5071 bytemask = (lit >> (offset*8)) & 0xff;
5073 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5075 if (isOperandVolatile (left, FALSE))
5077 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5078 hc08_freeReg( hc08_reg_a);
5080 storeConstToAop (zero, AOP (result), offset);
5082 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5084 transferAopAop (AOP (left), offset, AOP (result), offset);
5088 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5089 accopWithAop ("and", AOP (right), offset);
5090 storeRegToAop (hc08_reg_a, AOP (result), offset);
5091 hc08_freeReg (hc08_reg_a);
5097 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5098 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5099 freeAsmop (result, NULL, ic, TRUE);
5102 /*-----------------------------------------------------------------*/
5103 /* genOr - code for or */
5104 /*-----------------------------------------------------------------*/
5106 genOr (iCode * ic, iCode * ifx)
5108 operand *left, *right, *result;
5109 int size, offset = 0;
5110 unsigned long lit = 0L;
5111 unsigned char bytemask;
5113 D(emitcode ("; genOr",""));
5115 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5116 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5117 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5120 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5122 AOP_TYPE (left), AOP_TYPE (right)));
5123 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5125 AOP_SIZE (left), AOP_SIZE (right)));
5128 /* if left is a literal & right is not then exchange them */
5129 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5131 operand *tmp = right;
5136 /* if left is accumulator & right is not then exchange them */
5137 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5139 operand *tmp = right;
5144 if (AOP_TYPE (right) == AOP_LIT)
5145 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5147 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5149 if (AOP_TYPE (result) == AOP_CRY
5151 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5153 /* this generates ugly code, but meets volatility requirements */
5154 loadRegFromConst (hc08_reg_a, zero);
5155 pushReg (hc08_reg_a, TRUE);
5160 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5161 accopWithAop ("ora", AOP (right), offset);
5162 emitcode ("ora", "1,s");
5163 emitcode ("sta", "1,s");
5167 pullReg (hc08_reg_a);
5168 emitcode ("tsta", "");
5169 genIfxJump (ifx, "a");
5173 if (AOP_TYPE (result) == AOP_CRY)
5175 symbol *tlbl = NULL;
5176 wassertl (ifx, "AOP_CRY result without ifx");
5181 bytemask = (lit >> (offset*8)) & 0xff;
5183 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5185 rmwWithAop ("tst", AOP (left), offset);
5189 tlbl = newiTempLabel (NULL);
5190 emitBranch ("bne", tlbl);
5195 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5196 accopWithAop ("ora", AOP (right), offset);
5197 hc08_freeReg( hc08_reg_a);
5201 tlbl = newiTempLabel (NULL);
5202 emitBranch ("bne", tlbl);
5209 genIfxJump (ifx, "a");
5212 if (AOP_TYPE (right) == AOP_LIT)
5213 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5215 size = AOP_SIZE (result);
5217 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5218 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5219 (AOP_TYPE (left) == AOP_DIR))
5221 int bitpos = isLiteralBit(lit)-1;
5222 emitcode ("bset","#%d,%s",bitpos & 7,
5223 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5230 bytemask = (lit >> (offset*8)) & 0xff;
5232 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5234 if (isOperandVolatile (left, FALSE))
5236 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5237 hc08_freeReg( hc08_reg_a);
5239 transferAopAop (AOP (right), offset, AOP (result), offset);
5241 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5243 transferAopAop (AOP (left), offset, AOP (result), offset);
5247 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5248 accopWithAop ("ora", AOP (right), offset);
5249 storeRegToAop (hc08_reg_a, AOP (result), offset);
5250 hc08_freeReg (hc08_reg_a);
5257 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5258 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5259 freeAsmop (result, NULL, ic, TRUE);
5262 /*-----------------------------------------------------------------*/
5263 /* genXor - code for xclusive or */
5264 /*-----------------------------------------------------------------*/
5266 genXor (iCode * ic, iCode * ifx)
5268 operand *left, *right, *result;
5269 int size, offset = 0;
5270 unsigned long lit = 0L;
5272 D(emitcode ("; genXor",""));
5274 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5275 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5276 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5279 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5281 AOP_TYPE (left), AOP_TYPE (right)));
5282 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5284 AOP_SIZE (left), AOP_SIZE (right)));
5287 /* if left is a literal & right is not ||
5288 if left needs acc & right does not */
5289 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5291 operand *tmp = right;
5296 /* if left is accumulator & right is not then exchange them */
5297 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5299 operand *tmp = right;
5304 if (AOP_TYPE (result) == AOP_CRY)
5307 wassertl (ifx, "AOP_CPY result without ifx");
5309 tlbl = newiTempLabel (NULL);
5310 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5314 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5315 if ((AOP_TYPE (right) == AOP_LIT)
5316 && (((lit >> (offset*8)) & 0xff) == 0))
5317 emitcode ("tsta","");
5319 accopWithAop ("eor", AOP (right), offset);
5320 hc08_freeReg( hc08_reg_a);
5322 emitBranch ("bne", tlbl);
5326 genIfxJump (ifx, "a");
5332 if (AOP_TYPE (right) == AOP_LIT)
5333 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5335 size = AOP_SIZE (result);
5339 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5340 accopWithAop ("eor", AOP (right), offset);
5341 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5342 hc08_freeReg( hc08_reg_a);
5346 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5347 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5348 freeAsmop (result, NULL, ic, TRUE);
5352 emitinline (iCode * ic, char *inlin)
5358 symbol *sym, *tempsym;
5367 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5371 //printf("Found possible symbol '%s'\n",symname);
5372 tempsym = newSymbol (symname, ic->level);
5373 tempsym->block = ic->block;
5374 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5383 aop = aopForSym (ic, sym, FALSE);
5384 l = aopAdrStr (aop, aop->size - 1, TRUE);
5388 if (sym->level && !sym->allocreq && !sym->ismyparm)
5390 werror (E_ID_UNDEF, sym->name);
5392 " Add 'volatile' to the variable declaration so that it\n"
5393 " can be referenced within inline assembly");
5395 //printf("Replacing with '%s'\n",l);
5399 if ((2+bp-buffer)>sizeof(buffer))
5408 if ((2+bp-buffer)>sizeof(buffer))
5415 if ((2+bp-buffer)>sizeof(buffer))
5416 fprintf(stderr, "Inline assembly buffer overflow\n");
5418 //printf("%s\n",buffer);
5419 emitcode (buffer,"");
5423 /*-----------------------------------------------------------------*/
5424 /* genInline - write the inline code out */
5425 /*-----------------------------------------------------------------*/
5427 genInline (iCode * ic)
5429 char *buffer, *bp, *bp1;
5431 D(emitcode ("; genInline",""));
5433 _G.inLine += (!options.asmpeep);
5435 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5436 strcpy (buffer, IC_INLINE (ic));
5438 /* emit each line as a code */
5444 /* emitcode (bp1, ""); */
5445 emitinline (ic, bp1);
5464 /* emitcode (bp1, ""); */
5465 emitinline (ic, bp1);
5467 /* emitcode("",buffer); */
5468 _G.inLine -= (!options.asmpeep);
5471 /*-----------------------------------------------------------------*/
5472 /* genRRC - rotate right with carry */
5473 /*-----------------------------------------------------------------*/
5477 operand *left, *result;
5478 int size, offset = 0;
5479 bool needpula = FALSE;
5480 bool resultInA = FALSE;
5483 D(emitcode ("; genRRC",""));
5485 /* rotate right with carry */
5486 left = IC_LEFT (ic);
5487 result = IC_RESULT (ic);
5488 aopOp (left, ic, FALSE);
5489 aopOp (result, ic, FALSE);
5491 if ((AOP_TYPE (result) == AOP_REG)
5492 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5495 size = AOP_SIZE (result);
5499 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5503 rmwWithAop (shift, AOP (result), offset--);
5511 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5512 rmwWithReg (shift, hc08_reg_a);
5513 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5514 hc08_freeReg (hc08_reg_a);
5519 if ((!hc08_reg_a->isFree) || resultInA)
5521 pushReg (hc08_reg_a, TRUE);
5525 /* now we need to put the carry into the
5526 highest order byte of the result */
5527 offset = AOP_SIZE (result) - 1;
5528 emitcode ("clra","");
5529 emitcode ("rora","");
5530 hc08_dirtyReg (hc08_reg_a, FALSE);
5533 emitcode ("ora", "1,s");
5534 emitcode ("ais", "#1");
5535 hc08_dirtyReg (hc08_reg_a, FALSE);
5539 accopWithAop ("ora", AOP (result), offset);
5540 storeRegToAop (hc08_reg_a, AOP (result), offset);
5542 pullOrFreeReg (hc08_reg_a, needpula);
5544 freeAsmop (left, NULL, ic, TRUE);
5545 freeAsmop (result, NULL, ic, TRUE);
5548 /*-----------------------------------------------------------------*/
5549 /* genRLC - generate code for rotate left with carry */
5550 /*-----------------------------------------------------------------*/
5554 operand *left, *result;
5555 int size, offset = 0;
5557 bool resultInA = FALSE;
5558 bool needpula = FALSE;
5560 D(emitcode ("; genRLC",""));
5562 /* rotate right with carry */
5563 left = IC_LEFT (ic);
5564 result = IC_RESULT (ic);
5565 aopOp (left, ic, FALSE);
5566 aopOp (result, ic, FALSE);
5568 if ((AOP_TYPE (result) == AOP_REG)
5569 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5572 size = AOP_SIZE (result);
5576 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5580 rmwWithAop (shift, AOP (result), offset--);
5588 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5589 rmwWithReg (shift, hc08_reg_a);
5590 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5591 hc08_freeReg (hc08_reg_a);
5596 if ((!hc08_reg_a->isFree) || resultInA)
5598 pushReg (hc08_reg_a, TRUE);
5602 /* now we need to put the carry into the
5603 lowest order byte of the result */
5605 emitcode ("clra","");
5606 emitcode ("rola","");
5607 hc08_dirtyReg (hc08_reg_a, FALSE);
5610 emitcode ("ora", "1,s");
5611 emitcode ("ais", "#1");
5612 hc08_dirtyReg (hc08_reg_a, FALSE);
5616 accopWithAop ("ora", AOP (result), offset);
5617 storeRegToAop (hc08_reg_a, AOP (result), offset);
5619 pullOrFreeReg (hc08_reg_a, needpula);
5621 freeAsmop (left, NULL, ic, TRUE);
5622 freeAsmop (result, NULL, ic, TRUE);
5625 /*-----------------------------------------------------------------*/
5626 /* genGetHbit - generates code get highest order bit */
5627 /*-----------------------------------------------------------------*/
5629 genGetHbit (iCode * ic)
5631 operand *left, *result;
5633 D(emitcode ("; genGetHbit",""));
5635 left = IC_LEFT (ic);
5636 result = IC_RESULT (ic);
5637 aopOp (left, ic, FALSE);
5638 aopOp (result, ic, FALSE);
5640 /* get the highest order byte into a */
5641 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5642 emitcode ("rola", "");
5643 emitcode ("clra", "");
5644 emitcode ("rola", "");
5645 hc08_dirtyReg (hc08_reg_a, FALSE);
5646 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5647 hc08_freeReg (hc08_reg_a);
5649 freeAsmop (left, NULL, ic, TRUE);
5650 freeAsmop (result, NULL, ic, TRUE);
5653 /*-----------------------------------------------------------------*/
5654 /* genSwap - generates code to swap nibbles or bytes */
5655 /*-----------------------------------------------------------------*/
5657 genSwap (iCode * ic)
5659 operand *left, *result;
5661 D(emitcode ("; genSwap",""));
5663 left = IC_LEFT (ic);
5664 result = IC_RESULT (ic);
5665 aopOp (left, ic, FALSE);
5666 aopOp (result, ic, FALSE);
5668 switch (AOP_SIZE (left))
5670 case 1: /* swap nibbles in byte */
5671 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5672 emitcode ("nsa", "");
5673 hc08_dirtyReg (hc08_reg_a, FALSE);
5674 storeRegToAop (hc08_reg_a, AOP (result), 0);
5675 hc08_freeReg (hc08_reg_a);
5677 case 2: /* swap bytes in a word */
5678 if (operandsEqu (left, result))
5680 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5681 hc08_useReg (hc08_reg_a);
5682 transferAopAop (AOP (left), 1, AOP (result), 0);
5683 storeRegToAop (hc08_reg_a, AOP (result), 1);
5684 hc08_freeReg (hc08_reg_a);
5688 transferAopAop (AOP (left), 0, AOP (result), 1);
5689 transferAopAop (AOP (left), 1, AOP (result), 0);
5693 wassertl(FALSE, "unsupported SWAP operand size");
5696 freeAsmop (left, NULL, ic, TRUE);
5697 freeAsmop (result, NULL, ic, TRUE);
5701 /*-----------------------------------------------------------------*/
5702 /* AccRol - rotate left accumulator by known count */
5703 /*-----------------------------------------------------------------*/
5705 AccRol (int shCount)
5707 shCount &= 0x0007; // shCount : 0..7
5714 emitcode ("rola", ""); /* 1 cycle */
5717 emitcode ("rola", ""); /* 1 cycle */
5718 emitcode ("rola", ""); /* 1 cycle */
5721 emitcode ("nsa", "");
5722 emitcode ("rora", "");
5725 emitcode ("nsa", ""); /* 3 cycles */
5728 emitcode ("nsa", ""); /* 3 cycles */
5729 emitcode ("rola", ""); /* 1 cycle */
5732 emitcode ("nsa", ""); /* 3 cycles */
5733 emitcode ("rola", ""); /* 1 cycle */
5734 emitcode ("rola", ""); /* 1 cycle */
5737 emitcode ("nsa", ""); /* 3 cycles */
5738 emitcode ("rola", ""); /* 1 cycle */
5739 emitcode ("rola", ""); /* 1 cycle */
5740 emitcode ("rola", ""); /* 1 cycle */
5747 /*-----------------------------------------------------------------*/
5748 /* AccLsh - left shift accumulator by known count */
5749 /*-----------------------------------------------------------------*/
5751 AccLsh (int shCount)
5755 shCount &= 0x0007; // shCount : 0..7
5757 /* Shift counts of 4 and 5 are currently optimized for code size. */
5758 /* Falling through to the unrolled loop would be optimal for code speed. */
5759 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5763 if (optimize.codeSpeed)
5765 accopWithMisc ("nsa", "");
5766 accopWithMisc ("and", "#0xf0");
5767 /* total: 5 cycles, 3 bytes */
5770 if (optimize.codeSpeed)
5772 accopWithMisc ("nsa", "");
5773 accopWithMisc ("and", "#0xf0");
5774 accopWithMisc ("lsla", "");
5775 /* total: 6 cycles, 4 bytes */
5778 accopWithMisc ("rora", "");
5779 accopWithMisc ("rora", "");
5780 accopWithMisc ("rora", "");
5781 accopWithMisc ("and", "#0xc0");
5782 /* total: 5 cycles, 5 bytes */
5785 accopWithMisc ("rora", "");
5786 accopWithMisc ("clra", "");
5787 accopWithMisc ("rora", "");
5788 /* total: 3 cycles, 3 bytes */
5792 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5793 /* the fastest (shCount<6) and shortest (shCount<4). */
5794 for (i=0;i<shCount;i++)
5795 accopWithMisc ("lsla", "");
5799 /*-----------------------------------------------------------------*/
5800 /* AccSRsh - signed right shift accumulator by known count */
5801 /*-----------------------------------------------------------------*/
5803 AccSRsh (int shCount)
5807 shCount &= 0x0007; // shCount : 0..7
5811 accopWithMisc ("rola", "");
5812 accopWithMisc ("clra", "");
5813 accopWithMisc ("sbc", zero);
5814 /* total: 4 cycles, 4 bytes */
5818 for (i=0;i<shCount;i++)
5819 accopWithMisc ("asra", "");
5822 /*-----------------------------------------------------------------*/
5823 /* AccRsh - right shift accumulator by known count */
5824 /*-----------------------------------------------------------------*/
5826 AccRsh (int shCount, bool sign)
5836 shCount &= 0x0007; // shCount : 0..7
5838 /* Shift counts of 4 and 5 are currently optimized for code size. */
5839 /* Falling through to the unrolled loop would be optimal for code speed. */
5840 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5844 if (optimize.codeSpeed)
5846 accopWithMisc ("nsa", "");
5847 accopWithMisc ("and", "#0x0f");
5848 /* total: 5 cycles, 3 bytes */
5851 if (optimize.codeSpeed)
5853 accopWithMisc ("nsa", "");
5854 accopWithMisc ("and", "#0x0f");
5855 accopWithMisc ("lsra", "");
5856 /* total: 6 cycles, 4 bytes */
5859 accopWithMisc ("rola", "");
5860 accopWithMisc ("rola", "");
5861 accopWithMisc ("rola", "");
5862 accopWithMisc ("and", "#0x03");
5863 /* total: 5 cycles, 5 bytes */
5866 accopWithMisc ("rola", "");
5867 accopWithMisc ("clra", "");
5868 accopWithMisc ("rola", "");
5869 /* total: 3 cycles, 3 bytes */
5873 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5874 /* the fastest (shCount<6) and shortest (shCount<4). */
5875 for (i=0;i<shCount;i++)
5876 accopWithMisc ("lsra", "");
5880 /*-----------------------------------------------------------------*/
5881 /* XAccLsh - left shift register pair XA by known count */
5882 /*-----------------------------------------------------------------*/
5884 XAccLsh (int shCount)
5888 shCount &= 0x000f; // shCount : 0..15
5893 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5894 loadRegFromConst (hc08_reg_a, zero);
5898 /* if we can beat 2n cycles or bytes for some special case, do it here */
5902 /* bytes cycles reg x reg a carry
5903 ** abcd efgh ijkl mnop ?
5904 ** lsrx 1 1 0abc defg ijkl mnop h
5905 ** rora 1 1 0abc defg hijk lmno p
5906 ** tax 1 1 hijk lmno hijk lmno p
5907 ** clra 1 1 hijk lmno 0000 0000 p
5908 ** rora 1 1 hijk lmno p000 0000 0
5909 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5911 rmwWithReg ("lsr", hc08_reg_x);
5912 rmwWithReg ("ror", hc08_reg_a);
5913 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5914 loadRegFromConst (hc08_reg_a, zero);
5915 rmwWithReg ("ror", hc08_reg_a);
5922 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5923 /* the fastest and shortest. */
5924 for (i=0;i<shCount;i++)
5926 rmwWithReg ("lsl", hc08_reg_a);
5927 rmwWithReg ("rol", hc08_reg_x);
5931 /*-----------------------------------------------------------------*/
5932 /* XAccSRsh - signed right shift register pair XA by known count */
5933 /*-----------------------------------------------------------------*/
5935 XAccSRsh (int shCount)
5939 shCount &= 0x000f; // shCount : 0..7
5941 /* if we can beat 2n cycles or bytes for some special case, do it here */
5945 /* bytes cycles reg x reg a carry
5946 ** abcd efgh ijkl mnop ?
5947 ** lslx 1 1 bcde fgh0 ijkl mnop a
5948 ** clra 1 1 bcde fgh0 0000 0000 a
5949 ** rola 1 1 bcde fgh0 0000 000a 0
5950 ** nega 1 1 bcde fgh0 aaaa aaaa a
5951 ** tax 1 1 aaaa aaaa aaaa aaaa a
5952 ** total: 5 cycles, 5 bytes
5954 rmwWithReg ("lsl", hc08_reg_x);
5955 loadRegFromConst (hc08_reg_a, zero);
5956 rmwWithReg ("rol", hc08_reg_a);
5957 rmwWithReg ("neg", hc08_reg_a);
5958 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5968 /* bytes cycles reg x reg a carry
5969 ** abcd efgh ijkl mnop ?
5970 ** txa 1 1 abcd efgh abcd efgh ?
5971 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5972 ** lsla 1 1 abcd efgh ???? ???? a
5973 ** clrx 1 1 0000 0000 ???? ???? a
5974 ** rolx 1 1 0000 000a ???? ???? 0
5975 ** negx 1 1 aaaa aaaa ???? ???? a
5976 ** rora 1 1 aaaa aaaa LSBresult 0
5977 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5979 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5980 AccSRsh (shCount-8);
5981 rmwWithReg ("lsl", hc08_reg_a);
5982 loadRegFromConst (hc08_reg_x, zero);
5983 rmwWithReg ("rol", hc08_reg_x);
5984 rmwWithReg ("neg", hc08_reg_x);
5985 rmwWithReg ("ror", hc08_reg_a);
5992 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5993 /* the fastest and shortest. */
5994 for (i=0;i<shCount;i++)
5996 rmwWithReg ("asr", hc08_reg_x);
5997 rmwWithReg ("ror", hc08_reg_a);
6001 /*-----------------------------------------------------------------*/
6002 /* XAccRsh - right shift register pair XA by known count */
6003 /*-----------------------------------------------------------------*/
6005 XAccRsh (int shCount, bool sign)
6015 shCount &= 0x000f; // shCount : 0..f
6017 /* if we can beat 2n cycles or bytes for some special case, do it here */
6021 /* bytes cycles reg x reg a carry
6022 ** abcd efgh ijkl mnop ?
6023 ** clra 1 1 abcd efgh 0000 0000 a
6024 ** lslx 1 1 bcde fgh0 0000 0000 a
6025 ** rola 1 1 bcde fgh0 0000 000a 0
6026 ** clrx 1 1 0000 0000 0000 000a 0
6027 ** total: 4 cycles, 4 bytes
6029 loadRegFromConst (hc08_reg_x, zero);
6030 rmwWithReg ("lsl", hc08_reg_x);
6031 rmwWithReg ("rol", hc08_reg_a);
6032 loadRegFromConst (hc08_reg_a, zero);
6036 /* bytes cycles reg x reg a carry
6037 ** abcd efgh ijkl mnop ?
6038 ** clra 1 1 abcd efgh 0000 0000 a
6039 ** lslx 1 1 bcde fgh0 0000 0000 a
6040 ** rola 1 1 bcde fgh0 0000 000a 0
6041 ** lslx 1 1 cdef gh00 0000 000a b
6042 ** rola 1 1 cdef gh00 0000 00ab 0
6043 ** clrx 1 1 0000 0000 0000 00ab 0
6044 ** total: 6 cycles, 6 bytes
6046 loadRegFromConst (hc08_reg_x, zero);
6047 rmwWithReg ("lsl", hc08_reg_x);
6048 rmwWithReg ("rol", hc08_reg_a);
6049 rmwWithReg ("lsl", hc08_reg_x);
6050 rmwWithReg ("rol", hc08_reg_a);
6051 loadRegFromConst (hc08_reg_a, zero);
6060 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6061 AccRsh (shCount-8, FALSE);
6062 loadRegFromConst (hc08_reg_x, zero);
6066 /* bytes cycles reg x reg a carry
6067 ** abcd efgh ijkl mnop ?
6068 ** lsla 1 1 abcd efgh jklm nop0 i
6069 ** txa 1 1 abcd efgh abcd efgh i
6070 ** rola 1 1 abcd efgh bcde fghi a
6071 ** clrx 1 1 0000 0000 bcde fghi a
6072 ** rolx 1 1 0000 000a bcde fghi 0
6073 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6075 rmwWithReg ("lsl", hc08_reg_a);
6076 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6077 rmwWithReg ("rol", hc08_reg_a);
6078 loadRegFromConst (hc08_reg_x, zero);
6079 rmwWithReg ("rol", hc08_reg_x);
6082 /* bytes cycles reg x reg a carry
6083 ** abcd efgh ijkl mnop ?
6084 ** lsla 1 1 abcd efgh jklm nop0 i
6085 ** rolx 1 1 bcde fghi jklm nop0 a
6086 ** rola 1 1 bcde fghi klmn op0a j
6087 ** rolx 1 1 cdef ghij klmn op0a b
6088 ** rola 1 1 cdef ghij lmno p0ab k
6089 ** and #3 2 2 cdef ghij 0000 00ab k
6090 ** psha 1 2 cdef ghij 0000 00ab k
6091 ** txa 1 1 cdef ghij cdef ghij k
6092 ** pula 1 2 0000 00ab cdef ghij k
6093 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6099 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6100 /* the fastest and shortest. */
6101 for (i=0;i<shCount;i++)
6103 rmwWithReg ("lsr", hc08_reg_x);
6104 rmwWithReg ("ror", hc08_reg_a);
6111 /*-----------------------------------------------------------------*/
6112 /* shiftR1Left2Result - shift right one byte from left to result */
6113 /*-----------------------------------------------------------------*/
6115 shiftR1Left2Result (operand * left, int offl,
6116 operand * result, int offr,
6117 int shCount, int sign)
6119 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6120 /* shift right accumulator */
6121 AccRsh (shCount, sign);
6122 storeRegToAop (hc08_reg_a, AOP (result), offr);
6126 /*-----------------------------------------------------------------*/
6127 /* shiftL1Left2Result - shift left one byte from left to result */
6128 /*-----------------------------------------------------------------*/
6130 shiftL1Left2Result (operand * left, int offl,
6131 operand * result, int offr, int shCount)
6133 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6134 /* shift left accumulator */
6136 storeRegToAop (hc08_reg_a, AOP (result), offr);
6139 /*-----------------------------------------------------------------*/
6140 /* movLeft2Result - move byte from left to result */
6141 /*-----------------------------------------------------------------*/
6143 movLeft2Result (operand * left, int offl,
6144 operand * result, int offr, int sign)
6146 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6148 transferAopAop (AOP (left), offl, AOP (result), offr);
6153 /*-----------------------------------------------------------------*/
6154 /* shiftL2Left2Result - shift left two bytes from left to result */
6155 /*-----------------------------------------------------------------*/
6157 shiftL2Left2Result (operand * left, int offl,
6158 operand * result, int offr, int shCount)
6161 bool needpula = FALSE;
6162 bool needpulx = FALSE;
6164 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6165 needpula = pushRegIfUsed (hc08_reg_a);
6168 if (!IS_AOP_XA (AOP (left)))
6169 needpulx = pushRegIfUsed (hc08_reg_x);
6173 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6178 rmwWithReg ("lsr", hc08_reg_x);
6179 rmwWithReg ("ror", hc08_reg_a);
6180 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6181 rmwWithReg ("clr", hc08_reg_a);
6182 rmwWithReg ("ror", hc08_reg_a);
6185 for (i=0; i<shCount; i++)
6187 rmwWithReg ("lsl", hc08_reg_a);
6188 rmwWithReg ("rol", hc08_reg_x);
6191 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6193 pullOrFreeReg (hc08_reg_x, needpulx);
6194 pullOrFreeReg (hc08_reg_a, needpula);
6200 /*-----------------------------------------------------------------*/
6201 /* shiftR2Left2Result - shift right two bytes from left to result */
6202 /*-----------------------------------------------------------------*/
6204 shiftR2Left2Result (operand * left, int offl,
6205 operand * result, int offr,
6206 int shCount, int sign)
6209 bool needpula = FALSE;
6210 bool needpulx = FALSE;
6212 needpula = pushRegIfUsed (hc08_reg_a);
6213 needpulx = pushRegIfUsed (hc08_reg_x);
6215 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6216 for (i=0; i<shCount; i++)
6219 rmwWithReg ("asr", hc08_reg_x);
6221 rmwWithReg ("lsr", hc08_reg_x);
6222 rmwWithReg ("ror", hc08_reg_a);
6224 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6226 pullOrFreeReg (hc08_reg_x, needpulx);
6227 pullOrFreeReg (hc08_reg_a, needpula);
6232 /*-----------------------------------------------------------------*/
6233 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6234 /*-----------------------------------------------------------------*/
6236 shiftLLeftOrResult (operand * left, int offl,
6237 operand * result, int offr, int shCount)
6239 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6240 /* shift left accumulator */
6242 /* or with result */
6243 accopWithAop ("ora", AOP (result), offr);
6244 /* back to result */
6245 storeRegToAop (hc08_reg_a, AOP (result), offr);
6246 hc08_freeReg (hc08_reg_a);
6250 /*-----------------------------------------------------------------*/
6251 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6252 /*-----------------------------------------------------------------*/
6254 shiftRLeftOrResult (operand * left, int offl,
6255 operand * result, int offr, int shCount)
6257 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6258 /* shift left accumulator */
6259 AccRsh (shCount, FALSE);
6260 /* or with result */
6261 accopWithAop ("ora", AOP (result), offr);
6262 /* back to result */
6263 storeRegToAop (hc08_reg_a, AOP (result), offr);
6264 hc08_freeReg (hc08_reg_a);
6267 /*-----------------------------------------------------------------*/
6268 /* genlshOne - left shift a one byte quantity by known count */
6269 /*-----------------------------------------------------------------*/
6271 genlshOne (operand * result, operand * left, int shCount)
6273 D(emitcode ("; genlshOne",""));
6275 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6278 /*-----------------------------------------------------------------*/
6279 /* genlshTwo - left shift two bytes by known amount != 0 */
6280 /*-----------------------------------------------------------------*/
6282 genlshTwo (operand * result, operand * left, int shCount)
6286 D(emitcode ("; genlshTwo",""));
6289 size = getDataSize (result);
6291 /* if shCount >= 8 */
6298 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6300 storeRegToAop (hc08_reg_a, AOP (result), 1);
6302 storeConstToAop(zero, AOP (result), LSB);
6305 /* 1 <= shCount <= 7 */
6308 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6310 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6314 /*-----------------------------------------------------------------*/
6315 /* shiftLLong - shift left one long from left to result */
6316 /* offr = LSB or MSB16 */
6317 /*-----------------------------------------------------------------*/
6319 shiftLLong (operand * left, operand * result, int offr)
6322 // int size = AOP_SIZE (result);
6324 bool needpula = FALSE;
6325 bool needpulx = FALSE;
6327 needpula = pushRegIfUsed (hc08_reg_a);
6328 needpulx = pushRegIfUsed (hc08_reg_x);
6330 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6331 rmwWithReg ("lsl", hc08_reg_a);
6332 rmwWithReg ("rol", hc08_reg_x);
6336 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6337 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6338 rmwWithReg ("rol", hc08_reg_a);
6339 rmwWithReg ("rol", hc08_reg_x);
6340 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6342 else if (offr==MSB16)
6344 storeRegToAop (hc08_reg_a, AOP (result), offr);
6345 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6346 storeRegToAop (hc08_reg_x, AOP (result), offr+1);
6347 rmwWithReg ("rol", hc08_reg_a);
6348 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6349 storeConstToAop (zero, AOP (result), 0);
6352 pullOrFreeReg (hc08_reg_x, needpulx);
6353 pullOrFreeReg (hc08_reg_a, needpula);
6356 /*-----------------------------------------------------------------*/
6357 /* genlshFour - shift four byte by a known amount != 0 */
6358 /*-----------------------------------------------------------------*/
6360 genlshFour (operand * result, operand * left, int shCount)
6364 D(emitcode ("; genlshFour",""));
6366 size = AOP_SIZE (result);
6368 /* TODO: deal with the &result == &left case */
6370 /* if shifting more that 3 bytes */
6375 /* lowest order of left goes to the highest
6376 order of the destination */
6377 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6379 movLeft2Result (left, LSB, result, MSB32, 0);
6380 storeConstToAop (zero, AOP (result), LSB);
6381 storeConstToAop (zero, AOP (result), MSB16);
6382 storeConstToAop (zero, AOP (result), MSB24);
6386 /* more than two bytes */
6387 else if (shCount >= 16)
6389 /* lower order two bytes goes to higher order two bytes */
6391 /* if some more remaining */
6393 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6396 movLeft2Result (left, MSB16, result, MSB32, 0);
6397 movLeft2Result (left, LSB, result, MSB24, 0);
6399 storeConstToAop (zero, AOP (result), LSB);
6400 storeConstToAop (zero, AOP (result), MSB16);
6404 /* if more than 1 byte */
6405 else if (shCount >= 8)
6407 /* lower order three bytes goes to higher order three bytes */
6412 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6414 movLeft2Result (left, LSB, result, MSB16, 0);
6420 movLeft2Result (left, MSB24, result, MSB32, 0);
6421 movLeft2Result (left, MSB16, result, MSB24, 0);
6422 movLeft2Result (left, LSB, result, MSB16, 0);
6423 storeConstToAop (zero, AOP (result), LSB);
6425 else if (shCount == 1)
6426 shiftLLong (left, result, MSB16);
6429 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6430 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6431 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6432 storeConstToAop (zero, AOP (result), LSB);
6437 /* 1 <= shCount <= 7 */
6438 else if (shCount <= 2)
6440 shiftLLong (left, result, LSB);
6442 shiftLLong (result, result, LSB);
6444 /* 3 <= shCount <= 7, optimize */
6447 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6448 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6449 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6453 /*-----------------------------------------------------------------*/
6454 /* genLeftShiftLiteral - left shifting by known count */
6455 /*-----------------------------------------------------------------*/
6457 genLeftShiftLiteral (operand * left,
6462 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6465 D(emitcode ("; genLeftShiftLiteral",""));
6467 freeAsmop (right, NULL, ic, TRUE);
6469 aopOp (left, ic, FALSE);
6470 aopOp (result, ic, FALSE);
6472 // size = getSize (operandType (result));
6473 size = AOP_SIZE (result);
6476 D(emitcode ("; shift left ", "result %d, left %d", size,
6483 transferAopAop( AOP(left), size, AOP(result), size);
6485 else if (shCount >= (size * 8))
6488 storeConstToAop (zero, AOP (result), size);
6495 genlshOne (result, left, shCount);
6499 genlshTwo (result, left, shCount);
6503 genlshFour (result, left, shCount);
6506 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6507 "*** ack! mystery literal shift!\n");
6511 freeAsmop (left, NULL, ic, TRUE);
6512 freeAsmop (result, NULL, ic, TRUE);
6515 /*-----------------------------------------------------------------*/
6516 /* genLeftShift - generates code for left shifting */
6517 /*-----------------------------------------------------------------*/
6519 genLeftShift (iCode * ic)
6521 operand *left, *right, *result;
6523 symbol *tlbl, *tlbl1;
6526 D(emitcode ("; genLeftShift",""));
6528 right = IC_RIGHT (ic);
6529 left = IC_LEFT (ic);
6530 result = IC_RESULT (ic);
6532 aopOp (right, ic, FALSE);
6534 /* if the shift count is known then do it
6535 as efficiently as possible */
6536 if (AOP_TYPE (right) == AOP_LIT)
6538 genLeftShiftLiteral (left, right, result, ic);
6542 /* shift count is unknown then we have to form
6543 a loop get the loop count in A : Note: we take
6544 only the lower order byte since shifting
6545 more that 32 bits make no sense anyway, ( the
6546 largest size of an object can be only 32 bits ) */
6548 aopOp (result, ic, FALSE);
6549 aopOp (left, ic, FALSE);
6551 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6552 AOP (result) = forceStackedAop (AOP (result));
6554 /* now move the left to the result if they are not the
6556 if (!sameRegs (AOP (left), AOP (result)))
6558 size = AOP_SIZE (result);
6562 transferAopAop (AOP (left), offset, AOP (result), offset);
6566 freeAsmop (left, NULL, ic, TRUE);
6568 tlbl = newiTempLabel (NULL);
6569 size = AOP_SIZE (result);
6571 tlbl1 = newiTempLabel (NULL);
6573 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6574 emitcode ("tstx", "");
6575 emitBranch ("beq", tlbl1);
6579 for (offset=0;offset<size;offset++)
6581 rmwWithAop (shift, AOP (result), offset);
6584 rmwWithReg ("dec", hc08_reg_x);
6585 emitBranch ("bne", tlbl);
6587 hc08_freeReg (hc08_reg_x);
6589 freeAsmop (result, NULL, ic, TRUE);
6590 freeAsmop (right, NULL, ic, TRUE);
6593 /*-----------------------------------------------------------------*/
6594 /* genrshOne - right shift a one byte quantity by known count */
6595 /*-----------------------------------------------------------------*/
6597 genrshOne (operand * result, operand * left,
6598 int shCount, int sign)
6600 D(emitcode ("; genrshOne",""));
6602 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6603 AccRsh (shCount, sign);
6604 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6607 /*-----------------------------------------------------------------*/
6608 /* genrshTwo - right shift two bytes by known amount != 0 */
6609 /*-----------------------------------------------------------------*/
6611 genrshTwo (operand * result, operand * left,
6612 int shCount, int sign)
6614 D(emitcode ("; genrshTwo",""));
6616 /* if shCount >= 8 */
6619 if (shCount || sign)
6621 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6622 AccRsh (shCount-8, sign);
6623 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6627 transferAopAop (AOP (left), 1, AOP (result), 0);
6628 storeConstToAop (zero, AOP (result), 1);
6632 /* 1 <= shCount <= 7 */
6635 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6636 XAccRsh (shCount, sign);
6637 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6641 /*-----------------------------------------------------------------*/
6642 /* shiftRLong - shift right one long from left to result */
6643 /* offl = LSB or MSB16 */
6644 /*-----------------------------------------------------------------*/
6646 shiftRLong (operand * left, int offl,
6647 operand * result, int sign)
6650 // int size = AOP_SIZE (result);
6652 bool needpula = FALSE;
6653 bool needpulx = FALSE;
6655 needpula = pushRegIfUsed (hc08_reg_a);
6656 needpulx = pushRegIfUsed (hc08_reg_x);
6660 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6662 rmwWithReg ("asr", hc08_reg_x);
6664 rmwWithReg ("lsr", hc08_reg_x);
6665 rmwWithReg ("ror", hc08_reg_a);
6666 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6667 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6669 else if (offl==MSB16)
6671 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6673 rmwWithReg ("asr", hc08_reg_a);
6675 rmwWithReg ("lsr", hc08_reg_a);
6676 loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
6677 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6678 loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
6681 rmwWithReg ("ror", hc08_reg_x);
6682 rmwWithReg ("ror", hc08_reg_a);
6683 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6689 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6690 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6694 storeConstToAop (zero, AOP (result), MSB32);
6698 pullOrFreeReg (hc08_reg_x, needpulx);
6699 pullOrFreeReg (hc08_reg_a, needpula);
6702 /*-----------------------------------------------------------------*/
6703 /* genrshFour - shift four byte by a known amount != 0 */
6704 /*-----------------------------------------------------------------*/
6706 genrshFour (operand * result, operand * left,
6707 int shCount, int sign)
6709 /* TODO: handle cases where left == result */
6711 D(emitcode ("; genrshFour",""));
6713 /* if shifting more that 3 bytes */
6716 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6717 AccRsh (shCount-24, sign);
6718 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6721 else if (shCount >= 16)
6723 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6724 XAccRsh (shCount-16, sign);
6725 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6728 else if (shCount >= 8)
6731 shiftRLong (left, MSB16, result, sign);
6732 else if (shCount == 8)
6734 transferAopAop (AOP (left), 1, AOP (result), 0);
6735 transferAopAop (AOP (left), 2, AOP (result), 1);
6736 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6737 storeRegToAop (hc08_reg_a, AOP (result), 2);
6738 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6740 else if (shCount == 9)
6742 shiftRLong (left, MSB16, result, sign);
6746 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6747 XAccRsh (shCount-8, FALSE);
6748 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6749 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6750 loadRegFromConst (hc08_reg_a, zero);
6751 XAccRsh (shCount-8, sign);
6752 accopWithAop ("ora", AOP (result), 1);
6753 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6754 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6758 { /* 1 <= shCount <= 7 */
6761 shiftRLong (left, LSB, result, sign);
6765 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6766 XAccRsh (shCount, FALSE);
6767 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6768 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6770 accopWithAop ("ora", AOP (result), 1);
6771 storeRegToAop (hc08_reg_a, AOP (result), 1);
6772 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6773 XAccRsh (shCount, sign);
6774 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6779 /*-----------------------------------------------------------------*/
6780 /* genRightShiftLiteral - right shifting by known count */
6781 /*-----------------------------------------------------------------*/
6783 genRightShiftLiteral (operand * left,
6789 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6792 D(emitcode ("; genRightShiftLiteral",""));
6794 freeAsmop (right, NULL, ic, TRUE);
6796 aopOp (left, ic, FALSE);
6797 aopOp (result, ic, FALSE);
6800 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6804 size = getDataSize (left);
6805 /* test the LEFT size !!! */
6807 /* I suppose that the left size >= result size */
6810 size = getDataSize (result);
6812 transferAopAop (AOP (left), size, AOP(result), size);
6814 else if (shCount >= (size * 8))
6817 /* get sign in acc.7 */
6818 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6820 addSign (result, LSB, sign);
6827 genrshOne (result, left, shCount, sign);
6831 genrshTwo (result, left, shCount, sign);
6835 genrshFour (result, left, shCount, sign);
6841 freeAsmop (left, NULL, ic, TRUE);
6842 freeAsmop (result, NULL, ic, TRUE);
6846 /*-----------------------------------------------------------------*/
6847 /* genRightShift - generate code for right shifting */
6848 /*-----------------------------------------------------------------*/
6850 genRightShift (iCode * ic)
6852 operand *right, *left, *result;
6855 symbol *tlbl, *tlbl1;
6859 D(emitcode ("; genRightShift",""));
6861 /* if signed then we do it the hard way preserve the
6862 sign bit moving it inwards */
6863 retype = getSpec (operandType (IC_RESULT (ic)));
6864 sign = !SPEC_USIGN (retype);
6866 /* signed & unsigned types are treated the same : i.e. the
6867 signed is NOT propagated inwards : quoting from the
6868 ANSI - standard : "for E1 >> E2, is equivalent to division
6869 by 2**E2 if unsigned or if it has a non-negative value,
6870 otherwise the result is implementation defined ", MY definition
6871 is that the sign does not get propagated */
6873 right = IC_RIGHT (ic);
6874 left = IC_LEFT (ic);
6875 result = IC_RESULT (ic);
6877 aopOp (right, ic, FALSE);
6879 /* if the shift count is known then do it
6880 as efficiently as possible */
6881 if (AOP_TYPE (right) == AOP_LIT)
6883 genRightShiftLiteral (left, right, result, ic, sign);
6887 /* shift count is unknown then we have to form
6888 a loop get the loop count in X : Note: we take
6889 only the lower order byte since shifting
6890 more that 32 bits make no sense anyway, ( the
6891 largest size of an object can be only 32 bits ) */
6893 aopOp (result, ic, FALSE);
6894 aopOp (left, ic, FALSE);
6896 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6897 AOP (result) = forceStackedAop (AOP (result));
6899 /* now move the left to the result if they are not the
6901 if (!sameRegs (AOP (left), AOP (result)))
6903 size = AOP_SIZE (result);
6907 transferAopAop (AOP (left), offset, AOP (result), offset);
6911 freeAsmop (left, NULL, ic, TRUE);
6913 tlbl = newiTempLabel (NULL);
6914 size = AOP_SIZE (result);
6916 tlbl1 = newiTempLabel (NULL);
6918 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6919 emitcode ("tstx", "");
6920 emitBranch ("beq", tlbl1);
6923 shift= sign ? "asr" : "lsr";
6924 for (offset=size-1;offset>=0;offset--)
6926 rmwWithAop (shift, AOP (result), offset);
6929 rmwWithReg ("dec", hc08_reg_x);
6930 emitBranch ("bne", tlbl);
6932 hc08_freeReg (hc08_reg_x);
6934 freeAsmop (result, NULL, ic, TRUE);
6935 freeAsmop (right, NULL, ic, TRUE);
6939 /*-----------------------------------------------------------------*/
6940 /* genUnpackBits - generates code for unpacking bits */
6941 /*-----------------------------------------------------------------*/
6943 genUnpackBits (operand * result, iCode *ifx)
6945 int offset = 0; /* result byte offset */
6946 int rsize; /* result size */
6947 int rlen = 0; /* remaining bitfield length */
6948 sym_link *etype; /* bitfield type information */
6949 int blen; /* bitfield length */
6950 int bstr; /* bitfield starting bit within byte */
6952 D(emitcode ("; genUnpackBits",""));
6954 etype = getSpec (operandType (result));
6955 rsize = getSize (operandType (result));
6956 blen = SPEC_BLEN (etype);
6957 bstr = SPEC_BSTR (etype);
6959 if (ifx && blen <= 8)
6961 emitcode ("lda", ",x");
6962 hc08_dirtyReg (hc08_reg_a, FALSE);
6965 emitcode ("and", "#0x%02x",
6966 (((unsigned char) -1) >> (8 - blen)) << bstr);
6968 genIfxJump (ifx, "a");
6973 /* If the bitfield length is less than a byte */
6976 emitcode ("lda", ",x");
6977 hc08_dirtyReg (hc08_reg_a, FALSE);
6978 AccRsh (bstr, FALSE);
6979 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6980 if (!SPEC_USIGN (etype))
6982 /* signed bitfield */
6983 symbol *tlbl = newiTempLabel (NULL);
6985 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
6986 emitcode ("beq", "%05d$", tlbl->key + 100);
6987 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
6990 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6994 /* Bit field did not fit in a byte. Copy all
6995 but the partial byte at the end. */
6996 for (rlen=blen;rlen>=8;rlen-=8)
6998 emitcode ("lda", ",x");
6999 hc08_dirtyReg (hc08_reg_a, FALSE);
7000 storeRegToAop (hc08_reg_a, AOP (result), offset);
7003 emitcode ("aix", "#1");
7006 /* Handle the partial byte at the end */
7009 emitcode ("lda", ",x");
7010 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7011 if (!SPEC_USIGN (etype))
7013 /* signed bitfield */
7014 symbol *tlbl = newiTempLabel (NULL);
7016 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7017 emitcode ("beq", "%05d$", tlbl->key + 100);
7018 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7021 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7028 if (SPEC_USIGN (etype))
7031 storeConstToAop (zero, AOP (result), offset++);
7035 /* signed bitfield: sign extension with 0x00 or 0xff */
7036 emitcode ("rola", "");
7037 emitcode ("clra", "");
7038 emitcode ("sbc", zero);
7041 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7047 /*-----------------------------------------------------------------*/
7048 /* genUnpackBitsImmed - generates code for unpacking bits */
7049 /*-----------------------------------------------------------------*/
7051 genUnpackBitsImmed (operand * left,
7057 int offset = 0; /* result byte offset */
7058 int rsize; /* result size */
7059 int rlen = 0; /* remaining bitfield length */
7060 sym_link *etype; /* bitfield type information */
7061 int blen; /* bitfield length */
7062 int bstr; /* bitfield starting bit within byte */
7065 D(emitcode ("; genUnpackBitsImmed",""));
7067 aopOp (result, ic, TRUE);
7068 size = AOP_SIZE (result);
7070 derefaop = aopDerefAop (AOP (left));
7071 freeAsmop (left, NULL, ic, TRUE);
7072 derefaop->size = size;
7074 etype = getSpec (operandType (result));
7075 rsize = getSize (operandType (result));
7076 blen = SPEC_BLEN (etype);
7077 bstr = SPEC_BSTR (etype);
7079 /* if the bitfield is a single bit in the direct page */
7080 if (blen == 1 && derefaop->type == AOP_DIR)
7084 symbol *tlbl = newiTempLabel (NULL);
7086 loadRegFromConst (hc08_reg_a, zero);
7087 emitcode ("brclr", "#%d,%s,%05d$",
7088 bstr, aopAdrStr (derefaop, 0, FALSE),
7090 if (SPEC_USIGN (etype))
7091 rmwWithReg ("inc", hc08_reg_a);
7093 rmwWithReg ("dec", hc08_reg_a);
7095 storeRegToAop (hc08_reg_a, AOP (result), offset);
7096 hc08_freeReg (hc08_reg_a);
7102 symbol *tlbl = newiTempLabel (NULL);
7108 jlbl = IC_TRUE (ifx);
7113 jlbl = IC_FALSE (ifx);
7116 emitcode (inst, "#%d,%s,%05d$",
7117 bstr, aopAdrStr (derefaop, 0, FALSE),
7119 emitBranch ("jmp", jlbl);
7127 /* If the bitfield length is less than a byte */
7130 loadRegFromAop (hc08_reg_a, derefaop, 0);
7133 AccRsh (bstr, FALSE);
7134 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7135 hc08_dirtyReg (hc08_reg_a, FALSE);
7136 if (!SPEC_USIGN (etype))
7138 /* signed bitfield */
7139 symbol *tlbl = newiTempLabel (NULL);
7141 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7142 emitcode ("beq", "%05d$", tlbl->key + 100);
7143 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7146 storeRegToAop (hc08_reg_a, AOP (result), offset);
7150 emitcode ("and", "#0x%02x",
7151 (((unsigned char) -1) >> (8 - blen)) << bstr);
7152 hc08_dirtyReg (hc08_reg_a, FALSE);
7158 /* Bit field did not fit in a byte. Copy all
7159 but the partial byte at the end. */
7160 for (rlen=blen;rlen>=8;rlen-=8)
7162 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7164 storeRegToAop (hc08_reg_a, AOP (result), offset);
7166 emitcode ("tsta", "");
7170 /* Handle the partial byte at the end */
7173 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7174 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7175 if (!SPEC_USIGN (etype))
7177 /* signed bitfield */
7178 symbol *tlbl = newiTempLabel (NULL);
7180 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7181 emitcode ("beq", "%05d$", tlbl->key + 100);
7182 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7185 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7192 if (SPEC_USIGN (etype))
7195 storeConstToAop (zero, AOP (result), offset++);
7199 /* signed bitfield: sign extension with 0x00 or 0xff */
7200 emitcode ("rola", "");
7201 emitcode ("clra", "");
7202 emitcode ("sbc", zero);
7205 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7209 freeAsmop (NULL, derefaop, ic, TRUE);
7210 freeAsmop (result, NULL, ic, TRUE);
7212 if (ifx && !ifx->generated)
7214 genIfxJump (ifx, "a");
7219 /*-----------------------------------------------------------------*/
7220 /* genDataPointerGet - generates code when ptr offset is known */
7221 /*-----------------------------------------------------------------*/
7223 genDataPointerGet (operand * left,
7231 D(emitcode ("; genDataPointerGet",""));
7233 aopOp (result, ic, TRUE);
7234 size = AOP_SIZE (result);
7236 derefaop = aopDerefAop (AOP (left));
7237 freeAsmop (left, NULL, ic, TRUE);
7238 derefaop->size = size;
7243 transferAopAop (derefaop, size, AOP (result), size);
7245 loadRegFromAop (hc08_reg_a, derefaop, size);
7248 freeAsmop (NULL, derefaop, ic, TRUE);
7249 freeAsmop (result, NULL, ic, TRUE);
7251 if (ifx && !ifx->generated)
7253 genIfxJump (ifx, "a");
7258 /*-----------------------------------------------------------------*/
7259 /* genPointerGet - generate code for pointer get */
7260 /*-----------------------------------------------------------------*/
7262 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7264 operand *left = IC_LEFT (ic);
7265 operand *result = IC_RESULT (ic);
7267 sym_link *retype = getSpec (operandType (result));
7269 D(emitcode ("; genPointerGet",""));
7271 if (getSize (operandType (result))>1)
7274 aopOp (left, ic, FALSE);
7276 /* if left is rematerialisable and
7277 result is not bit variable type */
7278 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7280 if (!IS_BITVAR (retype))
7282 genDataPointerGet (left, result, ic, ifx);
7287 genUnpackBitsImmed (left, result, ic, ifx);
7292 /* if the operand is already in hx
7293 then we do nothing else we move the value to hx */
7294 if (AOP_TYPE (left) != AOP_STR)
7296 /* if this is remateriazable */
7297 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7300 /* so hx now contains the address */
7301 aopOp (result, ic, FALSE);
7303 /* if bit then unpack */
7304 if (IS_BITVAR (retype))
7305 genUnpackBits (result, ifx);
7308 size = AOP_SIZE (result);
7313 accopWithMisc ("lda", ",x");
7316 emitcode ("aix", "#1");
7317 hc08_dirtyReg (hc08_reg_hx, FALSE);
7320 storeRegToAop (hc08_reg_a, AOP (result), offset);
7322 hc08_freeReg (hc08_reg_a);
7326 freeAsmop (left, NULL, ic, TRUE);
7327 freeAsmop (result, NULL, ic, TRUE);
7330 aopOp (IC_RESULT (pi), pi, FALSE);
7331 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7332 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7336 if (ifx && !ifx->generated)
7338 genIfxJump (ifx, "a");
7341 hc08_freeReg (hc08_reg_hx);
7345 /*-----------------------------------------------------------------*/
7346 /* genPackBits - generates code for packed bit storage */
7347 /*-----------------------------------------------------------------*/
7349 genPackBits (sym_link * etype,
7352 int offset = 0; /* source byte offset */
7353 int rlen = 0; /* remaining bitfield length */
7354 int blen; /* bitfield length */
7355 int bstr; /* bitfield starting bit within byte */
7356 int litval; /* source literal value (if AOP_LIT) */
7357 unsigned char mask; /* bitmask within current byte */
7360 D(emitcode ("; genPackBits",""));
7362 blen = SPEC_BLEN (etype);
7363 bstr = SPEC_BSTR (etype);
7365 /* If the bitfield length is less than a byte */
7368 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7369 (unsigned char) (0xFF >> (8 - bstr)));
7371 if (AOP_TYPE (right) == AOP_LIT)
7373 /* Case with a bitfield length <8 and literal source
7375 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7377 litval &= (~mask) & 0xff;
7379 emitcode ("lda", ",x");
7380 if ((mask|litval)!=0xff)
7381 emitcode ("and","#0x%02x", mask);
7383 emitcode ("ora","#0x%02x", litval);
7384 hc08_dirtyReg (hc08_reg_a, FALSE);
7385 emitcode ("sta", ",x");
7387 hc08_freeReg (hc08_reg_a);
7391 /* Case with a bitfield length < 8 and arbitrary source
7393 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7394 /* shift and mask source value */
7396 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7397 hc08_dirtyReg (hc08_reg_a, FALSE);
7398 pushReg (hc08_reg_a, TRUE);
7400 emitcode ("lda", ",x");
7401 emitcode ("and", "#0x%02x", mask);
7402 emitcode ("ora", "1,s");
7403 emitcode ("sta", ",x");
7404 pullReg (hc08_reg_a);
7406 hc08_freeReg (hc08_reg_a);
7410 /* Bit length is greater than 7 bits. In this case, copy */
7411 /* all except the partial byte at the end */
7412 for (rlen=blen;rlen>=8;rlen-=8)
7414 if (AOP (right)->type == AOP_DIR)
7416 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7421 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7422 emitcode ("sta", "%d,x", offset);
7427 /* If there was a partial byte at the end */
7430 mask = (((unsigned char) -1 << rlen) & 0xff);
7432 if (AOP_TYPE (right) == AOP_LIT)
7434 /* Case with partial byte and literal source
7436 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7437 litval >>= (blen-rlen);
7438 litval &= (~mask) & 0xff;
7439 emitcode ("lda", "%d,x", offset - xoffset);
7440 hc08_dirtyReg (hc08_reg_a, FALSE);
7441 if ((mask|litval)!=0xff)
7442 emitcode ("and","#0x%02x", mask);
7444 emitcode ("ora","#0x%02x", litval);
7445 emitcode ("sta", "%d,x", offset - xoffset);
7446 hc08_dirtyReg (hc08_reg_a, FALSE);
7447 hc08_freeReg (hc08_reg_a);
7451 /* Case with partial byte and arbitrary source
7453 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7454 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7455 hc08_dirtyReg (hc08_reg_a, FALSE);
7456 pushReg (hc08_reg_a, TRUE);
7458 emitcode ("lda", "%d,x", offset - xoffset);
7459 emitcode ("and", "#0x%02x", mask);
7460 emitcode ("ora", "1,s");
7461 emitcode ("sta", "%d,x", offset - xoffset);
7462 pullReg (hc08_reg_a);
7465 hc08_freeReg (hc08_reg_a);
7468 /*-----------------------------------------------------------------*/
7469 /* genPackBitsImmed - generates code for packed bit storage */
7470 /*-----------------------------------------------------------------*/
7472 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7476 int offset = 0; /* source byte offset */
7477 int rlen = 0; /* remaining bitfield length */
7478 int blen; /* bitfield length */
7479 int bstr; /* bitfield starting bit within byte */
7480 int litval; /* source literal value (if AOP_LIT) */
7481 unsigned char mask; /* bitmask within current byte */
7483 D(emitcode ("; genPackBitsImmed",""));
7485 blen = SPEC_BLEN (etype);
7486 bstr = SPEC_BSTR (etype);
7488 aopOp (right, ic, FALSE);
7489 size = AOP_SIZE (right);
7491 derefaop = aopDerefAop (AOP (result));
7492 freeAsmop (result, NULL, ic, TRUE);
7493 derefaop->size = size;
7495 /* if the bitfield is a single bit in the direct page */
7496 if (blen == 1 && derefaop->type == AOP_DIR)
7498 if (AOP_TYPE (right) == AOP_LIT)
7500 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7502 emitcode ((litval & 1) ? "bset" : "bclr",
7503 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7507 symbol *tlbl1 = newiTempLabel (NULL);
7508 symbol *tlbl2 = newiTempLabel (NULL);
7510 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7511 emitcode ("bit", "#1");
7512 emitBranch ("bne", tlbl1);
7513 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7514 emitBranch ("bra", tlbl2);
7516 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7518 hc08_freeReg (hc08_reg_a);
7523 /* If the bitfield length is less than a byte */
7526 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7527 (unsigned char) (0xFF >> (8 - bstr)));
7529 if (AOP_TYPE (right) == AOP_LIT)
7531 /* Case with a bitfield length <8 and literal source
7533 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7535 litval &= (~mask) & 0xff;
7537 loadRegFromAop (hc08_reg_a, derefaop, 0);
7538 if ((mask|litval)!=0xff)
7539 emitcode ("and","#0x%02x", mask);
7541 emitcode ("ora","#0x%02x", litval);
7542 hc08_dirtyReg (hc08_reg_a, FALSE);
7543 storeRegToAop (hc08_reg_a, derefaop, 0);
7545 hc08_freeReg (hc08_reg_a);
7549 /* Case with a bitfield length < 8 and arbitrary source
7551 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7552 /* shift and mask source value */
7554 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7555 hc08_dirtyReg (hc08_reg_a, FALSE);
7556 pushReg (hc08_reg_a, TRUE);
7558 loadRegFromAop (hc08_reg_a, derefaop, 0);
7559 emitcode ("and", "#0x%02x", mask);
7560 emitcode ("ora", "1,s");
7561 storeRegToAop (hc08_reg_a, derefaop, 0);
7562 pullReg (hc08_reg_a);
7564 hc08_freeReg (hc08_reg_a);
7568 /* Bit length is greater than 7 bits. In this case, copy */
7569 /* all except the partial byte at the end */
7570 for (rlen=blen;rlen>=8;rlen-=8)
7572 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7576 /* If there was a partial byte at the end */
7579 mask = (((unsigned char) -1 << rlen) & 0xff);
7581 if (AOP_TYPE (right) == AOP_LIT)
7583 /* Case with partial byte and literal source
7585 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7586 litval >>= (blen-rlen);
7587 litval &= (~mask) & 0xff;
7588 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7589 if ((mask|litval)!=0xff)
7590 emitcode ("and","#0x%02x", mask);
7592 emitcode ("ora","#0x%02x", litval);
7593 hc08_dirtyReg (hc08_reg_a, FALSE);
7594 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7595 hc08_dirtyReg (hc08_reg_a, FALSE);
7596 hc08_freeReg (hc08_reg_a);
7600 /* Case with partial byte and arbitrary source
7602 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7603 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7604 hc08_dirtyReg (hc08_reg_a, FALSE);
7605 pushReg (hc08_reg_a, TRUE);
7607 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7608 emitcode ("and", "#0x%02x", mask);
7609 emitcode ("ora", "1,s");
7610 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7611 pullReg (hc08_reg_a);
7614 hc08_freeReg (hc08_reg_a);
7617 freeAsmop (right, NULL, ic, TRUE);
7618 freeAsmop (NULL, derefaop, ic, TRUE);
7621 /*-----------------------------------------------------------------*/
7622 /* genDataPointerSet - remat pointer to data space */
7623 /*-----------------------------------------------------------------*/
7625 genDataPointerSet (operand * right,
7632 D(emitcode ("; genDataPointerSet",""));
7634 aopOp (right, ic, FALSE);
7635 size = AOP_SIZE (right);
7637 derefaop = aopDerefAop (AOP (result));
7638 freeAsmop (result, NULL, ic, TRUE);
7639 derefaop->size = size;
7643 transferAopAop (AOP (right), size, derefaop, size);
7646 freeAsmop (right, NULL, ic, TRUE);
7647 freeAsmop (NULL, derefaop, ic, TRUE);
7651 /*-----------------------------------------------------------------*/
7652 /* genPointerSet - stores the value into a pointer location */
7653 /*-----------------------------------------------------------------*/
7655 genPointerSet (iCode * ic, iCode *pi)
7657 operand *right = IC_RIGHT (ic);
7658 operand *result = IC_RESULT (ic);
7659 sym_link *type, *etype;
7661 sym_link *retype = getSpec (operandType (right));
7662 sym_link *letype = getSpec (operandType (result));
7664 D(emitcode ("; genPointerSet",""));
7666 type = operandType (result);
7667 etype = getSpec (type);
7669 aopOp (result, ic, FALSE);
7671 /* if the result is rematerializable */
7672 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7674 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7676 genDataPointerSet (right, result, ic);
7681 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7686 /* if the operand is already in hx
7687 then we do nothing else we move the value to hx */
7688 if (AOP_TYPE (result) != AOP_STR)
7690 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7692 /* so hx now contains the address */
7693 aopOp (right, ic, FALSE);
7695 /* if bit then unpack */
7696 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7697 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7700 size = AOP_SIZE (right);
7705 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7706 accopWithMisc ("sta", ",x");
7709 emitcode ("aix", "#1");
7711 hc08_freeReg (hc08_reg_a);
7715 freeAsmop (result, NULL, ic, TRUE);
7716 freeAsmop (right, NULL, ic, TRUE);
7719 aopOp (IC_RESULT (pi), pi, FALSE);
7720 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7721 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7725 hc08_freeReg (hc08_reg_hx);
7729 /*-----------------------------------------------------------------*/
7730 /* genIfx - generate code for Ifx statement */
7731 /*-----------------------------------------------------------------*/
7733 genIfx (iCode * ic, iCode * popIc)
7735 operand *cond = IC_COND (ic);
7738 D(emitcode ("; genIfx",""));
7740 aopOp (cond, ic, FALSE);
7742 /* If the condition is a literal, we can just do an unconditional */
7743 /* branch or no branch */
7744 if (AOP_TYPE (cond) == AOP_LIT)
7746 unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
7747 freeAsmop (cond, NULL, ic, TRUE);
7749 /* if there was something to be popped then do it */
7755 emitBranch ("jmp", IC_TRUE (ic));
7760 emitBranch ("jmp", IC_FALSE (ic));
7766 /* get the value into acc */
7767 if (AOP_TYPE (cond) != AOP_CRY)
7768 asmopToBool (AOP (cond), FALSE);
7771 /* the result is now in the accumulator */
7772 freeAsmop (cond, NULL, ic, TRUE);
7774 /* if there was something to be popped then do it */
7778 /* if the condition is a bit variable */
7779 if (isbit && IS_ITEMP (cond) &&
7781 genIfxJump (ic, SPIL_LOC (cond)->rname);
7782 else if (isbit && !IS_ITEMP (cond))
7783 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7785 genIfxJump (ic, "a");
7790 /*-----------------------------------------------------------------*/
7791 /* genAddrOf - generates code for address of */
7792 /*-----------------------------------------------------------------*/
7794 genAddrOf (iCode * ic)
7796 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7799 D(emitcode ("; genAddrOf",""));
7801 aopOp (IC_RESULT (ic), ic, FALSE);
7803 /* if the operand is on the stack then we
7804 need to get the stack offset of this
7808 /* if it has an offset then we need to compute it */
7809 offset = _G.stackOfs + _G.stackPushes + sym->stack;
7810 hc08_useReg (hc08_reg_hx);
7811 emitcode ("tsx", "");
7812 while (offset > 127)
7814 emitcode ("aix", "#127");
7817 while (offset < -128)
7819 emitcode ("aix", "#-128");
7822 emitcode ("aix", "#%d", offset);
7823 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7824 hc08_freeReg (hc08_reg_hx);
7829 /* object not on stack then we need the name */
7830 size = AOP_SIZE (IC_RESULT (ic));
7835 char s[SDCC_NAME_MAX+10];
7838 sprintf (s, "#%s", sym->rname);
7841 sprintf (s, "#>%s", sym->rname);
7844 sprintf (s, "#(%s >> %d)",
7848 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7852 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7856 /*-----------------------------------------------------------------*/
7857 /* genAssign - generate code for assignment */
7858 /*-----------------------------------------------------------------*/
7860 genAssign (iCode * ic)
7862 operand *result, *right;
7864 // unsigned long lit = 0L;
7866 D(emitcode("; genAssign",""));
7868 result = IC_RESULT (ic);
7869 right = IC_RIGHT (ic);
7871 /* if they are the same */
7872 if (operandsEqu (result, right)) {
7876 aopOp (right, ic, FALSE);
7877 aopOp (result, ic, TRUE);
7879 /* if they are the same registers */
7880 if (sameRegs (AOP (right), AOP (result)))
7883 if ((AOP_TYPE (right) == AOP_LIT)
7884 && (IS_AOP_HX(AOP(result))))
7886 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7891 size = AOP_SIZE (result);
7894 transferAopAop (AOP (right), size, AOP (result), size);
7898 freeAsmop (right, NULL, ic, TRUE);
7899 freeAsmop (result, NULL, ic, TRUE);
7902 /*-----------------------------------------------------------------*/
7903 /* genJumpTab - generates code for jump table */
7904 /*-----------------------------------------------------------------*/
7906 genJumpTab (iCode * ic)
7909 symbol *jtablo = newiTempLabel (NULL);
7910 symbol *jtabhi = newiTempLabel (NULL);
7912 D(emitcode ("; genJumpTab",""));
7914 aopOp (IC_JTCOND (ic), ic, FALSE);
7916 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7918 /* get the condition into x */
7919 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7920 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7921 loadRegFromConst (hc08_reg_h, zero);
7923 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7924 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7925 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7926 emitcode ("jmp", ",x");
7928 hc08_dirtyReg (hc08_reg_a, TRUE);
7929 hc08_dirtyReg (hc08_reg_hx, TRUE);
7934 pushReg(hc08_reg_hx, TRUE);
7936 /* get the condition into x */
7937 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7938 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7939 loadRegFromConst (hc08_reg_h, zero);
7941 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7942 emitcode ("sta", "3,s");
7943 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7944 emitcode ("sta", "4,s");
7946 pullReg(hc08_reg_hx);
7947 emitcode ("rts", "");
7948 _G.stackPushes += 2;
7952 /* now generate the jump labels */
7954 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7955 jtab = setNextItem (IC_JTLABELS (ic)))
7956 emitcode (".db", "%05d$", jtab->key + 100);
7958 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7959 jtab = setNextItem (IC_JTLABELS (ic)))
7960 emitcode (".db", ">%05d$", jtab->key + 100);
7964 /*-----------------------------------------------------------------*/
7965 /* genCast - gen code for casting */
7966 /*-----------------------------------------------------------------*/
7968 genCast (iCode * ic)
7970 operand *result = IC_RESULT (ic);
7971 sym_link *ctype = operandType (IC_LEFT (ic));
7972 sym_link *rtype = operandType (IC_RIGHT (ic));
7973 operand *right = IC_RIGHT (ic);
7976 D(emitcode("; genCast",""));
7978 /* if they are equivalent then do nothing */
7979 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7982 aopOp (right, ic, FALSE);
7983 aopOp (result, ic, FALSE);
7986 /* if they are the same size : or less */
7987 if (AOP_SIZE (result) <= AOP_SIZE (right))
7990 /* if they are in the same place */
7992 if (sameRegs (AOP (right), AOP (result)))
7996 /* if they in different places then copy */
7997 size = AOP_SIZE (result);
8001 transferAopAop(AOP (right), offset, AOP (result), offset);
8008 /* if the result is of type pointer */
8013 sym_link *type = operandType (right);
8014 sym_link *etype = getSpec (type);
8016 /* pointer to generic pointer */
8017 if (IS_GENPTR (ctype))
8020 p_type = DCL_TYPE (type);
8023 if (SPEC_SCLS(etype)==S_REGISTER) {
8024 // let's assume it is a generic pointer
8027 /* we have to go by the storage class */
8028 p_type = PTR_TYPE (SPEC_OCLS (etype));
8032 /* the first two bytes are known */
8033 size = GPTRSIZE - 1;
8037 transferAopAop(AOP (right), offset, AOP (result), offset);
8040 /* the last byte depending on type */
8043 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8048 // pointerTypeToGPByte will have bitched.
8052 sprintf(gpValStr, "#0x%x", gpVal);
8053 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8059 /* just copy the pointers */
8060 size = AOP_SIZE (result);
8064 transferAopAop(AOP (right), offset, AOP (result), offset);
8070 /* so we now know that the size of destination is greater
8071 than the size of the source */
8072 /* we move to result for the size of source */
8073 size = AOP_SIZE (right);
8077 transferAopAop(AOP (right), offset, AOP (result), offset);
8081 /* now depending on the sign of the source && destination */
8082 size = AOP_SIZE (result) - AOP_SIZE (right);
8083 /* if unsigned or not an integral type */
8084 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8087 storeConstToAop (zero, AOP (result), offset++);
8091 /* we need to extend the sign :{ */
8092 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8093 accopWithMisc ("rola", "");
8094 accopWithMisc ("clra", "");
8095 accopWithMisc ("sbc", zero);
8097 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8100 /* we are done hurray !!!! */
8103 freeAsmop (right, NULL, ic, TRUE);
8104 freeAsmop (result, NULL, ic, TRUE);
8108 /*-----------------------------------------------------------------*/
8109 /* genDjnz - generate decrement & jump if not zero instrucion */
8110 /*-----------------------------------------------------------------*/
8112 genDjnz (iCode * ic, iCode * ifx)
8118 D(emitcode ("; genDjnz",""));
8120 /* if the if condition has a false label
8121 then we cannot save */
8125 /* if the minus is not of the form
8127 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8128 !IS_OP_LITERAL (IC_RIGHT (ic)))
8131 if (operandLitValue (IC_RIGHT (ic)) != 1)
8134 /* dbnz doesn't support extended mode */
8135 if (isOperandInFarSpace (IC_RESULT (ic)))
8138 /* if the size of this greater than one then no
8140 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8142 aopOp (IC_RESULT (ic), ic, FALSE);
8143 if (AOP_SIZE (IC_RESULT (ic))>1)
8145 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8149 /* otherwise we can save BIG */
8150 lbl = newiTempLabel (NULL);
8151 lbl1 = newiTempLabel (NULL);
8154 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8157 emitBranch ("bra", lbl1);
8159 emitBranch ("jmp", IC_TRUE (ifx));
8162 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8167 /*-----------------------------------------------------------------*/
8168 /* genReceive - generate code for a receive iCode */
8169 /*-----------------------------------------------------------------*/
8171 genReceive (iCode * ic)
8175 D(emitcode ("; genReceive",""));
8177 aopOp (IC_RESULT (ic), ic, FALSE);
8178 size = AOP_SIZE (IC_RESULT (ic));
8183 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8184 AOP (IC_RESULT (ic)), offset);
8185 if (hc08_aop_pass[offset]->type == AOP_REG)
8186 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8191 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8194 /*-----------------------------------------------------------------*/
8195 /* genDummyRead - generate code for dummy read of volatiles */
8196 /*-----------------------------------------------------------------*/
8198 genDummyRead (iCode * ic)
8203 D(emitcode("; genDummyRead",""));
8206 if (op && IS_SYMOP (op))
8209 aopOp (op, ic, FALSE);
8211 size = AOP_SIZE (op);
8216 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8217 hc08_freeReg (hc08_reg_a);
8221 freeAsmop (op, NULL, ic, TRUE);
8224 if (op && IS_SYMOP (op))
8227 aopOp (op, ic, FALSE);
8229 size = AOP_SIZE (op);
8234 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8235 hc08_freeReg (hc08_reg_a);
8239 freeAsmop (op, NULL, ic, TRUE);
8243 /*-----------------------------------------------------------------*/
8244 /* genCritical - generate code for start of a critical sequence */
8245 /*-----------------------------------------------------------------*/
8247 genCritical (iCode *ic)
8249 D(emitcode("; genCritical",""));
8252 aopOp (IC_RESULT (ic), ic, TRUE);
8254 emitcode ("tpa", "");
8255 hc08_dirtyReg (hc08_reg_a, FALSE);
8256 emitcode ("sei", "");
8259 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8261 pushReg (hc08_reg_a, FALSE);
8263 hc08_freeReg (hc08_reg_a);
8265 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8268 /*-----------------------------------------------------------------*/
8269 /* genEndCritical - generate code for end of a critical sequence */
8270 /*-----------------------------------------------------------------*/
8272 genEndCritical (iCode *ic)
8274 D(emitcode("; genEndCritical",""));
8278 aopOp (IC_RIGHT (ic), ic, FALSE);
8279 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8280 emitcode ("tap", "");
8281 hc08_freeReg (hc08_reg_a);
8282 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8286 pullReg (hc08_reg_a);
8287 emitcode ("tap", "");
8293 /*-----------------------------------------------------------------*/
8294 /* genhc08Code - generate code for HC08 based controllers */
8295 /*-----------------------------------------------------------------*/
8297 genhc08Code (iCode * lic)
8304 lineHead = lineCurr = NULL;
8306 /* print the allocation information */
8307 if (allocInfo && currFunc)
8308 printAllocInfo (currFunc, codeOutFile);
8309 /* if debug information required */
8310 if (options.debug && currFunc)
8312 debugFile->writeFunction (currFunc, lic);
8315 if (IS_STATIC (currFunc->etype))
8316 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8318 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8322 /* stack pointer name */
8323 if (options.useXstack)
8328 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8330 hc08_aop_pass[0] = newAsmop (AOP_REG);
8331 hc08_aop_pass[0]->size=1;
8332 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8333 hc08_aop_pass[1] = newAsmop (AOP_REG);
8334 hc08_aop_pass[1]->size=1;
8335 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8336 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8337 hc08_aop_pass[2]->size=1;
8338 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8339 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8340 hc08_aop_pass[3]->size=1;
8341 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8343 for (ic = lic; ic; ic = ic->next)
8346 _G.current_iCode = ic;
8348 if (ic->level != clevel || ic->block != cblock)
8352 debugFile->writeScope(ic);
8358 if (ic->lineno && cln != ic->lineno)
8362 debugFile->writeCLine(ic);
8365 emitcode ("", "C$%s$%d$%d$%d ==.",
8366 FileBaseName (ic->filename), ic->lineno,
8367 ic->level, ic->block);
8371 if (!options.noCcodeInAsm) {
8372 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8373 printCLine(ic->filename, ic->lineno));
8377 if (options.iCodeInAsm) {
8381 for (i=0; i<6; i++) {
8382 sprintf (®sInUse[i],
8383 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8386 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8388 /* if the result is marked as
8389 spilt and rematerializable or code for
8390 this has already been generated then
8392 if (resultRemat (ic) || ic->generated)
8400 for (i=A_IDX;i<=XA_IDX;i++)
8402 reg = hc08_regWithIdx(i);
8404 emitcode("","; %s = %s offset %d", reg->name,
8405 aopName(reg->aop), reg->aopofs);
8408 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8410 sym = OP_SYMBOL (IC_LEFT (ic));
8411 if (sym->accuse == ACCUSE_HX)
8413 hc08_reg_h->isFree = FALSE;
8414 hc08_reg_x->isFree = FALSE;
8416 else if (sym->accuse == ACCUSE_XA)
8418 hc08_reg_a->isFree = FALSE;
8420 hc08_reg_x->isFree = FALSE;
8423 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8425 sym = OP_SYMBOL (IC_RIGHT (ic));
8426 if (sym->accuse == ACCUSE_HX)
8428 hc08_reg_h->isFree = FALSE;
8429 hc08_reg_x->isFree = FALSE;
8431 else if (sym->accuse == ACCUSE_XA)
8433 hc08_reg_a->isFree = FALSE;
8435 hc08_reg_x->isFree = FALSE;
8440 /* depending on the operation */
8460 /* IPOP happens only when trying to restore a
8461 spilt live range, if there is an ifx statement
8462 following this pop then the if statement might
8463 be using some of the registers being popped which
8464 would destory the contents of the register so
8465 we need to check for this condition and handle it */
8467 ic->next->op == IFX &&
8468 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8469 genIfx (ic->next, ic);
8487 genEndFunction (ic);
8503 if (!genPointerGetSetOfs (ic))
8508 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8528 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8533 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8545 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8549 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8553 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8580 case GET_VALUE_AT_ADDRESS:
8582 hasInc (IC_LEFT (ic), ic,
8583 getSize (operandType (IC_RESULT (ic)))),
8584 ifxForOp (IC_RESULT (ic), ic) );
8588 if (POINTER_SET (ic))
8589 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8615 addSet (&_G.sendSet, ic);
8618 case DUMMY_READ_VOLATILE:
8627 genEndCritical (ic);
8638 if (!hc08_reg_a->isFree)
8639 D(emitcode("","; forgot to free a"));
8640 if (!hc08_reg_x->isFree)
8641 D(emitcode("","; forgot to free x"));
8642 if (!hc08_reg_h->isFree)
8643 D(emitcode("","; forgot to free h"));
8644 if (!hc08_reg_hx->isFree)
8645 D(emitcode("","; forgot to free hx"));
8646 if (!hc08_reg_xa->isFree)
8647 D(emitcode("","; forgot to free xa"));
8650 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8653 /* now we are ready to call the
8654 peep hole optimizer */
8655 if (!options.nopeep)
8656 peepHole (&lineHead);
8658 /* now do the actual printing */
8659 printLine (lineHead, codeOutFile);