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);
49 static char *zero = "#0x00";
50 static char *one = "#0x01";
54 {"a", "x", "_ret2", "_ret3"};
55 unsigned fReturnSizeHC08 = 4; /* shared with ralloc.c */
56 char **fReturn2 = fReturnhc08;
74 static asmop *hc08_aop_pass[4];
76 extern int hc08_ptrRegReq;
77 extern int hc08_nRegs;
78 extern FILE *codeOutFile;
79 //static void saveRBank (int, iCode *, bool);
80 static bool operandsEqu (operand * op1, operand * op2);
81 static void loadRegFromConst (regs *reg, char *c);
82 static char *aopName (asmop *aop);
83 static asmop * newAsmop (short type);
84 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
85 #define RESULTONSTACK(x) \
86 (IC_RESULT(x) && IC_RESULT(x)->aop && \
87 IC_RESULT(x)->aop->type == AOP_STK )
89 #define IS_AOP_HX(x) \
90 (((x)->type == AOP_REG) \
91 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
92 && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
94 #define IS_AOP_XA(x) \
95 (((x)->type == AOP_REG) \
96 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
97 && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
100 (((x)->type == AOP_REG) \
101 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
102 && ((x)->size == 1) )
104 #define IS_AOP_X(x) \
105 (((x)->type == AOP_REG) \
106 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
107 && ((x)->size == 1) )
109 #define IS_AOP_H(x) \
110 (((x)->type == AOP_REG) \
111 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
112 && ((x)->size == 1) )
114 #define CLRC emitcode("clc","")
116 static lineNode *lineHead = NULL;
117 static lineNode *lineCurr = NULL;
120 static unsigned char SLMask[] =
121 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
122 0xE0, 0xC0, 0x80, 0x00};
123 static unsigned char SRMask[] =
124 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
125 0x07, 0x03, 0x01, 0x00};
133 #define AOP(op) op->aop
134 #define AOP_TYPE(op) AOP(op)->type
135 #define AOP_SIZE(op) AOP(op)->size
136 #define AOP_OP(aop) aop->op
139 /*-----------------------------------------------------------------*/
140 /* emitcode - writes the code into a file : for now it is simple */
141 /*-----------------------------------------------------------------*/
143 emitcode (char *inst, char *fmt,...)
146 char lb[INITIAL_INLINEASM];
154 sprintf (lb, "%s\t", inst);
156 sprintf (lb, "%s", inst);
157 vsprintf (lb + (strlen (lb)), fmt, ap);
160 vsprintf (lb, fmt, ap);
162 while (isspace (*lbp))
166 lineCurr = (lineCurr ?
167 connectLine (lineCurr, newLineNode (lb)) :
168 (lineHead = newLineNode (lb)));
169 lineCurr->isInline = _G.inLine;
170 lineCurr->isDebug = _G.debugLine;
172 //printf("%s\n", lb);
177 emitBranch (char *branchop, symbol *tlbl)
179 emitcode (branchop, "%05d$", (tlbl->key + 100));
183 emitLabel (symbol *tlbl)
185 emitcode ("", "%05d$:", (tlbl->key +100));
190 /*--------------------------------------------------------------------------*/
191 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
192 /* freesrc is true, sreg is marked free and available for */
193 /* reuse. sreg and dreg must be of equal size */
194 /*--------------------------------------------------------------------------*/
196 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
202 /* Nothing to do if no destination. */
206 /* But it's definately an error if there's no source. */
209 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
210 "NULL sreg in transferRegReg");
214 emitcode ("", "; transferRegReg(%s,%s)",
215 sreg->name, dreg->name);
228 case H_IDX: /* H to A */
229 emitcode ("pshh", "");
230 emitcode ("pula", "");
232 case X_IDX: /* X to A */
233 emitcode ("txa", "");
242 case A_IDX: /* A to H */
243 emitcode ("psha", "");
244 emitcode ("pulh", "");
246 case X_IDX: /* X to H */
247 emitcode ("pshx", "");
248 emitcode ("pulh", "");
257 case A_IDX: /* A to X */
258 emitcode ("tax", "");
260 case H_IDX: /* H to X */
261 emitcode ("pshh", "");
262 emitcode ("pulx", "");
271 case XA_IDX: /* XA to HX */
272 emitcode ("pshx", "");
273 emitcode ("pulh", "");
274 emitcode ("tax", "");
283 case HX_IDX: /* HX to XA */
284 emitcode ("txa", "");
285 emitcode ("pshh", "");
286 emitcode ("pulx", "");
296 wassertl (!error, "bad combo in transferRegReg");
301 dreg->aop = sreg->aop;
302 dreg->aopofs = sreg->aopofs;
303 dreg->isFree = FALSE;
307 /*--------------------------------------------------------------------------*/
308 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
309 /* marked free and available for reuse. */
310 /*--------------------------------------------------------------------------*/
312 pushReg (regs *reg, bool freereg)
314 int regidx = reg->rIdx;
319 emitcode ("psha", "");
323 emitcode ("pshx", "");
327 emitcode ("pshh", "");
331 emitcode ("pshx", "");
332 emitcode ("pshh", "");
336 emitcode ("psha", "");
337 emitcode ("pshx", "");
345 return -_G.stackOfs-_G.stackPushes;
348 /*--------------------------------------------------------------------------*/
349 /* pullReg - Pull register reg off the stack. */
350 /*--------------------------------------------------------------------------*/
354 int regidx = reg->rIdx;
359 emitcode ("pula", "");
363 emitcode ("pulx", "");
367 emitcode ("pulh", "");
371 emitcode ("pulx", "");
372 emitcode ("pulh", "");
376 emitcode ("pula", "");
377 emitcode ("pulx", "");
384 hc08_dirtyReg(reg, FALSE);
387 /*--------------------------------------------------------------------------*/
388 /* pullNull - Discard n bytes off the top of the stack */
389 /*--------------------------------------------------------------------------*/
395 emitcode("ais","#%d",n);
400 /*--------------------------------------------------------------------------*/
401 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
402 /* push was performed, false otherwise. */
403 /*--------------------------------------------------------------------------*/
405 pushRegIfUsed (regs *reg)
416 /*--------------------------------------------------------------------------*/
417 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
418 /* stack. Otherwise register reg is marked as free. */
419 /*--------------------------------------------------------------------------*/
421 pullOrFreeReg (regs *reg, bool needpull)
429 /*--------------------------------------------------------------------------*/
430 /* adjustStack - Adjust the stack pointer by n bytes. */
431 /*--------------------------------------------------------------------------*/
440 emitcode ("ais","#127");
445 emitcode ("ais","#-128");
450 emitcode ("ais", "#%d", n);
457 /*--------------------------------------------------------------------------*/
458 /* aopName - Return a string with debugging information about an asmop. */
459 /*--------------------------------------------------------------------------*/
463 static char buffer[256];
467 return "(asmop*)NULL";
472 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
475 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
478 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
481 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
484 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
487 sprintf (buf, "REG(%s,%s,%s,%s)",
488 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
489 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
490 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
491 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
498 sprintf (buf,"?%d", aop->type);
506 /*--------------------------------------------------------------------------*/
507 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
508 /*--------------------------------------------------------------------------*/
510 loadRegFromAop (regs *reg, asmop *aop, int loffset)
512 int regidx = reg->rIdx;
514 if (aop->stacked && aop->stk_aop[loffset])
516 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
521 printf("loadRegFromAop called\n");
524 printf(" reg = NULL\n");
527 printf(" reg = %s\n", reg->name);
530 printf(" aop = NULL\n");
533 printf(" aop->type = %d\n", aop->type);
534 printf(" loffset = %d\n", loffset);
537 printf(" aop has operand link\n");
539 printf(" aop missing operand link\n");
541 printf(" reg has operand link\n");
543 printf(" reg missing operand link\n");
546 emitcode ("", "; loadRegFromAop (%s, %s, %d)",
547 reg->name, aopName (aop), loffset);
549 /* If operand is volatile, we cannot optimize. */
550 if (!aop->op || isOperandVolatile (aop->op, FALSE))
554 /* If this register already has this offset of the operand
555 then we need only mark it as in use. */
556 if (reg->aop && reg->aop->op && aop->op
557 && operandsEqu(reg->aop->op,aop->op)
558 && (reg->aopofs == loffset))
561 emitcode ("","; already had correct value for %s", reg->name);
565 /* TODO: check to see if we can transfer from another register */
567 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
568 && operandsEqu(hc08_reg_h->aop->op,aop->op)
569 && (hc08_reg_h->aopofs == loffset))
571 emitcode ("","; found correct value for %s in h", reg->name);
572 transferRegReg (hc08_reg_h, reg, FALSE);
578 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
579 && operandsEqu(hc08_reg_x->aop->op,aop->op)
580 && (hc08_reg_x->aopofs == loffset))
582 emitcode ("","; found correct value for %s in x", reg->name);
583 transferRegReg (hc08_reg_x, reg, FALSE);
588 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
589 && operandsEqu(hc08_reg_a->aop->op,aop->op)
590 && (hc08_reg_a->aopofs == loffset))
592 emitcode ("","; found correct value for %s in a", reg->name);
593 transferRegReg (hc08_reg_a, reg, FALSE);
603 if (aop->type == AOP_REG)
605 if (loffset < aop->size)
606 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
608 emitcode ("clra", ""); /* TODO: handle sign extension */
611 emitcode ("lda","%s", aopAdrStr (aop, loffset, FALSE));
614 if (aop->type == AOP_REG)
616 if (loffset < aop->size)
617 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
619 emitcode ("clrx", ""); /* TODO: handle sign extension */
622 emitcode ("ldx","%s", aopAdrStr (aop, loffset, FALSE));
625 if (hc08_reg_a->isFree)
627 loadRegFromAop (hc08_reg_a, aop, loffset);
628 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
630 else if (hc08_reg_x->isFree)
632 loadRegFromAop (hc08_reg_x, aop, loffset);
633 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
637 pushReg (hc08_reg_a, TRUE);
638 loadRegFromAop (hc08_reg_a, aop, loffset);
639 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
640 pullReg (hc08_reg_a);
646 else if (IS_AOP_XA(aop))
647 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
648 else if ((aop->type == AOP_DIR))
650 if (aop->size>(loffset+1))
651 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
654 loadRegFromAop (hc08_reg_x, aop, loffset);
655 loadRegFromConst (hc08_reg_h, zero);
658 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
660 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
665 needpula = pushRegIfUsed (hc08_reg_a);
666 loadRegFromAop (hc08_reg_a, aop, loffset+1);
667 loadRegFromAop (hc08_reg_x, aop, loffset);
668 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
669 pullOrFreeReg (hc08_reg_a, needpula);
675 else if (IS_AOP_HX(aop))
676 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
679 loadRegFromAop (hc08_reg_a, aop, loffset);
680 loadRegFromAop (hc08_reg_x, aop, loffset+1);
685 // ignore caching for now
688 reg->aopofs = loffset;
693 /*--------------------------------------------------------------------------*/
694 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
695 /* freeAsmop is called with aop, the stacked data will */
696 /* be copied to the original aop location and */
697 /*--------------------------------------------------------------------------*/
699 forceStackedAop (asmop *aop)
702 asmop *newaop = newAsmop (aop->type);
703 memcpy (newaop, aop, sizeof(*newaop));
705 emitcode("", "; forcedStackAop %s", aopName(aop));
706 for (loffset=0; loffset < newaop->size; loffset++)
708 asmop *aopsof = newAsmop (AOP_SOF);
710 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
711 aopsof->op = aop->op;
712 newaop->stk_aop[loffset] = aopsof;
719 /*--------------------------------------------------------------------------*/
720 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
721 /*--------------------------------------------------------------------------*/
723 storeRegToAop (regs *reg, asmop *aop, int loffset)
725 int regidx = reg->rIdx;
731 emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
732 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr);
734 if ((reg->rIdx == HX_IDX) && aop->stacked
735 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
737 storeRegToAop (hc08_reg_h, aop, loffset+1);
738 storeRegToAop (hc08_reg_x, aop, loffset);
742 if ((reg->rIdx == XA_IDX) && aop->stacked
743 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
745 storeRegToAop (hc08_reg_x, aop, loffset+1);
746 storeRegToAop (hc08_reg_a, aop, loffset);
750 if (aop->stacked && aop->stk_aop[loffset])
752 storeRegToAop (reg, aop->stk_aop[loffset], 0);
756 if (aop->type == AOP_STR)
759 transferRegReg (reg, hc08_reg_x, FALSE);
761 transferRegReg (reg, hc08_reg_h, FALSE);
768 if ((aop->type == AOP_REG) && (loffset < aop->size))
769 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
771 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
774 if ((aop->type == AOP_REG) && (loffset < aop->size))
775 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
777 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
780 if (hc08_reg_a->isFree)
782 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
783 storeRegToAop (hc08_reg_a, aop, loffset);
784 hc08_freeReg (hc08_reg_a);
786 else if (hc08_reg_x->isFree)
788 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
789 storeRegToAop (hc08_reg_x, aop, loffset);
790 hc08_freeReg (hc08_reg_x);
794 pushReg (hc08_reg_a, TRUE);
795 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
796 storeRegToAop (hc08_reg_a, aop, loffset);
797 pullReg (hc08_reg_a);
801 if ((aop->type == AOP_DIR) )
803 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
805 else if (IS_AOP_XA(aop))
806 transferRegReg(reg, hc08_reg_xa, FALSE);
807 else if (IS_AOP_HX(aop))
812 needpula = pushRegIfUsed (hc08_reg_a);
813 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
814 storeRegToAop (hc08_reg_a, aop, loffset+1);
815 storeRegToAop (hc08_reg_x, aop, loffset);
816 pullOrFreeReg (hc08_reg_a, needpula);
821 transferRegReg(reg, hc08_reg_hx, FALSE);
822 else if (IS_AOP_XA(aop))
826 storeRegToAop (hc08_reg_a, aop, loffset);
827 storeRegToAop (hc08_reg_x, aop, loffset+1);
832 /* Disable the register tracking for now */
834 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
837 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
839 otherreg=hc08_regWithIdx(otheridx);
840 if (otherreg && otherreg->aop
841 && otherreg->aop->op && aop->op
842 && operandsEqu(otherreg->aop->op,aop->op)
843 && (otherreg->aopofs == loffset))
845 emitcode("","; marking %s stale", otherreg->name);
849 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
851 hc08_reg_hx->aop = NULL;
852 emitcode("","; marking hx stale");
854 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
856 hc08_reg_xa->aop = NULL;
857 emitcode("","; marking xa stale");
861 reg->aopofs = loffset;
866 /*--------------------------------------------------------------------------*/
867 /* loadRegFromConst - Load register reg from constant c. */
868 /*--------------------------------------------------------------------------*/
870 loadRegFromConst (regs *reg, char *c)
876 emitcode ("clra", "");
878 emitcode ("lda", "%s", c);
882 emitcode ("clrx", "");
884 emitcode ("ldx", "%s", c);
888 emitcode ("clrh", "");
889 else if (hc08_reg_a->isFree)
891 loadRegFromConst (hc08_reg_a, c);
892 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
894 else if (hc08_reg_x->isFree)
896 loadRegFromConst (hc08_reg_x, c);
897 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
901 pushReg (hc08_reg_a, TRUE);
902 loadRegFromConst (hc08_reg_a, c);
903 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
904 pullReg (hc08_reg_a);
908 emitcode ("ldhx", "%s", c);
911 emitcode ("lda", "%s", c);
912 emitcode ("ldx", "%s >> 8", c);
915 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
916 "Bad rIdx in loadRegFromConst");
923 /*--------------------------------------------------------------------------*/
924 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
925 /*--------------------------------------------------------------------------*/
927 storeConstToAop (char *c, asmop *aop, int loffset)
929 if (aop->stacked && aop->stk_aop[loffset])
931 storeConstToAop (c, aop->stk_aop[loffset], 0);
939 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
941 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
944 if (loffset>(aop->size-1))
946 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
949 if (hc08_reg_a->isFree)
951 loadRegFromConst (hc08_reg_a, c);
952 storeRegToAop( hc08_reg_a, aop, loffset);
953 hc08_freeReg (hc08_reg_a);
955 else if (hc08_reg_x->isFree)
957 loadRegFromConst (hc08_reg_x, c);
958 storeRegToAop( hc08_reg_x, aop, loffset);
959 hc08_freeReg (hc08_reg_x);
963 pushReg (hc08_reg_a, TRUE);
964 loadRegFromConst (hc08_reg_a, c);
965 storeRegToAop( hc08_reg_a, aop, loffset);
966 pullReg (hc08_reg_a);
972 /*--------------------------------------------------------------------------*/
973 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
974 /* reg is extended to fill logical offsets loffset */
975 /* and above of asmop aop. Otherwise, logical */
976 /* offsets loffset and above of asmop aop are */
977 /* zeroed. reg must be an 8-bit register. */
978 /*--------------------------------------------------------------------------*/
980 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
982 // int regidx = reg->rIdx;
983 int size = aop->size;
992 storeConstToAop(zero, aop, loffset++);
997 transferRegReg (reg, hc08_reg_a, FALSE);
998 emitcode ("rola","");
999 emitcode ("clra","");
1000 emitcode ("sbc", "#0");
1001 hc08_useReg (hc08_reg_a);
1002 while (loffset<size)
1003 storeRegToAop (hc08_reg_a, aop, loffset++);
1004 hc08_freeReg (hc08_reg_a);
1008 /*--------------------------------------------------------------------------*/
1009 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1010 /* padding and/or truncation as needed. If isSigned is */
1011 /* true, sign extension will take place in the padding. */
1012 /*--------------------------------------------------------------------------*/
1014 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1016 int regidx = reg->rIdx;
1017 int size = aop->size;
1024 storeRegToAop (reg, aop, 0);
1025 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1030 storeRegToAop (hc08_reg_x, aop, 0);
1034 storeRegToAop (reg, aop, 0);
1035 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1041 storeRegToAop (hc08_reg_a, aop, 0);
1045 storeRegToAop (reg, aop, 0);
1046 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1052 /*--------------------------------------------------------------------------*/
1053 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1054 /* srcaop to logical offset dstofs of asmop dstofs. */
1055 /*--------------------------------------------------------------------------*/
1057 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1059 bool needpula = FALSE;
1062 bool keepreg = FALSE;
1064 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1066 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1070 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1072 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1076 // emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1077 // aopName (srcaop), srcofs, aopName (dstaop), dstofs);
1078 // emitcode ("", "; srcaop->type = %d", srcaop->type);
1079 // emitcode ("", "; dstaop->type = %d", dstaop->type);
1081 if (dstofs >= dstaop->size)
1084 if ((dstaop->type == AOP_DIR)
1085 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1087 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1088 aopAdrStr(dstaop, dstofs, FALSE));
1092 if (dstaop->type == AOP_REG)
1094 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1095 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1097 reg = dstaop->aopu.aop_reg[dstofs];
1102 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1104 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1105 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1107 reg = srcaop->aopu.aop_reg[srcofs];
1114 if (hc08_reg_a->isFree)
1116 else if (hc08_reg_x->isFree)
1120 pushReg (hc08_reg_a, TRUE);
1126 loadRegFromAop (reg, srcaop, srcofs);
1127 storeRegToAop (reg, dstaop, dstofs);
1130 pullOrFreeReg (hc08_reg_a, needpula);
1134 /*--------------------------------------------------------------------------*/
1135 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1136 /* parameter param. */
1137 /*--------------------------------------------------------------------------*/
1139 accopWithMisc (char *accop, char *param)
1141 emitcode (accop, "%s", param);
1142 hc08_dirtyReg (hc08_reg_a, FALSE);
1145 /*--------------------------------------------------------------------------*/
1146 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1147 /* byte at logical offset loffset of asmop aop. */
1148 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1149 /*--------------------------------------------------------------------------*/
1151 accopWithAop (char *accop, asmop *aop, int loffset)
1153 if (aop->stacked && aop->stk_aop[loffset])
1155 accopWithAop (accop, aop->stk_aop[loffset], 0);
1159 if (aop->type == AOP_REG)
1161 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1162 emitcode (accop, "1,s");
1166 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1168 hc08_dirtyReg (hc08_reg_a, FALSE);
1172 /*--------------------------------------------------------------------------*/
1173 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1174 /* byte at logical offset loffset of asmop aop. Register reg */
1175 /* must be 8-bit. */
1176 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1177 /*--------------------------------------------------------------------------*/
1179 rmwWithReg (char *rmwop, regs *reg)
1182 char *rmwaop = rmwbuf;
1184 if (reg->rIdx == A_IDX)
1186 sprintf(rmwaop,"%sa", rmwop);
1187 emitcode (rmwaop, "");
1188 hc08_dirtyReg (hc08_reg_a, FALSE);
1190 else if (reg->rIdx == X_IDX)
1192 sprintf(rmwaop,"%sx", rmwop);
1193 emitcode (rmwaop, "");
1194 hc08_dirtyReg (hc08_reg_a, FALSE);
1196 else if (hc08_reg_a->isFree)
1198 transferRegReg(reg, hc08_reg_a, FALSE);
1199 sprintf(rmwaop,"%sa", rmwop);
1200 emitcode (rmwaop, "");
1201 hc08_dirtyReg (hc08_reg_a, FALSE);
1202 transferRegReg(hc08_reg_a, reg, TRUE);
1206 pushReg (reg, FALSE);
1207 emitcode (rmwop, "1,s");
1209 hc08_dirtyReg (reg, FALSE);
1213 /*--------------------------------------------------------------------------*/
1214 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1215 /* logical offset loffset of asmop aop. */
1216 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1217 /*--------------------------------------------------------------------------*/
1219 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1221 bool needpula = FALSE;
1223 if (aop->stacked && aop->stk_aop[loffset])
1225 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1232 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1235 needpula = pushRegIfUsed (hc08_reg_a);
1236 loadRegFromAop (hc08_reg_a, aop, loffset);
1237 rmwWithReg (rmwop, hc08_reg_a);
1238 storeRegToAop (hc08_reg_a, aop, loffset);
1239 pullOrFreeReg (hc08_reg_a, needpula);
1242 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1248 /*-----------------------------------------------------------------*/
1249 /* newAsmop - creates a new asmOp */
1250 /*-----------------------------------------------------------------*/
1252 newAsmop (short type)
1256 aop = Safe_calloc (1, sizeof (asmop));
1263 /*-----------------------------------------------------------------*/
1264 /* pointerCode - returns the code for a pointer type */
1265 /*-----------------------------------------------------------------*/
1267 pointerCode (sym_link * etype)
1270 return PTR_TYPE (SPEC_OCLS (etype));
1275 /*-----------------------------------------------------------------*/
1276 /* aopForSym - for a true symbol */
1277 /*-----------------------------------------------------------------*/
1279 aopForSym (iCode * ic, symbol * sym, bool result)
1284 wassertl (ic != NULL, "Got a null iCode");
1285 wassertl (sym != NULL, "Got a null symbol");
1287 // printf("in aopForSym for symbol %s\n", sym->name);
1289 space = SPEC_OCLS (sym->etype);
1291 /* if already has one */
1297 /* special case for a function */
1298 if (IS_FUNC (sym->type))
1300 sym->aop = aop = newAsmop (AOP_IMMD);
1301 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1302 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1303 aop->size = FPTRSIZE;
1307 /* if it is in direct space */
1308 if (IN_DIRSPACE (space))
1310 sym->aop = aop = newAsmop (AOP_DIR);
1311 aop->aopu.aop_dir = sym->rname;
1312 aop->size = getSize (sym->type);
1316 /* if it is in far space */
1317 if (IN_FARSPACE (space))
1319 sym->aop = aop = newAsmop (AOP_EXT);
1320 aop->aopu.aop_dir = sym->rname;
1321 aop->size = getSize (sym->type);
1325 if (IN_STACK (sym->etype))
1327 sym->aop = aop = newAsmop (AOP_SOF);
1328 aop->aopu.aop_dir = sym->rname;
1329 aop->size = getSize (sym->type);
1330 aop->aopu.aop_stk = sym->stack;
1336 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1337 "aopForSym should never reach here");
1341 /* if it is in code space */
1342 if (IN_CODESPACE (space))
1348 /*-----------------------------------------------------------------*/
1349 /* aopForRemat - rematerialzes an object */
1350 /*-----------------------------------------------------------------*/
1352 aopForRemat (symbol * sym)
1354 iCode *ic = sym->rematiCode;
1355 asmop *aop = newAsmop (AOP_IMMD);
1362 val += (int) operandLitValue (IC_RIGHT (ic));
1363 else if (ic->op == '-')
1364 val -= (int) operandLitValue (IC_RIGHT (ic));
1365 else if (IS_CAST_ICODE(ic)) {
1366 sym_link *from_type = operandType(IC_RIGHT(ic));
1367 aop->aopu.aop_immd.from_cast_remat = 1;
1368 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1369 ptr_type = DCL_TYPE(from_type);
1370 if (ptr_type == IPOINTER) {
1377 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1381 sprintf (buffer, "(%s %c 0x%04x)",
1382 OP_SYMBOL (IC_LEFT (ic))->rname,
1383 val >= 0 ? '+' : '-',
1384 abs (val) & 0xffff);
1386 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1388 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1389 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1390 /* set immd2 field if required */
1391 if (aop->aopu.aop_immd.from_cast_remat) {
1392 sprintf(buffer,"#0x%02x",ptr_type);
1393 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1394 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1400 /*-----------------------------------------------------------------*/
1401 /* regsInCommon - two operands have some registers in common */
1402 /*-----------------------------------------------------------------*/
1404 regsInCommon (operand * op1, operand * op2)
1406 symbol *sym1, *sym2;
1409 /* if they have registers in common */
1410 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1413 sym1 = OP_SYMBOL (op1);
1414 sym2 = OP_SYMBOL (op2);
1416 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1419 for (i = 0; i < sym1->nRegs; i++)
1425 for (j = 0; j < sym2->nRegs; j++)
1430 if (sym2->regs[j] == sym1->regs[i])
1438 /*-----------------------------------------------------------------*/
1439 /* operandsEqu - equivalent */
1440 /*-----------------------------------------------------------------*/
1442 operandsEqu (operand * op1, operand * op2)
1444 symbol *sym1, *sym2;
1446 /* if they not symbols */
1447 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1450 sym1 = OP_SYMBOL (op1);
1451 sym2 = OP_SYMBOL (op2);
1453 /* if both are itemps & one is spilt
1454 and the other is not then false */
1455 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1456 sym1->isspilt != sym2->isspilt)
1459 /* if they are the same */
1463 if (strcmp (sym1->rname, sym2->rname) == 0)
1467 /* if left is a tmp & right is not */
1468 if (IS_ITEMP (op1) &&
1471 (sym1->usl.spillLoc == sym2))
1474 if (IS_ITEMP (op2) &&
1478 (sym2->usl.spillLoc == sym1))
1484 /*-----------------------------------------------------------------*/
1485 /* sameRegs - two asmops have the same registers */
1486 /*-----------------------------------------------------------------*/
1488 sameRegs (asmop * aop1, asmop * aop2)
1495 // if (aop1->size != aop2->size)
1498 if (aop1->type == aop2->type)
1503 for (i = 0; i < aop1->size; i++)
1504 if (aop1->aopu.aop_reg[i] !=
1505 aop2->aopu.aop_reg[i])
1509 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1512 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1519 /*-----------------------------------------------------------------*/
1520 /* aopOp - allocates an asmop for an operand : */
1521 /*-----------------------------------------------------------------*/
1523 aopOp (operand * op, iCode * ic, bool result)
1532 // Is this a pointer set result?
1534 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1538 // printf("checking literal\n");
1539 /* if this a literal */
1540 if (IS_OP_LITERAL (op))
1542 op->aop = aop = newAsmop (AOP_LIT);
1543 aop->aopu.aop_lit = op->operand.valOperand;
1544 aop->size = getSize (operandType (op));
1546 aop->isaddr = op->isaddr;
1550 // printf("checking pre-existing\n");
1551 /* if already has a asmop then continue */
1555 op->aop->isaddr = op->isaddr;
1559 // printf("checking underlying sym\n");
1560 /* if the underlying symbol has a aop */
1561 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1563 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1564 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1565 //op->aop = aop = OP_SYMBOL (op)->aop;
1566 aop->size = getSize( operandType (op));
1567 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1568 //printf (" with size = %d\n", aop->size);
1571 aop->isaddr = op->isaddr;
1572 /* if (aop->isaddr & IS_ITEMP (op))
1574 aop->psize=aop->size;
1575 aop->size = getSize( operandType (op)->next);
1580 // printf("checking true sym\n");
1581 /* if this is a true symbol */
1582 if (IS_TRUE_SYMOP (op))
1584 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1586 aop->isaddr = op->isaddr;
1587 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1588 //printf (" with size = %d\n", aop->size);
1592 /* this is a temporary : this has
1598 e) can be a return use only */
1600 sym = OP_SYMBOL (op);
1602 // printf("checking conditional\n");
1603 /* if the type is a conditional */
1604 if (sym->regType == REG_CND)
1606 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1609 aop->isaddr = op->isaddr;
1613 // printf("checking spilt\n");
1614 /* if it is spilt then two situations
1616 b) has a spill location */
1617 if (sym->isspilt || sym->nRegs == 0)
1620 // printf("checking remat\n");
1621 /* rematerialize it NOW */
1624 sym->aop = op->aop = aop =
1626 aop->size = getSize (sym->type);
1628 aop->isaddr = op->isaddr;
1629 /* if (aop->isaddr & IS_ITEMP (op))
1631 aop->psize=aop->size;
1632 aop->size = getSize( operandType (op)->next);
1637 // printf("checking accuse\n");
1640 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1641 aop->size = getSize (sym->type);
1642 switch (sym->accuse)
1645 aop->aopu.aop_reg[0] = hc08_reg_a;
1646 aop->aopu.aop_reg[1] = hc08_reg_x;
1649 aop->aopu.aop_reg[0] = hc08_reg_x;
1650 aop->aopu.aop_reg[1] = hc08_reg_h;
1654 aop->isaddr = op->isaddr;
1658 // printf("checking ruonly\n");
1664 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1665 aop->size = getSize (sym->type);
1666 for (i = 0; i < fReturnSizeHC08; i++)
1667 aop->aopu.aop_str[i] = fReturn2[i];
1669 aop->isaddr = op->isaddr;
1673 /* else spill location */
1674 // printf("checking spill loc\n");
1675 // if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1676 if (sym->usl.spillLoc && sym->usl.spillLoc->aop
1677 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1679 /* force a new aop if sizes differ */
1680 sym->usl.spillLoc->aop = NULL;
1681 //printf ("forcing new aop\n");
1683 sym->aop = op->aop = aop =
1684 aopForSym (ic, sym->usl.spillLoc, result);
1685 aop->size = getSize (sym->type);
1687 aop->isaddr = op->isaddr;
1688 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1689 //printf (" with size = %d\n", aop->size);
1690 /* if (aop->isaddr & IS_ITEMP (op))
1692 aop->psize=aop->size;
1693 aop->size = getSize( operandType (op)->next);
1698 // printf("assuming register\n");
1699 /* must be in a register */
1700 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1701 aop->size = sym->nRegs;
1702 for (i = 0; i < sym->nRegs; i++)
1703 aop->aopu.aop_reg[i] = sym->regs[i];
1705 aop->isaddr = op->isaddr;
1709 /*-----------------------------------------------------------------*/
1710 /* freeAsmop - free up the asmop given to an operand */
1711 /*----------------------------------------------------------------*/
1713 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1735 emitcode ("","; freeAsmop restoring stacked %s", aopName(aop));
1738 for (loffset=0; loffset<aop->size; loffset++)
1739 if (aop->stk_aop[loffset])
1741 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1744 pullNull (stackAdjust);
1748 /* all other cases just dealloc */
1754 OP_SYMBOL (op)->aop = NULL;
1755 /* if the symbol has a spill */
1757 SPIL_LOC (op)->aop = NULL;
1763 /*-----------------------------------------------------------------*/
1764 /* aopDerefAop - treating the aop parameter as a pointer, return */
1765 /* an asmop for the object it references */
1766 /*-----------------------------------------------------------------*/
1768 aopDerefAop (asmop *aop)
1773 asmop *newaop = NULL;
1774 sym_link *type, *etype;
1777 emitcode ("", "; aopDerefAop(%s)", aopName(aop));
1781 type = operandType (aop->op);
1782 etype = getSpec (type);
1783 /* if op is of type of pointer then it is simple */
1784 if (IS_PTR (type) && !IS_FUNC (type->next))
1785 p_type = DCL_TYPE (type);
1788 /* we have to go by the storage class */
1789 p_type = PTR_TYPE (SPEC_OCLS (etype));
1798 if (p_type == POINTER)
1799 newaop = newAsmop (AOP_DIR);
1801 newaop = newAsmop (AOP_EXT);
1802 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1805 adr = (int) floatFromVal (aop->aopu.aop_lit);
1806 if (p_type == POINTER)
1811 newaop = newAsmop (AOP_DIR);
1812 sprintf (s, "0x%02x",adr);
1816 newaop = newAsmop (AOP_EXT);
1817 sprintf (s, "0x%04x",adr);
1819 rs = Safe_calloc (1, strlen (s) + 1);
1821 newaop->aopu.aop_dir = rs;
1824 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1825 "unsupported asmop");
1835 /*-----------------------------------------------------------------*/
1836 /* aopAdrStr - for referencing the address of the aop */
1837 /*-----------------------------------------------------------------*/
1839 aopAdrStr (asmop * aop, int loffset, bool bit16)
1843 int offset = aop->size - 1 - loffset;
1846 /* offset is greater than
1848 if (loffset > (aop->size - 1) &&
1849 aop->type != AOP_LIT)
1852 /* depending on type */
1857 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1858 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1860 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1864 sprintf (s, "#(%s >> %d)",
1865 aop->aopu.aop_immd.aop_immd1,
1869 aop->aopu.aop_immd.aop_immd1);
1873 aop->aopu.aop_immd.aop_immd1);
1874 rs = Safe_calloc (1, strlen (s) + 1);
1880 sprintf (s, "*(%s + %d)",
1884 sprintf (s, "*%s", aop->aopu.aop_dir);
1885 rs = Safe_calloc (1, strlen (s) + 1);
1891 sprintf (s, "(%s + %d)",
1895 sprintf (s, "%s", aop->aopu.aop_dir);
1896 rs = Safe_calloc (1, strlen (s) + 1);
1901 return aop->aopu.aop_reg[loffset]->name;
1905 return aopLiteralLong (aop->aopu.aop_lit, loffset, 2);
1907 return aopLiteral (aop->aopu.aop_lit, loffset);
1911 return aop->aopu.aop_str[loffset];
1914 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
1916 rs = Safe_calloc (1, strlen (s) + 1);
1922 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1923 "aopAdrStr got unsupported aop->type");
1932 /*-----------------------------------------------------------------*/
1933 /* opIsGptr: returns non-zero if the passed operand is */
1934 /* a generic pointer type. */
1935 /*-----------------------------------------------------------------*/
1937 opIsGptr (operand * op)
1939 sym_link *type = operandType (op);
1941 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1949 /*-----------------------------------------------------------------*/
1950 /* getDataSize - get the operand data size */
1951 /*-----------------------------------------------------------------*/
1953 getDataSize (operand * op)
1956 size = AOP_SIZE (op);
1960 /*-----------------------------------------------------------------*/
1961 /* outAcc - output Acc */
1962 /*-----------------------------------------------------------------*/
1964 outAcc (operand * result)
1967 size = getDataSize (result);
1970 storeRegToAop (hc08_reg_a, AOP (result), 0);
1973 /* unsigned or positive */
1976 storeConstToAop (zero, AOP (result), offset++);
1981 /*-----------------------------------------------------------------*/
1982 /* outBitC - output a bit C */
1983 /*-----------------------------------------------------------------*/
1985 outBitC (operand * result)
1989 /* if the result is bit */
1990 if (AOP_TYPE (result) == AOP_CRY)
1991 aopPut (AOP (result), "c", 0);
1995 emitcode ("clra", "");
1996 emitcode ("rola", "");
2001 /*-----------------------------------------------------------------*/
2002 /* outBitNV - output a bit N^V */
2003 /*-----------------------------------------------------------------*/
2005 outBitNV (operand * result)
2007 symbol *tlbl, *tlbl1;
2009 tlbl = newiTempLabel (NULL);
2010 tlbl1 = newiTempLabel (NULL);
2012 emitBranch ("blt", tlbl);
2013 loadRegFromConst (hc08_reg_a, zero);
2014 emitBranch ("bra", tlbl1);
2016 loadRegFromConst (hc08_reg_a, one);
2022 /*-----------------------------------------------------------------*/
2023 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2024 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2025 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2026 /*-----------------------------------------------------------------*/
2028 asmopToBool (asmop *aop, bool resultInA)
2030 symbol *tlbl, *tlbl1;
2031 int size = aop->size;
2032 bool needpula = FALSE;
2033 bool flagsonly = TRUE;
2038 hc08_freeReg(hc08_reg_a);
2045 emitcode ("tsta", "");
2048 else if (IS_AOP_X(aop))
2049 emitcode ("tstx", "");
2050 else if (IS_AOP_H(aop))
2052 if (hc08_reg_a->isFree)
2054 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2055 emitcode ("tsta", "");
2057 hc08_freeReg(hc08_reg_a);
2059 else if (hc08_reg_x->isFree)
2061 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2062 emitcode ("tstx", "");
2063 hc08_freeReg(hc08_reg_x);
2067 emitcode ("pshh", "");
2068 emitcode ("tst", "1,s");
2069 emitcode ("ais", "#1");
2072 else if (IS_AOP_HX(aop))
2073 emitcode ("cphx", zero);
2074 else if (IS_AOP_XA(aop))
2076 symbol *tlbl = newiTempLabel (NULL);
2077 emitcode ("tsta", "");
2078 emitcode ("bne", "%05d$", (tlbl->key + 100));
2079 emitcode ("tstx", "");
2080 emitcode ("", "%05d$:", (tlbl->key + 100));
2083 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2084 "Bad rIdx in asmToBool");
2090 needpula = pushRegIfUsed (hc08_reg_a);
2091 loadRegFromAop (hc08_reg_a, aop, 0);
2092 for (offset=1; offset<size; offset++)
2093 accopWithAop ("ora", aop, offset);
2095 pullReg (hc08_reg_a);
2098 hc08_freeReg (hc08_reg_a);
2107 loadRegFromAop (hc08_reg_a, aop, 0);
2108 hc08_freeReg (hc08_reg_a);
2112 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2117 if (hc08_reg_a->isFree)
2119 loadRegFromAop (hc08_reg_a, aop, 0);
2120 accopWithAop ("ora", aop, 1);
2121 hc08_freeReg (hc08_reg_a);
2126 tlbl = newiTempLabel (NULL);
2127 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2128 emitcode ("bne", "%05d$", (tlbl->key + 100));
2129 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2130 emitcode ("", "%05d$:", (tlbl->key + 100));
2136 needpula = pushRegIfUsed (hc08_reg_a);
2137 loadRegFromAop (hc08_reg_a, aop, 0);
2138 for (offset=1; offset<size; offset++)
2139 accopWithAop ("ora", aop, offset);
2141 pullReg (hc08_reg_a);
2144 hc08_freeReg (hc08_reg_a);
2152 tlbl = newiTempLabel (NULL);
2156 tlbl1 = newiTempLabel (NULL);
2157 emitBranch ("bne", tlbl1);
2158 loadRegFromConst (hc08_reg_a, zero);
2159 emitBranch ("bra", tlbl);
2161 loadRegFromConst (hc08_reg_a, one);
2165 emitBranch ("beq", tlbl);
2166 loadRegFromConst (hc08_reg_a, one);
2169 hc08_useReg (hc08_reg_a);
2175 /*-----------------------------------------------------------------*/
2176 /* genNot - generate code for ! operation */
2177 /*-----------------------------------------------------------------*/
2181 D(emitcode ("; genNot",""));
2183 /* assign asmOps to operand & result */
2184 aopOp (IC_LEFT (ic), ic, FALSE);
2185 aopOp (IC_RESULT (ic), ic, TRUE);
2187 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2188 emitcode ("eor", one);
2189 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2191 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2192 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2196 /*-----------------------------------------------------------------*/
2197 /* genCpl - generate code for complement */
2198 /*-----------------------------------------------------------------*/
2204 regs* reg = hc08_reg_a;
2208 D(emitcode ("; genCpl",""));
2210 /* assign asmOps to operand & result */
2211 aopOp (IC_LEFT (ic), ic, FALSE);
2212 aopOp (IC_RESULT (ic), ic, TRUE);
2214 size = AOP_SIZE (IC_RESULT (ic));
2217 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2218 rmwWithReg ("com", reg);
2220 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2224 /* release the aops */
2225 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2226 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2229 /*-----------------------------------------------------------------*/
2230 /* genUminusFloat - unary minus for floating points */
2231 /*-----------------------------------------------------------------*/
2233 genUminusFloat (operand * op, operand * result)
2235 int size, offset = 0;
2238 D(emitcode ("; genUminusFloat",""));
2240 /* for this we just copy and then flip the bit */
2242 size = AOP_SIZE (op) - 1;
2248 needpula = pushRegIfUsed (hc08_reg_a);
2249 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2250 emitcode ("eor", "#0x80");
2251 hc08_useReg (hc08_reg_a);
2252 storeRegToAop (hc08_reg_a, AOP (result), offset);
2253 pullOrFreeReg (hc08_reg_a, needpula);
2256 transferAopAop (AOP (op), offset, AOP (result), offset);
2262 /*-----------------------------------------------------------------*/
2263 /* genUminus - unary minus code generation */
2264 /*-----------------------------------------------------------------*/
2266 genUminus (iCode * ic)
2269 sym_link *optype, *rtype;
2273 D(emitcode ("; genUminus",""));
2276 aopOp (IC_LEFT (ic), ic, FALSE);
2277 aopOp (IC_RESULT (ic), ic, TRUE);
2279 optype = operandType (IC_LEFT (ic));
2280 rtype = operandType (IC_RESULT (ic));
2282 /* if float then do float stuff */
2283 if (IS_FLOAT (optype))
2285 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2289 /* otherwise subtract from zero */
2290 size = AOP_SIZE (IC_LEFT (ic));
2295 needpula = pushRegIfUsed (hc08_reg_a);
2296 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2297 emitcode ("nega", "");
2298 hc08_freeReg (hc08_reg_a);
2299 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2300 SPEC_USIGN (operandType (IC_LEFT (ic))));
2301 pullOrFreeReg (hc08_reg_a, needpula);
2305 needpula = pushRegIfUsed (hc08_reg_a);
2309 loadRegFromConst (hc08_reg_a, zero);
2310 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2311 storeRegToAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset++);
2314 storeRegSignToUpperAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset,
2315 SPEC_USIGN (operandType (IC_LEFT (ic))));
2316 pullOrFreeReg (hc08_reg_a, needpula);
2322 /* release the aops */
2323 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2324 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2327 /*-----------------------------------------------------------------*/
2328 /* saveRegisters - will look for a call and save the registers */
2329 /*-----------------------------------------------------------------*/
2331 saveRegisters (iCode * lic)
2338 for (ic = lic; ic; ic = ic->next)
2339 if (ic->op == CALL || ic->op == PCALL)
2344 fprintf (stderr, "found parameter push with no function call\n");
2348 /* if the registers have been saved already or don't need to be then
2352 if (IS_SYMOP(IC_LEFT(ic)) &&
2353 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2354 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2357 /* safe the registers in use at this time but skip the
2358 ones for the result */
2359 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2360 hc08_rUmaskForOp (IC_RESULT(ic)));
2363 for (i = 0; i < hc08_nRegs; i++)
2365 if (bitVectBitValue (rsave, i))
2366 pushReg ( hc08_regWithIdx (i), FALSE);
2370 /*-----------------------------------------------------------------*/
2371 /* unsaveRegisters - pop the pushed registers */
2372 /*-----------------------------------------------------------------*/
2374 unsaveRegisters (iCode * ic)
2379 /* restore the registers in use at this time but skip the
2380 ones for the result */
2381 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2382 hc08_rUmaskForOp (IC_RESULT(ic)));
2384 for (i = hc08_nRegs; i >= 0; i--)
2386 if (bitVectBitValue (rsave, i))
2387 pullReg ( hc08_regWithIdx (i));
2393 /*-----------------------------------------------------------------*/
2395 /*-----------------------------------------------------------------*/
2397 pushSide (operand * oper, int size)
2402 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2403 pushReg ( hc08_reg_a, TRUE);
2407 /*-----------------------------------------------------------------*/
2408 /* assignResultValue - */
2409 /*-----------------------------------------------------------------*/
2411 assignResultValue (operand * oper)
2413 int size = AOP_SIZE (oper);
2417 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2418 if (hc08_aop_pass[offset]->type == AOP_REG)
2419 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2426 /*-----------------------------------------------------------------*/
2427 /* genIpush - genrate code for pushing this gets a little complex */
2428 /*-----------------------------------------------------------------*/
2430 genIpush (iCode * ic)
2432 int size, offset = 0;
2435 D(emitcode ("; genIpush",""));
2437 /* if this is not a parm push : ie. it is spill push
2438 and spill push is always done on the local stack */
2442 /* and the item is spilt then do nothing */
2443 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2446 aopOp (IC_LEFT (ic), ic, FALSE);
2447 size = AOP_SIZE (IC_LEFT (ic));
2449 /* push it on the stack */
2452 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2453 pushReg ( hc08_reg_a, TRUE);
2459 /* this is a paramter push: in this case we call
2460 the routine to find the call and save those
2461 registers that need to be saved */
2464 /* then do the push */
2465 aopOp (IC_LEFT (ic), ic, FALSE);
2468 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2469 size = AOP_SIZE (IC_LEFT (ic));
2472 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2473 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2475 if ((size==2) && hc08_reg_hx->isFree)
2477 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2478 pushReg (hc08_reg_hx, TRUE);
2485 // printf("loading %d\n", offset);
2486 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2487 // printf("pushing \n");
2488 pushReg (hc08_reg_a, TRUE);
2492 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2495 /*-----------------------------------------------------------------*/
2496 /* genIpop - recover the registers: can happen only for spilling */
2497 /*-----------------------------------------------------------------*/
2499 genIpop (iCode * ic)
2503 D(emitcode ("; genIpop",""));
2505 /* if the temp was not pushed then */
2506 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2509 aopOp (IC_LEFT (ic), ic, FALSE);
2510 size = AOP_SIZE (IC_LEFT (ic));
2514 pullReg (hc08_reg_a);
2515 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2517 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2521 /*-----------------------------------------------------------------*/
2522 /* genSend - gen code for SEND */
2523 /*-----------------------------------------------------------------*/
2524 static void genSend(set *sendSet)
2528 for (sic = setFirstItem (_G.sendSet); sic;
2529 sic = setNextItem (_G.sendSet)) {
2530 int size, offset = 0;
2531 aopOp (IC_LEFT (sic), sic, FALSE);
2532 size = AOP_SIZE (IC_LEFT (sic));
2537 transferAopAop( AOP (IC_LEFT (sic)), offset,
2538 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2542 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2546 /*-----------------------------------------------------------------*/
2547 /* genCall - generates a call statement */
2548 /*-----------------------------------------------------------------*/
2550 genCall (iCode * ic)
2553 // bool restoreBank = FALSE;
2554 // bool swapBanks = FALSE;
2556 D(emitcode("; genCall",""));
2558 dtype = operandType (IC_LEFT (ic));
2559 /* if send set is not empty the assign */
2562 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2563 genSend(reverseSet(_G.sendSet));
2565 genSend(_G.sendSet);
2571 /* if caller saves & we have not saved then */
2577 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2578 OP_SYMBOL (IC_LEFT (ic))->rname :
2579 OP_SYMBOL (IC_LEFT (ic))->name));
2582 /* if we need assign a result value */
2583 if ((IS_ITEMP (IC_RESULT (ic)) &&
2584 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2585 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2586 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2587 IS_TRUE_SYMOP (IC_RESULT (ic)))
2591 aopOp (IC_RESULT (ic), ic, FALSE);
2594 assignResultValue (IC_RESULT (ic));
2596 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2599 /* adjust the stack for parameters if
2603 pullNull (ic->parmBytes);
2606 /* if we had saved some registers then unsave them */
2607 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2608 unsaveRegisters (ic);
2612 /*-----------------------------------------------------------------*/
2613 /* -10l - generates a call by pointer statement */
2614 /*-----------------------------------------------------------------*/
2616 genPcall (iCode * ic)
2619 symbol *rlbl = newiTempLabel (NULL);
2620 symbol *tlbl = newiTempLabel (NULL);
2621 // bool restoreBank=FALSE;
2622 // bool swapBanks = FALSE;
2624 D(emitcode("; genPCall",""));
2626 /* if caller saves & we have not saved then */
2630 /* if we are calling a not _naked function that is not using
2631 the same register bank then we need to save the
2632 destination registers on the stack */
2633 dtype = operandType (IC_LEFT (ic))->next;
2635 /* now push the calling address */
2636 emitBranch ("bsr", tlbl);
2637 emitBranch ("bra", rlbl);
2640 /* Push the function's address */
2641 aopOp (IC_LEFT (ic), ic, FALSE);
2642 pushSide (IC_LEFT (ic), FPTRSIZE);
2643 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2645 /* if send set is not empty the assign */
2648 genSend(reverseSet(_G.sendSet));
2654 emitcode ("rts", "");
2659 /* if we need assign a result value */
2660 if ((IS_ITEMP (IC_RESULT (ic)) &&
2661 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2662 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2663 IS_TRUE_SYMOP (IC_RESULT (ic)))
2667 aopOp (IC_RESULT (ic), ic, FALSE);
2670 assignResultValue (IC_RESULT (ic));
2672 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2675 /* adjust the stack for parameters if
2679 pullNull (ic->parmBytes);
2682 /* if we hade saved some registers then
2684 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2685 unsaveRegisters (ic);
2688 /*-----------------------------------------------------------------*/
2689 /* resultRemat - result is rematerializable */
2690 /*-----------------------------------------------------------------*/
2692 resultRemat (iCode * ic)
2694 if (SKIP_IC (ic) || ic->op == IFX)
2697 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2699 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2700 if (sym->remat && !POINTER_SET (ic))
2707 #if defined(__BORLANDC__) || defined(_MSC_VER)
2708 #define STRCASECMP stricmp
2710 #define STRCASECMP strcasecmp
2713 /*-----------------------------------------------------------------*/
2714 /* inExcludeList - return 1 if the string is in exclude Reg list */
2715 /*-----------------------------------------------------------------*/
2717 regsCmp(void *p1, void *p2)
2719 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2723 inExcludeList (char *s)
2725 const char *p = setFirstItem(options.excludeRegsSet);
2727 if (p == NULL || STRCASECMP(p, "none") == 0)
2731 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2734 /*-----------------------------------------------------------------*/
2735 /* genFunction - generated code for function entry */
2736 /*-----------------------------------------------------------------*/
2738 genFunction (iCode * ic)
2742 int calleesaves_saved_register = -1;
2746 /* create the function header */
2747 emitcode (";", "-----------------------------------------");
2748 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2749 emitcode (";", "-----------------------------------------");
2751 emitcode ("", "%s:", sym->rname);
2752 ftype = operandType (IC_LEFT (ic));
2754 if (IFFUNC_ISNAKED(ftype))
2756 emitcode(";", "naked function: no prologue.");
2762 /* if this is an interrupt service routine then
2764 if (IFFUNC_ISISR (sym->type))
2767 if (!inExcludeList ("h"))
2768 emitcode ("pshh", "");
2772 /* if callee-save to be used for this function
2773 then save the registers being used in this function */
2774 if (IFFUNC_CALLEESAVES(sym->type))
2778 /* if any registers used */
2781 /* save the registers used */
2782 for (i = 0; i < sym->regsUsed->size; i++)
2784 if (bitVectBitValue (sym->regsUsed, i))
2786 /* remember one saved register for later usage */
2787 if (calleesaves_saved_register < 0)
2788 calleesaves_saved_register = i;
2789 pushReg (hc08_regWithIdx (i), FALSE);
2797 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2802 /* adjust the stack for the function */
2808 // werror (W_STACK_OVERFLOW, sym->name);
2812 _G.stackOfs = sym->stack;
2815 /* if critical function then turn interrupts off */
2816 if (IFFUNC_ISCRITICAL (ftype))
2818 if (IFFUNC_ARGS (ftype))
2820 /* Function was passed parameters, so make sure A is preserved */
2821 pushReg (hc08_reg_a, FALSE);
2822 pushReg (hc08_reg_a, FALSE);
2823 emitcode ("tpa", "");
2824 emitcode ("sta", "2,s");
2825 emitcode ("sei", "");
2826 pullReg (hc08_reg_a);
2830 /* No passed parameters, so A can be freely modified */
2831 emitcode ("tpa", "");
2832 pushReg (hc08_reg_a, TRUE);
2833 emitcode ("sei", "");
2839 /*-----------------------------------------------------------------*/
2840 /* genEndFunction - generates epilogue for functions */
2841 /*-----------------------------------------------------------------*/
2843 genEndFunction (iCode * ic)
2845 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2847 if (IFFUNC_ISNAKED(sym->type))
2849 emitcode(";", "naked function: no epilogue.");
2853 if (IFFUNC_ISCRITICAL (sym->type))
2855 if (!IS_VOID(sym->type->next))
2857 /* Function has return value, so make sure A is preserved */
2858 pushReg (hc08_reg_a, FALSE);
2859 emitcode ("lda", "2,s");
2860 emitcode ("tap", "");
2861 pullReg (hc08_reg_a);
2866 /* Function returns void, so A can be freely modified */
2867 pullReg (hc08_reg_a);
2868 emitcode ("tap", "");
2872 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2878 _G.stackPushes += sym->stack;
2879 adjustStack (sym->stack);
2883 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2887 if (IFFUNC_ISISR (sym->type))
2890 if (!inExcludeList ("h"))
2891 emitcode ("pulh", "");
2894 /* if debug then send end of function */
2895 if (options.debug && currFunc)
2898 emitcode ("", "C$%s$%d$%d$%d ==.",
2899 FileBaseName (ic->filename), currFunc->lastLine,
2900 ic->level, ic->block);
2901 if (IS_STATIC (currFunc->etype))
2902 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2904 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2908 emitcode ("rti", "");
2912 if (IFFUNC_CALLEESAVES(sym->type))
2916 /* if any registers used */
2919 /* save the registers used */
2920 for (i = sym->regsUsed->size; i >= 0; i--)
2922 if (bitVectBitValue (sym->regsUsed, i) ||
2923 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
2924 emitcode ("pop", "%s", hc08_regWithIdx (i)->dname);
2930 /* if debug then send end of function */
2931 if (options.debug && currFunc)
2934 emitcode ("", "C$%s$%d$%d$%d ==.",
2935 FileBaseName (ic->filename), currFunc->lastLine,
2936 ic->level, ic->block);
2937 if (IS_STATIC (currFunc->etype))
2938 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2940 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2944 emitcode ("rts", "");
2949 /*-----------------------------------------------------------------*/
2950 /* genRet - generate code for return statement */
2951 /*-----------------------------------------------------------------*/
2955 int size, offset = 0;
2958 D(emitcode ("; genRet",""));
2960 /* if we have no return value then
2961 just generate the "ret" */
2965 /* we have something to return then
2966 move the return value into place */
2967 aopOp (IC_LEFT (ic), ic, FALSE);
2968 size = AOP_SIZE (IC_LEFT (ic));
2974 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
2981 /* 4 byte return: store value in the global return variable */
2985 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
2986 STA (fReturn2[offset--], FALSE);
2987 hc08_freeReg (hc08_reg_a);
2991 /* 2 byte return: store value in x:a */
2992 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
2993 hc08_freeReg (hc08_reg_xa);
2996 /* 1 byte return: store value in a */
2997 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
2998 hc08_freeReg (hc08_reg_a);
3003 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3006 /* generate a jump to the return label
3007 if the next is not the return statement */
3008 if (!(ic->next && ic->next->op == LABEL &&
3009 IC_LABEL (ic->next) == returnLabel))
3011 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3015 /*-----------------------------------------------------------------*/
3016 /* genLabel - generates a label */
3017 /*-----------------------------------------------------------------*/
3019 genLabel (iCode * ic)
3024 /* For the high level labels we cannot depend on any */
3025 /* register's contents. Amnesia time. */
3026 for (i=A_IDX;i<=XA_IDX;i++)
3028 reg = hc08_regWithIdx(i);
3033 /* special case never generate */
3034 if (IC_LABEL (ic) == entryLabel)
3037 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3041 /*-----------------------------------------------------------------*/
3042 /* genGoto - generates a jmp */
3043 /*-----------------------------------------------------------------*/
3045 genGoto (iCode * ic)
3047 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3051 /*-----------------------------------------------------------------*/
3052 /* findLabelBackwards: walks back through the iCode chain looking */
3053 /* for the given label. Returns number of iCode instructions */
3054 /* between that label and given ic. */
3055 /* Returns zero if label not found. */
3056 /*-----------------------------------------------------------------*/
3058 findLabelBackwards (iCode * ic, int key)
3067 /* If we have any pushes or pops, we cannot predict the distance.
3068 I don't like this at all, this should be dealt with in the
3070 if (ic->op == IPUSH || ic->op == IPOP) {
3074 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3084 /*-----------------------------------------------------------------*/
3085 /* genPlusIncr :- does addition with increment if possible */
3086 /*-----------------------------------------------------------------*/
3088 genPlusIncr (iCode * ic)
3096 unsigned int size = getDataSize (IC_RESULT (ic));
3098 symbol *tlbl = NULL;
3100 left = IC_LEFT (ic);
3101 result = IC_RESULT (ic);
3103 /* will try to generate an increment */
3104 /* if the right side is not a literal
3106 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3109 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3111 emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left)));
3113 if ((IS_AOP_HX (AOP (left)) ||
3114 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3116 && (icount>=-128) && (icount<=127) && (size==2))
3118 needpulx = pushRegIfUsed (hc08_reg_x);
3119 needpulh = pushRegIfUsed (hc08_reg_h);
3120 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3121 emitcode ("aix","#%d", icount);
3122 hc08_dirtyReg (hc08_reg_hx, FALSE);
3123 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3124 pullOrFreeReg (hc08_reg_h, needpulh);
3125 pullOrFreeReg (hc08_reg_x, needpulx);
3129 emitcode ("", "; icount = %d, sameRegs=%d", icount,
3130 sameRegs (AOP (left), AOP (result)));
3132 if ((icount > 255) || (icount<0))
3135 if (!sameRegs (AOP (left), AOP (result)))
3138 D(emitcode ("; genPlusIncr",""));
3141 tlbl = newiTempLabel (NULL);
3146 rmwWithAop ("inc", AOP (result), 0);
3148 emitBranch ("bne", tlbl);
3152 needpula = pushRegIfUsed (hc08_reg_a);
3153 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3154 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3155 hc08_useReg (hc08_reg_a);
3156 storeRegToAop (hc08_reg_a, AOP (result), 0);
3157 hc08_freeReg (hc08_reg_a);
3159 emitBranch ("bcc", tlbl);
3161 for (offset=1; offset<size; offset++)
3163 rmwWithAop ("inc", AOP (result), offset);
3164 if ((offset+1)<size)
3165 emitBranch ("bne", tlbl);
3171 pullOrFreeReg (hc08_reg_a, needpula);
3178 /*-----------------------------------------------------------------*/
3179 /* genPlus - generates code for addition */
3180 /*-----------------------------------------------------------------*/
3182 genPlus (iCode * ic)
3184 int size, offset = 0;
3186 asmop *leftOp, *rightOp;
3188 /* special cases :- */
3190 D(emitcode ("; genPlus",""));
3192 aopOp (IC_LEFT (ic), ic, FALSE);
3193 aopOp (IC_RIGHT (ic), ic, FALSE);
3194 aopOp (IC_RESULT (ic), ic, TRUE);
3196 /* we want registers on the left and literals on the right */
3197 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3198 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3200 operand *t = IC_RIGHT (ic);
3201 IC_RIGHT (ic) = IC_LEFT (ic);
3206 /* if I can do an increment instead
3207 of add then GOOD for ME */
3208 if (genPlusIncr (ic) == TRUE)
3211 emitcode("","; left size = %d", getDataSize (IC_LEFT(ic)));
3212 emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic)));
3213 emitcode("","; result size = %d", getDataSize (IC_RESULT(ic)));
3215 size = getDataSize (IC_RESULT (ic));
3217 leftOp = AOP(IC_LEFT(ic));
3218 rightOp = AOP(IC_RIGHT(ic));
3224 loadRegFromAop (hc08_reg_a, leftOp, offset);
3225 accopWithAop(add, rightOp, offset);
3226 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3227 hc08_freeReg (hc08_reg_a);
3228 add = "adc"; /* further adds must propagate carry */
3232 // adjustArithmeticResult (ic);
3235 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3236 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3237 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3240 /*-----------------------------------------------------------------*/
3241 /* genMinusDec :- does subtraction with deccrement if possible */
3242 /*-----------------------------------------------------------------*/
3244 genMinusDec (iCode * ic)
3246 unsigned int icount;
3251 unsigned int size = getDataSize (IC_RESULT (ic));
3255 left = IC_LEFT (ic);
3256 result = IC_RESULT (ic);
3258 /* will try to generate an increment */
3259 /* if the right side is not a literal
3261 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3264 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3266 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3267 && (icount>=-127) && (icount<=128) && (size==2))
3269 needpulx = pushRegIfUsed (hc08_reg_x);
3270 needpulh = pushRegIfUsed (hc08_reg_h);
3271 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3272 emitcode ("aix","#%d", -icount);
3273 hc08_dirtyReg (hc08_reg_hx, FALSE);
3274 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3275 pullOrFreeReg (hc08_reg_h, needpulh);
3276 pullOrFreeReg (hc08_reg_x, needpulx);
3280 if ((icount > 1) || (icount<0))
3283 if (!sameRegs (AOP (left), AOP (result)))
3289 D(emitcode ("; genMinusDec",""));
3291 rmwWithAop ("dec", AOP (result), 0);
3296 /*-----------------------------------------------------------------*/
3297 /* addSign - complete with sign */
3298 /*-----------------------------------------------------------------*/
3300 addSign (operand * result, int offset, int sign)
3302 int size = (getDataSize (result) - offset);
3307 emitcode ("rola", "");
3308 emitcode ("clra", "");
3309 emitcode ("sbc", zero);
3311 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3315 storeConstToAop (zero, AOP (result), offset++);
3320 /*-----------------------------------------------------------------*/
3321 /* genMinus - generates code for subtraction */
3322 /*-----------------------------------------------------------------*/
3324 genMinus (iCode * ic)
3327 int size, offset = 0;
3329 asmop *leftOp, *rightOp;
3331 D(emitcode ("; genMinus",""));
3333 aopOp (IC_LEFT (ic), ic, FALSE);
3334 aopOp (IC_RIGHT (ic), ic, FALSE);
3335 aopOp (IC_RESULT (ic), ic, TRUE);
3337 /* special cases :- */
3338 /* if I can do an decrement instead
3339 of subtract then GOOD for ME */
3340 if (genMinusDec (ic) == TRUE)
3343 size = getDataSize (IC_RESULT (ic));
3346 leftOp = AOP(IC_LEFT(ic));
3347 rightOp = AOP(IC_RIGHT(ic));
3353 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3354 accopWithAop(sub, rightOp, offset);
3355 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3360 // adjustArithmeticResult (ic);
3363 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3364 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3365 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3370 /*-----------------------------------------------------------------*/
3371 /* genMultOneByte : 8*8=8/16 bit multiplication */
3372 /*-----------------------------------------------------------------*/
3374 genMultOneByte (operand * left,
3378 sym_link *opetype = operandType (result);
3379 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3380 int size=AOP_SIZE(result);
3381 bool negLiteral = FALSE;
3383 D(emitcode ("; genMultOneByte",""));
3385 if (size<1 || size>2) {
3386 // this should never happen
3387 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3388 AOP_SIZE(result), __FILE__, lineno);
3392 /* (if two literals: the value is computed before) */
3393 /* if one literal, literal on the right */
3394 if (AOP_TYPE (left) == AOP_LIT)
3399 //emitcode (";", "swapped left and right");
3402 if (SPEC_USIGN(opetype))
3404 // just an unsigned 8*8=8/16 multiply
3405 //emitcode (";","unsigned");
3407 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3408 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3409 emitcode ("mul", "");
3410 hc08_dirtyReg (hc08_reg_xa, FALSE);
3411 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3412 hc08_freeReg (hc08_reg_xa);
3417 // we have to do a signed multiply
3420 //emitcode (";", "signed");
3422 emitcode ("clr", "1,s");
3424 tlbl1 = newiTempLabel (NULL);
3425 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3426 emitcode ("tsta","");
3427 emitBranch ("bpl", tlbl1);
3428 emitcode ("inc", "1,s");
3429 rmwWithReg ("neg", hc08_reg_a);
3432 if (AOP_TYPE(right)==AOP_LIT)
3434 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3435 /* AND literal negative */
3437 emitcode ("ldx", "#0x%02x", -val);
3440 emitcode ("ldx", "#0x%02x", val);
3442 hc08_useReg (hc08_reg_x);
3446 tlbl2 = newiTempLabel (NULL);
3447 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3448 emitcode ("tstx", "");
3449 emitBranch ("bpl", tlbl2);
3450 emitcode ("inc", "1,s");
3451 rmwWithReg ("neg", hc08_reg_x);
3455 emitcode ("mul", "");
3456 hc08_dirtyReg (hc08_reg_xa, FALSE);
3458 tlbl3 = newiTempLabel (NULL);
3459 emitcode ("dec", "1,s");
3461 emitBranch ("bne", tlbl3);
3463 emitBranch ("beq", tlbl3);
3465 rmwWithReg ("neg", hc08_reg_a);
3468 tlbl4 = newiTempLabel (NULL);
3469 emitBranch ("bcc", tlbl4);
3470 rmwWithReg ("inc", hc08_reg_x);
3472 rmwWithReg ("neg", hc08_reg_x);
3477 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3478 hc08_freeReg (hc08_reg_xa);
3482 /*-----------------------------------------------------------------*/
3483 /* genMult - generates code for multiplication */
3484 /*-----------------------------------------------------------------*/
3486 genMult (iCode * ic)
3488 operand *left = IC_LEFT (ic);
3489 operand *right = IC_RIGHT (ic);
3490 operand *result = IC_RESULT (ic);
3492 D(emitcode ("; genMult",""));
3494 /* assign the amsops */
3495 aopOp (left, ic, FALSE);
3496 aopOp (right, ic, FALSE);
3497 aopOp (result, ic, TRUE);
3499 /* special cases first */
3500 /* if both are of size == 1 */
3501 // if (getSize(operandType(left)) == 1 &&
3502 // getSize(operandType(right)) == 1)
3503 if (AOP_SIZE (left) == 1 &&
3504 AOP_SIZE (right) == 1)
3506 genMultOneByte (left, right, result);
3510 /* should have been converted to function call */
3511 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3512 getSize(OP_SYMBOL(right)->type));
3513 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3518 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3519 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3520 freeAsmop (result, NULL, ic, TRUE);
3523 /*-----------------------------------------------------------------*/
3524 /* genDivOneByte : 8 bit division */
3525 /*-----------------------------------------------------------------*/
3527 genDivOneByte (operand * left,
3531 sym_link *opetype = operandType (result);
3533 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3535 bool negLiteral = FALSE;
3537 D(emitcode ("; genDivOneByte",""));
3539 size = AOP_SIZE (result);
3540 /* signed or unsigned */
3541 if (SPEC_USIGN (opetype))
3543 /* unsigned is easy */
3544 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3545 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3546 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3547 emitcode ("div", "");
3548 hc08_dirtyReg (hc08_reg_a, FALSE);
3549 hc08_dirtyReg (hc08_reg_h, FALSE);
3550 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3551 hc08_freeReg (hc08_reg_a);
3552 hc08_freeReg (hc08_reg_x);
3553 hc08_freeReg (hc08_reg_h);
3557 /* signed is a little bit more difficult */
3560 emitcode ("clr", "1,s");
3562 tlbl1 = newiTempLabel (NULL);
3563 tlbl2 = newiTempLabel (NULL);
3564 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3565 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3566 emitBranch ("bpl", tlbl1);
3567 emitcode ("inc", "1,s");
3568 rmwWithReg ("neg", hc08_reg_a);
3569 emitBranch ("bcc", tlbl2);
3570 rmwWithReg ("inc", hc08_reg_x);
3572 rmwWithReg ("neg", hc08_reg_x);
3573 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3576 if (AOP_TYPE(right)==AOP_LIT)
3578 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3579 /* AND literal negative */
3581 emitcode ("ldx", "#0x%02x", -val);
3584 emitcode ("ldx", "#0x%02x", val);
3586 hc08_useReg (hc08_reg_x);
3590 tlbl3 = newiTempLabel (NULL);
3591 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3592 emitBranch ("bpl", tlbl3);
3593 emitcode ("inc", "1,s");
3594 rmwWithReg ("neg", hc08_reg_x);
3598 emitcode ("div", "");
3599 hc08_dirtyReg (hc08_reg_x, FALSE);
3600 hc08_dirtyReg (hc08_reg_a, FALSE);
3601 hc08_dirtyReg (hc08_reg_h, FALSE);
3603 tlbl4 = newiTempLabel (NULL);
3604 emitcode ("dec", "1,s");
3606 emitBranch ("bne", tlbl4);
3608 emitBranch ("beq", tlbl4);
3609 rmwWithReg ("neg", hc08_reg_a);
3613 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3614 hc08_freeReg (hc08_reg_a);
3615 hc08_freeReg (hc08_reg_x);
3616 hc08_freeReg (hc08_reg_h);
3621 /*-----------------------------------------------------------------*/
3622 /* genDiv - generates code for division */
3623 /*-----------------------------------------------------------------*/
3627 operand *left = IC_LEFT (ic);
3628 operand *right = IC_RIGHT (ic);
3629 operand *result = IC_RESULT (ic);
3631 D(emitcode ("; genDiv",""));
3633 /* assign the amsops */
3634 aopOp (left, ic, FALSE);
3635 aopOp (right, ic, FALSE);
3636 aopOp (result, ic, TRUE);
3638 /* special cases first */
3639 /* if both are of size == 1 */
3640 if (AOP_SIZE (left) <= 2 &&
3641 AOP_SIZE (right) == 1)
3643 genDivOneByte (left, right, result);
3647 /* should have been converted to function call */
3650 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3651 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3652 freeAsmop (result, NULL, ic, TRUE);
3655 /*-----------------------------------------------------------------*/
3656 /* genModOneByte : 8 bit modulus */
3657 /*-----------------------------------------------------------------*/
3659 genModOneByte (operand * left,
3663 sym_link *opetype = operandType (result);
3665 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3667 bool negLiteral = FALSE;
3669 D(emitcode ("; genModOneByte",""));
3671 size = AOP_SIZE (result);
3672 /* signed or unsigned */
3673 if (SPEC_USIGN (opetype))
3675 /* unsigned is easy */
3676 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3677 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3678 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3679 emitcode ("div", "");
3680 hc08_dirtyReg (hc08_reg_a, FALSE);
3681 hc08_dirtyReg (hc08_reg_h, FALSE);
3682 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3683 hc08_freeReg (hc08_reg_a);
3684 hc08_freeReg (hc08_reg_x);
3685 hc08_freeReg (hc08_reg_h);
3689 /* signed is a little bit more difficult */
3692 emitcode ("clr", "1,s");
3694 tlbl1 = newiTempLabel (NULL);
3695 tlbl2 = newiTempLabel (NULL);
3696 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3697 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3698 emitBranch ("bpl", tlbl1);
3699 emitcode ("inc", "1,s");
3700 rmwWithReg ("neg", hc08_reg_a);
3701 emitBranch ("bcc", tlbl2);
3702 rmwWithReg ("inc", hc08_reg_x);
3704 rmwWithReg ("neg", hc08_reg_x);
3705 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3708 if (AOP_TYPE(right)==AOP_LIT)
3710 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3711 /* AND literal negative */
3713 emitcode ("ldx", "#0x%02x", -val);
3716 emitcode ("ldx", "#0x%02x", val);
3718 hc08_useReg (hc08_reg_x);
3722 tlbl3 = newiTempLabel (NULL);
3723 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3724 emitBranch ("bpl", tlbl3);
3725 emitcode ("inc", "1,s");
3726 rmwWithReg ("neg", hc08_reg_x);
3730 emitcode ("div", "");
3731 hc08_dirtyReg (hc08_reg_x, FALSE);
3732 hc08_dirtyReg (hc08_reg_a, FALSE);
3733 hc08_dirtyReg (hc08_reg_h, FALSE);
3735 tlbl4 = newiTempLabel (NULL);
3736 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3737 emitcode ("dec", "1,s");
3739 emitBranch ("bne", tlbl4);
3741 emitBranch ("beq", tlbl4);
3742 rmwWithReg ("neg", hc08_reg_a);
3746 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3747 hc08_freeReg (hc08_reg_a);
3748 hc08_freeReg (hc08_reg_x);
3749 hc08_freeReg (hc08_reg_h);
3753 /*-----------------------------------------------------------------*/
3754 /* genMod - generates code for division */
3755 /*-----------------------------------------------------------------*/
3759 operand *left = IC_LEFT (ic);
3760 operand *right = IC_RIGHT (ic);
3761 operand *result = IC_RESULT (ic);
3763 D(emitcode ("; genMod",""));
3765 /* assign the amsops */
3766 aopOp (left, ic, FALSE);
3767 aopOp (right, ic, FALSE);
3768 aopOp (result, ic, TRUE);
3770 /* special cases first */
3771 /* if both are of size == 1 */
3772 if (AOP_SIZE (left) <= 2 &&
3773 AOP_SIZE (right) == 1)
3775 genModOneByte (left, right, result);
3779 /* should have been converted to function call */
3783 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3784 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3785 freeAsmop (result, NULL, ic, TRUE);
3788 /*-----------------------------------------------------------------*/
3789 /* genIfxJump :- will create a jump depending on the ifx */
3790 /*-----------------------------------------------------------------*/
3792 genIfxJump (iCode * ic, char *jval)
3795 symbol *tlbl = newiTempLabel (NULL);
3798 D(emitcode ("; genIfxJump",""));
3800 /* if true label then we jump if condition
3804 jlbl = IC_TRUE (ic);
3805 if (!strcmp (jval, "a"))
3807 else if (!strcmp (jval, "c"))
3814 /* false label is present */
3815 jlbl = IC_FALSE (ic);
3816 if (!strcmp (jval, "a"))
3818 else if (!strcmp (jval, "c"))
3823 emitBranch (inst, tlbl);
3824 emitBranch ("jmp", jlbl);
3827 /* mark the icode as generated */
3831 /*-----------------------------------------------------------------*/
3832 /* genCmp :- greater or less than comparison */
3833 /*-----------------------------------------------------------------*/
3835 genCmp (operand * left, operand * right,
3836 operand * result, iCode * ifx, int sign, iCode *ic)
3838 int size, offset = 0;
3839 unsigned long lit = 0L;
3841 bool needpula = FALSE;
3843 D(emitcode ("; genCmp",""));
3845 /* subtract right from left if at the
3846 end the carry flag is set then we know that
3847 left is greater than right */
3848 size = max (AOP_SIZE (left), AOP_SIZE (right));
3850 if (AOP_TYPE (right) == AOP_LIT)
3852 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3853 /* optimize if(x < 0) or if(x >= 0) */
3862 needpula = pushRegIfUsed (hc08_reg_a);
3863 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3864 emitcode ("rola", "");
3865 hc08_useReg (hc08_reg_a);
3873 && ((AOP_TYPE (right) == AOP_LIT) ||
3874 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3875 && hc08_reg_hx->isFree)
3877 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3878 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3879 hc08_freeReg (hc08_reg_hx);
3890 loadRegFromAop (hc08_reg_a, AOP (left), offset);
3891 accopWithAop (sub, AOP (right), offset);
3892 hc08_freeReg (hc08_reg_a);
3898 freeAsmop (right, NULL, ic, TRUE);
3899 freeAsmop (left, NULL, ic, TRUE);
3900 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3906 /* if the result is used in the next
3907 ifx conditional branch then generate
3908 code a little differently */
3911 pullOrFreeReg(hc08_reg_a,needpula);
3912 genIfxJump (ifx, sign ? "s" : "c");
3919 pullOrFreeReg(hc08_reg_a,needpula);
3923 /*-----------------------------------------------------------------*/
3924 /* genCmpGt :- greater than comparison */
3925 /*-----------------------------------------------------------------*/
3927 genCmpGt (iCode * ic, iCode * ifx)
3929 operand *left, *right, *result;
3930 sym_link *letype, *retype;
3933 D(emitcode ("; genCmpGt",""));
3935 result = IC_RESULT (ic);
3936 left = IC_LEFT (ic);
3937 right = IC_RIGHT (ic);
3939 letype = getSpec (operandType (left));
3940 retype = getSpec (operandType (right));
3941 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3942 /* assign the amsops */
3943 aopOp (left, ic, FALSE);
3944 aopOp (right, ic, FALSE);
3945 aopOp (result, ic, TRUE);
3947 genCmp (right, left, result, ifx, sign,ic);
3949 freeAsmop (result, NULL, ic, TRUE);
3952 /*-----------------------------------------------------------------*/
3953 /* genCmpLt - less than comparisons */
3954 /*-----------------------------------------------------------------*/
3956 genCmpLt (iCode * ic, iCode * ifx)
3958 operand *left, *right, *result;
3959 sym_link *letype, *retype;
3962 D(emitcode ("; genCmpLt",""));
3964 result = IC_RESULT (ic);
3965 left = IC_LEFT (ic);
3966 right = IC_RIGHT (ic);
3968 letype = getSpec (operandType (left));
3969 retype = getSpec (operandType (right));
3970 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3972 /* assign the amsops */
3973 aopOp (left, ic, FALSE);
3974 aopOp (right, ic, FALSE);
3975 aopOp (result, ic, TRUE);
3977 genCmp (left, right, result, ifx, sign,ic);
3979 freeAsmop (result, NULL, ic, TRUE);
3982 /*-----------------------------------------------------------------*/
3983 /* - compare and branch if not equal */
3984 /*-----------------------------------------------------------------*/
3986 gencbneshort (operand * left, operand * right, symbol * lbl)
3988 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3990 unsigned long lit = 0L;
3992 /* if the left side is a literal or
3993 if the right is in a pointer register and left
3995 if (AOP_TYPE (left) == AOP_LIT)
4001 if (AOP_TYPE (right) == AOP_LIT)
4002 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4006 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4007 accopWithAop ("cmp", AOP (right), offset);
4008 hc08_useReg (hc08_reg_a);
4009 hc08_freeReg (hc08_reg_a);
4010 emitBranch ("bne", lbl);
4016 /*-----------------------------------------------------------------*/
4017 /* gencjne - compare and jump if not equal */
4018 /*-----------------------------------------------------------------*/
4020 gencjne (operand * left, operand * right, symbol * lbl)
4022 symbol *tlbl = newiTempLabel (NULL);
4024 gencbneshort (left, right, lbl);
4026 loadRegFromConst (hc08_reg_a, one);
4027 emitBranch ("bra", tlbl);
4029 loadRegFromConst (hc08_reg_a, zero);
4032 hc08_useReg(hc08_reg_a);
4033 hc08_freeReg(hc08_reg_a);
4036 /*-----------------------------------------------------------------*/
4037 /* genCmpEq - generates code for equal to */
4038 /*-----------------------------------------------------------------*/
4040 genCmpEq (iCode * ic, iCode * ifx)
4042 operand *left, *right, *result;
4044 D(emitcode ("; genCmpEq",""));
4046 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4047 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4048 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4050 /* if literal, literal on the right or
4051 if the right is in a pointer register and left
4053 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4055 operand *t = IC_RIGHT (ic);
4056 IC_RIGHT (ic) = IC_LEFT (ic);
4060 if (ifx && !AOP_SIZE (result))
4063 tlbl = newiTempLabel (NULL);
4064 gencbneshort (left, right, tlbl);
4067 emitBranch ("jmp", IC_TRUE (ifx));
4072 symbol *lbl = newiTempLabel (NULL);
4073 emitBranch ("bra", lbl);
4075 emitBranch ("jmp", IC_FALSE (ifx));
4079 /* mark the icode as generated */
4084 gencjne (left, right, newiTempLabel (NULL));
4085 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4087 storeRegToAop (hc08_reg_a, AOP (result), 0);
4092 genIfxJump (ifx, "a");
4095 /* if the result is used in an arithmetic operation
4096 then put the result in place */
4097 if (AOP_TYPE (result) != AOP_CRY)
4101 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4102 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4103 freeAsmop (result, NULL, ic, TRUE);
4106 /*-----------------------------------------------------------------*/
4107 /* ifxForOp - returns the icode containing the ifx for operand */
4108 /*-----------------------------------------------------------------*/
4110 ifxForOp (operand * op, iCode * ic)
4112 /* if true symbol then needs to be assigned */
4113 if (IS_TRUE_SYMOP (op))
4116 /* if this has register type condition and
4117 the next instruction is ifx with the same operand
4118 and live to of the operand is upto the ifx only then */
4120 ic->next->op == IFX &&
4121 IC_COND (ic->next)->key == op->key &&
4122 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4129 genPointerGetSetOfs (iCode *ic)
4131 iCode *lic = ic->next;
4137 /* Make sure we have a next iCode */
4138 emitcode("","; checking lic");
4142 /* Make sure the result of the addition is an iCode */
4143 emitcode("","; checking IS_ITEMP");
4144 if (!IS_ITEMP (IC_RESULT (ic)))
4147 /* Make sure the next iCode is a pointer set or get */
4148 pset = POINTER_SET(lic);
4149 pget = POINTER_GET(lic);
4150 emitcode("","; pset=%d, pget=%d",pset,pget);
4154 emitcode("", "; checking pset operandsEqu");
4155 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4158 emitcode("", "; checking pget operandsEqu");
4159 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4162 emitcode("", "; checking IS_SYMOP");
4163 if (!IS_SYMOP (IC_LEFT (ic)))
4166 emitcode("", "; checking !IS_TRUE_SYMOP");
4167 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4170 sym = OP_SYMBOL (IC_LEFT (ic));
4172 emitcode("", "; checking remat");
4178 D(emitcode ("; genPointerGetOfs",""));
4179 aopOp (IC_LEFT(ic), ic, FALSE);
4180 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4181 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4183 aopOp (IC_RIGHT(ic), ic, FALSE);
4184 aopOp (IC_RESULT(lic), lic, FALSE);
4187 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4188 size = AOP_SIZE (IC_RESULT(lic));
4189 derefaop->size = size;
4194 emitcode ("lda", "%s,x",
4195 aopAdrStr (derefaop, offset, TRUE));
4196 hc08_useReg (hc08_reg_a);
4197 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4198 hc08_freeReg (hc08_reg_a);
4202 hc08_freeReg (hc08_reg_hx);
4204 freeAsmop (NULL, derefaop, ic, TRUE);
4205 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4206 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4213 D(emitcode ("; genPointerSetOfs",""));
4214 aopOp (IC_LEFT(ic), ic, FALSE);
4215 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4216 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4218 aopOp (IC_RIGHT(ic), ic, FALSE);
4219 aopOp (IC_RIGHT(lic), lic, FALSE);
4222 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4223 size = AOP_SIZE (IC_RIGHT(lic));
4224 derefaop->size = size;
4229 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4230 emitcode ("sta", "%s,x",
4231 aopAdrStr (derefaop, offset, TRUE));
4232 hc08_freeReg (hc08_reg_a);
4237 hc08_freeReg (hc08_reg_hx);
4239 freeAsmop (NULL, derefaop, ic, TRUE);
4240 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4241 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4250 /*-----------------------------------------------------------------*/
4251 /* hasInc - operand is incremented before any other use */
4252 /*-----------------------------------------------------------------*/
4254 hasInc (operand *op, iCode *ic,int osize)
4256 sym_link *type = operandType(op);
4257 sym_link *retype = getSpec (type);
4258 iCode *lic = ic->next;
4261 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4262 if (!IS_SYMOP(op)) return NULL;
4264 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4265 if (IS_AGGREGATE(type->next)) return NULL;
4266 if (osize != (isize = getSize(type->next))) return NULL;
4269 /* if operand of the form op = op + <sizeof *op> */
4270 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4271 isOperandEqual(IC_RESULT(lic),op) &&
4272 isOperandLiteral(IC_RIGHT(lic)) &&
4273 operandLitValue(IC_RIGHT(lic)) == isize) {
4276 /* if the operand used or deffed */
4277 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4280 /* if GOTO or IFX */
4281 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4287 /*-----------------------------------------------------------------*/
4288 /* genAndOp - for && operation */
4289 /*-----------------------------------------------------------------*/
4291 genAndOp (iCode * ic)
4293 operand *left, *right, *result;
4294 symbol *tlbl, *tlbl0;
4296 D(emitcode ("; genAndOp",""));
4298 /* note here that && operations that are in an
4299 if statement are taken away by backPatchLabels
4300 only those used in arthmetic operations remain */
4301 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4302 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4303 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4305 tlbl = newiTempLabel (NULL);
4306 tlbl0 = newiTempLabel (NULL);
4308 asmopToBool (AOP (left), FALSE);
4309 emitBranch ("beq", tlbl0);
4310 asmopToBool (AOP (right), FALSE);
4311 emitBranch ("beq", tlbl0);
4312 loadRegFromConst (hc08_reg_a,one);
4313 emitBranch ("bra", tlbl);
4315 loadRegFromConst (hc08_reg_a,zero);
4318 hc08_useReg (hc08_reg_a);
4319 hc08_freeReg (hc08_reg_a);
4321 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4323 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4324 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4325 freeAsmop (result, NULL, ic, TRUE);
4329 /*-----------------------------------------------------------------*/
4330 /* genOrOp - for || operation */
4331 /*-----------------------------------------------------------------*/
4333 genOrOp (iCode * ic)
4335 operand *left, *right, *result;
4336 symbol *tlbl, *tlbl0;
4338 D(emitcode ("; genOrOp",""));
4340 /* note here that || operations that are in an
4341 if statement are taken away by backPatchLabels
4342 only those used in arthmetic operations remain */
4343 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4344 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4345 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4347 tlbl = newiTempLabel (NULL);
4348 tlbl0 = newiTempLabel (NULL);
4350 asmopToBool (AOP (left), FALSE);
4351 emitBranch ("bne", tlbl0);
4352 asmopToBool (AOP (right), FALSE);
4353 emitBranch ("bne", tlbl0);
4354 loadRegFromConst (hc08_reg_a,zero);
4355 emitBranch ("bra", tlbl);
4357 loadRegFromConst (hc08_reg_a,one);
4360 hc08_useReg (hc08_reg_a);
4361 hc08_freeReg (hc08_reg_a);
4363 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4366 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4367 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4368 freeAsmop (result, NULL, ic, TRUE);
4371 /*-----------------------------------------------------------------*/
4372 /* isLiteralBit - test if lit == 2^n */
4373 /*-----------------------------------------------------------------*/
4375 isLiteralBit (unsigned long lit)
4377 unsigned long pw[32] =
4378 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4379 0x100L, 0x200L, 0x400L, 0x800L,
4380 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4381 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4382 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4383 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4384 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4387 for (idx = 0; idx < 32; idx++)
4394 /*-----------------------------------------------------------------*/
4395 /* continueIfTrue - */
4396 /*-----------------------------------------------------------------*/
4398 continueIfTrue (iCode * ic)
4401 emitBranch ("jmp", IC_TRUE (ic));
4405 /*-----------------------------------------------------------------*/
4407 /*-----------------------------------------------------------------*/
4409 jumpIfTrue (iCode * ic)
4412 emitBranch ("jmp", IC_FALSE (ic));
4416 /*-----------------------------------------------------------------*/
4417 /* jmpTrueOrFalse - */
4418 /*-----------------------------------------------------------------*/
4420 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4422 // ugly but optimized by peephole
4425 symbol *nlbl = newiTempLabel (NULL);
4426 emitBranch ("bra", nlbl);
4428 emitBranch ("jmp", IC_TRUE (ic));
4433 emitBranch ("jmp", IC_FALSE (ic));
4440 /*-----------------------------------------------------------------*/
4441 /* genAnd - code for and */
4442 /*-----------------------------------------------------------------*/
4444 genAnd (iCode * ic, iCode * ifx)
4446 operand *left, *right, *result;
4447 int size, offset = 0;
4448 unsigned long lit = 0L;
4449 unsigned long litinv;
4455 D(emitcode ("; genAnd",""));
4457 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4458 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4459 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4462 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4464 AOP_TYPE (left), AOP_TYPE (right));
4465 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4467 AOP_SIZE (left), AOP_SIZE (right));
4470 /* if left is a literal & right is not then exchange them */
4471 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4473 operand *tmp = right;
4478 /* if left is accumulator & right is not then exchange them */
4479 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4481 operand *tmp = right;
4486 size = AOP_SIZE (result);
4488 if (AOP_TYPE (right) == AOP_LIT)
4490 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4491 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4493 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4494 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4496 int bitpos = isLiteralBit(litinv)-1;
4497 emitcode ("bclr","#%d,%s",bitpos & 7,
4498 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4506 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4507 if ((AOP_TYPE (right) != AOP_LIT)
4508 || (((lit >> (offset*8)) & 0xff) != 0xff))
4509 accopWithAop ("and", AOP (right), offset);
4510 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4511 hc08_freeReg( hc08_reg_a);
4515 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4517 freeAsmop (result, NULL, ic, TRUE);
4520 /*-----------------------------------------------------------------*/
4521 /* genOr - code for or */
4522 /*-----------------------------------------------------------------*/
4524 genOr (iCode * ic, iCode * ifx)
4526 operand *left, *right, *result;
4527 int size, offset = 0;
4528 unsigned long lit = 0L;
4530 D(emitcode ("; genOr",""));
4532 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4533 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4534 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4537 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4539 AOP_TYPE (left), AOP_TYPE (right));
4540 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4542 AOP_SIZE (left), AOP_SIZE (right));
4545 /* if left is a literal & right is not then exchange them */
4546 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4548 operand *tmp = right;
4553 /* if left is accumulator & right is not then exchange them */
4554 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4556 operand *tmp = right;
4561 /* if right is bit then exchange them */
4562 if (AOP_TYPE (right) == AOP_CRY &&
4563 AOP_TYPE (left) != AOP_CRY)
4565 operand *tmp = right;
4569 if (AOP_TYPE (right) == AOP_LIT)
4570 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4572 size = AOP_SIZE (result);
4574 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4575 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4576 (AOP_TYPE (left) == AOP_DIR))
4578 int bitpos = isLiteralBit(lit)-1;
4579 emitcode ("bset","#%d,%s",bitpos & 7,
4580 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4589 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4590 accopWithAop ("ora", AOP (right), offset);
4591 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4592 hc08_freeReg( hc08_reg_a);
4597 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4598 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4599 freeAsmop (result, NULL, ic, TRUE);
4602 /*-----------------------------------------------------------------*/
4603 /* genXor - code for xclusive or */
4604 /*-----------------------------------------------------------------*/
4606 genXor (iCode * ic, iCode * ifx)
4608 operand *left, *right, *result;
4609 int size, offset = 0;
4610 unsigned long lit = 0L;
4612 D(emitcode ("; genXor",""));
4614 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4615 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4616 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4619 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4621 AOP_TYPE (left), AOP_TYPE (right));
4622 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4624 AOP_SIZE (left), AOP_SIZE (right));
4627 /* if left is a literal & right is not ||
4628 if left needs acc & right does not */
4629 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4631 operand *tmp = right;
4636 /* if left is accumulator & right is not then exchange them */
4637 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4639 operand *tmp = right;
4644 /* if right is bit then exchange them */
4645 if (AOP_TYPE (right) == AOP_CRY &&
4646 AOP_TYPE (left) != AOP_CRY)
4648 operand *tmp = right;
4652 if (AOP_TYPE (right) == AOP_LIT)
4653 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4655 size = AOP_SIZE (result);
4659 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4660 accopWithAop ("eor", AOP (right), offset);
4661 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4662 hc08_freeReg( hc08_reg_a);
4667 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4668 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4669 freeAsmop (result, NULL, ic, TRUE);
4673 emitinline (iCode * ic, char *inlin)
4679 symbol *sym, *tempsym;
4688 while (isalnum(*inlin) || (*inlin == '_'))
4692 //printf("Found possible symbol '%s'\n",symname);
4693 tempsym = newSymbol (symname, ic->level);
4694 tempsym->block = ic->block;
4695 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4704 aop = aopForSym (ic, sym, FALSE);
4705 l = aopAdrStr (aop, aop->size - 1, TRUE);
4709 if (!sym->allocreq && !sym->ismyparm)
4711 werror (E_ID_UNDEF, sym->name);
4713 " Add 'volatile' to the variable declaration so that it\n"
4714 " can be referenced within inline assembly");
4716 //printf("Replacing with '%s'\n",l);
4720 if ((2+bp-buffer)>sizeof(buffer))
4729 if ((2+bp-buffer)>sizeof(buffer))
4736 if ((2+bp-buffer)>sizeof(buffer))
4737 fprintf(stderr, "Inline assembly buffer overflow\n");
4739 //printf("%s\n",buffer);
4740 emitcode (buffer,"");
4744 /*-----------------------------------------------------------------*/
4745 /* genInline - write the inline code out */
4746 /*-----------------------------------------------------------------*/
4748 genInline (iCode * ic)
4750 char *buffer, *bp, *bp1;
4752 D(emitcode ("; genInline",""));
4754 _G.inLine += (!options.asmpeep);
4756 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4757 strcpy (buffer, IC_INLINE (ic));
4759 /* emit each line as a code */
4765 /* emitcode (bp1, ""); */
4766 emitinline (ic, bp1);
4785 /* emitcode (bp1, ""); */
4786 emitinline (ic, bp1);
4788 /* emitcode("",buffer); */
4789 _G.inLine -= (!options.asmpeep);
4792 /*-----------------------------------------------------------------*/
4793 /* genRRC - rotate right with carry */
4794 /*-----------------------------------------------------------------*/
4798 operand *left, *result;
4799 int size, offset = 0;
4800 bool needpula = FALSE;
4801 bool resultInA = FALSE;
4804 D(emitcode ("; genRRC",""));
4806 /* rotate right with carry */
4807 left = IC_LEFT (ic);
4808 result = IC_RESULT (ic);
4809 aopOp (left, ic, FALSE);
4810 aopOp (result, ic, FALSE);
4812 if ((AOP_TYPE (result) == AOP_REG)
4813 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4816 size = AOP_SIZE (result);
4820 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4824 rmwWithAop (shift, AOP (result), offset--);
4832 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4833 rmwWithReg (shift, hc08_reg_a);
4834 storeRegToAop (hc08_reg_a, AOP (result), offset--);
4835 hc08_freeReg (hc08_reg_a);
4840 if ((!hc08_reg_a->isFree) || resultInA)
4842 pushReg (hc08_reg_a, TRUE);
4846 /* now we need to put the carry into the
4847 highest order byte of the result */
4848 offset = AOP_SIZE (result) - 1;
4849 emitcode ("clra","");
4850 emitcode ("rora","");
4851 hc08_dirtyReg (hc08_reg_a, FALSE);
4854 emitcode ("ora", "1,s");
4855 emitcode ("ais", "#1");
4856 hc08_dirtyReg (hc08_reg_a, FALSE);
4860 accopWithAop ("ora", AOP (result), offset);
4861 storeRegToAop (hc08_reg_a, AOP (result), offset);
4863 pullOrFreeReg (hc08_reg_a, needpula);
4865 freeAsmop (left, NULL, ic, TRUE);
4866 freeAsmop (result, NULL, ic, TRUE);
4869 /*-----------------------------------------------------------------*/
4870 /* genRLC - generate code for rotate left with carry */
4871 /*-----------------------------------------------------------------*/
4875 operand *left, *result;
4876 int size, offset = 0;
4878 bool resultInA = FALSE;
4879 bool needpula = FALSE;
4881 D(emitcode ("; genRLC",""));
4883 /* rotate right with carry */
4884 left = IC_LEFT (ic);
4885 result = IC_RESULT (ic);
4886 aopOp (left, ic, FALSE);
4887 aopOp (result, ic, FALSE);
4889 if ((AOP_TYPE (result) == AOP_REG)
4890 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4893 size = AOP_SIZE (result);
4897 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4901 rmwWithAop (shift, AOP (result), offset--);
4909 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4910 rmwWithReg (shift, hc08_reg_a);
4911 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4912 hc08_freeReg (hc08_reg_a);
4917 if ((!hc08_reg_a->isFree) || resultInA)
4919 pushReg (hc08_reg_a, TRUE);
4923 /* now we need to put the carry into the
4924 lowest order byte of the result */
4926 emitcode ("clra","");
4927 emitcode ("rola","");
4928 hc08_dirtyReg (hc08_reg_a, FALSE);
4931 emitcode ("ora", "1,s");
4932 emitcode ("ais", "#1");
4933 hc08_dirtyReg (hc08_reg_a, FALSE);
4937 accopWithAop ("ora", AOP (result), offset);
4938 storeRegToAop (hc08_reg_a, AOP (result), offset);
4940 pullOrFreeReg (hc08_reg_a, needpula);
4942 freeAsmop (left, NULL, ic, TRUE);
4943 freeAsmop (result, NULL, ic, TRUE);
4946 /*-----------------------------------------------------------------*/
4947 /* genGetHbit - generates code get highest order bit */
4948 /*-----------------------------------------------------------------*/
4950 genGetHbit (iCode * ic)
4952 operand *left, *result;
4954 D(emitcode ("; genGetHbit",""));
4956 left = IC_LEFT (ic);
4957 result = IC_RESULT (ic);
4958 aopOp (left, ic, FALSE);
4959 aopOp (result, ic, FALSE);
4961 /* get the highest order byte into a */
4962 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
4963 emitcode ("rola", "");
4964 emitcode ("clra", "");
4965 emitcode ("rola", "");
4966 hc08_dirtyReg (hc08_reg_a, FALSE);
4967 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4969 freeAsmop (left, NULL, ic, TRUE);
4970 freeAsmop (result, NULL, ic, TRUE);
4974 /*-----------------------------------------------------------------*/
4975 /* AccRol - rotate left accumulator by known count */
4976 /*-----------------------------------------------------------------*/
4978 AccRol (int shCount)
4980 shCount &= 0x0007; // shCount : 0..7
4987 emitcode ("rola", ""); /* 1 cycle */
4990 emitcode ("rola", ""); /* 1 cycle */
4991 emitcode ("rola", ""); /* 1 cycle */
4994 emitcode ("nsa", "");
4995 emitcode ("rora", "");
4998 emitcode ("nsa", ""); /* 3 cycles */
5001 emitcode ("nsa", ""); /* 3 cycles */
5002 emitcode ("rola", ""); /* 1 cycle */
5005 emitcode ("nsa", ""); /* 3 cycles */
5006 emitcode ("rola", ""); /* 1 cycle */
5007 emitcode ("rola", ""); /* 1 cycle */
5010 emitcode ("nsa", ""); /* 3 cycles */
5011 emitcode ("rola", ""); /* 1 cycle */
5012 emitcode ("rola", ""); /* 1 cycle */
5013 emitcode ("rola", ""); /* 1 cycle */
5020 /*-----------------------------------------------------------------*/
5021 /* AccLsh - left shift accumulator by known count */
5022 /*-----------------------------------------------------------------*/
5024 AccLsh (int shCount)
5028 shCount &= 0x0007; // shCount : 0..7
5030 /* Shift counts of 4 and 5 are currently optimized for code size. */
5031 /* Falling through to the unrolled loop would be optimal for code speed. */
5032 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5036 accopWithMisc ("nsa", "");
5037 accopWithMisc ("and", "#0xf0");
5038 /* total: 5 cycles, 3 bytes */
5041 accopWithMisc ("nsa", "");
5042 accopWithMisc ("and", "#0xf0");
5043 accopWithMisc ("lsla", "");
5044 /* total: 6 cycles, 4 bytes */
5047 accopWithMisc ("rora", "");
5048 accopWithMisc ("rora", "");
5049 accopWithMisc ("rora", "");
5050 accopWithMisc ("and", "#0xc0");
5051 /* total: 5 cycles, 5 bytes */
5054 accopWithMisc ("rora", "");
5055 accopWithMisc ("clra", "");
5056 accopWithMisc ("rora", "");
5057 /* total: 3 cycles, 3 bytes */
5061 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5062 /* the fastest (shCount<6) and shortest (shCount<4). */
5063 for (i=0;i<shCount;i++)
5064 accopWithMisc ("lsla", "");
5068 /*-----------------------------------------------------------------*/
5069 /* AccSRsh - signed right shift accumulator by known count */
5070 /*-----------------------------------------------------------------*/
5072 AccSRsh (int shCount)
5076 shCount &= 0x0007; // shCount : 0..7
5080 accopWithMisc ("rola", "");
5081 accopWithMisc ("clra", "");
5082 accopWithMisc ("sbc", zero);
5083 /* total: 4 cycles, 4 bytes */
5087 for (i=0;i<shCount;i++)
5088 accopWithMisc ("asra", "");
5091 /*-----------------------------------------------------------------*/
5092 /* AccRsh - right shift accumulator by known count */
5093 /*-----------------------------------------------------------------*/
5095 AccRsh (int shCount, bool sign)
5105 shCount &= 0x0007; // shCount : 0..7
5107 /* Shift counts of 4 and 5 are currently optimized for code size. */
5108 /* Falling through to the unrolled loop would be optimal for code speed. */
5109 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5113 accopWithMisc ("nsa", "");
5114 accopWithMisc ("and", "#0x0f");
5115 /* total: 5 cycles, 3 bytes */
5118 accopWithMisc ("nsa", "");
5119 accopWithMisc ("and", "#0x0f");
5120 accopWithMisc ("lsra", "");
5121 /* total: 6 cycles, 4 bytes */
5124 accopWithMisc ("rola", "");
5125 accopWithMisc ("rola", "");
5126 accopWithMisc ("rola", "");
5127 accopWithMisc ("and", "#0x03");
5128 /* total: 5 cycles, 5 bytes */
5131 accopWithMisc ("rola", "");
5132 accopWithMisc ("clra", "");
5133 accopWithMisc ("rola", "");
5134 /* total: 3 cycles, 3 bytes */
5138 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5139 /* the fastest (shCount<6) and shortest (shCount<4). */
5140 for (i=0;i<shCount;i++)
5141 accopWithMisc ("lsra", "");
5145 /*-----------------------------------------------------------------*/
5146 /* XAccLsh - left shift register pair XA by known count */
5147 /*-----------------------------------------------------------------*/
5149 XAccLsh (int shCount)
5153 shCount &= 0x000f; // shCount : 0..15
5158 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5159 loadRegFromConst (hc08_reg_a, zero);
5163 /* if we can beat 2n cycles or bytes for some special case, do it here */
5167 /* bytes cycles reg x reg a carry
5168 ** abcd efgh ijkl mnop ?
5169 ** lsrx 1 1 0abc defg ijkl mnop h
5170 ** rora 1 1 0abc defg hijk lmno p
5171 ** tax 1 1 hijk lmno hijk lmno p
5172 ** clra 1 1 hijk lmno 0000 0000 p
5173 ** rora 1 1 hijk lmno p000 0000 0
5174 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5176 rmwWithReg ("lsr", hc08_reg_x);
5177 rmwWithReg ("ror", hc08_reg_a);
5178 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5179 loadRegFromConst (hc08_reg_a, zero);
5180 rmwWithReg ("ror", hc08_reg_a);
5187 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5188 /* the fastest and shortest. */
5189 for (i=0;i<shCount;i++)
5191 rmwWithReg ("lsl", hc08_reg_a);
5192 rmwWithReg ("rol", hc08_reg_x);
5196 /*-----------------------------------------------------------------*/
5197 /* XAccSRsh - signed right shift register pair XA by known count */
5198 /*-----------------------------------------------------------------*/
5200 XAccSRsh (int shCount)
5204 shCount &= 0x000f; // shCount : 0..7
5206 /* if we can beat 2n cycles or bytes for some special case, do it here */
5210 /* bytes cycles reg x reg a carry
5211 ** abcd efgh ijkl mnop ?
5212 ** lslx 1 1 bcde fgh0 ijkl mnop a
5213 ** clra 1 1 bcde fgh0 0000 0000 a
5214 ** rola 1 1 bcde fgh0 0000 000a 0
5215 ** nega 1 1 bcde fgh0 aaaa aaaa a
5216 ** tax 1 1 aaaa aaaa aaaa aaaa a
5217 ** total: 5 cycles, 5 bytes
5219 rmwWithReg ("lsl", hc08_reg_x);
5220 loadRegFromConst (hc08_reg_a, zero);
5221 rmwWithReg ("rol", hc08_reg_a);
5222 rmwWithReg ("neg", hc08_reg_a);
5223 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5233 /* bytes cycles reg x reg a carry
5234 ** abcd efgh ijkl mnop ?
5235 ** txa 1 1 abcd efgh abcd efgh ?
5236 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5237 ** lsla 1 1 abcd efgh ???? ???? a
5238 ** clrx 1 1 0000 0000 ???? ???? a
5239 ** rolx 1 1 0000 000a ???? ???? 0
5240 ** negx 1 1 aaaa aaaa ???? ???? a
5241 ** rora 1 1 aaaa aaaa LSBresult 0
5242 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5244 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5245 AccSRsh (shCount-8);
5246 rmwWithReg ("lsl", hc08_reg_a);
5247 loadRegFromConst (hc08_reg_x, zero);
5248 rmwWithReg ("rol", hc08_reg_x);
5249 rmwWithReg ("neg", hc08_reg_x);
5250 rmwWithReg ("ror", hc08_reg_a);
5257 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5258 /* the fastest and shortest. */
5259 for (i=0;i<shCount;i++)
5261 rmwWithReg ("asr", hc08_reg_x);
5262 rmwWithReg ("ror", hc08_reg_a);
5266 /*-----------------------------------------------------------------*/
5267 /* XAccRsh - right shift register pair XA by known count */
5268 /*-----------------------------------------------------------------*/
5270 XAccRsh (int shCount, bool sign)
5280 shCount &= 0x000f; // shCount : 0..7
5282 /* if we can beat 2n cycles or bytes for some special case, do it here */
5286 /* bytes cycles reg x reg a carry
5287 ** abcd efgh ijkl mnop ?
5288 ** clra 1 1 abcd efgh 0000 0000 a
5289 ** lslx 1 1 bcde fgh0 0000 0000 a
5290 ** rola 1 1 bcde fgh0 0000 000a 0
5291 ** clrx 1 1 0000 0000 0000 000a 0
5292 ** total: 4 cycles, 4 bytes
5294 loadRegFromConst (hc08_reg_x, zero);
5295 rmwWithReg ("lsl", hc08_reg_x);
5296 rmwWithReg ("rol", hc08_reg_a);
5297 loadRegFromConst (hc08_reg_a, zero);
5301 /* bytes cycles reg x reg a carry
5302 ** abcd efgh ijkl mnop ?
5303 ** clra 1 1 abcd efgh 0000 0000 a
5304 ** lslx 1 1 bcde fgh0 0000 0000 a
5305 ** rola 1 1 bcde fgh0 0000 000a 0
5306 ** lslx 1 1 cdef gh00 0000 000a b
5307 ** rola 1 1 cdef gh00 0000 00ab 0
5308 ** clrx 1 1 0000 0000 0000 000a 0
5309 ** total: 6 cycles, 6 bytes
5311 loadRegFromConst (hc08_reg_x, zero);
5312 rmwWithReg ("lsl", hc08_reg_x);
5313 rmwWithReg ("rol", hc08_reg_a);
5314 rmwWithReg ("lsl", hc08_reg_x);
5315 rmwWithReg ("rol", hc08_reg_a);
5316 loadRegFromConst (hc08_reg_a, zero);
5325 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5326 AccRsh (shCount-8, FALSE);
5327 loadRegFromConst (hc08_reg_x, zero);
5331 /* bytes cycles reg x reg a carry
5332 ** abcd efgh ijkl mnop ?
5333 ** lsla 1 1 abcd efgh jklm nop0 i
5334 ** txa 1 1 abcd efgh abcd efgh i
5335 ** rola 1 1 abcd efgh bcde fghi a
5336 ** clrx 1 1 0000 0000 bcde fghi a
5337 ** rolx 1 1 0000 000a bcde fghi 0
5338 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5340 rmwWithReg ("lsl", hc08_reg_a);
5341 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5342 rmwWithReg ("rol", hc08_reg_a);
5343 loadRegFromConst (hc08_reg_x, zero);
5344 rmwWithReg ("rol", hc08_reg_x);
5347 /* bytes cycles reg x reg a carry
5348 ** abcd efgh ijkl mnop ?
5349 ** lsla 1 1 abcd efgh jklm nop0 i
5350 ** rolx 1 1 bcde fghi jklm nop0 a
5351 ** rola 1 1 bcde fghi klmn op0a j
5352 ** rolx 1 1 cdef ghij klmn op0a b
5353 ** rola 1 1 cdef ghij lmno p0ab k
5354 ** and #3 2 2 cdef ghij 0000 00ab k
5355 ** psha 1 2 cdef ghij 0000 00ab k
5356 ** txa 1 1 cdef ghij cdef ghij k
5357 ** pula 1 2 0000 00ab cdef ghij k
5358 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5364 /* lslx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5365 /* the fastest and shortest. */
5366 for (i=0;i<shCount;i++)
5368 rmwWithReg ("lsl", hc08_reg_x);
5369 rmwWithReg ("rol", hc08_reg_a);
5376 /*-----------------------------------------------------------------*/
5377 /* shiftR1Left2Result - shift right one byte from left to result */
5378 /*-----------------------------------------------------------------*/
5380 shiftR1Left2Result (operand * left, int offl,
5381 operand * result, int offr,
5382 int shCount, int sign)
5384 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5385 /* shift right accumulator */
5386 AccRsh (shCount, sign);
5387 storeRegToAop (hc08_reg_a, AOP (result), offr);
5391 /*-----------------------------------------------------------------*/
5392 /* shiftL1Left2Result - shift left one byte from left to result */
5393 /*-----------------------------------------------------------------*/
5395 shiftL1Left2Result (operand * left, int offl,
5396 operand * result, int offr, int shCount)
5398 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5399 /* shift left accumulator */
5401 storeRegToAop (hc08_reg_a, AOP (result), offr);
5404 /*-----------------------------------------------------------------*/
5405 /* movLeft2Result - move byte from left to result */
5406 /*-----------------------------------------------------------------*/
5408 movLeft2Result (operand * left, int offl,
5409 operand * result, int offr, int sign)
5411 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5413 transferAopAop (AOP (left), offl, AOP (result), offr);
5418 /*-----------------------------------------------------------------*/
5419 /* AccAXRsh1 - right shift 0->a:x->c by 1 */
5420 /*-----------------------------------------------------------------*/
5424 emitcode ("lsra", "");
5425 emitcode ("ror", "%s", x);
5429 /*-----------------------------------------------------------------*/
5430 /* AccAXRshS1 - signed right shift s->a:x->c by 1 */
5431 /*-----------------------------------------------------------------*/
5433 AccAXRshS1 (char *x)
5435 emitcode ("asra", "");
5436 emitcode ("ror", "%s", x);
5439 /*-----------------------------------------------------------------*/
5440 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5441 /*-----------------------------------------------------------------*/
5445 emitcode ("rol", "%s", x);
5446 emitcode ("rola", "");
5449 /*-----------------------------------------------------------------*/
5450 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5451 /*-----------------------------------------------------------------*/
5455 emitcode ("lsl", "%s", x);
5456 emitcode ("rola", "");
5459 /*-----------------------------------------------------------------*/
5460 /* AccAXLsh - left shift a:x by known count (0..7) */
5461 /*-----------------------------------------------------------------*/
5463 AccAXLsh (char *x, int shCount)
5467 for (i=0;i<shCount;i++) {
5472 /*-----------------------------------------------------------------*/
5473 /* AccAXRsh - right shift a:x known count (0..7) */
5474 /*-----------------------------------------------------------------*/
5476 AccAXRsh (char *x, int shCount)
5480 for (i=0;i<shCount;i++) {
5486 /*-----------------------------------------------------------------*/
5487 /* AccAXRshS - right shift signed a:x known count (0..7) */
5488 /*-----------------------------------------------------------------*/
5490 AccAXRshS (char *x, int shCount)
5494 for (i=0;i<shCount;i++) {
5499 /*-----------------------------------------------------------------*/
5500 /* shiftL2Left2Result - shift left two bytes from left to result */
5501 /*-----------------------------------------------------------------*/
5503 shiftL2Left2Result (operand * left, int offl,
5504 operand * result, int offr, int shCount)
5507 bool needpula = FALSE;
5508 bool needpulx = FALSE;
5510 needpula = pushRegIfUsed (hc08_reg_a);
5511 needpulx = pushRegIfUsed (hc08_reg_x);
5513 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5518 rmwWithReg ("lsr", hc08_reg_x);
5519 rmwWithReg ("ror", hc08_reg_a);
5520 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5521 rmwWithReg ("clr", hc08_reg_a);
5522 rmwWithReg ("ror", hc08_reg_a);
5525 for (i=0; i<shCount; i++)
5527 rmwWithReg ("lsl", hc08_reg_a);
5528 rmwWithReg ("rol", hc08_reg_x);
5531 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5533 pullOrFreeReg (hc08_reg_x, needpulx);
5534 pullOrFreeReg (hc08_reg_a, needpula);
5540 /*-----------------------------------------------------------------*/
5541 /* shiftR2Left2Result - shift right two bytes from left to result */
5542 /*-----------------------------------------------------------------*/
5544 shiftR2Left2Result (operand * left, int offl,
5545 operand * result, int offr,
5546 int shCount, int sign)
5549 bool needpula = FALSE;
5550 bool needpulx = FALSE;
5552 needpula = pushRegIfUsed (hc08_reg_a);
5553 needpulx = pushRegIfUsed (hc08_reg_x);
5555 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5556 for (i=0; i<shCount; i++)
5559 rmwWithReg ("asr", hc08_reg_x);
5561 rmwWithReg ("lsr", hc08_reg_x);
5562 rmwWithReg ("ror", hc08_reg_a);
5564 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5566 pullOrFreeReg (hc08_reg_x, needpulx);
5567 pullOrFreeReg (hc08_reg_a, needpula);
5572 /*-----------------------------------------------------------------*/
5573 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5574 /*-----------------------------------------------------------------*/
5576 shiftLLeftOrResult (operand * left, int offl,
5577 operand * result, int offr, int shCount)
5579 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5580 /* shift left accumulator */
5582 /* or with result */
5583 accopWithAop ("ora", AOP (result), offr);
5584 /* back to result */
5585 storeRegToAop (hc08_reg_a, AOP (result), offr);
5586 hc08_freeReg (hc08_reg_a);
5590 /*-----------------------------------------------------------------*/
5591 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5592 /*-----------------------------------------------------------------*/
5594 shiftRLeftOrResult (operand * left, int offl,
5595 operand * result, int offr, int shCount)
5597 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5598 /* shift left accumulator */
5599 AccRsh (shCount, FALSE);
5600 /* or with result */
5601 accopWithAop ("ora", AOP (result), offr);
5602 /* back to result */
5603 storeRegToAop (hc08_reg_a, AOP (result), offr);
5604 hc08_freeReg (hc08_reg_a);
5607 /*-----------------------------------------------------------------*/
5608 /* genlshOne - left shift a one byte quantity by known count */
5609 /*-----------------------------------------------------------------*/
5611 genlshOne (operand * result, operand * left, int shCount)
5613 D(emitcode ("; genlshOne",""));
5615 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5618 /*-----------------------------------------------------------------*/
5619 /* genlshTwo - left shift two bytes by known amount != 0 */
5620 /*-----------------------------------------------------------------*/
5622 genlshTwo (operand * result, operand * left, int shCount)
5626 D(emitcode ("; genlshTwo",""));
5628 size = getDataSize (result);
5630 /* if shCount >= 8 */
5638 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5640 movLeft2Result (left, LSB, result, MSB16, 0);
5642 storeConstToAop(zero, AOP (result), LSB);
5645 /* 1 <= shCount <= 7 */
5649 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5651 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5655 /*-----------------------------------------------------------------*/
5656 /* shiftLLong - shift left one long from left to result */
5657 /* offl = LSB or MSB16 */
5658 /*-----------------------------------------------------------------*/
5660 shiftLLong (operand * left, operand * result, int offr)
5663 // int size = AOP_SIZE (result);
5665 bool needpula = FALSE;
5666 bool needpulx = FALSE;
5668 needpula = pushRegIfUsed (hc08_reg_a);
5669 needpulx = pushRegIfUsed (hc08_reg_x);
5671 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5672 rmwWithReg ("lsl", hc08_reg_a);
5673 rmwWithReg ("rol", hc08_reg_x);
5674 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5678 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5679 rmwWithReg ("rol", hc08_reg_a);
5680 rmwWithReg ("rol", hc08_reg_x);
5681 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5683 else if (offr==MSB16)
5685 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5686 rmwWithReg ("rol", hc08_reg_a);
5687 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5690 pullOrFreeReg (hc08_reg_x, needpulx);
5691 pullOrFreeReg (hc08_reg_a, needpula);
5694 /*-----------------------------------------------------------------*/
5695 /* genlshFour - shift four byte by a known amount != 0 */
5696 /*-----------------------------------------------------------------*/
5698 genlshFour (operand * result, operand * left, int shCount)
5702 D(emitcode ("; genlshFour",""));
5704 size = AOP_SIZE (result);
5706 /* TODO: deal with the &result == &left case */
5708 /* if shifting more that 3 bytes */
5713 /* lowest order of left goes to the highest
5714 order of the destination */
5715 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5717 movLeft2Result (left, LSB, result, MSB32, 0);
5718 storeConstToAop (zero, AOP (result), LSB);
5719 storeConstToAop (zero, AOP (result), MSB16);
5720 storeConstToAop (zero, AOP (result), MSB24);
5724 /* more than two bytes */
5725 else if (shCount >= 16)
5727 /* lower order two bytes goes to higher order two bytes */
5729 /* if some more remaining */
5731 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5734 movLeft2Result (left, MSB16, result, MSB32, 0);
5735 movLeft2Result (left, LSB, result, MSB24, 0);
5737 storeConstToAop (zero, AOP (result), LSB);
5738 storeConstToAop (zero, AOP (result), MSB16);
5742 /* if more than 1 byte */
5743 else if (shCount >= 8)
5745 /* lower order three bytes goes to higher order three bytes */
5750 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5752 movLeft2Result (left, LSB, result, MSB16, 0);
5758 movLeft2Result (left, MSB24, result, MSB32, 0);
5759 movLeft2Result (left, MSB16, result, MSB24, 0);
5760 movLeft2Result (left, LSB, result, MSB16, 0);
5761 storeConstToAop (zero, AOP (result), LSB);
5763 else if (shCount == 1)
5764 shiftLLong (left, result, MSB16);
5767 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5768 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5769 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5770 storeConstToAop (zero, AOP (result), LSB);
5775 /* 1 <= shCount <= 7 */
5776 else if (shCount <= 2)
5778 shiftLLong (left, result, LSB);
5780 shiftLLong (result, result, LSB);
5782 /* 3 <= shCount <= 7, optimize */
5785 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5786 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5787 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5791 /*-----------------------------------------------------------------*/
5792 /* genLeftShiftLiteral - left shifting by known count */
5793 /*-----------------------------------------------------------------*/
5795 genLeftShiftLiteral (operand * left,
5800 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5803 D(emitcode ("; genLeftShiftLiteral",""));
5805 freeAsmop (right, NULL, ic, TRUE);
5807 aopOp (left, ic, FALSE);
5808 aopOp (result, ic, FALSE);
5810 // size = getSize (operandType (result));
5811 size = AOP_SIZE (result);
5814 emitcode ("; shift left ", "result %d, left %d", size,
5821 transferAopAop( AOP(left), size, AOP(result), size);
5823 else if (shCount >= (size * 8))
5826 storeConstToAop (zero, AOP (result), size);
5833 genlshOne (result, left, shCount);
5837 genlshTwo (result, left, shCount);
5841 genlshFour (result, left, shCount);
5844 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5845 "*** ack! mystery literal shift!\n");
5849 freeAsmop (left, NULL, ic, TRUE);
5850 freeAsmop (result, NULL, ic, TRUE);
5853 /*-----------------------------------------------------------------*/
5854 /* genLeftShift - generates code for left shifting */
5855 /*-----------------------------------------------------------------*/
5857 genLeftShift (iCode * ic)
5859 operand *left, *right, *result;
5861 symbol *tlbl, *tlbl1;
5866 D(emitcode ("; genLeftShift",""));
5868 right = IC_RIGHT (ic);
5869 left = IC_LEFT (ic);
5870 result = IC_RESULT (ic);
5872 aopOp (right, ic, FALSE);
5874 /* if the shift count is known then do it
5875 as efficiently as possible */
5876 if (AOP_TYPE (right) == AOP_LIT)
5878 genLeftShiftLiteral (left, right, result, ic);
5882 /* shift count is unknown then we have to form
5883 a loop get the loop count in A : Note: we take
5884 only the lower order byte since shifting
5885 more that 32 bits make no sense anyway, ( the
5886 largest size of an object can be only 32 bits ) */
5888 aopOp (left, ic, FALSE);
5889 aopOp (result, ic, FALSE);
5891 /* now move the left to the result if they are not the
5893 if (!sameRegs (AOP (left), AOP (result)))
5896 size = AOP_SIZE (result);
5900 transferAopAop (AOP (left), offset, AOP (result), offset);
5904 freeAsmop (left, NULL, ic, TRUE);
5906 tlbl = newiTempLabel (NULL);
5907 size = AOP_SIZE (result);
5909 tlbl1 = newiTempLabel (NULL);
5913 loadRegFromAop (reg, AOP (right), 0);
5914 freeAsmop (right, NULL, ic, TRUE);
5915 emitBranch ("beq", tlbl1);
5919 for (offset=0;offset<size;offset++)
5921 rmwWithAop (shift, AOP (result), offset);
5924 rmwWithReg ("dec", reg);
5925 emitBranch ("bne", tlbl);
5929 freeAsmop (result, NULL, ic, TRUE);
5932 /*-----------------------------------------------------------------*/
5933 /* genrshOne - right shift a one byte quantity by known count */
5934 /*-----------------------------------------------------------------*/
5936 genrshOne (operand * result, operand * left,
5937 int shCount, int sign)
5939 D(emitcode ("; genrshOne",""));
5941 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5942 AccRsh (shCount, sign);
5943 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5946 /*-----------------------------------------------------------------*/
5947 /* genrshTwo - right shift two bytes by known amount != 0 */
5948 /*-----------------------------------------------------------------*/
5950 genrshTwo (operand * result, operand * left,
5951 int shCount, int sign)
5953 D(emitcode ("; genrshTwo",""));
5955 /* if shCount >= 8 */
5958 if (shCount || sign)
5960 loadRegFromAop (hc08_reg_a, AOP (left), 1);
5961 AccRsh (shCount-8, sign);
5962 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5966 transferAopAop (AOP (left), 1, AOP (result), 0);
5967 storeConstToAop (zero, AOP (result), 1);
5971 /* 1 <= shCount <= 7 */
5974 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5975 XAccRsh (shCount, sign);
5976 storeRegToAop (hc08_reg_xa, AOP (result), 0);
5980 /*-----------------------------------------------------------------*/
5981 /* shiftRLong - shift right one long from left to result */
5982 /* offl = LSB or MSB16 */
5983 /*-----------------------------------------------------------------*/
5985 shiftRLong (operand * left, int offl,
5986 operand * result, int sign)
5989 // int size = AOP_SIZE (result);
5991 bool needpula = FALSE;
5992 bool needpulx = FALSE;
5994 needpula = pushRegIfUsed (hc08_reg_a);
5995 needpulx = pushRegIfUsed (hc08_reg_x);
5999 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6001 rmwWithReg ("asr", hc08_reg_x);
6003 rmwWithReg ("lsr", hc08_reg_x);
6004 rmwWithReg ("rol", hc08_reg_a);
6005 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6007 else if (offl==MSB16)
6009 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6011 rmwWithReg ("asr", hc08_reg_a);
6013 rmwWithReg ("lsr", hc08_reg_a);
6014 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6017 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6018 rmwWithReg ("ror", hc08_reg_x);
6019 rmwWithReg ("ror", hc08_reg_a);
6020 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6023 pullOrFreeReg (hc08_reg_x, needpulx);
6024 pullOrFreeReg (hc08_reg_a, needpula);
6027 /*-----------------------------------------------------------------*/
6028 /* genrshFour - shift four byte by a known amount != 0 */
6029 /*-----------------------------------------------------------------*/
6031 genrshFour (operand * result, operand * left,
6032 int shCount, int sign)
6034 /* TODO: handle cases where left == result */
6036 D(emitcode ("; genrshFour",""));
6038 /* if shifting more that 3 bytes */
6041 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6042 AccRsh (shCount-24, sign);
6043 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6046 else if (shCount >= 16)
6048 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6049 XAccRsh (shCount-16, sign);
6050 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6053 else if (shCount >= 8)
6056 shiftRLong (left, MSB16, result, sign);
6057 else if (shCount == 8)
6059 transferAopAop (AOP (left), 1, AOP (result), 0);
6060 transferAopAop (AOP (left), 2, AOP (result), 1);
6061 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6062 storeRegToAop (hc08_reg_a, AOP (result), 2);
6063 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6065 else if (shCount == 9)
6067 shiftRLong (left, MSB16, result, sign);
6071 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6072 XAccRsh (shCount-8, FALSE);
6073 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6074 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6075 loadRegFromConst (hc08_reg_a, zero);
6076 XAccRsh (shCount-8, sign);
6077 accopWithAop ("ora", AOP (result), 1);
6078 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6082 { /* 1 <= shCount <= 7 */
6085 shiftRLong (left, LSB, result, sign);
6089 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6090 XAccRsh (shCount, FALSE);
6091 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6092 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6094 accopWithAop ("ora", AOP (result), 1);
6095 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6096 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6097 XAccRsh (shCount, sign);
6098 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6103 /*-----------------------------------------------------------------*/
6104 /* genRightShiftLiteral - right shifting by known count */
6105 /*-----------------------------------------------------------------*/
6107 genRightShiftLiteral (operand * left,
6113 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6116 D(emitcode ("; genRightShiftLiteral",""));
6118 freeAsmop (right, NULL, ic, TRUE);
6120 aopOp (left, ic, FALSE);
6121 aopOp (result, ic, FALSE);
6124 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6128 size = getDataSize (left);
6129 /* test the LEFT size !!! */
6131 /* I suppose that the left size >= result size */
6134 size = getDataSize (result);
6136 transferAopAop (AOP (left), size, AOP(result), size);
6138 else if (shCount >= (size * 8))
6141 /* get sign in acc.7 */
6142 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6144 addSign (result, LSB, sign);
6151 genrshOne (result, left, shCount, sign);
6155 genrshTwo (result, left, shCount, sign);
6159 genrshFour (result, left, shCount, sign);
6165 freeAsmop (left, NULL, ic, TRUE);
6166 freeAsmop (result, NULL, ic, TRUE);
6170 /*-----------------------------------------------------------------*/
6171 /* genRightShift - generate code for right shifting */
6172 /*-----------------------------------------------------------------*/
6174 genRightShift (iCode * ic)
6176 operand *right, *left, *result;
6180 symbol *tlbl, *tlbl1;
6184 D(emitcode ("; genRightShift",""));
6186 /* if signed then we do it the hard way preserve the
6187 sign bit moving it inwards */
6188 retype = getSpec (operandType (IC_RESULT (ic)));
6189 sign = !SPEC_USIGN (retype);
6191 /* signed & unsigned types are treated the same : i.e. the
6192 signed is NOT propagated inwards : quoting from the
6193 ANSI - standard : "for E1 >> E2, is equivalent to division
6194 by 2**E2 if unsigned or if it has a non-negative value,
6195 otherwise the result is implementation defined ", MY definition
6196 is that the sign does not get propagated */
6198 right = IC_RIGHT (ic);
6199 left = IC_LEFT (ic);
6200 result = IC_RESULT (ic);
6202 aopOp (right, ic, FALSE);
6204 /* if the shift count is known then do it
6205 as efficiently as possible */
6206 if (AOP_TYPE (right) == AOP_LIT)
6208 genRightShiftLiteral (left, right, result, ic, sign);
6212 /* shift count is unknown then we have to form
6213 a loop get the loop count in X : Note: we take
6214 only the lower order byte since shifting
6215 more that 32 bits make no sense anyway, ( the
6216 largest size of an object can be only 32 bits ) */
6218 aopOp (left, ic, FALSE);
6219 aopOp (result, ic, FALSE);
6221 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6222 AOP (result) = forceStackedAop (AOP (result));
6224 size = AOP_SIZE (result);
6228 transferAopAop (AOP (left), offset, AOP (result), offset);
6232 tlbl = newiTempLabel (NULL);
6233 size = AOP_SIZE (result);
6235 tlbl1 = newiTempLabel (NULL);
6237 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6238 emitcode ("tstx", "");
6239 emitcode ("beq", "%05d$", tlbl1->key + 100);
6240 emitcode ("", "%05d$:", tlbl->key + 100);
6241 shift= sign ? "asr" : "lsr";
6242 for (offset=size-1;offset>=0;offset--)
6244 rmwWithAop (shift, AOP (result), offset);
6247 rmwWithReg ("dec", hc08_reg_x);
6248 emitcode ("bne","%05d$", tlbl->key + 100);
6249 emitcode ("", "%05d$:", tlbl1->key + 100);
6251 freeAsmop (result, NULL, ic, TRUE);
6252 freeAsmop (left, NULL, ic, TRUE);
6253 freeAsmop (right, NULL, ic, TRUE);
6256 /*-----------------------------------------------------------------*/
6257 /* genUnpackBits - generates code for unpacking bits */
6258 /*-----------------------------------------------------------------*/
6260 genUnpackBits (operand * result)
6262 int offset = 0; /* result byte offset */
6263 int rsize; /* result size */
6264 int rlen = 0; /* remaining bitfield length */
6265 sym_link *etype; /* bitfield type information */
6266 int blen; /* bitfield length */
6267 int bstr; /* bitfield starting bit within byte */
6269 D(emitcode ("; genUnpackBits",""));
6271 etype = getSpec (operandType (result));
6272 rsize = getSize (operandType (result));
6273 blen = SPEC_BLEN (etype);
6274 bstr = SPEC_BSTR (etype);
6276 /* If the bitfield length is less than a byte */
6279 emitcode ("lda", ",x");
6280 hc08_dirtyReg (hc08_reg_a, FALSE);
6281 AccRsh (bstr, FALSE);
6282 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6283 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6287 /* Bit field did not fit in a byte. Copy all
6288 but the partial byte at the end. */
6289 for (rlen=blen;rlen>=8;rlen-=8)
6291 emitcode ("lda", ",x");
6292 hc08_dirtyReg (hc08_reg_a, FALSE);
6293 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6295 emitcode ("aix", "#1");
6298 /* Handle the partial byte at the end */
6301 emitcode ("lda", ",x");
6302 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6303 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6311 storeConstToAop (zero, AOP (result), offset++);
6316 /*-----------------------------------------------------------------*/
6317 /* genDataPointerGet - generates code when ptr offset is known */
6318 /*-----------------------------------------------------------------*/
6320 genDataPointerGet (operand * left,
6324 int size, offset = 0;
6327 D(emitcode ("; genDataPointerGet",""));
6329 aopOp (result, ic, TRUE);
6330 size = AOP_SIZE (result);
6332 derefaop = aopDerefAop (AOP (left));
6333 freeAsmop (left, NULL, ic, TRUE);
6334 derefaop->size = size;
6338 transferAopAop(derefaop, offset, AOP (result), offset);
6342 freeAsmop (NULL, derefaop, ic, TRUE);
6343 freeAsmop (result, NULL, ic, TRUE);
6346 /*-----------------------------------------------------------------*/
6347 /* genNearPointerGet - emitcode for near pointer fetch */
6348 /*-----------------------------------------------------------------*/
6350 genNearPointerGet (operand * left,
6356 sym_link *retype = getSpec (operandType (result));
6358 D(emitcode ("; genNearPointerGet",""));
6360 aopOp (left, ic, FALSE);
6362 /* if left is rematerialisable and
6363 result is not bit variable type and
6364 the left is pointer to data space i.e
6365 lower 128 bytes of space */
6366 if ((AOP_TYPE (left) == AOP_IMMD)
6367 || (AOP_TYPE (left) == AOP_LIT)
6368 /* !IS_BITVAR (retype) */
6369 /* && DCL_TYPE (ltype) == POINTER */ )
6371 genDataPointerGet (left, result, ic);
6375 /* if the operand is already in hx
6376 then we do nothing else we move the value to hx */
6377 if (AOP_TYPE (left) != AOP_STR)
6379 /* if this is remateriazable */
6380 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6381 loadRegFromConst (hc08_reg_h, zero);
6384 /* so hx now contains the address */
6385 aopOp (result, ic, FALSE);
6387 /* if bit then unpack */
6388 if (IS_BITVAR (retype))
6389 genUnpackBits (result);
6392 size = AOP_SIZE (result);
6397 accopWithMisc ("lda", ",x");
6400 rmwWithReg ("inc", hc08_reg_x);
6402 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6403 hc08_freeReg (hc08_reg_a);
6407 freeAsmop (left, NULL, ic, TRUE);
6408 freeAsmop (result, NULL, ic, TRUE);
6410 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6411 aopOp (IC_RESULT (pi), pi, FALSE);
6412 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6413 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6417 hc08_freeReg (hc08_reg_hx);
6422 /*-----------------------------------------------------------------*/
6423 /* genFarPointerGet - get value from far space */
6424 /*-----------------------------------------------------------------*/
6426 genFarPointerGet (operand * left,
6427 operand * result, iCode * ic, iCode * pi)
6430 sym_link *retype = getSpec (operandType (result));
6432 D(emitcode ("; genFarPointerGet",""));
6434 aopOp (left, ic, FALSE);
6436 /* if left is rematerialisable and
6437 result is not bit variable type and
6438 the left is pointer to data space i.e
6439 lower 128 bytes of space */
6440 if (AOP_TYPE (left) == AOP_IMMD &&
6442 /* && DCL_TYPE (ltype) == POINTER */ )
6444 genDataPointerGet (left, result, ic);
6448 /* if the operand is already in hx
6449 then we do nothing else we move the value to hx */
6450 if (AOP_TYPE (left) != AOP_STR)
6452 /* if this is remateriazable */
6453 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6456 /* so hx now contains the address */
6457 aopOp (result, ic, FALSE);
6459 /* if bit then unpack */
6460 if (IS_BITVAR (retype))
6461 genUnpackBits (result);
6464 size = AOP_SIZE (result);
6469 accopWithMisc ("lda", ",x");
6472 emitcode ("aix", "#1");
6473 hc08_dirtyReg (hc08_reg_hx, FALSE);
6475 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6476 hc08_freeReg (hc08_reg_a);
6480 freeAsmop (left, NULL, ic, TRUE);
6481 freeAsmop (result, NULL, ic, TRUE);
6483 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6484 aopOp (IC_RESULT (pi), pi, FALSE);
6485 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6486 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6490 hc08_freeReg (hc08_reg_hx);
6496 /*-----------------------------------------------------------------*/
6497 /* genPointerGet - generate code for pointer get */
6498 /*-----------------------------------------------------------------*/
6500 genPointerGet (iCode * ic, iCode *pi)
6502 operand *left, *result;
6503 sym_link *type, *etype;
6506 D(emitcode ("; genPointerGet",""));
6508 left = IC_LEFT (ic);
6509 result = IC_RESULT (ic);
6511 /* depending on the type of pointer we need to
6512 move it to the correct pointer register */
6513 type = operandType (left);
6514 etype = getSpec (type);
6515 /* if left is of type of pointer then it is simple */
6516 if (IS_PTR (type) && !IS_FUNC (type->next))
6517 p_type = DCL_TYPE (type);
6520 /* we have to go by the storage class */
6521 p_type = PTR_TYPE (SPEC_OCLS (etype));
6524 /* special case when cast remat */
6525 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
6526 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6527 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6528 type = operandType (left);
6529 p_type = DCL_TYPE (type);
6531 /* now that we have the pointer type we assign
6532 the pointer values */
6539 genNearPointerGet (left, result, ic, pi);
6545 genFarPointerGet (left, result, ic, pi);
6552 /*-----------------------------------------------------------------*/
6553 /* genPackBits - generates code for packed bit storage */
6554 /*-----------------------------------------------------------------*/
6556 genPackBits (sym_link * etype,
6559 int offset = 0; /* source byte offset */
6560 int rlen = 0; /* remaining bitfield length */
6561 int blen; /* bitfield length */
6562 int bstr; /* bitfield starting bit within byte */
6563 int litval; /* source literal value (if AOP_LIT) */
6564 unsigned char mask; /* bitmask within current byte */
6566 D(emitcode ("; genPackBits",""));
6568 blen = SPEC_BLEN (etype);
6569 bstr = SPEC_BSTR (etype);
6571 /* If the bitfield length is less than a byte */
6574 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6575 (unsigned char) (0xFF >> (8 - bstr)));
6577 if (AOP_TYPE (right) == AOP_LIT)
6579 /* Case with a bitfield length <8 and literal source
6581 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6583 litval &= (~mask) & 0xff;
6585 emitcode ("lda", ",x");
6586 if ((mask|litval)!=0xff)
6587 emitcode ("and","#0x%02x", mask);
6589 emitcode ("ora","#0x%02x", litval);
6590 hc08_dirtyReg (hc08_reg_a, FALSE);
6591 emitcode ("sta", ",x");
6593 hc08_freeReg (hc08_reg_a);
6597 /* Case with a bitfield length < 8 and arbitrary source
6599 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6600 /* shift and mask source value */
6602 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6603 hc08_dirtyReg (hc08_reg_a, FALSE);
6604 pushReg (hc08_reg_a, TRUE);
6606 emitcode ("lda", ",x");
6607 emitcode ("and", "#0x%02x", mask);
6608 emitcode ("ora", "1,s");
6609 emitcode ("sta", ",x");
6610 pullReg (hc08_reg_a);
6612 hc08_freeReg (hc08_reg_a);
6616 /* Bit length is greater than 7 bits. In this case, copy */
6617 /* all except the partial byte at the end */
6618 for (rlen=blen;rlen>=8;rlen-=8)
6620 if (AOP (right)->type == AOP_DIR)
6622 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6626 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6627 emitcode ("sta", "%d,x", offset);
6632 /* If there was a partial byte at the end */
6635 mask = (((unsigned char) -1 << rlen) & 0xff);
6637 if (AOP_TYPE (right) == AOP_LIT)
6639 /* Case with partial byte and literal source
6641 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6642 litval >>= (blen-rlen);
6643 litval &= (~mask) & 0xff;
6644 emitcode ("lda", "%d,x", offset);
6645 hc08_dirtyReg (hc08_reg_a, FALSE);
6646 if ((mask|litval)!=0xff)
6647 emitcode ("and","#0x%02x", mask);
6649 emitcode ("ora","#0x%02x", litval);
6650 emitcode ("sta", "%d,x", offset);
6651 hc08_dirtyReg (hc08_reg_a, FALSE);
6652 hc08_freeReg (hc08_reg_a);
6656 /* Case with partial byte and arbitrary source
6658 loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6659 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6660 hc08_dirtyReg (hc08_reg_a, FALSE);
6661 pushReg (hc08_reg_a, TRUE);
6663 emitcode ("lda", ",x");
6664 emitcode ("and", "#0x%02x", mask);
6665 emitcode ("ora", "1,s");
6666 emitcode ("sta", ",x");
6669 hc08_freeReg (hc08_reg_a);
6672 /*-----------------------------------------------------------------*/
6673 /* genDataPointerSet - remat pointer to data space */
6674 /*-----------------------------------------------------------------*/
6676 genDataPointerSet (operand * right,
6680 int size, offset = 0;
6683 D(emitcode ("; genDataPointerSet",""));
6685 aopOp (right, ic, FALSE);
6686 size = AOP_SIZE (right);
6688 derefaop = aopDerefAop (AOP (result));
6689 freeAsmop (result, NULL, ic, TRUE);
6690 derefaop->size = size;
6694 transferAopAop (AOP (right), offset, derefaop, offset);
6698 freeAsmop (right, NULL, ic, TRUE);
6699 freeAsmop (NULL, derefaop, ic, TRUE);
6702 /*-----------------------------------------------------------------*/
6703 /* genNearPointerSet - emitcode for near pointer put */
6704 /*-----------------------------------------------------------------*/
6706 genNearPointerSet (operand * right,
6712 sym_link *retype = getSpec (operandType (right));
6713 sym_link *letype = getSpec (operandType (result));
6715 D(emitcode ("; genNearPointerSet",""));
6717 aopOp (result, ic, FALSE);
6719 /* if the result is rematerializable &
6720 in data space & not a bit variable */
6721 if (AOP_TYPE (result) == AOP_IMMD &&
6722 /* DCL_TYPE (ptype) == POINTER && */
6723 !IS_BITVAR (retype) &&
6724 !IS_BITVAR (letype))
6726 genDataPointerSet (right, result, ic);
6730 /* if the operand is already in hx
6731 then we do nothing else we move the value to hx */
6732 if (AOP_TYPE (result) != AOP_STR)
6734 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6735 loadRegFromConst (hc08_reg_h, zero);
6737 /* so hx now contains the address */
6738 aopOp (right, ic, FALSE);
6740 /* if bit then unpack */
6741 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6742 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6745 size = AOP_SIZE (right);
6750 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6751 accopWithMisc ("sta", ",x");
6754 rmwWithReg ("inc", hc08_reg_x);
6756 hc08_freeReg (hc08_reg_a);
6760 freeAsmop (result, NULL, ic, TRUE);
6761 freeAsmop (right, NULL, ic, TRUE);
6763 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6764 aopOp (IC_RESULT (pi), pi, FALSE);
6765 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6766 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6770 hc08_freeReg (hc08_reg_hx);
6775 /*-----------------------------------------------------------------*/
6776 /* genFarPointerSet - set value from far space */
6777 /*-----------------------------------------------------------------*/
6779 genFarPointerSet (operand * right,
6780 operand * result, iCode * ic, iCode * pi)
6783 sym_link *retype = getSpec (operandType (right));
6784 sym_link *letype = getSpec (operandType (result));
6786 D(emitcode ("; genFarPointerSet",""));
6788 aopOp (result, ic, FALSE);
6790 /* if the result is rematerializable &
6791 in data space & not a bit variable */
6792 if (AOP_TYPE (result) == AOP_IMMD &&
6793 /* DCL_TYPE (ptype) == POINTER && */
6794 !IS_BITVAR (retype) &&
6795 !IS_BITVAR (letype))
6797 genDataPointerSet (right, result, ic);
6801 /* if the operand is already in hx
6802 then we do nothing else we move the value to hx */
6803 if (AOP_TYPE (result) != AOP_STR)
6805 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6807 /* so hx now contains the address */
6808 aopOp (right, ic, FALSE);
6810 /* if bit then unpack */
6811 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6812 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6815 size = AOP_SIZE (right);
6820 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6821 accopWithMisc ("sta", ",x");
6824 emitcode ("aix", "#1");
6826 hc08_freeReg (hc08_reg_a);
6830 freeAsmop (result, NULL, ic, TRUE);
6831 freeAsmop (right, NULL, ic, TRUE);
6833 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6834 aopOp (IC_RESULT (pi), pi, FALSE);
6835 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6836 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6840 hc08_freeReg (hc08_reg_hx);
6846 /*-----------------------------------------------------------------*/
6847 /* genPointerSet - stores the value into a pointer location */
6848 /*-----------------------------------------------------------------*/
6850 genPointerSet (iCode * ic, iCode *pi)
6852 operand *right, *result;
6853 sym_link *type, *etype;
6856 D(emitcode ("; genPointerSet",""));
6858 right = IC_RIGHT (ic);
6859 result = IC_RESULT (ic);
6861 /* depending on the type of pointer we need to
6862 move it to the correct pointer register */
6863 type = operandType (result);
6864 etype = getSpec (type);
6865 /* if left is of type of pointer then it is simple */
6866 if (IS_PTR (type) && !IS_FUNC (type->next))
6868 p_type = DCL_TYPE (type);
6872 /* we have to go by the storage class */
6873 p_type = PTR_TYPE (SPEC_OCLS (etype));
6876 /* special case when cast remat */
6877 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
6878 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
6879 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
6880 type = operandType (result);
6881 p_type = DCL_TYPE (type);
6883 /* now that we have the pointer type we assign
6884 the pointer values */
6891 genNearPointerSet (right, result, ic, pi);
6897 genFarPointerSet (right, result, ic, pi);
6901 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6902 "genPointerSet: illegal pointer type");
6907 /*-----------------------------------------------------------------*/
6908 /* genIfx - generate code for Ifx statement */
6909 /*-----------------------------------------------------------------*/
6911 genIfx (iCode * ic, iCode * popIc)
6913 operand *cond = IC_COND (ic);
6916 D(emitcode ("; genIfx",""));
6918 aopOp (cond, ic, FALSE);
6920 /* get the value into acc */
6921 if (AOP_TYPE (cond) != AOP_CRY)
6922 asmopToBool (AOP (cond), FALSE);
6925 /* the result is now in the accumulator */
6926 freeAsmop (cond, NULL, ic, TRUE);
6928 /* if there was something to be popped then do it */
6932 /* if the condition is a bit variable */
6933 if (isbit && IS_ITEMP (cond) &&
6935 genIfxJump (ic, SPIL_LOC (cond)->rname);
6936 else if (isbit && !IS_ITEMP (cond))
6937 genIfxJump (ic, OP_SYMBOL (cond)->rname);
6939 genIfxJump (ic, "a");
6944 /*-----------------------------------------------------------------*/
6945 /* genAddrOf - generates code for address of */
6946 /*-----------------------------------------------------------------*/
6948 genAddrOf (iCode * ic)
6950 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
6953 D(emitcode ("; genAddrOf",""));
6955 aopOp (IC_RESULT (ic), ic, FALSE);
6957 /* if the operand is on the stack then we
6958 need to get the stack offset of this
6962 /* if it has an offset then we need to compute
6964 hc08_useReg (hc08_reg_hx);
6965 emitcode ("tsx", "");
6966 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
6967 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
6968 hc08_freeReg (hc08_reg_hx);
6973 /* object not on stack then we need the name */
6974 size = AOP_SIZE (IC_RESULT (ic));
6979 char s[SDCC_NAME_MAX+10];
6982 sprintf (s, "#%s", sym->rname);
6985 sprintf (s, "#>%s", sym->rname);
6988 sprintf (s, "#(%s >> %d)",
6992 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
6996 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7000 /*-----------------------------------------------------------------*/
7001 /* genAssign - generate code for assignment */
7002 /*-----------------------------------------------------------------*/
7004 genAssign (iCode * ic)
7006 operand *result, *right;
7008 // unsigned long lit = 0L;
7010 D(emitcode("; genAssign",""));
7012 result = IC_RESULT (ic);
7013 right = IC_RIGHT (ic);
7015 /* if they are the same */
7016 if (operandsEqu (result, right)) {
7020 aopOp (right, ic, FALSE);
7021 aopOp (result, ic, TRUE);
7023 /* if they are the same registers */
7024 if (sameRegs (AOP (right), AOP (result)))
7027 if ((AOP_TYPE (right) == AOP_LIT)
7028 && (IS_AOP_HX(AOP(result))))
7030 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7035 size = AOP_SIZE (result);
7040 transferAopAop (AOP (right), offset, AOP (result), offset);
7045 freeAsmop (right, NULL, ic, TRUE);
7046 freeAsmop (result, NULL, ic, TRUE);
7049 /*-----------------------------------------------------------------*/
7050 /* genJumpTab - genrates code for jump table */
7051 /*-----------------------------------------------------------------*/
7053 genJumpTab (iCode * ic)
7058 D(emitcode ("; genJumpTab",""));
7060 aopOp (IC_JTCOND (ic), ic, FALSE);
7061 /* get the condition into accumulator */
7062 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7063 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7064 /* multiply by three */
7065 pushReg (hc08_reg_a, FALSE);
7066 emitcode ("lsla", "");
7067 emitcode ("add","1,s");
7068 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7069 loadRegFromConst (hc08_reg_h, zero);
7071 jtab = newiTempLabel (NULL);
7072 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7073 emitcode ("", "%05d$:", jtab->key + 100);
7074 /* now generate the jump labels */
7075 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7076 jtab = setNextItem (IC_JTLABELS (ic)))
7077 emitcode ("jmp", "%05d$", jtab->key + 100);
7079 hc08_dirtyReg (hc08_reg_a, TRUE);
7080 hc08_dirtyReg (hc08_reg_hx, TRUE);
7083 /*-----------------------------------------------------------------*/
7084 /* genCast - gen code for casting */
7085 /*-----------------------------------------------------------------*/
7087 genCast (iCode * ic)
7089 operand *result = IC_RESULT (ic);
7090 sym_link *ctype = operandType (IC_LEFT (ic));
7091 sym_link *rtype = operandType (IC_RIGHT (ic));
7092 operand *right = IC_RIGHT (ic);
7095 D(emitcode("; genCast",""));
7097 /* if they are equivalent then do nothing */
7098 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7101 aopOp (right, ic, FALSE);
7102 aopOp (result, ic, FALSE);
7105 /* if they are the same size : or less */
7106 if (AOP_SIZE (result) <= AOP_SIZE (right))
7109 /* if they are in the same place */
7111 if (sameRegs (AOP (right), AOP (result)))
7115 /* if they in different places then copy */
7116 size = AOP_SIZE (result);
7120 transferAopAop(AOP (right), offset, AOP (result), offset);
7127 /* if the result is of type pointer */
7132 sym_link *type = operandType (right);
7133 sym_link *etype = getSpec (type);
7135 /* pointer to generic pointer */
7136 if (IS_GENPTR (ctype))
7139 p_type = DCL_TYPE (type);
7142 if (SPEC_SCLS(etype)==S_REGISTER) {
7143 // let's assume it is a generic pointer
7146 /* we have to go by the storage class */
7147 p_type = PTR_TYPE (SPEC_OCLS (etype));
7151 /* the first two bytes are known */
7152 size = GPTRSIZE - 1;
7156 transferAopAop(AOP (right), offset, AOP (result), offset);
7159 /* the last byte depending on type */
7162 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7167 // pointerTypeToGPByte will have bitched.
7171 sprintf(gpValStr, "#0x%d", gpVal);
7172 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7178 /* just copy the pointers */
7179 size = AOP_SIZE (result);
7183 transferAopAop(AOP (right), offset, AOP (result), offset);
7189 /* so we now know that the size of destination is greater
7190 than the size of the source */
7191 /* we move to result for the size of source */
7192 size = AOP_SIZE (right);
7196 transferAopAop(AOP (right), offset, AOP (result), offset);
7200 /* now depending on the sign of the source && destination */
7201 size = AOP_SIZE (result) - AOP_SIZE (right);
7202 /* if unsigned or not an integral type */
7203 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7206 storeConstToAop (zero, AOP (result), offset++);
7210 /* we need to extend the sign :{ */
7211 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7212 accopWithMisc ("rola", "");
7213 accopWithMisc ("clra", "");
7214 accopWithMisc ("sbc", zero);
7216 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7219 /* we are done hurray !!!! */
7222 freeAsmop (right, NULL, ic, TRUE);
7223 freeAsmop (result, NULL, ic, TRUE);
7227 /*-----------------------------------------------------------------*/
7228 /* genDjnz - generate decrement & jump if not zero instrucion */
7229 /*-----------------------------------------------------------------*/
7231 genDjnz (iCode * ic, iCode * ifx)
7237 D(emitcode ("; genDjnz",""));
7239 /* if the if condition has a false label
7240 then we cannot save */
7244 /* if the minus is not of the form
7246 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7247 !IS_OP_LITERAL (IC_RIGHT (ic)))
7250 if (operandLitValue (IC_RIGHT (ic)) != 1)
7253 /* if the size of this greater than one then no
7255 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7257 aopOp (IC_RESULT (ic), ic, FALSE);
7258 if (AOP_SIZE (IC_RESULT (ic))>1)
7260 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7264 /* otherwise we can save BIG */
7265 lbl = newiTempLabel (NULL);
7266 lbl1 = newiTempLabel (NULL);
7269 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7272 emitBranch ("bra", lbl1);
7274 emitBranch ("jmp", IC_TRUE (ifx));
7277 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7282 /*-----------------------------------------------------------------*/
7283 /* genReceive - generate code for a receive iCode */
7284 /*-----------------------------------------------------------------*/
7286 genReceive (iCode * ic)
7290 D(emitcode ("; genReceive",""));
7292 aopOp (IC_RESULT (ic), ic, FALSE);
7293 size = AOP_SIZE (IC_RESULT (ic));
7298 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7299 AOP (IC_RESULT (ic)), offset);
7300 if (hc08_aop_pass[offset]->type == AOP_REG)
7301 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7306 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7309 /*-----------------------------------------------------------------*/
7310 /* genhc08Code - generate code for HC08 based controllers */
7311 /*-----------------------------------------------------------------*/
7313 genhc08Code (iCode * lic)
7318 lineHead = lineCurr = NULL;
7320 /* print the allocation information */
7321 if (allocInfo && currFunc)
7322 printAllocInfo (currFunc, codeOutFile);
7323 /* if debug information required */
7324 if (options.debug && currFunc)
7326 debugFile->writeFunction(currFunc);
7328 if (IS_STATIC (currFunc->etype))
7329 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7331 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7334 /* stack pointer name */
7335 if (options.useXstack)
7340 hc08_aop_pass[0] = newAsmop (AOP_REG);
7341 hc08_aop_pass[0]->size=1;
7342 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7343 hc08_aop_pass[1] = newAsmop (AOP_REG);
7344 hc08_aop_pass[1]->size=1;
7345 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7346 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7347 hc08_aop_pass[2]->size=1;
7348 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7349 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7350 hc08_aop_pass[3]->size=1;
7351 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7353 for (ic = lic; ic; ic = ic->next)
7356 if (ic->lineno && cln != ic->lineno)
7361 emitcode ("", "C$%s$%d$%d$%d ==.",
7362 FileBaseName (ic->filename), ic->lineno,
7363 ic->level, ic->block);
7366 if (!options.noCcodeInAsm) {
7367 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7368 printCLine(ic->filename, ic->lineno));
7372 if (options.iCodeInAsm) {
7376 for (i=0; i<6; i++) {
7377 sprintf (®sInUse[i],
7378 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7381 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7383 /* if the result is marked as
7384 spilt and rematerializable or code for
7385 this has already been generated then
7387 if (resultRemat (ic) || ic->generated)
7395 for (i=A_IDX;i<=XA_IDX;i++)
7397 reg = hc08_regWithIdx(i);
7399 emitcode("","; %s = %s offset %d", reg->name,
7400 aopName(reg->aop), reg->aopofs);
7403 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7405 sym = OP_SYMBOL (IC_LEFT (ic));
7406 if (sym->accuse == ACCUSE_HX)
7408 hc08_reg_h->isFree = FALSE;
7409 hc08_reg_x->isFree = FALSE;
7411 else if (sym->accuse == ACCUSE_XA)
7413 hc08_reg_a->isFree = FALSE;
7415 hc08_reg_x->isFree = FALSE;
7418 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7420 sym = OP_SYMBOL (IC_RIGHT (ic));
7421 if (sym->accuse == ACCUSE_HX)
7423 hc08_reg_h->isFree = FALSE;
7424 hc08_reg_x->isFree = FALSE;
7426 else if (sym->accuse == ACCUSE_XA)
7428 hc08_reg_a->isFree = FALSE;
7430 hc08_reg_x->isFree = FALSE;
7435 /* depending on the operation */
7455 /* IPOP happens only when trying to restore a
7456 spilt live range, if there is an ifx statement
7457 following this pop then the if statement might
7458 be using some of the registers being popped which
7459 would destory the contents of the register so
7460 we need to check for this condition and handle it */
7462 ic->next->op == IFX &&
7463 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7464 genIfx (ic->next, ic);
7482 genEndFunction (ic);
7498 if (!genPointerGetSetOfs (ic))
7503 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7520 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7524 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7531 /* note these two are xlated by algebraic equivalence
7532 during parsing SDCC.y */
7533 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7534 "got '>=' or '<=' shouldn't have come here");
7538 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7550 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7554 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7558 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7585 case GET_VALUE_AT_ADDRESS:
7586 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7590 if (POINTER_SET (ic))
7591 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7617 addSet (&_G.sendSet, ic);
7624 if (!hc08_reg_a->isFree)
7625 emitcode("","; forgot to free a");
7626 if (!hc08_reg_x->isFree)
7627 emitcode("","; forgot to free x");
7628 if (!hc08_reg_h->isFree)
7629 emitcode("","; forgot to free h");
7630 if (!hc08_reg_hx->isFree)
7631 emitcode("","; forgot to free hx");
7632 if (!hc08_reg_xa->isFree)
7633 emitcode("","; forgot to free xa");
7637 /* now we are ready to call the
7638 peep hole optimizer */
7639 if (!options.nopeep)
7640 peepHole (&lineHead);
7642 /* now do the actual printing */
7643 printLine (lineHead, codeOutFile);