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)
1153 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1155 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1159 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1161 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1165 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1166 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1167 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1168 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1170 if (dstofs >= dstaop->size)
1173 if ((dstaop->type == AOP_DIR)
1174 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1176 if (srcaop->type == AOP_LIT)
1179 unsigned long bytemask;
1181 lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
1182 bytemask = (lit >> (srcofs*8)) & 0xff;
1186 emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
1191 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1192 aopAdrStr(dstaop, dstofs, FALSE));
1196 if (dstaop->type == AOP_REG)
1198 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1199 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1201 reg = dstaop->aopu.aop_reg[dstofs];
1206 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1208 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1209 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1211 reg = srcaop->aopu.aop_reg[srcofs];
1218 if (hc08_reg_a->isFree)
1220 else if (hc08_reg_x->isFree)
1224 pushReg (hc08_reg_a, TRUE);
1230 loadRegFromAop (reg, srcaop, srcofs);
1231 storeRegToAop (reg, dstaop, dstofs);
1234 pullOrFreeReg (hc08_reg_a, needpula);
1238 /*--------------------------------------------------------------------------*/
1239 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1240 /* parameter param. */
1241 /*--------------------------------------------------------------------------*/
1243 accopWithMisc (char *accop, char *param)
1245 emitcode (accop, "%s", param);
1246 hc08_dirtyReg (hc08_reg_a, FALSE);
1249 /*--------------------------------------------------------------------------*/
1250 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1251 /* byte at logical offset loffset of asmop aop. */
1252 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1253 /*--------------------------------------------------------------------------*/
1255 accopWithAop (char *accop, asmop *aop, int loffset)
1257 if (aop->stacked && aop->stk_aop[loffset])
1259 accopWithAop (accop, aop->stk_aop[loffset], 0);
1263 if (aop->type == AOP_DUMMY)
1266 if (aop->type == AOP_REG)
1268 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1269 emitcode (accop, "1,s");
1273 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1275 hc08_dirtyReg (hc08_reg_a, FALSE);
1279 /*--------------------------------------------------------------------------*/
1280 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1281 /* byte at logical offset loffset of asmop aop. Register reg */
1282 /* must be 8-bit. */
1283 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1284 /*--------------------------------------------------------------------------*/
1286 rmwWithReg (char *rmwop, regs *reg)
1289 char *rmwaop = rmwbuf;
1291 if (reg->rIdx == A_IDX)
1293 sprintf(rmwaop,"%sa", rmwop);
1294 emitcode (rmwaop, "");
1295 hc08_dirtyReg (hc08_reg_a, FALSE);
1297 else if (reg->rIdx == X_IDX)
1299 sprintf(rmwaop,"%sx", rmwop);
1300 emitcode (rmwaop, "");
1301 hc08_dirtyReg (hc08_reg_a, FALSE);
1303 else if (hc08_reg_a->isFree)
1305 transferRegReg(reg, hc08_reg_a, FALSE);
1306 sprintf(rmwaop,"%sa", rmwop);
1307 emitcode (rmwaop, "");
1308 hc08_dirtyReg (hc08_reg_a, FALSE);
1309 transferRegReg(hc08_reg_a, reg, TRUE);
1313 pushReg (reg, FALSE);
1314 emitcode (rmwop, "1,s");
1316 hc08_dirtyReg (reg, FALSE);
1320 /*--------------------------------------------------------------------------*/
1321 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1322 /* logical offset loffset of asmop aop. */
1323 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst */
1324 /*--------------------------------------------------------------------------*/
1326 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1328 bool needpula = FALSE;
1330 if (aop->stacked && aop->stk_aop[loffset])
1332 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1339 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1342 needpula = pushRegIfUsed (hc08_reg_a);
1343 loadRegFromAop (hc08_reg_a, aop, loffset);
1344 rmwWithReg (rmwop, hc08_reg_a);
1345 if (strcmp ("tst", rmwop))
1346 storeRegToAop (hc08_reg_a, aop, loffset);
1347 pullOrFreeReg (hc08_reg_a, needpula);
1352 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1358 /*-----------------------------------------------------------------*/
1359 /* newAsmop - creates a new asmOp */
1360 /*-----------------------------------------------------------------*/
1362 newAsmop (short type)
1366 aop = Safe_calloc (1, sizeof (asmop));
1373 /*-----------------------------------------------------------------*/
1374 /* pointerCode - returns the code for a pointer type */
1375 /*-----------------------------------------------------------------*/
1377 pointerCode (sym_link * etype)
1380 return PTR_TYPE (SPEC_OCLS (etype));
1385 /*-----------------------------------------------------------------*/
1386 /* aopForSym - for a true symbol */
1387 /*-----------------------------------------------------------------*/
1389 aopForSym (iCode * ic, symbol * sym, bool result)
1394 wassertl (ic != NULL, "Got a null iCode");
1395 wassertl (sym != NULL, "Got a null symbol");
1397 // printf("in aopForSym for symbol %s\n", sym->name);
1399 space = SPEC_OCLS (sym->etype);
1401 /* if already has one */
1407 /* special case for a function */
1408 if (IS_FUNC (sym->type))
1410 sym->aop = aop = newAsmop (AOP_IMMD);
1411 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1412 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1413 aop->size = FPTRSIZE;
1417 /* if it is in direct space */
1418 if (IN_DIRSPACE (space))
1420 sym->aop = aop = newAsmop (AOP_DIR);
1421 aop->aopu.aop_dir = sym->rname;
1422 aop->size = getSize (sym->type);
1426 /* if it is in far space */
1427 if (IN_FARSPACE (space))
1429 sym->aop = aop = newAsmop (AOP_EXT);
1430 aop->aopu.aop_dir = sym->rname;
1431 aop->size = getSize (sym->type);
1435 if (IN_STACK (sym->etype))
1437 sym->aop = aop = newAsmop (AOP_SOF);
1438 aop->aopu.aop_dir = sym->rname;
1439 aop->size = getSize (sym->type);
1440 aop->aopu.aop_stk = sym->stack;
1446 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1447 "aopForSym should never reach here");
1451 /* if it is in code space */
1452 if (IN_CODESPACE (space))
1458 /*-----------------------------------------------------------------*/
1459 /* aopForRemat - rematerialzes an object */
1460 /*-----------------------------------------------------------------*/
1462 aopForRemat (symbol * sym)
1464 iCode *ic = sym->rematiCode;
1472 val += (int) operandLitValue (IC_RIGHT (ic));
1473 else if (ic->op == '-')
1474 val -= (int) operandLitValue (IC_RIGHT (ic));
1475 else if (IS_CAST_ICODE(ic)) {
1476 sym_link *from_type = operandType(IC_RIGHT(ic));
1477 aop->aopu.aop_immd.from_cast_remat = 1;
1478 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1479 ptr_type = DCL_TYPE(from_type);
1480 if (ptr_type == IPOINTER) {
1487 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1490 if (ic->op == ADDRESS_OF)
1493 sprintf (buffer, "(%s %c 0x%04x)",
1494 OP_SYMBOL (IC_LEFT (ic))->rname,
1495 val >= 0 ? '+' : '-',
1496 abs (val) & 0xffff);
1498 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1500 aop = newAsmop (AOP_IMMD);
1501 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1502 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1503 /* set immd2 field if required */
1504 if (aop->aopu.aop_immd.from_cast_remat)
1506 sprintf(buffer,"#0x%02x",ptr_type);
1507 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1508 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1511 else if (ic->op == '=')
1513 val += (int) operandLitValue (IC_RIGHT (ic));
1515 sprintf (buffer, "0x%04x", val);
1516 aop = newAsmop (AOP_LIT);
1517 aop->aopu.aop_lit = constVal (buffer);
1520 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1521 "unexpected rematerialization");
1528 /*-----------------------------------------------------------------*/
1529 /* regsInCommon - two operands have some registers in common */
1530 /*-----------------------------------------------------------------*/
1532 regsInCommon (operand * op1, operand * op2)
1534 symbol *sym1, *sym2;
1537 /* if they have registers in common */
1538 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1541 sym1 = OP_SYMBOL (op1);
1542 sym2 = OP_SYMBOL (op2);
1544 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1547 for (i = 0; i < sym1->nRegs; i++)
1553 for (j = 0; j < sym2->nRegs; j++)
1558 if (sym2->regs[j] == sym1->regs[i])
1566 /*-----------------------------------------------------------------*/
1567 /* operandsEqu - equivalent */
1568 /*-----------------------------------------------------------------*/
1570 operandsEqu (operand * op1, operand * op2)
1572 symbol *sym1, *sym2;
1574 /* if they not symbols */
1575 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1578 sym1 = OP_SYMBOL (op1);
1579 sym2 = OP_SYMBOL (op2);
1581 /* if both are itemps & one is spilt
1582 and the other is not then false */
1583 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1584 sym1->isspilt != sym2->isspilt)
1587 /* if they are the same */
1591 if (sym1->rname[0] && sym2->rname[0]
1592 && strcmp (sym1->rname, sym2->rname) == 0)
1595 /* if left is a tmp & right is not */
1596 if (IS_ITEMP (op1) &&
1599 (sym1->usl.spillLoc == sym2))
1602 if (IS_ITEMP (op2) &&
1606 (sym2->usl.spillLoc == sym1))
1612 /*-----------------------------------------------------------------*/
1613 /* sameRegs - two asmops have the same registers */
1614 /*-----------------------------------------------------------------*/
1616 sameRegs (asmop * aop1, asmop * aop2)
1623 // if (aop1->size != aop2->size)
1626 if (aop1->type == aop2->type)
1631 for (i = 0; i < aop1->size; i++)
1632 if (aop1->aopu.aop_reg[i] !=
1633 aop2->aopu.aop_reg[i])
1637 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1640 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1647 /*-----------------------------------------------------------------*/
1648 /* aopOp - allocates an asmop for an operand : */
1649 /*-----------------------------------------------------------------*/
1651 aopOp (operand * op, iCode * ic, bool result)
1660 // Is this a pointer set result?
1662 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1666 // printf("checking literal\n");
1667 /* if this a literal */
1668 if (IS_OP_LITERAL (op))
1670 op->aop = aop = newAsmop (AOP_LIT);
1671 aop->aopu.aop_lit = op->operand.valOperand;
1672 aop->size = getSize (operandType (op));
1674 aop->isaddr = op->isaddr;
1678 // printf("checking pre-existing\n");
1679 /* if already has a asmop then continue */
1683 op->aop->isaddr = op->isaddr;
1687 // printf("checking underlying sym\n");
1688 /* if the underlying symbol has a aop */
1689 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1691 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1692 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1693 //op->aop = aop = OP_SYMBOL (op)->aop;
1694 aop->size = getSize( operandType (op));
1695 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1696 //printf (" with size = %d\n", aop->size);
1699 aop->isaddr = op->isaddr;
1700 /* if (aop->isaddr & IS_ITEMP (op))
1702 aop->psize=aop->size;
1703 aop->size = getSize( operandType (op)->next);
1708 // printf("checking true sym\n");
1709 /* if this is a true symbol */
1710 if (IS_TRUE_SYMOP (op))
1712 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1714 aop->isaddr = op->isaddr;
1715 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1716 //printf (" with size = %d\n", aop->size);
1720 /* this is a temporary : this has
1726 e) can be a return use only */
1728 sym = OP_SYMBOL (op);
1730 // printf("checking conditional\n");
1731 /* if the type is a conditional */
1732 if (sym->regType == REG_CND)
1734 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1737 aop->isaddr = op->isaddr;
1741 // printf("checking spilt\n");
1742 /* if it is spilt then two situations
1744 b) has a spill location */
1745 if (sym->isspilt || sym->nRegs == 0)
1748 // printf("checking remat\n");
1749 /* rematerialize it NOW */
1752 sym->aop = op->aop = aop =
1754 aop->size = getSize (sym->type);
1756 aop->isaddr = op->isaddr;
1757 /* if (aop->isaddr & IS_ITEMP (op))
1759 aop->psize=aop->size;
1760 aop->size = getSize( operandType (op)->next);
1765 // printf("checking accuse\n");
1768 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1769 aop->size = getSize (sym->type);
1770 switch (sym->accuse)
1773 aop->aopu.aop_reg[0] = hc08_reg_a;
1774 aop->aopu.aop_reg[1] = hc08_reg_x;
1777 aop->aopu.aop_reg[0] = hc08_reg_x;
1778 aop->aopu.aop_reg[1] = hc08_reg_h;
1782 aop->isaddr = op->isaddr;
1786 // printf("checking ruonly\n");
1792 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1793 aop->size = getSize (sym->type);
1794 for (i = 0; i < fReturnSizeHC08; i++)
1795 aop->aopu.aop_str[i] = fReturn2[i];
1797 aop->isaddr = op->isaddr;
1801 /* else spill location */
1802 if (sym->usl.spillLoc)
1804 if (sym->usl.spillLoc->aop
1805 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1807 /* force a new aop if sizes differ */
1808 sym->usl.spillLoc->aop = NULL;
1809 //printf ("forcing new aop\n");
1811 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1812 aop->size = getSize (sym->type);
1814 aop->isaddr = op->isaddr;
1815 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1816 //printf (" with size = %d\n", aop->size);
1820 /* else must be a dummy iTemp */
1821 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1822 aop->size = getSize (sym->type);
1826 // printf("assuming register\n");
1827 /* must be in a register */
1828 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1829 aop->size = sym->nRegs;
1830 for (i = 0; i < sym->nRegs; i++)
1831 aop->aopu.aop_reg[i] = sym->regs[i];
1833 aop->isaddr = op->isaddr;
1837 /*-----------------------------------------------------------------*/
1838 /* freeAsmop - free up the asmop given to an operand */
1839 /*----------------------------------------------------------------*/
1841 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1863 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1866 for (loffset=0; loffset<aop->size; loffset++)
1867 if (aop->stk_aop[loffset])
1869 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1872 pullNull (stackAdjust);
1876 /* all other cases just dealloc */
1882 OP_SYMBOL (op)->aop = NULL;
1883 /* if the symbol has a spill */
1885 SPIL_LOC (op)->aop = NULL;
1891 /*-----------------------------------------------------------------*/
1892 /* aopDerefAop - treating the aop parameter as a pointer, return */
1893 /* an asmop for the object it references */
1894 /*-----------------------------------------------------------------*/
1896 aopDerefAop (asmop *aop)
1901 asmop *newaop = NULL;
1902 sym_link *type, *etype;
1905 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1909 type = operandType (aop->op);
1910 etype = getSpec (type);
1911 /* if op is of type of pointer then it is simple */
1912 if (IS_PTR (type) && !IS_FUNC (type->next))
1913 p_type = DCL_TYPE (type);
1916 /* we have to go by the storage class */
1917 p_type = PTR_TYPE (SPEC_OCLS (etype));
1926 if (p_type == POINTER)
1927 newaop = newAsmop (AOP_DIR);
1929 newaop = newAsmop (AOP_EXT);
1930 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1933 adr = (int) floatFromVal (aop->aopu.aop_lit);
1934 if (p_type == POINTER)
1939 newaop = newAsmop (AOP_DIR);
1940 sprintf (s, "0x%02x",adr);
1944 newaop = newAsmop (AOP_EXT);
1945 sprintf (s, "0x%04x",adr);
1947 rs = Safe_calloc (1, strlen (s) + 1);
1949 newaop->aopu.aop_dir = rs;
1952 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1953 "unsupported asmop");
1963 /*-----------------------------------------------------------------*/
1964 /* aopAdrStr - for referencing the address of the aop */
1965 /*-----------------------------------------------------------------*/
1967 aopAdrStr (asmop * aop, int loffset, bool bit16)
1971 int offset = aop->size - 1 - loffset;
1974 /* offset is greater than
1976 if (loffset > (aop->size - 1) &&
1977 aop->type != AOP_LIT)
1980 /* depending on type */
1988 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1989 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1991 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1995 sprintf (s, "#(%s >> %d)",
1996 aop->aopu.aop_immd.aop_immd1,
2000 aop->aopu.aop_immd.aop_immd1);
2004 aop->aopu.aop_immd.aop_immd1);
2005 rs = Safe_calloc (1, strlen (s) + 1);
2011 sprintf (s, "*(%s + %d)",
2015 sprintf (s, "*%s", aop->aopu.aop_dir);
2016 rs = Safe_calloc (1, strlen (s) + 1);
2022 sprintf (s, "(%s + %d)",
2026 sprintf (s, "%s", aop->aopu.aop_dir);
2027 rs = Safe_calloc (1, strlen (s) + 1);
2032 return aop->aopu.aop_reg[loffset]->name;
2036 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
2038 return aopLiteral (aop->aopu.aop_lit, loffset);
2042 return aop->aopu.aop_str[loffset];
2045 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
2047 rs = Safe_calloc (1, strlen (s) + 1);
2053 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2054 "aopAdrStr got unsupported aop->type");
2063 /*-----------------------------------------------------------------*/
2064 /* opIsGptr: returns non-zero if the passed operand is */
2065 /* a generic pointer type. */
2066 /*-----------------------------------------------------------------*/
2068 opIsGptr (operand * op)
2070 sym_link *type = operandType (op);
2072 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
2080 /*-----------------------------------------------------------------*/
2081 /* getDataSize - get the operand data size */
2082 /*-----------------------------------------------------------------*/
2084 getDataSize (operand * op)
2087 size = AOP_SIZE (op);
2092 /*-----------------------------------------------------------------*/
2093 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2094 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2095 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2096 /*-----------------------------------------------------------------*/
2098 asmopToBool (asmop *aop, bool resultInA)
2100 symbol *tlbl, *tlbl1;
2101 int size = aop->size;
2102 bool needpula = FALSE;
2103 bool flagsonly = TRUE;
2108 hc08_freeReg(hc08_reg_a);
2115 emitcode ("tsta", "");
2118 else if (IS_AOP_X(aop))
2119 emitcode ("tstx", "");
2120 else if (IS_AOP_H(aop))
2122 if (hc08_reg_a->isFree)
2124 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2125 emitcode ("tsta", "");
2127 hc08_freeReg(hc08_reg_a);
2129 else if (hc08_reg_x->isFree)
2131 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2132 emitcode ("tstx", "");
2133 hc08_freeReg(hc08_reg_x);
2137 emitcode ("pshh", "");
2138 emitcode ("tst", "1,s");
2139 emitcode ("ais", "#1");
2142 else if (IS_AOP_HX(aop))
2143 emitcode ("cphx", zero);
2144 else if (IS_AOP_XA(aop))
2146 symbol *tlbl = newiTempLabel (NULL);
2147 emitcode ("tsta", "");
2148 emitcode ("bne", "%05d$", (tlbl->key + 100));
2149 emitcode ("tstx", "");
2150 emitcode ("", "%05d$:", (tlbl->key + 100));
2154 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2155 "Bad rIdx in asmToBool");
2163 needpula = pushRegIfUsed (hc08_reg_a);
2164 loadRegFromAop (hc08_reg_a, aop, 0);
2165 for (offset=1; offset<size; offset++)
2166 accopWithAop ("ora", aop, offset);
2168 pullReg (hc08_reg_a);
2171 hc08_freeReg (hc08_reg_a);
2176 /* Higher levels should optimize this case away but let's be safe */
2177 if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
2178 loadRegFromConst (hc08_reg_a, one);
2180 loadRegFromConst (hc08_reg_a, zero);
2181 hc08_freeReg(hc08_reg_a);
2188 loadRegFromAop (hc08_reg_a, aop, 0);
2189 hc08_freeReg (hc08_reg_a);
2193 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2198 if (hc08_reg_a->isFree)
2200 loadRegFromAop (hc08_reg_a, aop, 0);
2201 accopWithAop ("ora", aop, 1);
2202 hc08_freeReg (hc08_reg_a);
2207 tlbl = newiTempLabel (NULL);
2208 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2209 emitcode ("bne", "%05d$", (tlbl->key + 100));
2210 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2211 emitcode ("", "%05d$:", (tlbl->key + 100));
2217 needpula = pushRegIfUsed (hc08_reg_a);
2218 loadRegFromAop (hc08_reg_a, aop, 0);
2219 for (offset=1; offset<size; offset++)
2220 accopWithAop ("ora", aop, offset);
2222 pullReg (hc08_reg_a);
2225 hc08_freeReg (hc08_reg_a);
2233 tlbl = newiTempLabel (NULL);
2237 tlbl1 = newiTempLabel (NULL);
2238 emitBranch ("bne", tlbl1);
2239 loadRegFromConst (hc08_reg_a, zero);
2240 emitBranch ("bra", tlbl);
2242 loadRegFromConst (hc08_reg_a, one);
2246 emitBranch ("beq", tlbl);
2247 loadRegFromConst (hc08_reg_a, one);
2250 hc08_useReg (hc08_reg_a);
2256 /*-----------------------------------------------------------------*/
2257 /* genNot - generate code for ! operation */
2258 /*-----------------------------------------------------------------*/
2262 D(emitcode ("; genNot",""));
2264 /* assign asmOps to operand & result */
2265 aopOp (IC_LEFT (ic), ic, FALSE);
2266 aopOp (IC_RESULT (ic), ic, TRUE);
2268 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2269 emitcode ("eor", one);
2270 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2272 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2273 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2277 /*-----------------------------------------------------------------*/
2278 /* genCpl - generate code for complement */
2279 /*-----------------------------------------------------------------*/
2285 regs* reg = hc08_reg_a;
2289 D(emitcode ("; genCpl",""));
2291 /* assign asmOps to operand & result */
2292 aopOp (IC_LEFT (ic), ic, FALSE);
2293 aopOp (IC_RESULT (ic), ic, TRUE);
2295 size = AOP_SIZE (IC_RESULT (ic));
2298 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2299 rmwWithReg ("com", reg);
2301 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2306 /* release the aops */
2307 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2308 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2311 /*-----------------------------------------------------------------*/
2312 /* genUminusFloat - unary minus for floating points */
2313 /*-----------------------------------------------------------------*/
2315 genUminusFloat (operand * op, operand * result)
2317 int size, offset = 0;
2320 D(emitcode ("; genUminusFloat",""));
2322 /* for this we just copy and then flip the bit */
2324 size = AOP_SIZE (op) - 1;
2328 transferAopAop (AOP (op), offset, AOP (result), offset);
2332 needpula = pushRegIfUsed (hc08_reg_a);
2333 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2334 emitcode ("eor", "#0x80");
2335 hc08_useReg (hc08_reg_a);
2336 storeRegToAop (hc08_reg_a, AOP (result), offset);
2337 pullOrFreeReg (hc08_reg_a, needpula);
2340 /*-----------------------------------------------------------------*/
2341 /* genUminus - unary minus code generation */
2342 /*-----------------------------------------------------------------*/
2344 genUminus (iCode * ic)
2347 sym_link *optype, *rtype;
2352 D(emitcode ("; genUminus",""));
2355 aopOp (IC_LEFT (ic), ic, FALSE);
2356 aopOp (IC_RESULT (ic), ic, TRUE);
2358 optype = operandType (IC_LEFT (ic));
2359 rtype = operandType (IC_RESULT (ic));
2361 /* if float then do float stuff */
2362 if (IS_FLOAT (optype))
2364 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2368 /* otherwise subtract from zero */
2369 size = AOP_SIZE (IC_LEFT (ic));
2374 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2375 needpula = pushRegIfUsed (hc08_reg_a);
2378 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2379 emitcode ("nega", "");
2380 hc08_freeReg (hc08_reg_a);
2381 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2382 SPEC_USIGN (operandType (IC_LEFT (ic))));
2383 pullOrFreeReg (hc08_reg_a, needpula);
2387 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2388 result = forceStackedAop (AOP (IC_RESULT (ic)));
2390 result = AOP (IC_RESULT (ic));
2392 needpula = pushRegIfUsed (hc08_reg_a);
2396 loadRegFromConst (hc08_reg_a, zero);
2397 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2398 storeRegToAop (hc08_reg_a, result, offset++);
2401 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2402 SPEC_USIGN (operandType (IC_LEFT (ic))));
2403 pullOrFreeReg (hc08_reg_a, needpula);
2405 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2406 freeAsmop (NULL, result, ic, TRUE);
2412 /* release the aops */
2413 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2414 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2417 /*-----------------------------------------------------------------*/
2418 /* saveRegisters - will look for a call and save the registers */
2419 /*-----------------------------------------------------------------*/
2421 saveRegisters (iCode * lic)
2428 for (ic = lic; ic; ic = ic->next)
2429 if (ic->op == CALL || ic->op == PCALL)
2434 fprintf (stderr, "found parameter push with no function call\n");
2438 /* if the registers have been saved already or don't need to be then
2442 if (IS_SYMOP(IC_LEFT(ic)) &&
2443 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2444 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2447 /* safe the registers in use at this time but skip the
2448 ones for the result */
2449 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2450 hc08_rUmaskForOp (IC_RESULT(ic)));
2453 for (i = 0; i < hc08_nRegs; i++)
2455 if (bitVectBitValue (rsave, i))
2456 pushReg ( hc08_regWithIdx (i), FALSE);
2460 /*-----------------------------------------------------------------*/
2461 /* unsaveRegisters - pop the pushed registers */
2462 /*-----------------------------------------------------------------*/
2464 unsaveRegisters (iCode * ic)
2469 /* restore the registers in use at this time but skip the
2470 ones for the result */
2471 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2472 hc08_rUmaskForOp (IC_RESULT(ic)));
2474 for (i = hc08_nRegs; i >= 0; i--)
2476 if (bitVectBitValue (rsave, i))
2477 pullReg ( hc08_regWithIdx (i));
2483 /*-----------------------------------------------------------------*/
2485 /*-----------------------------------------------------------------*/
2487 pushSide (operand * oper, int size)
2492 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2493 pushReg ( hc08_reg_a, TRUE);
2497 /*-----------------------------------------------------------------*/
2498 /* assignResultValue - */
2499 /*-----------------------------------------------------------------*/
2501 assignResultValue (operand * oper)
2503 int size = AOP_SIZE (oper);
2507 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2508 if (hc08_aop_pass[offset]->type == AOP_REG)
2509 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2516 /*-----------------------------------------------------------------*/
2517 /* genIpush - genrate code for pushing this gets a little complex */
2518 /*-----------------------------------------------------------------*/
2520 genIpush (iCode * ic)
2522 int size, offset = 0;
2525 D(emitcode ("; genIpush",""));
2527 /* if this is not a parm push : ie. it is spill push
2528 and spill push is always done on the local stack */
2532 /* and the item is spilt then do nothing */
2533 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2536 aopOp (IC_LEFT (ic), ic, FALSE);
2537 size = AOP_SIZE (IC_LEFT (ic));
2539 /* push it on the stack */
2542 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2543 pushReg ( hc08_reg_a, TRUE);
2549 /* this is a paramter push: in this case we call
2550 the routine to find the call and save those
2551 registers that need to be saved */
2554 /* then do the push */
2555 aopOp (IC_LEFT (ic), ic, FALSE);
2558 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2559 size = AOP_SIZE (IC_LEFT (ic));
2562 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2563 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2565 if ((size==2) && hc08_reg_hx->isFree)
2567 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2568 pushReg (hc08_reg_hx, TRUE);
2575 // printf("loading %d\n", offset);
2576 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2577 // printf("pushing \n");
2578 pushReg (hc08_reg_a, TRUE);
2582 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2585 /*-----------------------------------------------------------------*/
2586 /* genIpop - recover the registers: can happen only for spilling */
2587 /*-----------------------------------------------------------------*/
2589 genIpop (iCode * ic)
2593 D(emitcode ("; genIpop",""));
2595 /* if the temp was not pushed then */
2596 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2599 aopOp (IC_LEFT (ic), ic, FALSE);
2600 size = AOP_SIZE (IC_LEFT (ic));
2604 pullReg (hc08_reg_a);
2605 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2607 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2611 /*-----------------------------------------------------------------*/
2612 /* genSend - gen code for SEND */
2613 /*-----------------------------------------------------------------*/
2614 static void genSend(set *sendSet)
2618 for (sic = setFirstItem (sendSet); sic;
2619 sic = setNextItem (sendSet)) {
2620 int size, offset = 0;
2621 aopOp (IC_LEFT (sic), sic, FALSE);
2622 size = AOP_SIZE (IC_LEFT (sic));
2627 transferAopAop( AOP (IC_LEFT (sic)), offset,
2628 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2632 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2636 /*-----------------------------------------------------------------*/
2637 /* genCall - generates a call statement */
2638 /*-----------------------------------------------------------------*/
2640 genCall (iCode * ic)
2643 // bool restoreBank = FALSE;
2644 // bool swapBanks = FALSE;
2646 D(emitcode("; genCall",""));
2648 dtype = operandType (IC_LEFT (ic));
2649 /* if send set is not empty then assign */
2652 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2653 genSend(reverseSet(_G.sendSet));
2655 genSend(_G.sendSet);
2661 /* if caller saves & we have not saved then */
2667 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2668 OP_SYMBOL (IC_LEFT (ic))->rname :
2669 OP_SYMBOL (IC_LEFT (ic))->name));
2672 /* if we need assign a result value */
2673 if ((IS_ITEMP (IC_RESULT (ic)) &&
2674 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2675 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2676 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2677 IS_TRUE_SYMOP (IC_RESULT (ic)))
2681 aopOp (IC_RESULT (ic), ic, FALSE);
2684 assignResultValue (IC_RESULT (ic));
2686 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2689 /* adjust the stack for parameters if
2693 pullNull (ic->parmBytes);
2696 /* if we had saved some registers then unsave them */
2697 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2698 unsaveRegisters (ic);
2702 /*-----------------------------------------------------------------*/
2703 /* -10l - generates a call by pointer statement */
2704 /*-----------------------------------------------------------------*/
2706 genPcall (iCode * ic)
2709 symbol *rlbl = newiTempLabel (NULL);
2710 symbol *tlbl = newiTempLabel (NULL);
2711 // bool restoreBank=FALSE;
2712 // bool swapBanks = FALSE;
2714 D(emitcode("; genPCall",""));
2716 /* if caller saves & we have not saved then */
2720 /* if we are calling a not _naked function that is not using
2721 the same register bank then we need to save the
2722 destination registers on the stack */
2723 dtype = operandType (IC_LEFT (ic))->next;
2725 /* now push the calling address */
2726 emitBranch ("bsr", tlbl);
2727 emitBranch ("bra", rlbl);
2730 /* Push the function's address */
2731 aopOp (IC_LEFT (ic), ic, FALSE);
2732 pushSide (IC_LEFT (ic), FPTRSIZE);
2733 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2735 /* if send set is not empty the assign */
2738 genSend(reverseSet(_G.sendSet));
2744 emitcode ("rts", "");
2749 /* if we need assign a result value */
2750 if ((IS_ITEMP (IC_RESULT (ic)) &&
2751 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2752 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2753 IS_TRUE_SYMOP (IC_RESULT (ic)))
2757 aopOp (IC_RESULT (ic), ic, FALSE);
2760 assignResultValue (IC_RESULT (ic));
2762 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2765 /* adjust the stack for parameters if
2769 pullNull (ic->parmBytes);
2772 /* if we hade saved some registers then
2774 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2775 unsaveRegisters (ic);
2778 /*-----------------------------------------------------------------*/
2779 /* resultRemat - result is rematerializable */
2780 /*-----------------------------------------------------------------*/
2782 resultRemat (iCode * ic)
2784 if (SKIP_IC (ic) || ic->op == IFX)
2787 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2789 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2790 if (sym->remat && !POINTER_SET (ic))
2797 #if defined(__BORLANDC__) || defined(_MSC_VER)
2798 #define STRCASECMP stricmp
2800 #define STRCASECMP strcasecmp
2803 /*-----------------------------------------------------------------*/
2804 /* inExcludeList - return 1 if the string is in exclude Reg list */
2805 /*-----------------------------------------------------------------*/
2807 regsCmp(void *p1, void *p2)
2809 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2813 inExcludeList (char *s)
2815 const char *p = setFirstItem(options.excludeRegsSet);
2817 if (p == NULL || STRCASECMP(p, "none") == 0)
2821 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2824 /*-----------------------------------------------------------------*/
2825 /* genFunction - generated code for function entry */
2826 /*-----------------------------------------------------------------*/
2828 genFunction (iCode * ic)
2830 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2832 iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
2833 int stackAdjust = sym->stack;
2834 int accIsFree = sym->recvSize == 0;
2838 /* create the function header */
2839 emitcode (";", "-----------------------------------------");
2840 emitcode (";", " function %s", sym->name);
2841 emitcode (";", "-----------------------------------------");
2843 emitcode ("", "%s:", sym->rname);
2844 ftype = operandType (IC_LEFT (ic));
2848 debugFile->writeFrameAddress (NULL, hc08_reg_sp, 0);
2850 if (IFFUNC_ISNAKED(ftype))
2852 emitcode(";", "naked function: no prologue.");
2856 /* if this is an interrupt service routine then
2858 if (IFFUNC_ISISR (sym->type))
2861 if (!inExcludeList ("h"))
2862 pushReg (hc08_reg_h, FALSE);
2865 /* For some cases it is worthwhile to perform a RECEIVE iCode */
2866 /* before setting up the stack frame completely. */
2867 while (ric && ric->next && ric->next->op == RECEIVE)
2869 while (ric && IC_RESULT (ric))
2871 symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
2872 int rsymSize = rsym ? getSize(rsym->type) : 0;
2876 if (rsym && rsym->regType == REG_CND)
2878 if (rsym && (rsym->accuse || rsym->ruonly))
2880 if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
2881 rsym = rsym->usl.spillLoc;
2884 /* If the RECEIVE operand immediately spills to the first entry on the */
2885 /* stack, we can push it directly rather than use an sp relative store. */
2886 if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
2890 _G.current_iCode = ric;
2891 D(emitcode ("; genReceive",""));
2892 for (ofs=0; ofs < rsymSize; ofs++)
2894 regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
2895 pushReg (reg, TRUE);
2896 if (reg->rIdx == A_IDX)
2900 _G.current_iCode = ic;
2903 ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
2906 /* adjust the stack for the function */
2909 adjustStack (-stackAdjust);
2911 _G.stackOfs = sym->stack;
2914 /* if critical function then turn interrupts off */
2915 if (IFFUNC_ISCRITICAL (ftype))
2919 /* Function was passed parameters, so make sure A is preserved */
2920 pushReg (hc08_reg_a, FALSE);
2921 pushReg (hc08_reg_a, FALSE);
2922 emitcode ("tpa", "");
2923 emitcode ("sta", "2,s");
2924 emitcode ("sei", "");
2925 pullReg (hc08_reg_a);
2929 /* No passed parameters, so A can be freely modified */
2930 emitcode ("tpa", "");
2931 pushReg (hc08_reg_a, TRUE);
2932 emitcode ("sei", "");
2938 /*-----------------------------------------------------------------*/
2939 /* genEndFunction - generates epilogue for functions */
2940 /*-----------------------------------------------------------------*/
2942 genEndFunction (iCode * ic)
2944 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2946 if (IFFUNC_ISNAKED(sym->type))
2948 emitcode(";", "naked function: no epilogue.");
2949 if (options.debug && currFunc)
2950 debugFile->writeEndFunction (currFunc, ic, 0);
2954 if (IFFUNC_ISCRITICAL (sym->type))
2956 if (!IS_VOID(sym->type->next))
2958 /* Function has return value, so make sure A is preserved */
2959 pushReg (hc08_reg_a, FALSE);
2960 emitcode ("lda", "2,s");
2961 emitcode ("tap", "");
2962 pullReg (hc08_reg_a);
2967 /* Function returns void, so A can be freely modified */
2968 pullReg (hc08_reg_a);
2969 emitcode ("tap", "");
2973 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2979 _G.stackPushes += sym->stack;
2980 adjustStack (sym->stack);
2984 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2988 if (IFFUNC_ISISR (sym->type))
2991 if (!inExcludeList ("h"))
2992 pullReg (hc08_reg_h);
2995 /* if debug then send end of function */
2996 if (options.debug && currFunc)
2998 debugFile->writeEndFunction (currFunc, ic, 1);
3001 emitcode ("rti", "");
3005 if (IFFUNC_CALLEESAVES(sym->type))
3009 /* if any registers used */
3012 /* save the registers used */
3013 for (i = sym->regsUsed->size; i >= 0; i--)
3015 if (bitVectBitValue (sym->regsUsed, i) ||
3016 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
3017 emitcode ("pop", "%s", hc08_regWithIdx (i)->name);
3023 /* if debug then send end of function */
3024 if (options.debug && currFunc)
3026 debugFile->writeEndFunction (currFunc, ic, 1);
3029 emitcode ("rts", "");
3034 /*-----------------------------------------------------------------*/
3035 /* genRet - generate code for return statement */
3036 /*-----------------------------------------------------------------*/
3040 int size, offset = 0;
3043 D(emitcode ("; genRet",""));
3045 /* if we have no return value then
3046 just generate the "ret" */
3050 /* we have something to return then
3051 move the return value into place */
3052 aopOp (IC_LEFT (ic), ic, FALSE);
3053 size = AOP_SIZE (IC_LEFT (ic));
3059 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3066 /* 4 byte return: store value in the global return variable */
3070 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3071 STA (fReturn2[offset--], FALSE);
3072 hc08_freeReg (hc08_reg_a);
3076 /* 2 byte return: store value in x:a */
3077 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3078 hc08_freeReg (hc08_reg_xa);
3081 /* 1 byte return: store value in a */
3082 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3083 hc08_freeReg (hc08_reg_a);
3088 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3091 /* generate a jump to the return label
3092 if the next is not the return statement */
3093 if (!(ic->next && ic->next->op == LABEL &&
3094 IC_LABEL (ic->next) == returnLabel))
3096 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3100 /*-----------------------------------------------------------------*/
3101 /* genLabel - generates a label */
3102 /*-----------------------------------------------------------------*/
3104 genLabel (iCode * ic)
3109 /* For the high level labels we cannot depend on any */
3110 /* register's contents. Amnesia time. */
3111 for (i=A_IDX;i<=XA_IDX;i++)
3113 reg = hc08_regWithIdx(i);
3118 /* special case never generate */
3119 if (IC_LABEL (ic) == entryLabel)
3122 debugFile->writeLabel(IC_LABEL (ic), ic);
3124 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3128 /*-----------------------------------------------------------------*/
3129 /* genGoto - generates a jmp */
3130 /*-----------------------------------------------------------------*/
3132 genGoto (iCode * ic)
3134 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3138 /*-----------------------------------------------------------------*/
3139 /* findLabelBackwards: walks back through the iCode chain looking */
3140 /* for the given label. Returns number of iCode instructions */
3141 /* between that label and given ic. */
3142 /* Returns zero if label not found. */
3143 /*-----------------------------------------------------------------*/
3145 findLabelBackwards (iCode * ic, int key)
3154 /* If we have any pushes or pops, we cannot predict the distance.
3155 I don't like this at all, this should be dealt with in the
3157 if (ic->op == IPUSH || ic->op == IPOP) {
3161 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3171 /*-----------------------------------------------------------------*/
3172 /* genPlusIncr :- does addition with increment if possible */
3173 /*-----------------------------------------------------------------*/
3175 genPlusIncr (iCode * ic)
3183 unsigned int size = getDataSize (IC_RESULT (ic));
3184 unsigned int offset;
3185 symbol *tlbl = NULL;
3187 left = IC_LEFT (ic);
3188 result = IC_RESULT (ic);
3190 /* will try to generate an increment */
3191 /* if the right side is not a literal
3193 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3196 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3198 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3200 if ((IS_AOP_HX (AOP (left)) ||
3201 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3203 && (icount>=-128) && (icount<=127) && (size==2))
3205 if (!IS_AOP_HX (AOP (left)))
3207 needpulx = pushRegIfUsed (hc08_reg_x);
3208 needpulh = pushRegIfUsed (hc08_reg_h);
3215 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3216 emitcode ("aix","#%d", icount);
3217 hc08_dirtyReg (hc08_reg_hx, FALSE);
3218 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3219 pullOrFreeReg (hc08_reg_h, needpulh);
3220 pullOrFreeReg (hc08_reg_x, needpulx);
3224 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3225 sameRegs (AOP (left), AOP (result))));
3227 if ((icount > 255) || (icount<0))
3230 if (!sameRegs (AOP (left), AOP (result)))
3233 D(emitcode ("; genPlusIncr",""));
3236 tlbl = newiTempLabel (NULL);
3241 rmwWithAop ("inc", AOP (result), 0);
3243 emitBranch ("bne", tlbl);
3247 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3248 needpula = pushRegIfUsed (hc08_reg_a);
3251 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3252 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3253 hc08_useReg (hc08_reg_a);
3254 storeRegToAop (hc08_reg_a, AOP (result), 0);
3255 hc08_freeReg (hc08_reg_a);
3257 emitBranch ("bcc", tlbl);
3259 for (offset=1; offset<size; offset++)
3261 rmwWithAop ("inc", AOP (result), offset);
3262 if ((offset+1)<size)
3263 emitBranch ("bne", tlbl);
3269 pullOrFreeReg (hc08_reg_a, needpula);
3276 /*-----------------------------------------------------------------*/
3277 /* genPlus - generates code for addition */
3278 /*-----------------------------------------------------------------*/
3280 genPlus (iCode * ic)
3282 int size, offset = 0;
3284 asmop *leftOp, *rightOp;
3286 /* special cases :- */
3288 D(emitcode ("; genPlus",""));
3290 aopOp (IC_LEFT (ic), ic, FALSE);
3291 aopOp (IC_RIGHT (ic), ic, FALSE);
3292 aopOp (IC_RESULT (ic), ic, TRUE);
3294 /* we want registers on the left and literals on the right */
3295 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3296 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3298 operand *t = IC_RIGHT (ic);
3299 IC_RIGHT (ic) = IC_LEFT (ic);
3304 /* if I can do an increment instead
3305 of add then GOOD for ME */
3306 if (genPlusIncr (ic) == TRUE)
3309 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3310 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3311 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3313 size = getDataSize (IC_RESULT (ic));
3315 leftOp = AOP(IC_LEFT(ic));
3316 rightOp = AOP(IC_RIGHT(ic));
3322 loadRegFromAop (hc08_reg_a, leftOp, offset);
3323 accopWithAop(add, rightOp, offset);
3324 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3325 hc08_freeReg (hc08_reg_a);
3326 add = "adc"; /* further adds must propagate carry */
3330 // adjustArithmeticResult (ic);
3333 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3334 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3335 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3338 /*-----------------------------------------------------------------*/
3339 /* genMinusDec :- does subtraction with decrement if possible */
3340 /*-----------------------------------------------------------------*/
3342 genMinusDec (iCode * ic)
3344 unsigned int icount;
3349 unsigned int size = getDataSize (IC_RESULT (ic));
3353 left = IC_LEFT (ic);
3354 result = IC_RESULT (ic);
3356 /* will try to generate an increment */
3357 /* if the right side is not a literal
3359 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3362 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3364 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3365 && (icount>=-127) && (icount<=128) && (size==2))
3367 if (!IS_AOP_HX (AOP (left)))
3369 needpulx = pushRegIfUsed (hc08_reg_x);
3370 needpulh = pushRegIfUsed (hc08_reg_h);
3377 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3378 emitcode ("aix","#%d", -icount);
3379 hc08_dirtyReg (hc08_reg_hx, FALSE);
3380 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3381 pullOrFreeReg (hc08_reg_h, needpulh);
3382 pullOrFreeReg (hc08_reg_x, needpulx);
3386 if ((icount > 1) || (icount<0))
3389 if (!sameRegs (AOP (left), AOP (result)))
3395 D(emitcode ("; genMinusDec",""));
3397 rmwWithAop ("dec", AOP (result), 0);
3402 /*-----------------------------------------------------------------*/
3403 /* addSign - complete with sign */
3404 /*-----------------------------------------------------------------*/
3406 addSign (operand * result, int offset, int sign)
3408 int size = (getDataSize (result) - offset);
3413 emitcode ("rola", "");
3414 emitcode ("clra", "");
3415 emitcode ("sbc", zero);
3417 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3421 storeConstToAop (zero, AOP (result), offset++);
3426 /*-----------------------------------------------------------------*/
3427 /* genMinus - generates code for subtraction */
3428 /*-----------------------------------------------------------------*/
3430 genMinus (iCode * ic)
3433 int size, offset = 0;
3435 asmop *leftOp, *rightOp;
3437 D(emitcode ("; genMinus",""));
3439 aopOp (IC_LEFT (ic), ic, FALSE);
3440 aopOp (IC_RIGHT (ic), ic, FALSE);
3441 aopOp (IC_RESULT (ic), ic, TRUE);
3443 /* special cases :- */
3444 /* if I can do an decrement instead
3445 of subtract then GOOD for ME */
3446 if (genMinusDec (ic) == TRUE)
3449 size = getDataSize (IC_RESULT (ic));
3452 leftOp = AOP(IC_LEFT(ic));
3453 rightOp = AOP(IC_RIGHT(ic));
3457 if (IS_AOP_A (rightOp))
3459 loadRegFromAop ( hc08_reg_a, rightOp, offset);
3460 accopWithAop (sub, leftOp, offset);
3461 accopWithMisc ("nega", "");
3462 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3468 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3469 accopWithAop (sub, rightOp, offset);
3470 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3475 // adjustArithmeticResult (ic);
3478 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3479 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3480 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3485 /*-----------------------------------------------------------------*/
3486 /* genMultOneByte : 8*8=8/16 bit multiplication */
3487 /*-----------------------------------------------------------------*/
3489 genMultOneByte (operand * left,
3493 /* sym_link *opetype = operandType (result); */
3494 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3495 int size=AOP_SIZE(result);
3496 bool negLiteral = FALSE;
3497 bool lUnsigned, rUnsigned;
3499 D(emitcode ("; genMultOneByte",""));
3501 if (size<1 || size>2) {
3502 // this should never happen
3503 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3504 AOP_SIZE(result), __FILE__, lineno);
3508 /* (if two literals: the value is computed before) */
3509 /* if one literal, literal on the right */
3510 if (AOP_TYPE (left) == AOP_LIT)
3516 /* if an operand is in A, make sure it is on the left */
3517 if (IS_AOP_A (AOP (right)))
3524 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3525 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3527 /* lUnsigned rUnsigned negLiteral negate case */
3528 /* false false false odd 3 */
3529 /* false false true even 3 */
3530 /* false true false odd 3 */
3531 /* false true true impossible */
3532 /* true false false odd 3 */
3533 /* true false true always 2 */
3534 /* true true false never 1 */
3535 /* true true true impossible */
3539 || (lUnsigned && rUnsigned))
3541 // just an unsigned 8*8=8/16 multiply
3542 //D(emitcode (";","unsigned"));
3544 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3545 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3546 emitcode ("mul", "");
3547 hc08_dirtyReg (hc08_reg_xa, FALSE);
3548 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3549 hc08_freeReg (hc08_reg_xa);
3554 // we have to do a signed multiply
3557 /* left unsigned, right signed literal -- literal determines sign handling */
3558 if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
3560 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3562 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3564 emitcode ("ldx", "#0x%02x", -val);
3566 emitcode ("ldx", "#0x%02x", val);
3568 emitcode ("mul", "");
3572 rmwWithReg ("neg", hc08_reg_a);
3573 tlbl4 = newiTempLabel (NULL);
3574 emitBranch ("bcc", tlbl4);
3575 rmwWithReg ("inc", hc08_reg_x);
3577 rmwWithReg ("neg", hc08_reg_x);
3580 hc08_dirtyReg (hc08_reg_xa, FALSE);
3581 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3582 hc08_freeReg (hc08_reg_xa);
3589 emitcode ("clr", "1,s");
3591 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3594 tlbl1 = newiTempLabel (NULL);
3595 emitcode ("tsta","");
3596 emitBranch ("bpl", tlbl1);
3597 emitcode ("inc", "1,s");
3598 rmwWithReg ("neg", hc08_reg_a);
3602 if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
3604 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
3605 /* AND literal negative */
3607 emitcode ("ldx", "#0x%02x", -val);
3610 emitcode ("ldx", "#0x%02x", val);
3612 hc08_useReg (hc08_reg_x);
3616 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3619 tlbl2 = newiTempLabel (NULL);
3620 emitcode ("tstx", "");
3621 emitBranch ("bpl", tlbl2);
3622 emitcode ("inc", "1,s");
3623 rmwWithReg ("neg", hc08_reg_x);
3628 emitcode ("mul", "");
3629 hc08_dirtyReg (hc08_reg_xa, FALSE);
3631 tlbl3 = newiTempLabel (NULL);
3632 emitcode ("dec", "1,s");
3633 if (!lUnsigned && !rUnsigned && negLiteral)
3634 emitBranch ("beq", tlbl3);
3636 emitBranch ("bne", tlbl3);
3638 rmwWithReg ("neg", hc08_reg_a);
3639 tlbl4 = newiTempLabel (NULL);
3640 emitBranch ("bcc", tlbl4);
3641 rmwWithReg ("inc", hc08_reg_x);
3643 rmwWithReg ("neg", hc08_reg_x);
3647 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3648 hc08_freeReg (hc08_reg_xa);
3652 /*-----------------------------------------------------------------*/
3653 /* genMult - generates code for multiplication */
3654 /*-----------------------------------------------------------------*/
3656 genMult (iCode * ic)
3658 operand *left = IC_LEFT (ic);
3659 operand *right = IC_RIGHT (ic);
3660 operand *result = IC_RESULT (ic);
3662 D(emitcode ("; genMult",""));
3664 /* assign the amsops */
3665 aopOp (left, ic, FALSE);
3666 aopOp (right, ic, FALSE);
3667 aopOp (result, ic, TRUE);
3669 /* special cases first */
3670 /* if both are of size == 1 */
3671 // if (getSize(operandType(left)) == 1 &&
3672 // getSize(operandType(right)) == 1)
3673 if (AOP_SIZE (left) == 1 &&
3674 AOP_SIZE (right) == 1)
3676 genMultOneByte (left, right, result);
3680 /* should have been converted to function call */
3681 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3682 getSize(OP_SYMBOL(right)->type));
3683 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3688 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3689 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3690 freeAsmop (result, NULL, ic, TRUE);
3693 /*-----------------------------------------------------------------*/
3694 /* genDivOneByte : 8 bit division */
3695 /*-----------------------------------------------------------------*/
3697 genDivOneByte (operand * left,
3701 symbol *tlbl1, *tlbl2, *tlbl3;
3704 bool lUnsigned, rUnsigned;
3705 bool runtimeSign, compiletimeSign;
3707 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3708 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3710 D(emitcode ("; genDivOneByte",""));
3712 size = AOP_SIZE (result);
3713 /* signed or unsigned */
3714 if (lUnsigned && rUnsigned)
3716 /* unsigned is easy */
3717 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3718 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3719 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3720 emitcode ("div", "");
3721 hc08_dirtyReg (hc08_reg_a, FALSE);
3722 hc08_dirtyReg (hc08_reg_h, FALSE);
3723 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3724 hc08_freeReg (hc08_reg_a);
3725 hc08_freeReg (hc08_reg_x);
3726 hc08_freeReg (hc08_reg_h);
3730 /* signed is a little bit more difficult */
3732 /* now sign adjust for both left & right */
3734 /* let's see what's needed: */
3735 /* apply negative sign during runtime */
3736 runtimeSign = FALSE;
3737 /* negative sign from literals */
3738 compiletimeSign = FALSE;
3742 if (AOP_TYPE(left) == AOP_LIT)
3744 /* signed literal */
3745 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3747 compiletimeSign = TRUE;
3750 /* signed but not literal */
3756 if (AOP_TYPE(right) == AOP_LIT)
3758 /* signed literal */
3759 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3761 compiletimeSign ^= TRUE;
3764 /* signed but not literal */
3768 /* initialize the runtime sign */
3771 if (compiletimeSign)
3772 loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
3774 loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
3775 pushReg (hc08_reg_x, TRUE);
3778 /* save the signs of the operands */
3779 if (AOP_TYPE(right) == AOP_LIT)
3781 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3783 if (!rUnsigned && val < 0)
3784 emitcode ("ldx", "#0x%02x", -val);
3786 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3788 else /* ! literal */
3790 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3793 tlbl1 = newiTempLabel (NULL);
3794 emitcode ("tstx", "");
3795 emitBranch ("bpl", tlbl1);
3796 emitcode ("inc", "1,s");
3797 rmwWithReg ("neg", hc08_reg_x);
3802 if (AOP_TYPE(left) == AOP_LIT)
3804 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3806 if (!lUnsigned && val < 0)
3807 emitcode ("lda", "#0x%02x", -val);
3809 emitcode ("lda", "#0x%02x", (unsigned char) val);
3811 else /* ! literal */
3813 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3816 tlbl2 = newiTempLabel (NULL);
3817 emitcode ("tsta", "");
3818 emitBranch ("bpl", tlbl2);
3819 emitcode ("inc", "1,s");
3820 rmwWithReg ("neg", hc08_reg_a);
3825 loadRegFromConst (hc08_reg_h, zero);
3826 emitcode ("div", "");
3827 hc08_dirtyReg (hc08_reg_x, FALSE);
3828 hc08_dirtyReg (hc08_reg_a, FALSE);
3829 hc08_dirtyReg (hc08_reg_h, FALSE);
3831 if (runtimeSign || compiletimeSign)
3833 tlbl3 = newiTempLabel (NULL);
3836 pullReg (hc08_reg_x);
3837 rmwWithReg ("lsr", hc08_reg_x);
3838 rmwWithReg ("ror", hc08_reg_x);
3839 emitBranch ("bpl", tlbl3);
3842 rmwWithReg ("neg", hc08_reg_a);
3846 storeRegToAop (hc08_reg_a, AOP (result), 0);
3850 /* msb is 0x00 or 0xff depending on the sign */
3853 rmwWithReg ("lsl", hc08_reg_x);
3854 emitcode ("clra", "");
3855 emitcode ("sbc", "#0");
3857 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
3859 else /* compiletimeSign */
3861 storeConstToAop ("#0xff", AOP (result), ++offset);
3866 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3869 hc08_freeReg (hc08_reg_a);
3870 hc08_freeReg (hc08_reg_x);
3871 hc08_freeReg (hc08_reg_h);
3874 /*-----------------------------------------------------------------*/
3875 /* genDiv - generates code for division */
3876 /*-----------------------------------------------------------------*/
3880 operand *left = IC_LEFT (ic);
3881 operand *right = IC_RIGHT (ic);
3882 operand *result = IC_RESULT (ic);
3884 D(emitcode ("; genDiv",""));
3886 /* assign the amsops */
3887 aopOp (left, ic, FALSE);
3888 aopOp (right, ic, FALSE);
3889 aopOp (result, ic, TRUE);
3891 /* special cases first */
3892 /* if both are of size == 1 */
3893 if (AOP_SIZE (left) <= 2 &&
3894 AOP_SIZE (right) == 1)
3896 genDivOneByte (left, right, result);
3900 /* should have been converted to function call */
3903 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3904 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3905 freeAsmop (result, NULL, ic, TRUE);
3908 /*-----------------------------------------------------------------*/
3909 /* genModOneByte : 8 bit modulus */
3910 /*-----------------------------------------------------------------*/
3912 genModOneByte (operand * left,
3916 symbol *tlbl1, *tlbl2, *tlbl3;
3919 bool lUnsigned, rUnsigned;
3920 bool runtimeSign, compiletimeSign;
3922 lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
3923 rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
3925 D(emitcode ("; genModOneByte",""));
3927 size = AOP_SIZE (result);
3929 if (lUnsigned && rUnsigned)
3931 /* unsigned is easy */
3932 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3933 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3934 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3935 emitcode ("div", "");
3936 hc08_freeReg (hc08_reg_a);
3937 hc08_freeReg (hc08_reg_x);
3938 hc08_dirtyReg (hc08_reg_h, FALSE);
3939 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3940 hc08_freeReg (hc08_reg_h);
3944 /* signed is a little bit more difficult */
3946 if (AOP_TYPE(right) == AOP_LIT)
3948 signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
3950 if (!rUnsigned && val < 0)
3951 emitcode ("ldx", "#0x%02x", -val);
3953 emitcode ("ldx", "#0x%02x", (unsigned char) val);
3955 else /* ! literal */
3957 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3960 tlbl1 = newiTempLabel (NULL);
3961 emitcode ("tstx", "");
3962 emitBranch ("bpl", tlbl1);
3963 rmwWithReg ("neg", hc08_reg_x);
3968 /* let's see what's needed: */
3969 /* apply negative sign during runtime */
3970 runtimeSign = FALSE;
3971 /* negative sign from literals */
3972 compiletimeSign = FALSE;
3974 /* sign adjust left side */
3975 if (AOP_TYPE(left) == AOP_LIT)
3977 signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
3979 if (!lUnsigned && val < 0)
3981 compiletimeSign = TRUE; /* set sign flag */
3982 emitcode ("lda", "#0x%02x", -val);
3985 emitcode ("lda", "#0x%02x", (unsigned char) val);
3987 else /* ! literal */
3990 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3995 emitcode ("clr", "1,s");
3997 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3998 tlbl2 = newiTempLabel (NULL);
3999 emitcode ("tsta", "");
4000 emitBranch ("bpl", tlbl2);
4001 emitcode ("inc", "1,s");
4002 rmwWithReg ("neg", hc08_reg_a);
4007 loadRegFromConst (hc08_reg_h, zero);
4008 emitcode ("div", "");
4009 hc08_freeReg (hc08_reg_a);
4010 hc08_freeReg (hc08_reg_x);
4011 hc08_dirtyReg (hc08_reg_h, FALSE);
4013 if (runtimeSign || compiletimeSign)
4015 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
4016 tlbl3 = newiTempLabel (NULL);
4019 pullReg (hc08_reg_x);
4020 rmwWithReg ("lsr", hc08_reg_x);
4021 rmwWithReg ("ror", hc08_reg_x);
4022 emitBranch ("bpl", tlbl3);
4025 rmwWithReg ("neg", hc08_reg_a);
4029 storeRegToAop (hc08_reg_a, AOP (result), 0);
4033 /* msb is 0x00 or 0xff depending on the sign */
4036 rmwWithReg ("lsl", hc08_reg_x);
4037 emitcode ("clra", "");
4038 emitcode ("sbc", "#0");
4040 storeRegToAop (hc08_reg_a, AOP (result), ++offset);
4042 else /* compiletimeSign */
4044 storeConstToAop ("#0xff", AOP (result), ++offset);
4049 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
4052 hc08_freeReg (hc08_reg_a);
4053 hc08_freeReg (hc08_reg_x);
4054 hc08_freeReg (hc08_reg_h);
4057 /*-----------------------------------------------------------------*/
4058 /* genMod - generates code for division */
4059 /*-----------------------------------------------------------------*/
4063 operand *left = IC_LEFT (ic);
4064 operand *right = IC_RIGHT (ic);
4065 operand *result = IC_RESULT (ic);
4067 D(emitcode ("; genMod",""));
4069 /* assign the amsops */
4070 aopOp (left, ic, FALSE);
4071 aopOp (right, ic, FALSE);
4072 aopOp (result, ic, TRUE);
4074 /* special cases first */
4075 /* if both are of size == 1 */
4076 if (AOP_SIZE (left) <= 2 &&
4077 AOP_SIZE (right) == 1)
4079 genModOneByte (left, right, result);
4083 /* should have been converted to function call */
4087 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4088 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4089 freeAsmop (result, NULL, ic, TRUE);
4092 /*-----------------------------------------------------------------*/
4093 /* genIfxJump :- will create a jump depending on the ifx */
4094 /*-----------------------------------------------------------------*/
4096 genIfxJump (iCode * ic, char *jval)
4099 symbol *tlbl = newiTempLabel (NULL);
4102 D(emitcode ("; genIfxJump",""));
4104 /* if true label then we jump if condition
4108 jlbl = IC_TRUE (ic);
4109 if (!strcmp (jval, "a"))
4111 else if (!strcmp (jval, "c"))
4118 /* false label is present */
4119 jlbl = IC_FALSE (ic);
4120 if (!strcmp (jval, "a"))
4122 else if (!strcmp (jval, "c"))
4127 emitBranch (inst, tlbl);
4128 emitBranch ("jmp", jlbl);
4131 /* mark the icode as generated */
4136 /*-----------------------------------------------------------------*/
4137 /* exchangedCmp : returns the opcode need if the two operands are */
4138 /* exchanged in a comparison */
4139 /*-----------------------------------------------------------------*/
4141 exchangedCmp (int opcode)
4158 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4159 "opcode not a comparison");
4161 return EQ_OP; /* shouldn't happen, but need to return something */
4164 /*------------------------------------------------------------------*/
4165 /* negatedCmp : returns the equivalent opcode for when a comparison */
4167 /*------------------------------------------------------------------*/
4169 negatedCmp (int opcode)
4186 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4187 "opcode not a comparison");
4189 return EQ_OP; /* shouldn't happen, but need to return something */
4192 /* compile only if the debugging macro D is enabled */
4195 nameCmp (int opcode)
4217 /*------------------------------------------------------------------*/
4218 /* branchInstCmp : returns the conditional branch instruction that */
4219 /* will branch if the comparison is true */
4220 /*------------------------------------------------------------------*/
4222 branchInstCmp (int opcode, int sign)
4230 return "bcs"; /* same as blo */
4245 return "bcc"; /* same as bhs */
4251 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
4252 "opcode not a comparison");
4258 /*------------------------------------------------------------------*/
4259 /* genCmp :- greater or less than (and maybe with equal) comparison */
4260 /*------------------------------------------------------------------*/
4262 genCmp (iCode * ic, iCode * ifx)
4264 operand *left, *right, *result;
4265 sym_link *letype, *retype;
4267 int size, offset = 0;
4268 unsigned long lit = 0L;
4270 symbol *jlbl = NULL;
4274 D(emitcode ("; genCmp", "(%s)",nameCmp (opcode)));
4276 result = IC_RESULT (ic);
4277 left = IC_LEFT (ic);
4278 right = IC_RIGHT (ic);
4280 letype = getSpec (operandType (left));
4281 retype = getSpec (operandType (right));
4282 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4283 /* assign the amsops */
4284 aopOp (left, ic, FALSE);
4285 aopOp (right, ic, FALSE);
4286 aopOp (result, ic, TRUE);
4288 /* need register operand on left, prefer literal operand on right */
4289 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4291 operand *temp = left;
4294 opcode = exchangedCmp (opcode);
4301 jlbl = IC_TRUE (ifx);
4302 opcode = negatedCmp (opcode);
4306 /* false label is present */
4307 jlbl = IC_FALSE (ifx);
4311 size = max (AOP_SIZE (left), AOP_SIZE (right));
4314 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4315 && ((AOP_TYPE (right) == AOP_LIT) ||
4316 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4317 && hc08_reg_hx->isFree)
4319 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4320 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4321 hc08_freeReg (hc08_reg_hx);
4332 /* These conditions depend on the Z flag bit, but Z is */
4333 /* only valid for the last byte of the comparison, not */
4334 /* the whole value. So exchange the operands to get a */
4335 /* comparison that doesn't depend on Z. (This is safe */
4336 /* to do here since ralloc won't assign multi-byte */
4337 /* operands to registers for comparisons) */
4338 if ((opcode == '>') || (opcode == LE_OP))
4340 operand *temp = left;
4343 opcode = exchangedCmp (opcode);
4346 if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
4348 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4349 while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
4358 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4359 accopWithAop (sub, AOP (right), offset);
4360 hc08_freeReg (hc08_reg_a);
4365 freeAsmop (right, NULL, ic, FALSE);
4366 freeAsmop (left, NULL, ic, FALSE);
4370 symbol *tlbl = newiTempLabel (NULL);
4373 freeAsmop (result, NULL, ic, TRUE);
4375 inst = branchInstCmp (opcode, sign);
4376 emitBranch (inst, tlbl);
4377 emitBranch ("jmp", jlbl);
4380 /* mark the icode as generated */
4385 symbol *tlbl1 = newiTempLabel (NULL);
4386 symbol *tlbl2 = newiTempLabel (NULL);
4388 emitBranch (branchInstCmp (opcode, sign), tlbl1);
4389 loadRegFromConst (hc08_reg_a, zero);
4390 emitBranch ("bra", tlbl2);
4392 loadRegFromConst (hc08_reg_a, one);
4394 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4395 freeAsmop (result, NULL, ic, TRUE);
4400 /*-----------------------------------------------------------------*/
4401 /* genCmpEQorNE - equal or not equal comparison */
4402 /*-----------------------------------------------------------------*/
4404 genCmpEQorNE (iCode * ic, iCode * ifx)
4406 operand *left, *right, *result;
4407 sym_link *letype, *retype;
4409 int size, offset = 0;
4411 symbol *jlbl = NULL;
4412 symbol *tlbl_NE = NULL;
4413 symbol *tlbl_EQ = NULL;
4417 D(emitcode ("; genCmpEQorNE", "(%s)",nameCmp (opcode)));
4419 result = IC_RESULT (ic);
4420 left = IC_LEFT (ic);
4421 right = IC_RIGHT (ic);
4423 letype = getSpec (operandType (left));
4424 retype = getSpec (operandType (right));
4425 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4426 /* assign the amsops */
4427 aopOp (left, ic, FALSE);
4428 aopOp (right, ic, FALSE);
4429 aopOp (result, ic, TRUE);
4431 /* need register operand on left, prefer literal operand on right */
4432 if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
4434 operand *temp = left;
4437 opcode = exchangedCmp (opcode);
4444 jlbl = IC_TRUE (ifx);
4445 opcode = negatedCmp (opcode);
4449 /* false label is present */
4450 jlbl = IC_FALSE (ifx);
4454 size = max (AOP_SIZE (left), AOP_SIZE (right));
4457 && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
4458 && ((AOP_TYPE (right) == AOP_LIT) ||
4459 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
4460 && hc08_reg_hx->isFree)
4462 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
4463 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
4464 hc08_freeReg (hc08_reg_hx);
4472 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4473 accopWithAop (sub, AOP (right), offset);
4477 tlbl_NE = newiTempLabel (NULL);
4478 emitBranch ("bne", tlbl_NE);
4480 hc08_freeReg (hc08_reg_a);
4484 freeAsmop (right, NULL, ic, FALSE);
4485 freeAsmop (left, NULL, ic, FALSE);
4489 freeAsmop (result, NULL, ic, TRUE);
4491 if (opcode == EQ_OP)
4494 tlbl_EQ = newiTempLabel (NULL);
4495 emitBranch ("beq", tlbl_EQ);
4497 emitLabel (tlbl_NE);
4498 emitBranch ("jmp", jlbl);
4499 emitLabel (tlbl_EQ);
4504 tlbl_NE = newiTempLabel (NULL);
4505 emitBranch ("bne", tlbl_NE);
4506 emitBranch ("jmp", jlbl);
4507 emitLabel (tlbl_NE);
4510 /* mark the icode as generated */
4515 symbol *tlbl = newiTempLabel (NULL);
4517 if (opcode == EQ_OP)
4520 tlbl_EQ = newiTempLabel (NULL);
4521 emitBranch ("beq", tlbl_EQ);
4523 emitLabel (tlbl_NE);
4524 loadRegFromConst (hc08_reg_a, zero);
4525 emitBranch ("bra", tlbl);
4526 emitLabel (tlbl_EQ);
4527 loadRegFromConst (hc08_reg_a, one);
4532 tlbl_NE = newiTempLabel (NULL);
4533 emitBranch ("bne", tlbl_NE);
4534 loadRegFromConst (hc08_reg_a, zero);
4535 emitBranch ("bra", tlbl);
4536 emitLabel (tlbl_NE);
4537 loadRegFromConst (hc08_reg_a, one);
4541 storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
4542 freeAsmop (result, NULL, ic, TRUE);
4548 /*-----------------------------------------------------------------*/
4549 /* ifxForOp - returns the icode containing the ifx for operand */
4550 /*-----------------------------------------------------------------*/
4552 ifxForOp (operand * op, iCode * ic)
4554 /* if true symbol then needs to be assigned */
4555 if (IS_TRUE_SYMOP (op))
4558 /* if this has register type condition and
4559 the next instruction is ifx with the same operand
4560 and live to of the operand is upto the ifx only then */
4562 ic->next->op == IFX &&
4563 IC_COND (ic->next)->key == op->key &&
4564 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4571 genPointerGetSetOfs (iCode *ic)
4573 iCode *lic = ic->next;
4579 /* Make sure we have a next iCode */
4580 D(emitcode("","; checking lic"));
4584 /* Make sure the result of the addition is an iCode */
4585 D(emitcode("","; checking IS_ITEMP"));
4586 if (!IS_ITEMP (IC_RESULT (ic)))
4589 /* Make sure the next iCode is a pointer set or get */
4590 pset = POINTER_SET(lic);
4591 pget = POINTER_GET(lic);
4592 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4596 /* Make sure this is the only use of the pointer */
4597 if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
4600 D(emitcode("", "; checking pset operandsEqu"));
4601 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4604 D(emitcode("", "; checking pget operandsEqu"));
4605 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4608 D(emitcode("", "; checking IS_SYMOP"));
4609 if (!IS_SYMOP (IC_LEFT (ic)))
4612 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4613 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4616 sym = OP_SYMBOL (IC_LEFT (ic));
4618 D(emitcode("", "; checking remat"));
4625 D(emitcode ("; genPointerGetOfs",""));
4626 aopOp (IC_LEFT(ic), ic, FALSE);
4627 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4628 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4630 aopOp (IC_RIGHT(ic), ic, FALSE);
4631 aopOp (IC_RESULT(lic), lic, FALSE);
4633 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4635 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4637 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4638 loadRegFromConst (hc08_reg_h, zero);
4642 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4643 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4644 emitcode ("rola","");
4645 emitcode ("clra","");
4646 emitcode ("sbc", "#0");
4647 hc08_useReg (hc08_reg_a);
4648 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4652 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4653 size = AOP_SIZE (IC_RESULT(lic));
4654 derefaop->size = size;
4658 emitcode ("lda", "%s,x",
4659 aopAdrStr (derefaop, size, TRUE));
4660 hc08_useReg (hc08_reg_a);
4661 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
4662 hc08_freeReg (hc08_reg_a);
4666 hc08_freeReg (hc08_reg_hx);
4668 freeAsmop (NULL, derefaop, ic, TRUE);
4669 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4670 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4677 D(emitcode ("; genPointerSetOfs",""));
4678 aopOp (IC_LEFT(ic), ic, FALSE);
4679 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4680 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4682 aopOp (IC_RIGHT(ic), ic, FALSE);
4683 aopOp (IC_RIGHT(lic), lic, FALSE);
4685 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4687 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4689 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4690 loadRegFromConst (hc08_reg_h, zero);
4694 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4695 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4696 emitcode ("rola","");
4697 emitcode ("clra","");
4698 emitcode ("sbc", "#0");
4699 hc08_useReg (hc08_reg_a);
4700 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4704 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4705 size = AOP_SIZE (IC_RIGHT(lic));
4706 derefaop->size = size;
4710 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
4711 emitcode ("sta", "%s,x",
4712 aopAdrStr (derefaop, size, TRUE));
4713 hc08_freeReg (hc08_reg_a);
4717 hc08_freeReg (hc08_reg_hx);
4719 freeAsmop (NULL, derefaop, ic, TRUE);
4720 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4721 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4730 /*-----------------------------------------------------------------*/
4731 /* hasInc - operand is incremented before any other use */
4732 /*-----------------------------------------------------------------*/
4734 hasInc (operand *op, iCode *ic,int osize)
4736 sym_link *type = operandType(op);
4737 sym_link *retype = getSpec (type);
4738 iCode *lic = ic->next;
4741 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4742 if (!IS_SYMOP(op)) return NULL;
4744 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4745 if (IS_AGGREGATE(type->next)) return NULL;
4746 if (osize != (isize = getSize(type->next))) return NULL;
4749 /* if operand of the form op = op + <sizeof *op> */
4750 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4751 isOperandEqual(IC_RESULT(lic),op) &&
4752 isOperandLiteral(IC_RIGHT(lic)) &&
4753 operandLitValue(IC_RIGHT(lic)) == isize) {
4756 /* if the operand used or deffed */
4757 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
4760 /* if GOTO or IFX */
4761 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4767 /*-----------------------------------------------------------------*/
4768 /* genAndOp - for && operation */
4769 /*-----------------------------------------------------------------*/
4771 genAndOp (iCode * ic)
4773 operand *left, *right, *result;
4774 symbol *tlbl, *tlbl0;
4776 D(emitcode ("; genAndOp",""));
4778 /* note here that && operations that are in an
4779 if statement are taken away by backPatchLabels
4780 only those used in arthmetic operations remain */
4781 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4782 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4783 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4785 tlbl = newiTempLabel (NULL);
4786 tlbl0 = newiTempLabel (NULL);
4788 asmopToBool (AOP (left), FALSE);
4789 emitBranch ("beq", tlbl0);
4790 asmopToBool (AOP (right), FALSE);
4791 emitBranch ("beq", tlbl0);
4792 loadRegFromConst (hc08_reg_a,one);
4793 emitBranch ("bra", tlbl);
4795 loadRegFromConst (hc08_reg_a,zero);
4798 hc08_useReg (hc08_reg_a);
4799 hc08_freeReg (hc08_reg_a);
4801 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4803 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4804 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4805 freeAsmop (result, NULL, ic, TRUE);
4809 /*-----------------------------------------------------------------*/
4810 /* genOrOp - for || operation */
4811 /*-----------------------------------------------------------------*/
4813 genOrOp (iCode * ic)
4815 operand *left, *right, *result;
4816 symbol *tlbl, *tlbl0;
4818 D(emitcode ("; genOrOp",""));
4820 /* note here that || operations that are in an
4821 if statement are taken away by backPatchLabels
4822 only those used in arthmetic operations remain */
4823 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4824 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4825 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4827 tlbl = newiTempLabel (NULL);
4828 tlbl0 = newiTempLabel (NULL);
4830 asmopToBool (AOP (left), FALSE);
4831 emitBranch ("bne", tlbl0);
4832 asmopToBool (AOP (right), FALSE);
4833 emitBranch ("bne", tlbl0);
4834 loadRegFromConst (hc08_reg_a,zero);
4835 emitBranch ("bra", tlbl);
4837 loadRegFromConst (hc08_reg_a,one);
4840 hc08_useReg (hc08_reg_a);
4841 hc08_freeReg (hc08_reg_a);
4843 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4846 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4847 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4848 freeAsmop (result, NULL, ic, TRUE);
4851 /*-----------------------------------------------------------------*/
4852 /* isLiteralBit - test if lit == 2^n */
4853 /*-----------------------------------------------------------------*/
4855 isLiteralBit (unsigned long lit)
4857 unsigned long pw[32] =
4858 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4859 0x100L, 0x200L, 0x400L, 0x800L,
4860 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4861 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4862 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4863 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4864 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4867 for (idx = 0; idx < 32; idx++)
4874 /*-----------------------------------------------------------------*/
4875 /* continueIfTrue - */
4876 /*-----------------------------------------------------------------*/
4878 continueIfTrue (iCode * ic)
4881 emitBranch ("jmp", IC_TRUE (ic));
4885 /*-----------------------------------------------------------------*/
4887 /*-----------------------------------------------------------------*/
4889 jumpIfTrue (iCode * ic)
4892 emitBranch ("jmp", IC_FALSE (ic));
4896 /*-----------------------------------------------------------------*/
4897 /* jmpTrueOrFalse - */
4898 /*-----------------------------------------------------------------*/
4900 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4902 // ugly but optimized by peephole
4905 symbol *nlbl = newiTempLabel (NULL);
4906 emitBranch ("bra", nlbl);
4908 emitBranch ("jmp", IC_TRUE (ic));
4913 emitBranch ("jmp", IC_FALSE (ic));
4920 /*-----------------------------------------------------------------*/
4921 /* genAnd - code for and */
4922 /*-----------------------------------------------------------------*/
4924 genAnd (iCode * ic, iCode * ifx)
4926 operand *left, *right, *result;
4927 int size, offset = 0;
4928 unsigned long lit = 0L;
4929 unsigned long litinv;
4930 unsigned char bytemask;
4936 D(emitcode ("; genAnd",""));
4938 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4939 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4940 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4943 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4945 AOP_TYPE (left), AOP_TYPE (right)));
4946 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4948 AOP_SIZE (left), AOP_SIZE (right)));
4951 /* if left is a literal & right is not then exchange them */
4952 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4954 operand *tmp = right;
4959 /* if right is accumulator & left is not then exchange them */
4960 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4962 operand *tmp = right;
4967 if (AOP_TYPE (right) == AOP_LIT)
4968 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4970 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4972 if (AOP_TYPE (result) == AOP_CRY
4974 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
4976 /* this generates ugly code, but meets volatility requirements */
4977 loadRegFromConst (hc08_reg_a, zero);
4978 pushReg (hc08_reg_a, TRUE);
4983 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4984 accopWithAop ("and", AOP (right), offset);
4985 emitcode ("ora", "1,s");
4986 emitcode ("sta", "1,s");
4990 pullReg (hc08_reg_a);
4991 emitcode ("tsta", "");
4992 genIfxJump (ifx, "a");
4996 if (AOP_TYPE (result) == AOP_CRY)
4998 symbol *tlbl = NULL;
4999 wassertl (ifx, "AOP_CRY result without ifx");
5004 bytemask = (lit >> (offset*8)) & 0xff;
5006 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5010 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5012 rmwWithAop ("tst", AOP (left), offset);
5016 tlbl = newiTempLabel (NULL);
5017 emitBranch ("bne", tlbl);
5022 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5023 accopWithAop ("and", AOP (right), offset);
5024 hc08_freeReg( hc08_reg_a);
5028 tlbl = newiTempLabel (NULL);
5029 emitBranch ("bne", tlbl);
5036 genIfxJump (ifx, "a");
5040 size = AOP_SIZE (result);
5042 if (AOP_TYPE (right) == AOP_LIT)
5044 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
5045 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5046 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
5048 int bitpos = isLiteralBit(litinv)-1;
5049 emitcode ("bclr","#%d,%s",bitpos & 7,
5050 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5058 bytemask = (lit >> (offset*8)) & 0xff;
5060 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5062 if (isOperandVolatile (left, FALSE))
5064 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5065 hc08_freeReg( hc08_reg_a);
5067 storeConstToAop (zero, AOP (result), offset);
5069 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5071 transferAopAop (AOP (left), offset, AOP (result), offset);
5075 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5076 accopWithAop ("and", AOP (right), offset);
5077 storeRegToAop (hc08_reg_a, AOP (result), offset);
5078 hc08_freeReg (hc08_reg_a);
5084 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5085 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5086 freeAsmop (result, NULL, ic, TRUE);
5089 /*-----------------------------------------------------------------*/
5090 /* genOr - code for or */
5091 /*-----------------------------------------------------------------*/
5093 genOr (iCode * ic, iCode * ifx)
5095 operand *left, *right, *result;
5096 int size, offset = 0;
5097 unsigned long lit = 0L;
5098 unsigned char bytemask;
5100 D(emitcode ("; genOr",""));
5102 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5103 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5104 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5107 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5109 AOP_TYPE (left), AOP_TYPE (right)));
5110 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5112 AOP_SIZE (left), AOP_SIZE (right)));
5115 /* if left is a literal & right is not then exchange them */
5116 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5118 operand *tmp = right;
5123 /* if left is accumulator & right is not then exchange them */
5124 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5126 operand *tmp = right;
5131 if (AOP_TYPE (right) == AOP_LIT)
5132 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5134 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5136 if (AOP_TYPE (result) == AOP_CRY
5138 && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
5140 /* this generates ugly code, but meets volatility requirements */
5141 loadRegFromConst (hc08_reg_a, zero);
5142 pushReg (hc08_reg_a, TRUE);
5147 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5148 accopWithAop ("ora", AOP (right), offset);
5149 emitcode ("ora", "1,s");
5150 emitcode ("sta", "1,s");
5154 pullReg (hc08_reg_a);
5155 emitcode ("tsta", "");
5156 genIfxJump (ifx, "a");
5160 if (AOP_TYPE (result) == AOP_CRY)
5162 symbol *tlbl = NULL;
5163 wassertl (ifx, "AOP_CRY result without ifx");
5168 bytemask = (lit >> (offset*8)) & 0xff;
5170 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
5172 rmwWithAop ("tst", AOP (left), offset);
5176 tlbl = newiTempLabel (NULL);
5177 emitBranch ("bne", tlbl);
5182 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5183 accopWithAop ("ora", AOP (right), offset);
5184 hc08_freeReg( hc08_reg_a);
5188 tlbl = newiTempLabel (NULL);
5189 emitBranch ("bne", tlbl);
5196 genIfxJump (ifx, "a");
5199 if (AOP_TYPE (right) == AOP_LIT)
5200 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5202 size = AOP_SIZE (result);
5204 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
5205 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
5206 (AOP_TYPE (left) == AOP_DIR))
5208 int bitpos = isLiteralBit(lit)-1;
5209 emitcode ("bset","#%d,%s",bitpos & 7,
5210 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
5217 bytemask = (lit >> (offset*8)) & 0xff;
5219 if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
5221 if (isOperandVolatile (left, FALSE))
5223 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5224 hc08_freeReg( hc08_reg_a);
5226 transferAopAop (AOP (right), offset, AOP (result), offset);
5228 else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
5230 transferAopAop (AOP (left), offset, AOP (result), offset);
5234 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5235 accopWithAop ("ora", AOP (right), offset);
5236 storeRegToAop (hc08_reg_a, AOP (result), offset);
5237 hc08_freeReg (hc08_reg_a);
5244 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5245 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5246 freeAsmop (result, NULL, ic, TRUE);
5249 /*-----------------------------------------------------------------*/
5250 /* genXor - code for xclusive or */
5251 /*-----------------------------------------------------------------*/
5253 genXor (iCode * ic, iCode * ifx)
5255 operand *left, *right, *result;
5256 int size, offset = 0;
5257 unsigned long lit = 0L;
5259 D(emitcode ("; genXor",""));
5261 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5262 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5263 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5266 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5268 AOP_TYPE (left), AOP_TYPE (right)));
5269 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5271 AOP_SIZE (left), AOP_SIZE (right)));
5274 /* if left is a literal & right is not ||
5275 if left needs acc & right does not */
5276 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
5278 operand *tmp = right;
5283 /* if left is accumulator & right is not then exchange them */
5284 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
5286 operand *tmp = right;
5291 if (AOP_TYPE (result) == AOP_CRY)
5294 wassertl (ifx, "AOP_CPY result without ifx");
5296 tlbl = newiTempLabel (NULL);
5297 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
5301 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5302 if ((AOP_TYPE (right) == AOP_LIT)
5303 && (((lit >> (offset*8)) & 0xff) == 0))
5304 emitcode ("tsta","");
5306 accopWithAop ("eor", AOP (right), offset);
5307 hc08_freeReg( hc08_reg_a);
5309 emitBranch ("bne", tlbl);
5313 genIfxJump (ifx, "a");
5319 if (AOP_TYPE (right) == AOP_LIT)
5320 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5322 size = AOP_SIZE (result);
5326 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5327 accopWithAop ("eor", AOP (right), offset);
5328 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5329 hc08_freeReg( hc08_reg_a);
5333 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5334 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5335 freeAsmop (result, NULL, ic, TRUE);
5339 emitinline (iCode * ic, char *inlin)
5345 symbol *sym, *tempsym;
5354 while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
5358 //printf("Found possible symbol '%s'\n",symname);
5359 tempsym = newSymbol (symname, ic->level);
5360 tempsym->block = ic->block;
5361 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
5370 aop = aopForSym (ic, sym, FALSE);
5371 l = aopAdrStr (aop, aop->size - 1, TRUE);
5375 if (sym->level && !sym->allocreq && !sym->ismyparm)
5377 werror (E_ID_UNDEF, sym->name);
5379 " Add 'volatile' to the variable declaration so that it\n"
5380 " can be referenced within inline assembly");
5382 //printf("Replacing with '%s'\n",l);
5386 if ((2+bp-buffer)>sizeof(buffer))
5395 if ((2+bp-buffer)>sizeof(buffer))
5402 if ((2+bp-buffer)>sizeof(buffer))
5403 fprintf(stderr, "Inline assembly buffer overflow\n");
5405 //printf("%s\n",buffer);
5406 emitcode (buffer,"");
5410 /*-----------------------------------------------------------------*/
5411 /* genInline - write the inline code out */
5412 /*-----------------------------------------------------------------*/
5414 genInline (iCode * ic)
5416 char *buffer, *bp, *bp1;
5418 D(emitcode ("; genInline",""));
5420 _G.inLine += (!options.asmpeep);
5422 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5423 strcpy (buffer, IC_INLINE (ic));
5425 /* emit each line as a code */
5431 /* emitcode (bp1, ""); */
5432 emitinline (ic, bp1);
5451 /* emitcode (bp1, ""); */
5452 emitinline (ic, bp1);
5454 /* emitcode("",buffer); */
5455 _G.inLine -= (!options.asmpeep);
5458 /*-----------------------------------------------------------------*/
5459 /* genRRC - rotate right with carry */
5460 /*-----------------------------------------------------------------*/
5464 operand *left, *result;
5465 int size, offset = 0;
5466 bool needpula = FALSE;
5467 bool resultInA = FALSE;
5470 D(emitcode ("; genRRC",""));
5472 /* rotate right with carry */
5473 left = IC_LEFT (ic);
5474 result = IC_RESULT (ic);
5475 aopOp (left, ic, FALSE);
5476 aopOp (result, ic, FALSE);
5478 if ((AOP_TYPE (result) == AOP_REG)
5479 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5482 size = AOP_SIZE (result);
5486 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5490 rmwWithAop (shift, AOP (result), offset--);
5498 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5499 rmwWithReg (shift, hc08_reg_a);
5500 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5501 hc08_freeReg (hc08_reg_a);
5506 if ((!hc08_reg_a->isFree) || resultInA)
5508 pushReg (hc08_reg_a, TRUE);
5512 /* now we need to put the carry into the
5513 highest order byte of the result */
5514 offset = AOP_SIZE (result) - 1;
5515 emitcode ("clra","");
5516 emitcode ("rora","");
5517 hc08_dirtyReg (hc08_reg_a, FALSE);
5520 emitcode ("ora", "1,s");
5521 emitcode ("ais", "#1");
5522 hc08_dirtyReg (hc08_reg_a, FALSE);
5526 accopWithAop ("ora", AOP (result), offset);
5527 storeRegToAop (hc08_reg_a, AOP (result), offset);
5529 pullOrFreeReg (hc08_reg_a, needpula);
5531 freeAsmop (left, NULL, ic, TRUE);
5532 freeAsmop (result, NULL, ic, TRUE);
5535 /*-----------------------------------------------------------------*/
5536 /* genRLC - generate code for rotate left with carry */
5537 /*-----------------------------------------------------------------*/
5541 operand *left, *result;
5542 int size, offset = 0;
5544 bool resultInA = FALSE;
5545 bool needpula = FALSE;
5547 D(emitcode ("; genRLC",""));
5549 /* rotate right with carry */
5550 left = IC_LEFT (ic);
5551 result = IC_RESULT (ic);
5552 aopOp (left, ic, FALSE);
5553 aopOp (result, ic, FALSE);
5555 if ((AOP_TYPE (result) == AOP_REG)
5556 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5559 size = AOP_SIZE (result);
5563 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5567 rmwWithAop (shift, AOP (result), offset--);
5575 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5576 rmwWithReg (shift, hc08_reg_a);
5577 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5578 hc08_freeReg (hc08_reg_a);
5583 if ((!hc08_reg_a->isFree) || resultInA)
5585 pushReg (hc08_reg_a, TRUE);
5589 /* now we need to put the carry into the
5590 lowest order byte of the result */
5592 emitcode ("clra","");
5593 emitcode ("rola","");
5594 hc08_dirtyReg (hc08_reg_a, FALSE);
5597 emitcode ("ora", "1,s");
5598 emitcode ("ais", "#1");
5599 hc08_dirtyReg (hc08_reg_a, FALSE);
5603 accopWithAop ("ora", AOP (result), offset);
5604 storeRegToAop (hc08_reg_a, AOP (result), offset);
5606 pullOrFreeReg (hc08_reg_a, needpula);
5608 freeAsmop (left, NULL, ic, TRUE);
5609 freeAsmop (result, NULL, ic, TRUE);
5612 /*-----------------------------------------------------------------*/
5613 /* genGetHbit - generates code get highest order bit */
5614 /*-----------------------------------------------------------------*/
5616 genGetHbit (iCode * ic)
5618 operand *left, *result;
5620 D(emitcode ("; genGetHbit",""));
5622 left = IC_LEFT (ic);
5623 result = IC_RESULT (ic);
5624 aopOp (left, ic, FALSE);
5625 aopOp (result, ic, FALSE);
5627 /* get the highest order byte into a */
5628 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5629 emitcode ("rola", "");
5630 emitcode ("clra", "");
5631 emitcode ("rola", "");
5632 hc08_dirtyReg (hc08_reg_a, FALSE);
5633 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5634 hc08_freeReg (hc08_reg_a);
5636 freeAsmop (left, NULL, ic, TRUE);
5637 freeAsmop (result, NULL, ic, TRUE);
5640 /*-----------------------------------------------------------------*/
5641 /* genSwap - generates code to swap nibbles or bytes */
5642 /*-----------------------------------------------------------------*/
5644 genSwap (iCode * ic)
5646 operand *left, *result;
5648 D(emitcode ("; genSwap",""));
5650 left = IC_LEFT (ic);
5651 result = IC_RESULT (ic);
5652 aopOp (left, ic, FALSE);
5653 aopOp (result, ic, FALSE);
5655 switch (AOP_SIZE (left))
5657 case 1: /* swap nibbles in byte */
5658 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5659 emitcode ("nsa", "");
5660 hc08_dirtyReg (hc08_reg_a, FALSE);
5661 storeRegToAop (hc08_reg_a, AOP (result), 0);
5662 hc08_freeReg (hc08_reg_a);
5664 case 2: /* swap bytes in a word */
5665 if (operandsEqu (left, result))
5667 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5668 hc08_useReg (hc08_reg_a);
5669 transferAopAop (AOP (left), 1, AOP (result), 0);
5670 storeRegToAop (hc08_reg_a, AOP (result), 1);
5671 hc08_freeReg (hc08_reg_a);
5675 transferAopAop (AOP (left), 0, AOP (result), 1);
5676 transferAopAop (AOP (left), 1, AOP (result), 0);
5680 wassertl(FALSE, "unsupported SWAP operand size");
5683 freeAsmop (left, NULL, ic, TRUE);
5684 freeAsmop (result, NULL, ic, TRUE);
5688 /*-----------------------------------------------------------------*/
5689 /* AccRol - rotate left accumulator by known count */
5690 /*-----------------------------------------------------------------*/
5692 AccRol (int shCount)
5694 shCount &= 0x0007; // shCount : 0..7
5701 emitcode ("rola", ""); /* 1 cycle */
5704 emitcode ("rola", ""); /* 1 cycle */
5705 emitcode ("rola", ""); /* 1 cycle */
5708 emitcode ("nsa", "");
5709 emitcode ("rora", "");
5712 emitcode ("nsa", ""); /* 3 cycles */
5715 emitcode ("nsa", ""); /* 3 cycles */
5716 emitcode ("rola", ""); /* 1 cycle */
5719 emitcode ("nsa", ""); /* 3 cycles */
5720 emitcode ("rola", ""); /* 1 cycle */
5721 emitcode ("rola", ""); /* 1 cycle */
5724 emitcode ("nsa", ""); /* 3 cycles */
5725 emitcode ("rola", ""); /* 1 cycle */
5726 emitcode ("rola", ""); /* 1 cycle */
5727 emitcode ("rola", ""); /* 1 cycle */
5734 /*-----------------------------------------------------------------*/
5735 /* AccLsh - left shift accumulator by known count */
5736 /*-----------------------------------------------------------------*/
5738 AccLsh (int shCount)
5742 shCount &= 0x0007; // shCount : 0..7
5744 /* Shift counts of 4 and 5 are currently optimized for code size. */
5745 /* Falling through to the unrolled loop would be optimal for code speed. */
5746 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5750 if (optimize.codeSpeed)
5752 accopWithMisc ("nsa", "");
5753 accopWithMisc ("and", "#0xf0");
5754 /* total: 5 cycles, 3 bytes */
5757 if (optimize.codeSpeed)
5759 accopWithMisc ("nsa", "");
5760 accopWithMisc ("and", "#0xf0");
5761 accopWithMisc ("lsla", "");
5762 /* total: 6 cycles, 4 bytes */
5765 accopWithMisc ("rora", "");
5766 accopWithMisc ("rora", "");
5767 accopWithMisc ("rora", "");
5768 accopWithMisc ("and", "#0xc0");
5769 /* total: 5 cycles, 5 bytes */
5772 accopWithMisc ("rora", "");
5773 accopWithMisc ("clra", "");
5774 accopWithMisc ("rora", "");
5775 /* total: 3 cycles, 3 bytes */
5779 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5780 /* the fastest (shCount<6) and shortest (shCount<4). */
5781 for (i=0;i<shCount;i++)
5782 accopWithMisc ("lsla", "");
5786 /*-----------------------------------------------------------------*/
5787 /* AccSRsh - signed right shift accumulator by known count */
5788 /*-----------------------------------------------------------------*/
5790 AccSRsh (int shCount)
5794 shCount &= 0x0007; // shCount : 0..7
5798 accopWithMisc ("rola", "");
5799 accopWithMisc ("clra", "");
5800 accopWithMisc ("sbc", zero);
5801 /* total: 4 cycles, 4 bytes */
5805 for (i=0;i<shCount;i++)
5806 accopWithMisc ("asra", "");
5809 /*-----------------------------------------------------------------*/
5810 /* AccRsh - right shift accumulator by known count */
5811 /*-----------------------------------------------------------------*/
5813 AccRsh (int shCount, bool sign)
5823 shCount &= 0x0007; // shCount : 0..7
5825 /* Shift counts of 4 and 5 are currently optimized for code size. */
5826 /* Falling through to the unrolled loop would be optimal for code speed. */
5827 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5831 if (optimize.codeSpeed)
5833 accopWithMisc ("nsa", "");
5834 accopWithMisc ("and", "#0x0f");
5835 /* total: 5 cycles, 3 bytes */
5838 if (optimize.codeSpeed)
5840 accopWithMisc ("nsa", "");
5841 accopWithMisc ("and", "#0x0f");
5842 accopWithMisc ("lsra", "");
5843 /* total: 6 cycles, 4 bytes */
5846 accopWithMisc ("rola", "");
5847 accopWithMisc ("rola", "");
5848 accopWithMisc ("rola", "");
5849 accopWithMisc ("and", "#0x03");
5850 /* total: 5 cycles, 5 bytes */
5853 accopWithMisc ("rola", "");
5854 accopWithMisc ("clra", "");
5855 accopWithMisc ("rola", "");
5856 /* total: 3 cycles, 3 bytes */
5860 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5861 /* the fastest (shCount<6) and shortest (shCount<4). */
5862 for (i=0;i<shCount;i++)
5863 accopWithMisc ("lsra", "");
5867 /*-----------------------------------------------------------------*/
5868 /* XAccLsh - left shift register pair XA by known count */
5869 /*-----------------------------------------------------------------*/
5871 XAccLsh (int shCount)
5875 shCount &= 0x000f; // shCount : 0..15
5880 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5881 loadRegFromConst (hc08_reg_a, zero);
5885 /* if we can beat 2n cycles or bytes for some special case, do it here */
5889 /* bytes cycles reg x reg a carry
5890 ** abcd efgh ijkl mnop ?
5891 ** lsrx 1 1 0abc defg ijkl mnop h
5892 ** rora 1 1 0abc defg hijk lmno p
5893 ** tax 1 1 hijk lmno hijk lmno p
5894 ** clra 1 1 hijk lmno 0000 0000 p
5895 ** rora 1 1 hijk lmno p000 0000 0
5896 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5898 rmwWithReg ("lsr", hc08_reg_x);
5899 rmwWithReg ("ror", hc08_reg_a);
5900 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5901 loadRegFromConst (hc08_reg_a, zero);
5902 rmwWithReg ("ror", hc08_reg_a);
5909 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5910 /* the fastest and shortest. */
5911 for (i=0;i<shCount;i++)
5913 rmwWithReg ("lsl", hc08_reg_a);
5914 rmwWithReg ("rol", hc08_reg_x);
5918 /*-----------------------------------------------------------------*/
5919 /* XAccSRsh - signed right shift register pair XA by known count */
5920 /*-----------------------------------------------------------------*/
5922 XAccSRsh (int shCount)
5926 shCount &= 0x000f; // shCount : 0..7
5928 /* if we can beat 2n cycles or bytes for some special case, do it here */
5932 /* bytes cycles reg x reg a carry
5933 ** abcd efgh ijkl mnop ?
5934 ** lslx 1 1 bcde fgh0 ijkl mnop a
5935 ** clra 1 1 bcde fgh0 0000 0000 a
5936 ** rola 1 1 bcde fgh0 0000 000a 0
5937 ** nega 1 1 bcde fgh0 aaaa aaaa a
5938 ** tax 1 1 aaaa aaaa aaaa aaaa a
5939 ** total: 5 cycles, 5 bytes
5941 rmwWithReg ("lsl", hc08_reg_x);
5942 loadRegFromConst (hc08_reg_a, zero);
5943 rmwWithReg ("rol", hc08_reg_a);
5944 rmwWithReg ("neg", hc08_reg_a);
5945 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5955 /* bytes cycles reg x reg a carry
5956 ** abcd efgh ijkl mnop ?
5957 ** txa 1 1 abcd efgh abcd efgh ?
5958 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5959 ** lsla 1 1 abcd efgh ???? ???? a
5960 ** clrx 1 1 0000 0000 ???? ???? a
5961 ** rolx 1 1 0000 000a ???? ???? 0
5962 ** negx 1 1 aaaa aaaa ???? ???? a
5963 ** rora 1 1 aaaa aaaa LSBresult 0
5964 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5966 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5967 AccSRsh (shCount-8);
5968 rmwWithReg ("lsl", hc08_reg_a);
5969 loadRegFromConst (hc08_reg_x, zero);
5970 rmwWithReg ("rol", hc08_reg_x);
5971 rmwWithReg ("neg", hc08_reg_x);
5972 rmwWithReg ("ror", hc08_reg_a);
5979 /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5980 /* the fastest and shortest. */
5981 for (i=0;i<shCount;i++)
5983 rmwWithReg ("asr", hc08_reg_x);
5984 rmwWithReg ("ror", hc08_reg_a);
5988 /*-----------------------------------------------------------------*/
5989 /* XAccRsh - right shift register pair XA by known count */
5990 /*-----------------------------------------------------------------*/
5992 XAccRsh (int shCount, bool sign)
6002 shCount &= 0x000f; // shCount : 0..f
6004 /* if we can beat 2n cycles or bytes for some special case, do it here */
6008 /* bytes cycles reg x reg a carry
6009 ** abcd efgh ijkl mnop ?
6010 ** clra 1 1 abcd efgh 0000 0000 a
6011 ** lslx 1 1 bcde fgh0 0000 0000 a
6012 ** rola 1 1 bcde fgh0 0000 000a 0
6013 ** clrx 1 1 0000 0000 0000 000a 0
6014 ** total: 4 cycles, 4 bytes
6016 loadRegFromConst (hc08_reg_x, zero);
6017 rmwWithReg ("lsl", hc08_reg_x);
6018 rmwWithReg ("rol", hc08_reg_a);
6019 loadRegFromConst (hc08_reg_a, zero);
6023 /* bytes cycles reg x reg a carry
6024 ** abcd efgh ijkl mnop ?
6025 ** clra 1 1 abcd efgh 0000 0000 a
6026 ** lslx 1 1 bcde fgh0 0000 0000 a
6027 ** rola 1 1 bcde fgh0 0000 000a 0
6028 ** lslx 1 1 cdef gh00 0000 000a b
6029 ** rola 1 1 cdef gh00 0000 00ab 0
6030 ** clrx 1 1 0000 0000 0000 00ab 0
6031 ** total: 6 cycles, 6 bytes
6033 loadRegFromConst (hc08_reg_x, zero);
6034 rmwWithReg ("lsl", hc08_reg_x);
6035 rmwWithReg ("rol", hc08_reg_a);
6036 rmwWithReg ("lsl", hc08_reg_x);
6037 rmwWithReg ("rol", hc08_reg_a);
6038 loadRegFromConst (hc08_reg_a, zero);
6047 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6048 AccRsh (shCount-8, FALSE);
6049 loadRegFromConst (hc08_reg_x, zero);
6053 /* bytes cycles reg x reg a carry
6054 ** abcd efgh ijkl mnop ?
6055 ** lsla 1 1 abcd efgh jklm nop0 i
6056 ** txa 1 1 abcd efgh abcd efgh i
6057 ** rola 1 1 abcd efgh bcde fghi a
6058 ** clrx 1 1 0000 0000 bcde fghi a
6059 ** rolx 1 1 0000 000a bcde fghi 0
6060 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
6062 rmwWithReg ("lsl", hc08_reg_a);
6063 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
6064 rmwWithReg ("rol", hc08_reg_a);
6065 loadRegFromConst (hc08_reg_x, zero);
6066 rmwWithReg ("rol", hc08_reg_x);
6069 /* bytes cycles reg x reg a carry
6070 ** abcd efgh ijkl mnop ?
6071 ** lsla 1 1 abcd efgh jklm nop0 i
6072 ** rolx 1 1 bcde fghi jklm nop0 a
6073 ** rola 1 1 bcde fghi klmn op0a j
6074 ** rolx 1 1 cdef ghij klmn op0a b
6075 ** rola 1 1 cdef ghij lmno p0ab k
6076 ** and #3 2 2 cdef ghij 0000 00ab k
6077 ** psha 1 2 cdef ghij 0000 00ab k
6078 ** txa 1 1 cdef ghij cdef ghij k
6079 ** pula 1 2 0000 00ab cdef ghij k
6080 ** total: 12 cycles, 10 bytes (beats 12 bytes)
6086 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
6087 /* the fastest and shortest. */
6088 for (i=0;i<shCount;i++)
6090 rmwWithReg ("lsr", hc08_reg_x);
6091 rmwWithReg ("ror", hc08_reg_a);
6098 /*-----------------------------------------------------------------*/
6099 /* shiftR1Left2Result - shift right one byte from left to result */
6100 /*-----------------------------------------------------------------*/
6102 shiftR1Left2Result (operand * left, int offl,
6103 operand * result, int offr,
6104 int shCount, int sign)
6106 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6107 /* shift right accumulator */
6108 AccRsh (shCount, sign);
6109 storeRegToAop (hc08_reg_a, AOP (result), offr);
6113 /*-----------------------------------------------------------------*/
6114 /* shiftL1Left2Result - shift left one byte from left to result */
6115 /*-----------------------------------------------------------------*/
6117 shiftL1Left2Result (operand * left, int offl,
6118 operand * result, int offr, int shCount)
6120 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6121 /* shift left accumulator */
6123 storeRegToAop (hc08_reg_a, AOP (result), offr);
6126 /*-----------------------------------------------------------------*/
6127 /* movLeft2Result - move byte from left to result */
6128 /*-----------------------------------------------------------------*/
6130 movLeft2Result (operand * left, int offl,
6131 operand * result, int offr, int sign)
6133 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
6135 transferAopAop (AOP (left), offl, AOP (result), offr);
6140 /*-----------------------------------------------------------------*/
6141 /* shiftL2Left2Result - shift left two bytes from left to result */
6142 /*-----------------------------------------------------------------*/
6144 shiftL2Left2Result (operand * left, int offl,
6145 operand * result, int offr, int shCount)
6148 bool needpula = FALSE;
6149 bool needpulx = FALSE;
6151 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
6152 needpula = pushRegIfUsed (hc08_reg_a);
6155 if (!IS_AOP_XA (AOP (left)))
6156 needpulx = pushRegIfUsed (hc08_reg_x);
6160 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6165 rmwWithReg ("lsr", hc08_reg_x);
6166 rmwWithReg ("ror", hc08_reg_a);
6167 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
6168 rmwWithReg ("clr", hc08_reg_a);
6169 rmwWithReg ("ror", hc08_reg_a);
6172 for (i=0; i<shCount; i++)
6174 rmwWithReg ("lsl", hc08_reg_a);
6175 rmwWithReg ("rol", hc08_reg_x);
6178 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6180 pullOrFreeReg (hc08_reg_x, needpulx);
6181 pullOrFreeReg (hc08_reg_a, needpula);
6187 /*-----------------------------------------------------------------*/
6188 /* shiftR2Left2Result - shift right two bytes from left to result */
6189 /*-----------------------------------------------------------------*/
6191 shiftR2Left2Result (operand * left, int offl,
6192 operand * result, int offr,
6193 int shCount, int sign)
6196 bool needpula = FALSE;
6197 bool needpulx = FALSE;
6199 needpula = pushRegIfUsed (hc08_reg_a);
6200 needpulx = pushRegIfUsed (hc08_reg_x);
6202 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6203 for (i=0; i<shCount; i++)
6206 rmwWithReg ("asr", hc08_reg_x);
6208 rmwWithReg ("lsr", hc08_reg_x);
6209 rmwWithReg ("ror", hc08_reg_a);
6211 storeRegToAop (hc08_reg_xa, AOP (result), offl);
6213 pullOrFreeReg (hc08_reg_x, needpulx);
6214 pullOrFreeReg (hc08_reg_a, needpula);
6219 /*-----------------------------------------------------------------*/
6220 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6221 /*-----------------------------------------------------------------*/
6223 shiftLLeftOrResult (operand * left, int offl,
6224 operand * result, int offr, int shCount)
6226 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6227 /* shift left accumulator */
6229 /* or with result */
6230 accopWithAop ("ora", AOP (result), offr);
6231 /* back to result */
6232 storeRegToAop (hc08_reg_a, AOP (result), offr);
6233 hc08_freeReg (hc08_reg_a);
6237 /*-----------------------------------------------------------------*/
6238 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6239 /*-----------------------------------------------------------------*/
6241 shiftRLeftOrResult (operand * left, int offl,
6242 operand * result, int offr, int shCount)
6244 loadRegFromAop (hc08_reg_a, AOP (left), offl);
6245 /* shift left accumulator */
6246 AccRsh (shCount, FALSE);
6247 /* or with result */
6248 accopWithAop ("ora", AOP (result), offr);
6249 /* back to result */
6250 storeRegToAop (hc08_reg_a, AOP (result), offr);
6251 hc08_freeReg (hc08_reg_a);
6254 /*-----------------------------------------------------------------*/
6255 /* genlshOne - left shift a one byte quantity by known count */
6256 /*-----------------------------------------------------------------*/
6258 genlshOne (operand * result, operand * left, int shCount)
6260 D(emitcode ("; genlshOne",""));
6262 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6265 /*-----------------------------------------------------------------*/
6266 /* genlshTwo - left shift two bytes by known amount != 0 */
6267 /*-----------------------------------------------------------------*/
6269 genlshTwo (operand * result, operand * left, int shCount)
6273 D(emitcode ("; genlshTwo",""));
6276 size = getDataSize (result);
6278 /* if shCount >= 8 */
6285 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6287 storeRegToAop (hc08_reg_a, AOP (result), 1);
6289 storeConstToAop(zero, AOP (result), LSB);
6292 /* 1 <= shCount <= 7 */
6295 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6297 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
6301 /*-----------------------------------------------------------------*/
6302 /* shiftLLong - shift left one long from left to result */
6303 /* offl = LSB or MSB16 */
6304 /*-----------------------------------------------------------------*/
6306 shiftLLong (operand * left, operand * result, int offr)
6309 // int size = AOP_SIZE (result);
6311 bool needpula = FALSE;
6312 bool needpulx = FALSE;
6314 needpula = pushRegIfUsed (hc08_reg_a);
6315 needpulx = pushRegIfUsed (hc08_reg_x);
6317 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
6318 rmwWithReg ("lsl", hc08_reg_a);
6319 rmwWithReg ("rol", hc08_reg_x);
6320 storeRegToAop (hc08_reg_xa, AOP (result), offr);
6324 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6325 rmwWithReg ("rol", hc08_reg_a);
6326 rmwWithReg ("rol", hc08_reg_x);
6327 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
6329 else if (offr==MSB16)
6331 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
6332 rmwWithReg ("rol", hc08_reg_a);
6333 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
6334 storeConstToAop (zero, AOP (result), 0);
6337 pullOrFreeReg (hc08_reg_x, needpulx);
6338 pullOrFreeReg (hc08_reg_a, needpula);
6341 /*-----------------------------------------------------------------*/
6342 /* genlshFour - shift four byte by a known amount != 0 */
6343 /*-----------------------------------------------------------------*/
6345 genlshFour (operand * result, operand * left, int shCount)
6349 D(emitcode ("; genlshFour",""));
6351 size = AOP_SIZE (result);
6353 /* TODO: deal with the &result == &left case */
6355 /* if shifting more that 3 bytes */
6360 /* lowest order of left goes to the highest
6361 order of the destination */
6362 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6364 movLeft2Result (left, LSB, result, MSB32, 0);
6365 storeConstToAop (zero, AOP (result), LSB);
6366 storeConstToAop (zero, AOP (result), MSB16);
6367 storeConstToAop (zero, AOP (result), MSB24);
6371 /* more than two bytes */
6372 else if (shCount >= 16)
6374 /* lower order two bytes goes to higher order two bytes */
6376 /* if some more remaining */
6378 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6381 movLeft2Result (left, MSB16, result, MSB32, 0);
6382 movLeft2Result (left, LSB, result, MSB24, 0);
6384 storeConstToAop (zero, AOP (result), LSB);
6385 storeConstToAop (zero, AOP (result), MSB16);
6389 /* if more than 1 byte */
6390 else if (shCount >= 8)
6392 /* lower order three bytes goes to higher order three bytes */
6397 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6399 movLeft2Result (left, LSB, result, MSB16, 0);
6405 movLeft2Result (left, MSB24, result, MSB32, 0);
6406 movLeft2Result (left, MSB16, result, MSB24, 0);
6407 movLeft2Result (left, LSB, result, MSB16, 0);
6408 storeConstToAop (zero, AOP (result), LSB);
6410 else if (shCount == 1)
6411 shiftLLong (left, result, MSB16);
6414 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6415 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6416 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6417 storeConstToAop (zero, AOP (result), LSB);
6422 /* 1 <= shCount <= 7 */
6423 else if (shCount <= 2)
6425 shiftLLong (left, result, LSB);
6427 shiftLLong (result, result, LSB);
6429 /* 3 <= shCount <= 7, optimize */
6432 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6433 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6434 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6438 /*-----------------------------------------------------------------*/
6439 /* genLeftShiftLiteral - left shifting by known count */
6440 /*-----------------------------------------------------------------*/
6442 genLeftShiftLiteral (operand * left,
6447 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6450 D(emitcode ("; genLeftShiftLiteral",""));
6452 freeAsmop (right, NULL, ic, TRUE);
6454 aopOp (left, ic, FALSE);
6455 aopOp (result, ic, FALSE);
6457 // size = getSize (operandType (result));
6458 size = AOP_SIZE (result);
6461 D(emitcode ("; shift left ", "result %d, left %d", size,
6468 transferAopAop( AOP(left), size, AOP(result), size);
6470 else if (shCount >= (size * 8))
6473 storeConstToAop (zero, AOP (result), size);
6480 genlshOne (result, left, shCount);
6484 genlshTwo (result, left, shCount);
6488 genlshFour (result, left, shCount);
6491 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6492 "*** ack! mystery literal shift!\n");
6496 freeAsmop (left, NULL, ic, TRUE);
6497 freeAsmop (result, NULL, ic, TRUE);
6500 /*-----------------------------------------------------------------*/
6501 /* genLeftShift - generates code for left shifting */
6502 /*-----------------------------------------------------------------*/
6504 genLeftShift (iCode * ic)
6506 operand *left, *right, *result;
6508 symbol *tlbl, *tlbl1;
6513 D(emitcode ("; genLeftShift",""));
6515 right = IC_RIGHT (ic);
6516 left = IC_LEFT (ic);
6517 result = IC_RESULT (ic);
6519 aopOp (right, ic, FALSE);
6521 /* if the shift count is known then do it
6522 as efficiently as possible */
6523 if (AOP_TYPE (right) == AOP_LIT)
6525 genLeftShiftLiteral (left, right, result, ic);
6529 /* shift count is unknown then we have to form
6530 a loop get the loop count in A : Note: we take
6531 only the lower order byte since shifting
6532 more that 32 bits make no sense anyway, ( the
6533 largest size of an object can be only 32 bits ) */
6535 aopOp (left, ic, FALSE);
6536 aopOp (result, ic, FALSE);
6538 /* now move the left to the result if they are not the
6540 if (!sameRegs (AOP (left), AOP (result)))
6543 size = AOP_SIZE (result);
6547 transferAopAop (AOP (left), offset, AOP (result), offset);
6551 freeAsmop (left, NULL, ic, TRUE);
6553 tlbl = newiTempLabel (NULL);
6554 size = AOP_SIZE (result);
6556 tlbl1 = newiTempLabel (NULL);
6560 loadRegFromAop (reg, AOP (right), 0);
6561 freeAsmop (right, NULL, ic, TRUE);
6562 emitBranch ("beq", tlbl1);
6566 for (offset=0;offset<size;offset++)
6568 rmwWithAop (shift, AOP (result), offset);
6571 rmwWithReg ("dec", reg);
6572 emitBranch ("bne", tlbl);
6576 freeAsmop (result, NULL, ic, TRUE);
6579 /*-----------------------------------------------------------------*/
6580 /* genrshOne - right shift a one byte quantity by known count */
6581 /*-----------------------------------------------------------------*/
6583 genrshOne (operand * result, operand * left,
6584 int shCount, int sign)
6586 D(emitcode ("; genrshOne",""));
6588 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6589 AccRsh (shCount, sign);
6590 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6593 /*-----------------------------------------------------------------*/
6594 /* genrshTwo - right shift two bytes by known amount != 0 */
6595 /*-----------------------------------------------------------------*/
6597 genrshTwo (operand * result, operand * left,
6598 int shCount, int sign)
6600 D(emitcode ("; genrshTwo",""));
6602 /* if shCount >= 8 */
6605 if (shCount || sign)
6607 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6608 AccRsh (shCount-8, sign);
6609 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6613 transferAopAop (AOP (left), 1, AOP (result), 0);
6614 storeConstToAop (zero, AOP (result), 1);
6618 /* 1 <= shCount <= 7 */
6621 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6622 XAccRsh (shCount, sign);
6623 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6627 /*-----------------------------------------------------------------*/
6628 /* shiftRLong - shift right one long from left to result */
6629 /* offl = LSB or MSB16 */
6630 /*-----------------------------------------------------------------*/
6632 shiftRLong (operand * left, int offl,
6633 operand * result, int sign)
6636 // int size = AOP_SIZE (result);
6638 bool needpula = FALSE;
6639 bool needpulx = FALSE;
6641 needpula = pushRegIfUsed (hc08_reg_a);
6642 needpulx = pushRegIfUsed (hc08_reg_x);
6646 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6648 rmwWithReg ("asr", hc08_reg_x);
6650 rmwWithReg ("lsr", hc08_reg_x);
6651 rmwWithReg ("ror", hc08_reg_a);
6652 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6654 else if (offl==MSB16)
6656 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6658 rmwWithReg ("asr", hc08_reg_a);
6660 rmwWithReg ("lsr", hc08_reg_a);
6661 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6662 storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
6665 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6666 rmwWithReg ("ror", hc08_reg_x);
6667 rmwWithReg ("ror", hc08_reg_a);
6668 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6671 pullOrFreeReg (hc08_reg_x, needpulx);
6672 pullOrFreeReg (hc08_reg_a, needpula);
6675 /*-----------------------------------------------------------------*/
6676 /* genrshFour - shift four byte by a known amount != 0 */
6677 /*-----------------------------------------------------------------*/
6679 genrshFour (operand * result, operand * left,
6680 int shCount, int sign)
6682 /* TODO: handle cases where left == result */
6684 D(emitcode ("; genrshFour",""));
6686 /* if shifting more that 3 bytes */
6689 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6690 AccRsh (shCount-24, sign);
6691 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6694 else if (shCount >= 16)
6696 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6697 XAccRsh (shCount-16, sign);
6698 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6701 else if (shCount >= 8)
6704 shiftRLong (left, MSB16, result, sign);
6705 else if (shCount == 8)
6707 transferAopAop (AOP (left), 1, AOP (result), 0);
6708 transferAopAop (AOP (left), 2, AOP (result), 1);
6709 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6710 storeRegToAop (hc08_reg_a, AOP (result), 2);
6711 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6713 else if (shCount == 9)
6715 shiftRLong (left, MSB16, result, sign);
6719 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6720 XAccRsh (shCount-8, FALSE);
6721 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6722 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6723 loadRegFromConst (hc08_reg_a, zero);
6724 XAccRsh (shCount-8, sign);
6725 accopWithAop ("ora", AOP (result), 1);
6726 storeRegToAop (hc08_reg_xa, AOP (result), 1);
6727 storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
6731 { /* 1 <= shCount <= 7 */
6734 shiftRLong (left, LSB, result, sign);
6738 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6739 XAccRsh (shCount, FALSE);
6740 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6741 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6743 accopWithAop ("ora", AOP (result), 1);
6744 storeRegToAop (hc08_reg_a, AOP (result), 1);
6745 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6746 XAccRsh (shCount, sign);
6747 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6752 /*-----------------------------------------------------------------*/
6753 /* genRightShiftLiteral - right shifting by known count */
6754 /*-----------------------------------------------------------------*/
6756 genRightShiftLiteral (operand * left,
6762 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6765 D(emitcode ("; genRightShiftLiteral",""));
6767 freeAsmop (right, NULL, ic, TRUE);
6769 aopOp (left, ic, FALSE);
6770 aopOp (result, ic, FALSE);
6773 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6777 size = getDataSize (left);
6778 /* test the LEFT size !!! */
6780 /* I suppose that the left size >= result size */
6783 size = getDataSize (result);
6785 transferAopAop (AOP (left), size, AOP(result), size);
6787 else if (shCount >= (size * 8))
6790 /* get sign in acc.7 */
6791 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6793 addSign (result, LSB, sign);
6800 genrshOne (result, left, shCount, sign);
6804 genrshTwo (result, left, shCount, sign);
6808 genrshFour (result, left, shCount, sign);
6814 freeAsmop (left, NULL, ic, TRUE);
6815 freeAsmop (result, NULL, ic, TRUE);
6819 /*-----------------------------------------------------------------*/
6820 /* genRightShift - generate code for right shifting */
6821 /*-----------------------------------------------------------------*/
6823 genRightShift (iCode * ic)
6825 operand *right, *left, *result;
6829 symbol *tlbl, *tlbl1;
6833 D(emitcode ("; genRightShift",""));
6835 /* if signed then we do it the hard way preserve the
6836 sign bit moving it inwards */
6837 retype = getSpec (operandType (IC_RESULT (ic)));
6838 sign = !SPEC_USIGN (retype);
6840 /* signed & unsigned types are treated the same : i.e. the
6841 signed is NOT propagated inwards : quoting from the
6842 ANSI - standard : "for E1 >> E2, is equivalent to division
6843 by 2**E2 if unsigned or if it has a non-negative value,
6844 otherwise the result is implementation defined ", MY definition
6845 is that the sign does not get propagated */
6847 right = IC_RIGHT (ic);
6848 left = IC_LEFT (ic);
6849 result = IC_RESULT (ic);
6851 aopOp (right, ic, FALSE);
6853 /* if the shift count is known then do it
6854 as efficiently as possible */
6855 if (AOP_TYPE (right) == AOP_LIT)
6857 genRightShiftLiteral (left, right, result, ic, sign);
6861 /* shift count is unknown then we have to form
6862 a loop get the loop count in X : Note: we take
6863 only the lower order byte since shifting
6864 more that 32 bits make no sense anyway, ( the
6865 largest size of an object can be only 32 bits ) */
6867 aopOp (left, ic, FALSE);
6868 aopOp (result, ic, FALSE);
6870 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6871 AOP (result) = forceStackedAop (AOP (result));
6873 size = AOP_SIZE (result);
6877 transferAopAop (AOP (left), offset, AOP (result), offset);
6881 tlbl = newiTempLabel (NULL);
6882 size = AOP_SIZE (result);
6884 tlbl1 = newiTempLabel (NULL);
6886 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6887 emitcode ("tstx", "");
6888 emitcode ("beq", "%05d$", tlbl1->key + 100);
6889 emitcode ("", "%05d$:", tlbl->key + 100);
6890 shift= sign ? "asr" : "lsr";
6891 for (offset=size-1;offset>=0;offset--)
6893 rmwWithAop (shift, AOP (result), offset);
6896 rmwWithReg ("dec", hc08_reg_x);
6897 emitcode ("bne","%05d$", tlbl->key + 100);
6898 emitcode ("", "%05d$:", tlbl1->key + 100);
6900 freeAsmop (result, NULL, ic, TRUE);
6901 freeAsmop (left, NULL, ic, TRUE);
6902 freeAsmop (right, NULL, ic, TRUE);
6906 /*-----------------------------------------------------------------*/
6907 /* genUnpackBits - generates code for unpacking bits */
6908 /*-----------------------------------------------------------------*/
6910 genUnpackBits (operand * result, iCode *ifx)
6912 int offset = 0; /* result byte offset */
6913 int rsize; /* result size */
6914 int rlen = 0; /* remaining bitfield length */
6915 sym_link *etype; /* bitfield type information */
6916 int blen; /* bitfield length */
6917 int bstr; /* bitfield starting bit within byte */
6919 D(emitcode ("; genUnpackBits",""));
6921 etype = getSpec (operandType (result));
6922 rsize = getSize (operandType (result));
6923 blen = SPEC_BLEN (etype);
6924 bstr = SPEC_BSTR (etype);
6926 if (ifx && blen <= 8)
6928 emitcode ("lda", ",x");
6929 hc08_dirtyReg (hc08_reg_a, FALSE);
6932 emitcode ("and", "#0x%02x",
6933 (((unsigned char) -1) >> (8 - blen)) << bstr);
6935 genIfxJump (ifx, "a");
6940 /* If the bitfield length is less than a byte */
6943 emitcode ("lda", ",x");
6944 hc08_dirtyReg (hc08_reg_a, FALSE);
6945 AccRsh (bstr, FALSE);
6946 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6947 if (!SPEC_USIGN (etype))
6949 /* signed bitfield */
6950 symbol *tlbl = newiTempLabel (NULL);
6952 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
6953 emitcode ("beq", "%05d$", tlbl->key + 100);
6954 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
6957 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6961 /* Bit field did not fit in a byte. Copy all
6962 but the partial byte at the end. */
6963 for (rlen=blen;rlen>=8;rlen-=8)
6965 emitcode ("lda", ",x");
6966 hc08_dirtyReg (hc08_reg_a, FALSE);
6967 storeRegToAop (hc08_reg_a, AOP (result), offset);
6970 emitcode ("aix", "#1");
6973 /* Handle the partial byte at the end */
6976 emitcode ("lda", ",x");
6977 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6978 if (!SPEC_USIGN (etype))
6980 /* signed bitfield */
6981 symbol *tlbl = newiTempLabel (NULL);
6983 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
6984 emitcode ("beq", "%05d$", tlbl->key + 100);
6985 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
6988 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6995 if (SPEC_USIGN (etype))
6998 storeConstToAop (zero, AOP (result), offset++);
7002 /* signed bitfield: sign extension with 0x00 or 0xff */
7003 emitcode ("rola", "");
7004 emitcode ("clra", "");
7005 emitcode ("sbc", zero);
7008 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7014 /*-----------------------------------------------------------------*/
7015 /* genUnpackBitsImmed - generates code for unpacking bits */
7016 /*-----------------------------------------------------------------*/
7018 genUnpackBitsImmed (operand * left,
7024 int offset = 0; /* result byte offset */
7025 int rsize; /* result size */
7026 int rlen = 0; /* remaining bitfield length */
7027 sym_link *etype; /* bitfield type information */
7028 int blen; /* bitfield length */
7029 int bstr; /* bitfield starting bit within byte */
7032 D(emitcode ("; genUnpackBitsImmed",""));
7034 aopOp (result, ic, TRUE);
7035 size = AOP_SIZE (result);
7037 derefaop = aopDerefAop (AOP (left));
7038 freeAsmop (left, NULL, ic, TRUE);
7039 derefaop->size = size;
7041 etype = getSpec (operandType (result));
7042 rsize = getSize (operandType (result));
7043 blen = SPEC_BLEN (etype);
7044 bstr = SPEC_BSTR (etype);
7046 /* if the bitfield is a single bit in the direct page */
7047 if (blen == 1 && derefaop->type == AOP_DIR)
7051 symbol *tlbl = newiTempLabel (NULL);
7053 loadRegFromConst (hc08_reg_a, zero);
7054 emitcode ("brclr", "#%d,%s,%05d$",
7055 bstr, aopAdrStr (derefaop, 0, FALSE),
7057 if (SPEC_USIGN (etype))
7058 rmwWithReg ("inc", hc08_reg_a);
7060 rmwWithReg ("dec", hc08_reg_a);
7062 storeRegToAop (hc08_reg_a, AOP (result), offset);
7063 hc08_freeReg (hc08_reg_a);
7069 symbol *tlbl = newiTempLabel (NULL);
7075 jlbl = IC_TRUE (ifx);
7080 jlbl = IC_FALSE (ifx);
7083 emitcode (inst, "#%d,%s,%05d$",
7084 bstr, aopAdrStr (derefaop, 0, FALSE),
7086 emitBranch ("jmp", jlbl);
7094 /* If the bitfield length is less than a byte */
7097 loadRegFromAop (hc08_reg_a, derefaop, 0);
7100 AccRsh (bstr, FALSE);
7101 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
7102 hc08_dirtyReg (hc08_reg_a, FALSE);
7103 if (!SPEC_USIGN (etype))
7105 /* signed bitfield */
7106 symbol *tlbl = newiTempLabel (NULL);
7108 emitcode ("bit", "#0x%02x", 1<<(blen - 1));
7109 emitcode ("beq", "%05d$", tlbl->key + 100);
7110 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
7113 storeRegToAop (hc08_reg_a, AOP (result), offset);
7117 emitcode ("and", "#0x%02x",
7118 (((unsigned char) -1) >> (8 - blen)) << bstr);
7119 hc08_dirtyReg (hc08_reg_a, FALSE);
7125 /* Bit field did not fit in a byte. Copy all
7126 but the partial byte at the end. */
7127 for (rlen=blen;rlen>=8;rlen-=8)
7129 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7131 storeRegToAop (hc08_reg_a, AOP (result), offset);
7133 emitcode ("tsta", "");
7137 /* Handle the partial byte at the end */
7140 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7141 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
7142 if (!SPEC_USIGN (etype))
7144 /* signed bitfield */
7145 symbol *tlbl = newiTempLabel (NULL);
7147 emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
7148 emitcode ("beq", "%05d$", tlbl->key + 100);
7149 emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
7152 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7159 if (SPEC_USIGN (etype))
7162 storeConstToAop (zero, AOP (result), offset++);
7166 /* signed bitfield: sign extension with 0x00 or 0xff */
7167 emitcode ("rola", "");
7168 emitcode ("clra", "");
7169 emitcode ("sbc", zero);
7172 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7176 freeAsmop (NULL, derefaop, ic, TRUE);
7177 freeAsmop (result, NULL, ic, TRUE);
7179 if (ifx && !ifx->generated)
7181 genIfxJump (ifx, "a");
7186 /*-----------------------------------------------------------------*/
7187 /* genDataPointerGet - generates code when ptr offset is known */
7188 /*-----------------------------------------------------------------*/
7190 genDataPointerGet (operand * left,
7198 D(emitcode ("; genDataPointerGet",""));
7200 aopOp (result, ic, TRUE);
7201 size = AOP_SIZE (result);
7203 derefaop = aopDerefAop (AOP (left));
7204 freeAsmop (left, NULL, ic, TRUE);
7205 derefaop->size = size;
7210 transferAopAop (derefaop, size, AOP (result), size);
7212 loadRegFromAop (hc08_reg_a, derefaop, size);
7215 freeAsmop (NULL, derefaop, ic, TRUE);
7216 freeAsmop (result, NULL, ic, TRUE);
7218 if (ifx && !ifx->generated)
7220 genIfxJump (ifx, "a");
7225 /*-----------------------------------------------------------------*/
7226 /* genPointerGet - generate code for pointer get */
7227 /*-----------------------------------------------------------------*/
7229 genPointerGet (iCode * ic, iCode *pi, iCode *ifx)
7231 operand *left = IC_LEFT (ic);
7232 operand *result = IC_RESULT (ic);
7234 sym_link *retype = getSpec (operandType (result));
7236 D(emitcode ("; genPointerGet",""));
7238 if (getSize (operandType (result))>1)
7241 aopOp (left, ic, FALSE);
7243 /* if left is rematerialisable and
7244 result is not bit variable type */
7245 if (AOP_TYPE (left) == AOP_IMMD || AOP_TYPE (left) == AOP_LIT)
7247 if (!IS_BITVAR (retype))
7249 genDataPointerGet (left, result, ic, ifx);
7254 genUnpackBitsImmed (left, result, ic, ifx);
7259 /* if the operand is already in hx
7260 then we do nothing else we move the value to hx */
7261 if (AOP_TYPE (left) != AOP_STR)
7263 /* if this is remateriazable */
7264 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
7267 /* so hx now contains the address */
7268 aopOp (result, ic, FALSE);
7270 /* if bit then unpack */
7271 if (IS_BITVAR (retype))
7272 genUnpackBits (result, ifx);
7275 size = AOP_SIZE (result);
7280 accopWithMisc ("lda", ",x");
7283 emitcode ("aix", "#1");
7284 hc08_dirtyReg (hc08_reg_hx, FALSE);
7287 storeRegToAop (hc08_reg_a, AOP (result), offset);
7289 hc08_freeReg (hc08_reg_a);
7293 freeAsmop (left, NULL, ic, TRUE);
7294 freeAsmop (result, NULL, ic, TRUE);
7297 aopOp (IC_RESULT (pi), pi, FALSE);
7298 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7299 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7303 if (ifx && !ifx->generated)
7305 genIfxJump (ifx, "a");
7308 hc08_freeReg (hc08_reg_hx);
7312 /*-----------------------------------------------------------------*/
7313 /* genPackBits - generates code for packed bit storage */
7314 /*-----------------------------------------------------------------*/
7316 genPackBits (sym_link * etype,
7319 int offset = 0; /* source byte offset */
7320 int rlen = 0; /* remaining bitfield length */
7321 int blen; /* bitfield length */
7322 int bstr; /* bitfield starting bit within byte */
7323 int litval; /* source literal value (if AOP_LIT) */
7324 unsigned char mask; /* bitmask within current byte */
7327 D(emitcode ("; genPackBits",""));
7329 blen = SPEC_BLEN (etype);
7330 bstr = SPEC_BSTR (etype);
7332 /* If the bitfield length is less than a byte */
7335 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7336 (unsigned char) (0xFF >> (8 - bstr)));
7338 if (AOP_TYPE (right) == AOP_LIT)
7340 /* Case with a bitfield length <8 and literal source
7342 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7344 litval &= (~mask) & 0xff;
7346 emitcode ("lda", ",x");
7347 if ((mask|litval)!=0xff)
7348 emitcode ("and","#0x%02x", mask);
7350 emitcode ("ora","#0x%02x", litval);
7351 hc08_dirtyReg (hc08_reg_a, FALSE);
7352 emitcode ("sta", ",x");
7354 hc08_freeReg (hc08_reg_a);
7358 /* Case with a bitfield length < 8 and arbitrary source
7360 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7361 /* shift and mask source value */
7363 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7364 hc08_dirtyReg (hc08_reg_a, FALSE);
7365 pushReg (hc08_reg_a, TRUE);
7367 emitcode ("lda", ",x");
7368 emitcode ("and", "#0x%02x", mask);
7369 emitcode ("ora", "1,s");
7370 emitcode ("sta", ",x");
7371 pullReg (hc08_reg_a);
7373 hc08_freeReg (hc08_reg_a);
7377 /* Bit length is greater than 7 bits. In this case, copy */
7378 /* all except the partial byte at the end */
7379 for (rlen=blen;rlen>=8;rlen-=8)
7381 if (AOP (right)->type == AOP_DIR)
7383 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
7388 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7389 emitcode ("sta", "%d,x", offset);
7394 /* If there was a partial byte at the end */
7397 mask = (((unsigned char) -1 << rlen) & 0xff);
7399 if (AOP_TYPE (right) == AOP_LIT)
7401 /* Case with partial byte and literal source
7403 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7404 litval >>= (blen-rlen);
7405 litval &= (~mask) & 0xff;
7406 emitcode ("lda", "%d,x", offset - xoffset);
7407 hc08_dirtyReg (hc08_reg_a, FALSE);
7408 if ((mask|litval)!=0xff)
7409 emitcode ("and","#0x%02x", mask);
7411 emitcode ("ora","#0x%02x", litval);
7412 emitcode ("sta", "%d,x", offset - xoffset);
7413 hc08_dirtyReg (hc08_reg_a, FALSE);
7414 hc08_freeReg (hc08_reg_a);
7418 /* Case with partial byte and arbitrary source
7420 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7421 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7422 hc08_dirtyReg (hc08_reg_a, FALSE);
7423 pushReg (hc08_reg_a, TRUE);
7425 emitcode ("lda", "%d,x", offset - xoffset);
7426 emitcode ("and", "#0x%02x", mask);
7427 emitcode ("ora", "1,s");
7428 emitcode ("sta", "%d,x", offset - xoffset);
7429 pullReg (hc08_reg_a);
7432 hc08_freeReg (hc08_reg_a);
7435 /*-----------------------------------------------------------------*/
7436 /* genPackBitsImmed - generates code for packed bit storage */
7437 /*-----------------------------------------------------------------*/
7439 genPackBitsImmed (operand *result, sym_link * etype, operand * right, iCode * ic)
7443 int offset = 0; /* source byte offset */
7444 int rlen = 0; /* remaining bitfield length */
7445 int blen; /* bitfield length */
7446 int bstr; /* bitfield starting bit within byte */
7447 int litval; /* source literal value (if AOP_LIT) */
7448 unsigned char mask; /* bitmask within current byte */
7450 D(emitcode ("; genPackBitsImmed",""));
7452 blen = SPEC_BLEN (etype);
7453 bstr = SPEC_BSTR (etype);
7455 aopOp (right, ic, FALSE);
7456 size = AOP_SIZE (right);
7458 derefaop = aopDerefAop (AOP (result));
7459 freeAsmop (result, NULL, ic, TRUE);
7460 derefaop->size = size;
7462 /* if the bitfield is a single bit in the direct page */
7463 if (blen == 1 && derefaop->type == AOP_DIR)
7465 if (AOP_TYPE (right) == AOP_LIT)
7467 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7469 emitcode ((litval & 1) ? "bset" : "bclr",
7470 "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7474 symbol *tlbl1 = newiTempLabel (NULL);
7475 symbol *tlbl2 = newiTempLabel (NULL);
7477 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7478 emitcode ("bit", "#1");
7479 emitBranch ("bne", tlbl1);
7480 emitcode ("bclr", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7481 emitBranch ("bra", tlbl2);
7483 emitcode ("bset", "#%d,%s", bstr, aopAdrStr (derefaop, 0, FALSE));
7485 hc08_freeReg (hc08_reg_a);
7490 /* If the bitfield length is less than a byte */
7493 mask = ((unsigned char) (0xFF << (blen + bstr)) |
7494 (unsigned char) (0xFF >> (8 - bstr)));
7496 if (AOP_TYPE (right) == AOP_LIT)
7498 /* Case with a bitfield length <8 and literal source
7500 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7502 litval &= (~mask) & 0xff;
7504 loadRegFromAop (hc08_reg_a, derefaop, 0);
7505 if ((mask|litval)!=0xff)
7506 emitcode ("and","#0x%02x", mask);
7508 emitcode ("ora","#0x%02x", litval);
7509 hc08_dirtyReg (hc08_reg_a, FALSE);
7510 storeRegToAop (hc08_reg_a, derefaop, 0);
7512 hc08_freeReg (hc08_reg_a);
7516 /* Case with a bitfield length < 8 and arbitrary source
7518 loadRegFromAop (hc08_reg_a, AOP (right), 0);
7519 /* shift and mask source value */
7521 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7522 hc08_dirtyReg (hc08_reg_a, FALSE);
7523 pushReg (hc08_reg_a, TRUE);
7525 loadRegFromAop (hc08_reg_a, derefaop, 0);
7526 emitcode ("and", "#0x%02x", mask);
7527 emitcode ("ora", "1,s");
7528 storeRegToAop (hc08_reg_a, derefaop, 0);
7529 pullReg (hc08_reg_a);
7531 hc08_freeReg (hc08_reg_a);
7535 /* Bit length is greater than 7 bits. In this case, copy */
7536 /* all except the partial byte at the end */
7537 for (rlen=blen;rlen>=8;rlen-=8)
7539 transferAopAop (AOP (right), offset, derefaop, size-offset-1);
7543 /* If there was a partial byte at the end */
7546 mask = (((unsigned char) -1 << rlen) & 0xff);
7548 if (AOP_TYPE (right) == AOP_LIT)
7550 /* Case with partial byte and literal source
7552 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
7553 litval >>= (blen-rlen);
7554 litval &= (~mask) & 0xff;
7555 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7556 if ((mask|litval)!=0xff)
7557 emitcode ("and","#0x%02x", mask);
7559 emitcode ("ora","#0x%02x", litval);
7560 hc08_dirtyReg (hc08_reg_a, FALSE);
7561 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7562 hc08_dirtyReg (hc08_reg_a, FALSE);
7563 hc08_freeReg (hc08_reg_a);
7567 /* Case with partial byte and arbitrary source
7569 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7570 emitcode ("and", "#0x%02x", (~mask) & 0xff);
7571 hc08_dirtyReg (hc08_reg_a, FALSE);
7572 pushReg (hc08_reg_a, TRUE);
7574 loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
7575 emitcode ("and", "#0x%02x", mask);
7576 emitcode ("ora", "1,s");
7577 storeRegToAop (hc08_reg_a, derefaop, size-offset-1);
7578 pullReg (hc08_reg_a);
7581 hc08_freeReg (hc08_reg_a);
7584 freeAsmop (right, NULL, ic, TRUE);
7585 freeAsmop (NULL, derefaop, ic, TRUE);
7588 /*-----------------------------------------------------------------*/
7589 /* genDataPointerSet - remat pointer to data space */
7590 /*-----------------------------------------------------------------*/
7592 genDataPointerSet (operand * right,
7599 D(emitcode ("; genDataPointerSet",""));
7601 aopOp (right, ic, FALSE);
7602 size = AOP_SIZE (right);
7604 derefaop = aopDerefAop (AOP (result));
7605 freeAsmop (result, NULL, ic, TRUE);
7606 derefaop->size = size;
7610 transferAopAop (AOP (right), size, derefaop, size);
7613 freeAsmop (right, NULL, ic, TRUE);
7614 freeAsmop (NULL, derefaop, ic, TRUE);
7618 /*-----------------------------------------------------------------*/
7619 /* genPointerSet - stores the value into a pointer location */
7620 /*-----------------------------------------------------------------*/
7622 genPointerSet (iCode * ic, iCode *pi)
7624 operand *right = IC_RIGHT (ic);
7625 operand *result = IC_RESULT (ic);
7626 sym_link *type, *etype;
7628 sym_link *retype = getSpec (operandType (right));
7629 sym_link *letype = getSpec (operandType (result));
7631 D(emitcode ("; genPointerSet",""));
7633 type = operandType (result);
7634 etype = getSpec (type);
7636 aopOp (result, ic, FALSE);
7638 /* if the result is rematerializable */
7639 if (AOP_TYPE (result) == AOP_IMMD || AOP_TYPE (result) == AOP_LIT)
7641 if (!IS_BITVAR (retype) && !IS_BITVAR (letype))
7643 genDataPointerSet (right, result, ic);
7648 genPackBitsImmed (result, (IS_BITVAR (retype) ? retype : letype), right, ic);
7653 /* if the operand is already in hx
7654 then we do nothing else we move the value to hx */
7655 if (AOP_TYPE (result) != AOP_STR)
7657 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
7659 /* so hx now contains the address */
7660 aopOp (right, ic, FALSE);
7662 /* if bit then unpack */
7663 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7664 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
7667 size = AOP_SIZE (right);
7672 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
7673 accopWithMisc ("sta", ",x");
7676 emitcode ("aix", "#1");
7678 hc08_freeReg (hc08_reg_a);
7682 freeAsmop (result, NULL, ic, TRUE);
7683 freeAsmop (right, NULL, ic, TRUE);
7686 aopOp (IC_RESULT (pi), pi, FALSE);
7687 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
7688 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
7692 hc08_freeReg (hc08_reg_hx);
7696 /*-----------------------------------------------------------------*/
7697 /* genIfx - generate code for Ifx statement */
7698 /*-----------------------------------------------------------------*/
7700 genIfx (iCode * ic, iCode * popIc)
7702 operand *cond = IC_COND (ic);
7705 D(emitcode ("; genIfx",""));
7707 aopOp (cond, ic, FALSE);
7709 /* If the condition is a literal, we can just do an unconditional */
7710 /* branch or no branch */
7711 if (AOP_TYPE (cond) == AOP_LIT)
7713 unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
7714 freeAsmop (cond, NULL, ic, TRUE);
7716 /* if there was something to be popped then do it */
7722 emitBranch ("jmp", IC_TRUE (ic));
7727 emitBranch ("jmp", IC_FALSE (ic));
7733 /* get the value into acc */
7734 if (AOP_TYPE (cond) != AOP_CRY)
7735 asmopToBool (AOP (cond), FALSE);
7738 /* the result is now in the accumulator */
7739 freeAsmop (cond, NULL, ic, TRUE);
7741 /* if there was something to be popped then do it */
7745 /* if the condition is a bit variable */
7746 if (isbit && IS_ITEMP (cond) &&
7748 genIfxJump (ic, SPIL_LOC (cond)->rname);
7749 else if (isbit && !IS_ITEMP (cond))
7750 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7752 genIfxJump (ic, "a");
7757 /*-----------------------------------------------------------------*/
7758 /* genAddrOf - generates code for address of */
7759 /*-----------------------------------------------------------------*/
7761 genAddrOf (iCode * ic)
7763 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7766 D(emitcode ("; genAddrOf",""));
7768 aopOp (IC_RESULT (ic), ic, FALSE);
7770 /* if the operand is on the stack then we
7771 need to get the stack offset of this
7775 /* if it has an offset then we need to compute
7777 hc08_useReg (hc08_reg_hx);
7778 emitcode ("tsx", "");
7779 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7780 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7781 hc08_freeReg (hc08_reg_hx);
7786 /* object not on stack then we need the name */
7787 size = AOP_SIZE (IC_RESULT (ic));
7792 char s[SDCC_NAME_MAX+10];
7795 sprintf (s, "#%s", sym->rname);
7798 sprintf (s, "#>%s", sym->rname);
7801 sprintf (s, "#(%s >> %d)",
7805 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7809 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7813 /*-----------------------------------------------------------------*/
7814 /* genAssign - generate code for assignment */
7815 /*-----------------------------------------------------------------*/
7817 genAssign (iCode * ic)
7819 operand *result, *right;
7821 // unsigned long lit = 0L;
7823 D(emitcode("; genAssign",""));
7825 result = IC_RESULT (ic);
7826 right = IC_RIGHT (ic);
7828 /* if they are the same */
7829 if (operandsEqu (result, right)) {
7833 aopOp (right, ic, FALSE);
7834 aopOp (result, ic, TRUE);
7836 /* if they are the same registers */
7837 if (sameRegs (AOP (right), AOP (result)))
7840 if ((AOP_TYPE (right) == AOP_LIT)
7841 && (IS_AOP_HX(AOP(result))))
7843 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7848 size = AOP_SIZE (result);
7851 transferAopAop (AOP (right), size, AOP (result), size);
7855 freeAsmop (right, NULL, ic, TRUE);
7856 freeAsmop (result, NULL, ic, TRUE);
7859 /*-----------------------------------------------------------------*/
7860 /* genJumpTab - generates code for jump table */
7861 /*-----------------------------------------------------------------*/
7863 genJumpTab (iCode * ic)
7866 symbol *jtablo = newiTempLabel (NULL);
7867 symbol *jtabhi = newiTempLabel (NULL);
7869 D(emitcode ("; genJumpTab",""));
7871 aopOp (IC_JTCOND (ic), ic, FALSE);
7873 if (hc08_reg_x->isFree && hc08_reg_x->isFree)
7875 /* get the condition into x */
7876 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7877 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7878 loadRegFromConst (hc08_reg_h, zero);
7880 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7881 emitcode ("ldx", "%05d$,x", jtablo->key + 100);
7882 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
7883 emitcode ("jmp", ",x");
7885 hc08_dirtyReg (hc08_reg_a, TRUE);
7886 hc08_dirtyReg (hc08_reg_hx, TRUE);
7891 pushReg(hc08_reg_hx, TRUE);
7893 /* get the condition into x */
7894 loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
7895 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7896 loadRegFromConst (hc08_reg_h, zero);
7898 emitcode ("lda", "%05d$,x", jtabhi->key + 100);
7899 emitcode ("sta", "3,s");
7900 emitcode ("lda", "%05d$,x", jtablo->key + 100);
7901 emitcode ("sta", "4,s");
7903 pullReg(hc08_reg_hx);
7904 emitcode ("rts", "");
7905 _G.stackPushes += 2;
7909 /* now generate the jump labels */
7911 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7912 jtab = setNextItem (IC_JTLABELS (ic)))
7913 emitcode (".db", "%05d$", jtab->key + 100);
7915 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7916 jtab = setNextItem (IC_JTLABELS (ic)))
7917 emitcode (".db", ">%05d$", jtab->key + 100);
7921 /*-----------------------------------------------------------------*/
7922 /* genCast - gen code for casting */
7923 /*-----------------------------------------------------------------*/
7925 genCast (iCode * ic)
7927 operand *result = IC_RESULT (ic);
7928 sym_link *ctype = operandType (IC_LEFT (ic));
7929 sym_link *rtype = operandType (IC_RIGHT (ic));
7930 operand *right = IC_RIGHT (ic);
7933 D(emitcode("; genCast",""));
7935 /* if they are equivalent then do nothing */
7936 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7939 aopOp (right, ic, FALSE);
7940 aopOp (result, ic, FALSE);
7943 /* if they are the same size : or less */
7944 if (AOP_SIZE (result) <= AOP_SIZE (right))
7947 /* if they are in the same place */
7949 if (sameRegs (AOP (right), AOP (result)))
7953 /* if they in different places then copy */
7954 size = AOP_SIZE (result);
7958 transferAopAop(AOP (right), offset, AOP (result), offset);
7965 /* if the result is of type pointer */
7970 sym_link *type = operandType (right);
7971 sym_link *etype = getSpec (type);
7973 /* pointer to generic pointer */
7974 if (IS_GENPTR (ctype))
7977 p_type = DCL_TYPE (type);
7980 if (SPEC_SCLS(etype)==S_REGISTER) {
7981 // let's assume it is a generic pointer
7984 /* we have to go by the storage class */
7985 p_type = PTR_TYPE (SPEC_OCLS (etype));
7989 /* the first two bytes are known */
7990 size = GPTRSIZE - 1;
7994 transferAopAop(AOP (right), offset, AOP (result), offset);
7997 /* the last byte depending on type */
8000 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
8005 // pointerTypeToGPByte will have bitched.
8009 sprintf(gpValStr, "#0x%x", gpVal);
8010 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
8016 /* just copy the pointers */
8017 size = AOP_SIZE (result);
8021 transferAopAop(AOP (right), offset, AOP (result), offset);
8027 /* so we now know that the size of destination is greater
8028 than the size of the source */
8029 /* we move to result for the size of source */
8030 size = AOP_SIZE (right);
8034 transferAopAop(AOP (right), offset, AOP (result), offset);
8038 /* now depending on the sign of the source && destination */
8039 size = AOP_SIZE (result) - AOP_SIZE (right);
8040 /* if unsigned or not an integral type */
8041 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
8044 storeConstToAop (zero, AOP (result), offset++);
8048 /* we need to extend the sign :{ */
8049 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
8050 accopWithMisc ("rola", "");
8051 accopWithMisc ("clra", "");
8052 accopWithMisc ("sbc", zero);
8054 storeRegToAop (hc08_reg_a, AOP (result), offset++);
8057 /* we are done hurray !!!! */
8060 freeAsmop (right, NULL, ic, TRUE);
8061 freeAsmop (result, NULL, ic, TRUE);
8065 /*-----------------------------------------------------------------*/
8066 /* genDjnz - generate decrement & jump if not zero instrucion */
8067 /*-----------------------------------------------------------------*/
8069 genDjnz (iCode * ic, iCode * ifx)
8075 D(emitcode ("; genDjnz",""));
8077 /* if the if condition has a false label
8078 then we cannot save */
8082 /* if the minus is not of the form
8084 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8085 !IS_OP_LITERAL (IC_RIGHT (ic)))
8088 if (operandLitValue (IC_RIGHT (ic)) != 1)
8091 /* dbnz doesn't support extended mode */
8092 if (isOperandInFarSpace (IC_RESULT (ic)))
8095 /* if the size of this greater than one then no
8097 // if (getSize (operandType (IC_RESULT (ic))) > 1)
8099 aopOp (IC_RESULT (ic), ic, FALSE);
8100 if (AOP_SIZE (IC_RESULT (ic))>1)
8102 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8106 /* otherwise we can save BIG */
8107 lbl = newiTempLabel (NULL);
8108 lbl1 = newiTempLabel (NULL);
8111 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
8114 emitBranch ("bra", lbl1);
8116 emitBranch ("jmp", IC_TRUE (ifx));
8119 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8124 /*-----------------------------------------------------------------*/
8125 /* genReceive - generate code for a receive iCode */
8126 /*-----------------------------------------------------------------*/
8128 genReceive (iCode * ic)
8132 D(emitcode ("; genReceive",""));
8134 aopOp (IC_RESULT (ic), ic, FALSE);
8135 size = AOP_SIZE (IC_RESULT (ic));
8140 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
8141 AOP (IC_RESULT (ic)), offset);
8142 if (hc08_aop_pass[offset]->type == AOP_REG)
8143 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
8148 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8151 /*-----------------------------------------------------------------*/
8152 /* genDummyRead - generate code for dummy read of volatiles */
8153 /*-----------------------------------------------------------------*/
8155 genDummyRead (iCode * ic)
8160 D(emitcode("; genDummyRead",""));
8163 if (op && IS_SYMOP (op))
8166 aopOp (op, ic, FALSE);
8168 size = AOP_SIZE (op);
8173 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8174 hc08_freeReg (hc08_reg_a);
8178 freeAsmop (op, NULL, ic, TRUE);
8181 if (op && IS_SYMOP (op))
8184 aopOp (op, ic, FALSE);
8186 size = AOP_SIZE (op);
8191 loadRegFromAop (hc08_reg_a, AOP (op), offset);
8192 hc08_freeReg (hc08_reg_a);
8196 freeAsmop (op, NULL, ic, TRUE);
8200 /*-----------------------------------------------------------------*/
8201 /* genCritical - generate code for start of a critical sequence */
8202 /*-----------------------------------------------------------------*/
8204 genCritical (iCode *ic)
8206 D(emitcode("; genCritical",""));
8209 aopOp (IC_RESULT (ic), ic, TRUE);
8211 emitcode ("tpa", "");
8212 hc08_dirtyReg (hc08_reg_a, FALSE);
8213 emitcode ("sei", "");
8216 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
8218 pushReg (hc08_reg_a, FALSE);
8220 hc08_freeReg (hc08_reg_a);
8222 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8225 /*-----------------------------------------------------------------*/
8226 /* genEndCritical - generate code for end of a critical sequence */
8227 /*-----------------------------------------------------------------*/
8229 genEndCritical (iCode *ic)
8231 D(emitcode("; genEndCritical",""));
8235 aopOp (IC_RIGHT (ic), ic, FALSE);
8236 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
8237 emitcode ("tap", "");
8238 hc08_freeReg (hc08_reg_a);
8239 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
8243 pullReg (hc08_reg_a);
8244 emitcode ("tap", "");
8250 /*-----------------------------------------------------------------*/
8251 /* genhc08Code - generate code for HC08 based controllers */
8252 /*-----------------------------------------------------------------*/
8254 genhc08Code (iCode * lic)
8261 lineHead = lineCurr = NULL;
8263 /* print the allocation information */
8264 if (allocInfo && currFunc)
8265 printAllocInfo (currFunc, codeOutFile);
8266 /* if debug information required */
8267 if (options.debug && currFunc)
8269 debugFile->writeFunction (currFunc, lic);
8272 if (IS_STATIC (currFunc->etype))
8273 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8275 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8279 /* stack pointer name */
8280 if (options.useXstack)
8285 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8287 hc08_aop_pass[0] = newAsmop (AOP_REG);
8288 hc08_aop_pass[0]->size=1;
8289 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
8290 hc08_aop_pass[1] = newAsmop (AOP_REG);
8291 hc08_aop_pass[1]->size=1;
8292 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
8293 hc08_aop_pass[2] = newAsmop (AOP_DIR);
8294 hc08_aop_pass[2]->size=1;
8295 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
8296 hc08_aop_pass[3] = newAsmop (AOP_DIR);
8297 hc08_aop_pass[3]->size=1;
8298 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
8300 for (ic = lic; ic; ic = ic->next)
8303 _G.current_iCode = ic;
8305 if (ic->level != clevel || ic->block != cblock)
8309 debugFile->writeScope(ic);
8315 if (ic->lineno && cln != ic->lineno)
8319 debugFile->writeCLine(ic);
8322 emitcode ("", "C$%s$%d$%d$%d ==.",
8323 FileBaseName (ic->filename), ic->lineno,
8324 ic->level, ic->block);
8328 if (!options.noCcodeInAsm) {
8329 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
8330 printCLine(ic->filename, ic->lineno));
8334 if (options.iCodeInAsm) {
8338 for (i=0; i<6; i++) {
8339 sprintf (®sInUse[i],
8340 "%c", ic->riu & (1<<i) ? i+'0' : '-');
8343 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
8345 /* if the result is marked as
8346 spilt and rematerializable or code for
8347 this has already been generated then
8349 if (resultRemat (ic) || ic->generated)
8357 for (i=A_IDX;i<=XA_IDX;i++)
8359 reg = hc08_regWithIdx(i);
8361 emitcode("","; %s = %s offset %d", reg->name,
8362 aopName(reg->aop), reg->aopofs);
8365 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
8367 sym = OP_SYMBOL (IC_LEFT (ic));
8368 if (sym->accuse == ACCUSE_HX)
8370 hc08_reg_h->isFree = FALSE;
8371 hc08_reg_x->isFree = FALSE;
8373 else if (sym->accuse == ACCUSE_XA)
8375 hc08_reg_a->isFree = FALSE;
8377 hc08_reg_x->isFree = FALSE;
8380 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
8382 sym = OP_SYMBOL (IC_RIGHT (ic));
8383 if (sym->accuse == ACCUSE_HX)
8385 hc08_reg_h->isFree = FALSE;
8386 hc08_reg_x->isFree = FALSE;
8388 else if (sym->accuse == ACCUSE_XA)
8390 hc08_reg_a->isFree = FALSE;
8392 hc08_reg_x->isFree = FALSE;
8397 /* depending on the operation */
8417 /* IPOP happens only when trying to restore a
8418 spilt live range, if there is an ifx statement
8419 following this pop then the if statement might
8420 be using some of the registers being popped which
8421 would destory the contents of the register so
8422 we need to check for this condition and handle it */
8424 ic->next->op == IFX &&
8425 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8426 genIfx (ic->next, ic);
8444 genEndFunction (ic);
8460 if (!genPointerGetSetOfs (ic))
8465 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8485 genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
8490 genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
8502 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8506 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8510 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8537 case GET_VALUE_AT_ADDRESS:
8539 hasInc (IC_LEFT (ic), ic,
8540 getSize (operandType (IC_RESULT (ic)))),
8541 ifxForOp (IC_RESULT (ic), ic) );
8545 if (POINTER_SET (ic))
8546 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
8572 addSet (&_G.sendSet, ic);
8575 case DUMMY_READ_VOLATILE:
8584 genEndCritical (ic);
8595 if (!hc08_reg_a->isFree)
8596 D(emitcode("","; forgot to free a"));
8597 if (!hc08_reg_x->isFree)
8598 D(emitcode("","; forgot to free x"));
8599 if (!hc08_reg_h->isFree)
8600 D(emitcode("","; forgot to free h"));
8601 if (!hc08_reg_hx->isFree)
8602 D(emitcode("","; forgot to free hx"));
8603 if (!hc08_reg_xa->isFree)
8604 D(emitcode("","; forgot to free xa"));
8607 debugFile->writeFrameAddress (NULL, NULL, 0); /* have no idea where frame is now */
8610 /* now we are ready to call the
8611 peep hole optimizer */
8612 if (!options.nopeep)
8613 peepHole (&lineHead);
8615 /* now do the actual printing */
8616 printLine (lineHead, codeOutFile);