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));
2084 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2085 "Bad rIdx in asmToBool");
2093 needpula = pushRegIfUsed (hc08_reg_a);
2094 loadRegFromAop (hc08_reg_a, aop, 0);
2095 for (offset=1; offset<size; offset++)
2096 accopWithAop ("ora", aop, offset);
2098 pullReg (hc08_reg_a);
2101 hc08_freeReg (hc08_reg_a);
2110 loadRegFromAop (hc08_reg_a, aop, 0);
2111 hc08_freeReg (hc08_reg_a);
2115 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2120 if (hc08_reg_a->isFree)
2122 loadRegFromAop (hc08_reg_a, aop, 0);
2123 accopWithAop ("ora", aop, 1);
2124 hc08_freeReg (hc08_reg_a);
2129 tlbl = newiTempLabel (NULL);
2130 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2131 emitcode ("bne", "%05d$", (tlbl->key + 100));
2132 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2133 emitcode ("", "%05d$:", (tlbl->key + 100));
2139 needpula = pushRegIfUsed (hc08_reg_a);
2140 loadRegFromAop (hc08_reg_a, aop, 0);
2141 for (offset=1; offset<size; offset++)
2142 accopWithAop ("ora", aop, offset);
2144 pullReg (hc08_reg_a);
2147 hc08_freeReg (hc08_reg_a);
2155 tlbl = newiTempLabel (NULL);
2159 tlbl1 = newiTempLabel (NULL);
2160 emitBranch ("bne", tlbl1);
2161 loadRegFromConst (hc08_reg_a, zero);
2162 emitBranch ("bra", tlbl);
2164 loadRegFromConst (hc08_reg_a, one);
2168 emitBranch ("beq", tlbl);
2169 loadRegFromConst (hc08_reg_a, one);
2172 hc08_useReg (hc08_reg_a);
2178 /*-----------------------------------------------------------------*/
2179 /* genNot - generate code for ! operation */
2180 /*-----------------------------------------------------------------*/
2184 D(emitcode ("; genNot",""));
2186 /* assign asmOps to operand & result */
2187 aopOp (IC_LEFT (ic), ic, FALSE);
2188 aopOp (IC_RESULT (ic), ic, TRUE);
2190 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2191 emitcode ("eor", one);
2192 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2194 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2195 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2199 /*-----------------------------------------------------------------*/
2200 /* genCpl - generate code for complement */
2201 /*-----------------------------------------------------------------*/
2207 regs* reg = hc08_reg_a;
2211 D(emitcode ("; genCpl",""));
2213 /* assign asmOps to operand & result */
2214 aopOp (IC_LEFT (ic), ic, FALSE);
2215 aopOp (IC_RESULT (ic), ic, TRUE);
2217 size = AOP_SIZE (IC_RESULT (ic));
2220 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2221 rmwWithReg ("com", reg);
2223 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2227 /* release the aops */
2228 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2229 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2232 /*-----------------------------------------------------------------*/
2233 /* genUminusFloat - unary minus for floating points */
2234 /*-----------------------------------------------------------------*/
2236 genUminusFloat (operand * op, operand * result)
2238 int size, offset = 0;
2241 D(emitcode ("; genUminusFloat",""));
2243 /* for this we just copy and then flip the bit */
2245 size = AOP_SIZE (op) - 1;
2251 needpula = pushRegIfUsed (hc08_reg_a);
2252 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2253 emitcode ("eor", "#0x80");
2254 hc08_useReg (hc08_reg_a);
2255 storeRegToAop (hc08_reg_a, AOP (result), offset);
2256 pullOrFreeReg (hc08_reg_a, needpula);
2259 transferAopAop (AOP (op), offset, AOP (result), offset);
2265 /*-----------------------------------------------------------------*/
2266 /* genUminus - unary minus code generation */
2267 /*-----------------------------------------------------------------*/
2269 genUminus (iCode * ic)
2272 sym_link *optype, *rtype;
2276 D(emitcode ("; genUminus",""));
2279 aopOp (IC_LEFT (ic), ic, FALSE);
2280 aopOp (IC_RESULT (ic), ic, TRUE);
2282 optype = operandType (IC_LEFT (ic));
2283 rtype = operandType (IC_RESULT (ic));
2285 /* if float then do float stuff */
2286 if (IS_FLOAT (optype))
2288 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2292 /* otherwise subtract from zero */
2293 size = AOP_SIZE (IC_LEFT (ic));
2298 needpula = pushRegIfUsed (hc08_reg_a);
2299 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2300 emitcode ("nega", "");
2301 hc08_freeReg (hc08_reg_a);
2302 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2303 SPEC_USIGN (operandType (IC_LEFT (ic))));
2304 pullOrFreeReg (hc08_reg_a, needpula);
2308 needpula = pushRegIfUsed (hc08_reg_a);
2312 loadRegFromConst (hc08_reg_a, zero);
2313 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2314 storeRegToAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset++);
2317 storeRegSignToUpperAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset,
2318 SPEC_USIGN (operandType (IC_LEFT (ic))));
2319 pullOrFreeReg (hc08_reg_a, needpula);
2325 /* release the aops */
2326 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2327 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2330 /*-----------------------------------------------------------------*/
2331 /* saveRegisters - will look for a call and save the registers */
2332 /*-----------------------------------------------------------------*/
2334 saveRegisters (iCode * lic)
2341 for (ic = lic; ic; ic = ic->next)
2342 if (ic->op == CALL || ic->op == PCALL)
2347 fprintf (stderr, "found parameter push with no function call\n");
2351 /* if the registers have been saved already or don't need to be then
2355 if (IS_SYMOP(IC_LEFT(ic)) &&
2356 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2357 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2360 /* safe the registers in use at this time but skip the
2361 ones for the result */
2362 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2363 hc08_rUmaskForOp (IC_RESULT(ic)));
2366 for (i = 0; i < hc08_nRegs; i++)
2368 if (bitVectBitValue (rsave, i))
2369 pushReg ( hc08_regWithIdx (i), FALSE);
2373 /*-----------------------------------------------------------------*/
2374 /* unsaveRegisters - pop the pushed registers */
2375 /*-----------------------------------------------------------------*/
2377 unsaveRegisters (iCode * ic)
2382 /* restore the registers in use at this time but skip the
2383 ones for the result */
2384 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2385 hc08_rUmaskForOp (IC_RESULT(ic)));
2387 for (i = hc08_nRegs; i >= 0; i--)
2389 if (bitVectBitValue (rsave, i))
2390 pullReg ( hc08_regWithIdx (i));
2396 /*-----------------------------------------------------------------*/
2398 /*-----------------------------------------------------------------*/
2400 pushSide (operand * oper, int size)
2405 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2406 pushReg ( hc08_reg_a, TRUE);
2410 /*-----------------------------------------------------------------*/
2411 /* assignResultValue - */
2412 /*-----------------------------------------------------------------*/
2414 assignResultValue (operand * oper)
2416 int size = AOP_SIZE (oper);
2420 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2421 if (hc08_aop_pass[offset]->type == AOP_REG)
2422 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2429 /*-----------------------------------------------------------------*/
2430 /* genIpush - genrate code for pushing this gets a little complex */
2431 /*-----------------------------------------------------------------*/
2433 genIpush (iCode * ic)
2435 int size, offset = 0;
2438 D(emitcode ("; genIpush",""));
2440 /* if this is not a parm push : ie. it is spill push
2441 and spill push is always done on the local stack */
2445 /* and the item is spilt then do nothing */
2446 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2449 aopOp (IC_LEFT (ic), ic, FALSE);
2450 size = AOP_SIZE (IC_LEFT (ic));
2452 /* push it on the stack */
2455 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2456 pushReg ( hc08_reg_a, TRUE);
2462 /* this is a paramter push: in this case we call
2463 the routine to find the call and save those
2464 registers that need to be saved */
2467 /* then do the push */
2468 aopOp (IC_LEFT (ic), ic, FALSE);
2471 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2472 size = AOP_SIZE (IC_LEFT (ic));
2475 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2476 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2478 if ((size==2) && hc08_reg_hx->isFree)
2480 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2481 pushReg (hc08_reg_hx, TRUE);
2488 // printf("loading %d\n", offset);
2489 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2490 // printf("pushing \n");
2491 pushReg (hc08_reg_a, TRUE);
2495 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2498 /*-----------------------------------------------------------------*/
2499 /* genIpop - recover the registers: can happen only for spilling */
2500 /*-----------------------------------------------------------------*/
2502 genIpop (iCode * ic)
2506 D(emitcode ("; genIpop",""));
2508 /* if the temp was not pushed then */
2509 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2512 aopOp (IC_LEFT (ic), ic, FALSE);
2513 size = AOP_SIZE (IC_LEFT (ic));
2517 pullReg (hc08_reg_a);
2518 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2520 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2524 /*-----------------------------------------------------------------*/
2525 /* genSend - gen code for SEND */
2526 /*-----------------------------------------------------------------*/
2527 static void genSend(set *sendSet)
2531 for (sic = setFirstItem (_G.sendSet); sic;
2532 sic = setNextItem (_G.sendSet)) {
2533 int size, offset = 0;
2534 aopOp (IC_LEFT (sic), sic, FALSE);
2535 size = AOP_SIZE (IC_LEFT (sic));
2540 transferAopAop( AOP (IC_LEFT (sic)), offset,
2541 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2545 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2549 /*-----------------------------------------------------------------*/
2550 /* genCall - generates a call statement */
2551 /*-----------------------------------------------------------------*/
2553 genCall (iCode * ic)
2556 // bool restoreBank = FALSE;
2557 // bool swapBanks = FALSE;
2559 D(emitcode("; genCall",""));
2561 dtype = operandType (IC_LEFT (ic));
2562 /* if send set is not empty the assign */
2565 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2566 genSend(reverseSet(_G.sendSet));
2568 genSend(_G.sendSet);
2574 /* if caller saves & we have not saved then */
2580 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2581 OP_SYMBOL (IC_LEFT (ic))->rname :
2582 OP_SYMBOL (IC_LEFT (ic))->name));
2585 /* if we need assign a result value */
2586 if ((IS_ITEMP (IC_RESULT (ic)) &&
2587 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2588 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2589 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2590 IS_TRUE_SYMOP (IC_RESULT (ic)))
2594 aopOp (IC_RESULT (ic), ic, FALSE);
2597 assignResultValue (IC_RESULT (ic));
2599 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2602 /* adjust the stack for parameters if
2606 pullNull (ic->parmBytes);
2609 /* if we had saved some registers then unsave them */
2610 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2611 unsaveRegisters (ic);
2615 /*-----------------------------------------------------------------*/
2616 /* -10l - generates a call by pointer statement */
2617 /*-----------------------------------------------------------------*/
2619 genPcall (iCode * ic)
2622 symbol *rlbl = newiTempLabel (NULL);
2623 symbol *tlbl = newiTempLabel (NULL);
2624 // bool restoreBank=FALSE;
2625 // bool swapBanks = FALSE;
2627 D(emitcode("; genPCall",""));
2629 /* if caller saves & we have not saved then */
2633 /* if we are calling a not _naked function that is not using
2634 the same register bank then we need to save the
2635 destination registers on the stack */
2636 dtype = operandType (IC_LEFT (ic))->next;
2638 /* now push the calling address */
2639 emitBranch ("bsr", tlbl);
2640 emitBranch ("bra", rlbl);
2643 /* Push the function's address */
2644 aopOp (IC_LEFT (ic), ic, FALSE);
2645 pushSide (IC_LEFT (ic), FPTRSIZE);
2646 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2648 /* if send set is not empty the assign */
2651 genSend(reverseSet(_G.sendSet));
2657 emitcode ("rts", "");
2662 /* if we need assign a result value */
2663 if ((IS_ITEMP (IC_RESULT (ic)) &&
2664 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2665 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2666 IS_TRUE_SYMOP (IC_RESULT (ic)))
2670 aopOp (IC_RESULT (ic), ic, FALSE);
2673 assignResultValue (IC_RESULT (ic));
2675 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2678 /* adjust the stack for parameters if
2682 pullNull (ic->parmBytes);
2685 /* if we hade saved some registers then
2687 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2688 unsaveRegisters (ic);
2691 /*-----------------------------------------------------------------*/
2692 /* resultRemat - result is rematerializable */
2693 /*-----------------------------------------------------------------*/
2695 resultRemat (iCode * ic)
2697 if (SKIP_IC (ic) || ic->op == IFX)
2700 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2702 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2703 if (sym->remat && !POINTER_SET (ic))
2710 #if defined(__BORLANDC__) || defined(_MSC_VER)
2711 #define STRCASECMP stricmp
2713 #define STRCASECMP strcasecmp
2716 /*-----------------------------------------------------------------*/
2717 /* inExcludeList - return 1 if the string is in exclude Reg list */
2718 /*-----------------------------------------------------------------*/
2720 regsCmp(void *p1, void *p2)
2722 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2726 inExcludeList (char *s)
2728 const char *p = setFirstItem(options.excludeRegsSet);
2730 if (p == NULL || STRCASECMP(p, "none") == 0)
2734 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2737 /*-----------------------------------------------------------------*/
2738 /* genFunction - generated code for function entry */
2739 /*-----------------------------------------------------------------*/
2741 genFunction (iCode * ic)
2745 int calleesaves_saved_register = -1;
2749 /* create the function header */
2750 emitcode (";", "-----------------------------------------");
2751 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2752 emitcode (";", "-----------------------------------------");
2754 emitcode ("", "%s:", sym->rname);
2755 ftype = operandType (IC_LEFT (ic));
2757 if (IFFUNC_ISNAKED(ftype))
2759 emitcode(";", "naked function: no prologue.");
2765 /* if this is an interrupt service routine then
2767 if (IFFUNC_ISISR (sym->type))
2770 if (!inExcludeList ("h"))
2771 emitcode ("pshh", "");
2775 /* if callee-save to be used for this function
2776 then save the registers being used in this function */
2777 if (IFFUNC_CALLEESAVES(sym->type))
2781 /* if any registers used */
2784 /* save the registers used */
2785 for (i = 0; i < sym->regsUsed->size; i++)
2787 if (bitVectBitValue (sym->regsUsed, i))
2789 /* remember one saved register for later usage */
2790 if (calleesaves_saved_register < 0)
2791 calleesaves_saved_register = i;
2792 pushReg (hc08_regWithIdx (i), FALSE);
2800 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2805 /* adjust the stack for the function */
2811 // werror (W_STACK_OVERFLOW, sym->name);
2815 _G.stackOfs = sym->stack;
2818 /* if critical function then turn interrupts off */
2819 if (IFFUNC_ISCRITICAL (ftype))
2821 if (IFFUNC_ARGS (ftype))
2823 /* Function was passed parameters, so make sure A is preserved */
2824 pushReg (hc08_reg_a, FALSE);
2825 pushReg (hc08_reg_a, FALSE);
2826 emitcode ("tpa", "");
2827 emitcode ("sta", "2,s");
2828 emitcode ("sei", "");
2829 pullReg (hc08_reg_a);
2833 /* No passed parameters, so A can be freely modified */
2834 emitcode ("tpa", "");
2835 pushReg (hc08_reg_a, TRUE);
2836 emitcode ("sei", "");
2842 /*-----------------------------------------------------------------*/
2843 /* genEndFunction - generates epilogue for functions */
2844 /*-----------------------------------------------------------------*/
2846 genEndFunction (iCode * ic)
2848 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2850 if (IFFUNC_ISNAKED(sym->type))
2852 emitcode(";", "naked function: no epilogue.");
2856 if (IFFUNC_ISCRITICAL (sym->type))
2858 if (!IS_VOID(sym->type->next))
2860 /* Function has return value, so make sure A is preserved */
2861 pushReg (hc08_reg_a, FALSE);
2862 emitcode ("lda", "2,s");
2863 emitcode ("tap", "");
2864 pullReg (hc08_reg_a);
2869 /* Function returns void, so A can be freely modified */
2870 pullReg (hc08_reg_a);
2871 emitcode ("tap", "");
2875 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2881 _G.stackPushes += sym->stack;
2882 adjustStack (sym->stack);
2886 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2890 if (IFFUNC_ISISR (sym->type))
2893 if (!inExcludeList ("h"))
2894 emitcode ("pulh", "");
2897 /* if debug then send end of function */
2898 if (options.debug && currFunc)
2901 emitcode ("", "C$%s$%d$%d$%d ==.",
2902 FileBaseName (ic->filename), currFunc->lastLine,
2903 ic->level, ic->block);
2904 if (IS_STATIC (currFunc->etype))
2905 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2907 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2911 emitcode ("rti", "");
2915 if (IFFUNC_CALLEESAVES(sym->type))
2919 /* if any registers used */
2922 /* save the registers used */
2923 for (i = sym->regsUsed->size; i >= 0; i--)
2925 if (bitVectBitValue (sym->regsUsed, i) ||
2926 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
2927 emitcode ("pop", "%s", hc08_regWithIdx (i)->dname);
2933 /* if debug then send end of function */
2934 if (options.debug && currFunc)
2937 emitcode ("", "C$%s$%d$%d$%d ==.",
2938 FileBaseName (ic->filename), currFunc->lastLine,
2939 ic->level, ic->block);
2940 if (IS_STATIC (currFunc->etype))
2941 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2943 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2947 emitcode ("rts", "");
2952 /*-----------------------------------------------------------------*/
2953 /* genRet - generate code for return statement */
2954 /*-----------------------------------------------------------------*/
2958 int size, offset = 0;
2961 D(emitcode ("; genRet",""));
2963 /* if we have no return value then
2964 just generate the "ret" */
2968 /* we have something to return then
2969 move the return value into place */
2970 aopOp (IC_LEFT (ic), ic, FALSE);
2971 size = AOP_SIZE (IC_LEFT (ic));
2977 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
2984 /* 4 byte return: store value in the global return variable */
2988 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
2989 STA (fReturn2[offset--], FALSE);
2990 hc08_freeReg (hc08_reg_a);
2994 /* 2 byte return: store value in x:a */
2995 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
2996 hc08_freeReg (hc08_reg_xa);
2999 /* 1 byte return: store value in a */
3000 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3001 hc08_freeReg (hc08_reg_a);
3006 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3009 /* generate a jump to the return label
3010 if the next is not the return statement */
3011 if (!(ic->next && ic->next->op == LABEL &&
3012 IC_LABEL (ic->next) == returnLabel))
3014 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3018 /*-----------------------------------------------------------------*/
3019 /* genLabel - generates a label */
3020 /*-----------------------------------------------------------------*/
3022 genLabel (iCode * ic)
3027 /* For the high level labels we cannot depend on any */
3028 /* register's contents. Amnesia time. */
3029 for (i=A_IDX;i<=XA_IDX;i++)
3031 reg = hc08_regWithIdx(i);
3036 /* special case never generate */
3037 if (IC_LABEL (ic) == entryLabel)
3040 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3044 /*-----------------------------------------------------------------*/
3045 /* genGoto - generates a jmp */
3046 /*-----------------------------------------------------------------*/
3048 genGoto (iCode * ic)
3050 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3054 /*-----------------------------------------------------------------*/
3055 /* findLabelBackwards: walks back through the iCode chain looking */
3056 /* for the given label. Returns number of iCode instructions */
3057 /* between that label and given ic. */
3058 /* Returns zero if label not found. */
3059 /*-----------------------------------------------------------------*/
3061 findLabelBackwards (iCode * ic, int key)
3070 /* If we have any pushes or pops, we cannot predict the distance.
3071 I don't like this at all, this should be dealt with in the
3073 if (ic->op == IPUSH || ic->op == IPOP) {
3077 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3087 /*-----------------------------------------------------------------*/
3088 /* genPlusIncr :- does addition with increment if possible */
3089 /*-----------------------------------------------------------------*/
3091 genPlusIncr (iCode * ic)
3099 unsigned int size = getDataSize (IC_RESULT (ic));
3101 symbol *tlbl = NULL;
3103 left = IC_LEFT (ic);
3104 result = IC_RESULT (ic);
3106 /* will try to generate an increment */
3107 /* if the right side is not a literal
3109 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3112 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3114 emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left)));
3116 if ((IS_AOP_HX (AOP (left)) ||
3117 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3119 && (icount>=-128) && (icount<=127) && (size==2))
3121 needpulx = pushRegIfUsed (hc08_reg_x);
3122 needpulh = pushRegIfUsed (hc08_reg_h);
3123 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3124 emitcode ("aix","#%d", icount);
3125 hc08_dirtyReg (hc08_reg_hx, FALSE);
3126 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3127 pullOrFreeReg (hc08_reg_h, needpulh);
3128 pullOrFreeReg (hc08_reg_x, needpulx);
3132 emitcode ("", "; icount = %d, sameRegs=%d", icount,
3133 sameRegs (AOP (left), AOP (result)));
3135 if ((icount > 255) || (icount<0))
3138 if (!sameRegs (AOP (left), AOP (result)))
3141 D(emitcode ("; genPlusIncr",""));
3144 tlbl = newiTempLabel (NULL);
3149 rmwWithAop ("inc", AOP (result), 0);
3151 emitBranch ("bne", tlbl);
3155 needpula = pushRegIfUsed (hc08_reg_a);
3156 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3157 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3158 hc08_useReg (hc08_reg_a);
3159 storeRegToAop (hc08_reg_a, AOP (result), 0);
3160 hc08_freeReg (hc08_reg_a);
3162 emitBranch ("bcc", tlbl);
3164 for (offset=1; offset<size; offset++)
3166 rmwWithAop ("inc", AOP (result), offset);
3167 if ((offset+1)<size)
3168 emitBranch ("bne", tlbl);
3174 pullOrFreeReg (hc08_reg_a, needpula);
3181 /*-----------------------------------------------------------------*/
3182 /* genPlus - generates code for addition */
3183 /*-----------------------------------------------------------------*/
3185 genPlus (iCode * ic)
3187 int size, offset = 0;
3189 asmop *leftOp, *rightOp;
3191 /* special cases :- */
3193 D(emitcode ("; genPlus",""));
3195 aopOp (IC_LEFT (ic), ic, FALSE);
3196 aopOp (IC_RIGHT (ic), ic, FALSE);
3197 aopOp (IC_RESULT (ic), ic, TRUE);
3199 /* we want registers on the left and literals on the right */
3200 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3201 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3203 operand *t = IC_RIGHT (ic);
3204 IC_RIGHT (ic) = IC_LEFT (ic);
3209 /* if I can do an increment instead
3210 of add then GOOD for ME */
3211 if (genPlusIncr (ic) == TRUE)
3214 emitcode("","; left size = %d", getDataSize (IC_LEFT(ic)));
3215 emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic)));
3216 emitcode("","; result size = %d", getDataSize (IC_RESULT(ic)));
3218 size = getDataSize (IC_RESULT (ic));
3220 leftOp = AOP(IC_LEFT(ic));
3221 rightOp = AOP(IC_RIGHT(ic));
3227 loadRegFromAop (hc08_reg_a, leftOp, offset);
3228 accopWithAop(add, rightOp, offset);
3229 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3230 hc08_freeReg (hc08_reg_a);
3231 add = "adc"; /* further adds must propagate carry */
3235 // adjustArithmeticResult (ic);
3238 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3239 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3240 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3243 /*-----------------------------------------------------------------*/
3244 /* genMinusDec :- does subtraction with deccrement if possible */
3245 /*-----------------------------------------------------------------*/
3247 genMinusDec (iCode * ic)
3249 unsigned int icount;
3254 unsigned int size = getDataSize (IC_RESULT (ic));
3258 left = IC_LEFT (ic);
3259 result = IC_RESULT (ic);
3261 /* will try to generate an increment */
3262 /* if the right side is not a literal
3264 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3267 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3269 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3270 && (icount>=-127) && (icount<=128) && (size==2))
3272 needpulx = pushRegIfUsed (hc08_reg_x);
3273 needpulh = pushRegIfUsed (hc08_reg_h);
3274 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3275 emitcode ("aix","#%d", -icount);
3276 hc08_dirtyReg (hc08_reg_hx, FALSE);
3277 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3278 pullOrFreeReg (hc08_reg_h, needpulh);
3279 pullOrFreeReg (hc08_reg_x, needpulx);
3283 if ((icount > 1) || (icount<0))
3286 if (!sameRegs (AOP (left), AOP (result)))
3292 D(emitcode ("; genMinusDec",""));
3294 rmwWithAop ("dec", AOP (result), 0);
3299 /*-----------------------------------------------------------------*/
3300 /* addSign - complete with sign */
3301 /*-----------------------------------------------------------------*/
3303 addSign (operand * result, int offset, int sign)
3305 int size = (getDataSize (result) - offset);
3310 emitcode ("rola", "");
3311 emitcode ("clra", "");
3312 emitcode ("sbc", zero);
3314 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3318 storeConstToAop (zero, AOP (result), offset++);
3323 /*-----------------------------------------------------------------*/
3324 /* genMinus - generates code for subtraction */
3325 /*-----------------------------------------------------------------*/
3327 genMinus (iCode * ic)
3330 int size, offset = 0;
3332 asmop *leftOp, *rightOp;
3334 D(emitcode ("; genMinus",""));
3336 aopOp (IC_LEFT (ic), ic, FALSE);
3337 aopOp (IC_RIGHT (ic), ic, FALSE);
3338 aopOp (IC_RESULT (ic), ic, TRUE);
3340 /* special cases :- */
3341 /* if I can do an decrement instead
3342 of subtract then GOOD for ME */
3343 if (genMinusDec (ic) == TRUE)
3346 size = getDataSize (IC_RESULT (ic));
3349 leftOp = AOP(IC_LEFT(ic));
3350 rightOp = AOP(IC_RIGHT(ic));
3356 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3357 accopWithAop(sub, rightOp, offset);
3358 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3363 // adjustArithmeticResult (ic);
3366 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3367 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3368 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3373 /*-----------------------------------------------------------------*/
3374 /* genMultOneByte : 8*8=8/16 bit multiplication */
3375 /*-----------------------------------------------------------------*/
3377 genMultOneByte (operand * left,
3381 sym_link *opetype = operandType (result);
3382 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3383 int size=AOP_SIZE(result);
3384 bool negLiteral = FALSE;
3386 D(emitcode ("; genMultOneByte",""));
3388 if (size<1 || size>2) {
3389 // this should never happen
3390 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3391 AOP_SIZE(result), __FILE__, lineno);
3395 /* (if two literals: the value is computed before) */
3396 /* if one literal, literal on the right */
3397 if (AOP_TYPE (left) == AOP_LIT)
3402 //emitcode (";", "swapped left and right");
3405 if (SPEC_USIGN(opetype))
3407 // just an unsigned 8*8=8/16 multiply
3408 //emitcode (";","unsigned");
3410 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3411 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3412 emitcode ("mul", "");
3413 hc08_dirtyReg (hc08_reg_xa, FALSE);
3414 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3415 hc08_freeReg (hc08_reg_xa);
3420 // we have to do a signed multiply
3423 //emitcode (";", "signed");
3425 emitcode ("clr", "1,s");
3427 tlbl1 = newiTempLabel (NULL);
3428 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3429 emitcode ("tsta","");
3430 emitBranch ("bpl", tlbl1);
3431 emitcode ("inc", "1,s");
3432 rmwWithReg ("neg", hc08_reg_a);
3435 if (AOP_TYPE(right)==AOP_LIT)
3437 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3438 /* AND literal negative */
3440 emitcode ("ldx", "#0x%02x", -val);
3443 emitcode ("ldx", "#0x%02x", val);
3445 hc08_useReg (hc08_reg_x);
3449 tlbl2 = newiTempLabel (NULL);
3450 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3451 emitcode ("tstx", "");
3452 emitBranch ("bpl", tlbl2);
3453 emitcode ("inc", "1,s");
3454 rmwWithReg ("neg", hc08_reg_x);
3458 emitcode ("mul", "");
3459 hc08_dirtyReg (hc08_reg_xa, FALSE);
3461 tlbl3 = newiTempLabel (NULL);
3462 emitcode ("dec", "1,s");
3464 emitBranch ("bne", tlbl3);
3466 emitBranch ("beq", tlbl3);
3468 rmwWithReg ("neg", hc08_reg_a);
3471 tlbl4 = newiTempLabel (NULL);
3472 emitBranch ("bcc", tlbl4);
3473 rmwWithReg ("inc", hc08_reg_x);
3475 rmwWithReg ("neg", hc08_reg_x);
3480 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3481 hc08_freeReg (hc08_reg_xa);
3485 /*-----------------------------------------------------------------*/
3486 /* genMult - generates code for multiplication */
3487 /*-----------------------------------------------------------------*/
3489 genMult (iCode * ic)
3491 operand *left = IC_LEFT (ic);
3492 operand *right = IC_RIGHT (ic);
3493 operand *result = IC_RESULT (ic);
3495 D(emitcode ("; genMult",""));
3497 /* assign the amsops */
3498 aopOp (left, ic, FALSE);
3499 aopOp (right, ic, FALSE);
3500 aopOp (result, ic, TRUE);
3502 /* special cases first */
3503 /* if both are of size == 1 */
3504 // if (getSize(operandType(left)) == 1 &&
3505 // getSize(operandType(right)) == 1)
3506 if (AOP_SIZE (left) == 1 &&
3507 AOP_SIZE (right) == 1)
3509 genMultOneByte (left, right, result);
3513 /* should have been converted to function call */
3514 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3515 getSize(OP_SYMBOL(right)->type));
3516 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3521 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3522 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3523 freeAsmop (result, NULL, ic, TRUE);
3526 /*-----------------------------------------------------------------*/
3527 /* genDivOneByte : 8 bit division */
3528 /*-----------------------------------------------------------------*/
3530 genDivOneByte (operand * left,
3534 sym_link *opetype = operandType (result);
3536 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3538 bool negLiteral = FALSE;
3540 D(emitcode ("; genDivOneByte",""));
3542 size = AOP_SIZE (result);
3543 /* signed or unsigned */
3544 if (SPEC_USIGN (opetype))
3546 /* unsigned is easy */
3547 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3548 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3549 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3550 emitcode ("div", "");
3551 hc08_dirtyReg (hc08_reg_a, FALSE);
3552 hc08_dirtyReg (hc08_reg_h, FALSE);
3553 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3554 hc08_freeReg (hc08_reg_a);
3555 hc08_freeReg (hc08_reg_x);
3556 hc08_freeReg (hc08_reg_h);
3560 /* signed is a little bit more difficult */
3563 emitcode ("clr", "1,s");
3565 tlbl1 = newiTempLabel (NULL);
3566 tlbl2 = newiTempLabel (NULL);
3567 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3568 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3569 emitBranch ("bpl", tlbl1);
3570 emitcode ("inc", "1,s");
3571 rmwWithReg ("neg", hc08_reg_a);
3572 emitBranch ("bcc", tlbl2);
3573 rmwWithReg ("inc", hc08_reg_x);
3575 rmwWithReg ("neg", hc08_reg_x);
3576 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3579 if (AOP_TYPE(right)==AOP_LIT)
3581 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3582 /* AND literal negative */
3584 emitcode ("ldx", "#0x%02x", -val);
3587 emitcode ("ldx", "#0x%02x", val);
3589 hc08_useReg (hc08_reg_x);
3593 tlbl3 = newiTempLabel (NULL);
3594 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3595 emitBranch ("bpl", tlbl3);
3596 emitcode ("inc", "1,s");
3597 rmwWithReg ("neg", hc08_reg_x);
3601 emitcode ("div", "");
3602 hc08_dirtyReg (hc08_reg_x, FALSE);
3603 hc08_dirtyReg (hc08_reg_a, FALSE);
3604 hc08_dirtyReg (hc08_reg_h, FALSE);
3606 tlbl4 = newiTempLabel (NULL);
3607 emitcode ("dec", "1,s");
3609 emitBranch ("bne", tlbl4);
3611 emitBranch ("beq", tlbl4);
3612 rmwWithReg ("neg", hc08_reg_a);
3616 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3617 hc08_freeReg (hc08_reg_a);
3618 hc08_freeReg (hc08_reg_x);
3619 hc08_freeReg (hc08_reg_h);
3624 /*-----------------------------------------------------------------*/
3625 /* genDiv - generates code for division */
3626 /*-----------------------------------------------------------------*/
3630 operand *left = IC_LEFT (ic);
3631 operand *right = IC_RIGHT (ic);
3632 operand *result = IC_RESULT (ic);
3634 D(emitcode ("; genDiv",""));
3636 /* assign the amsops */
3637 aopOp (left, ic, FALSE);
3638 aopOp (right, ic, FALSE);
3639 aopOp (result, ic, TRUE);
3641 /* special cases first */
3642 /* if both are of size == 1 */
3643 if (AOP_SIZE (left) <= 2 &&
3644 AOP_SIZE (right) == 1)
3646 genDivOneByte (left, right, result);
3650 /* should have been converted to function call */
3653 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3654 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3655 freeAsmop (result, NULL, ic, TRUE);
3658 /*-----------------------------------------------------------------*/
3659 /* genModOneByte : 8 bit modulus */
3660 /*-----------------------------------------------------------------*/
3662 genModOneByte (operand * left,
3666 sym_link *opetype = operandType (result);
3668 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3670 bool negLiteral = FALSE;
3672 D(emitcode ("; genModOneByte",""));
3674 size = AOP_SIZE (result);
3675 /* signed or unsigned */
3676 if (SPEC_USIGN (opetype))
3678 /* unsigned is easy */
3679 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3680 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3681 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3682 emitcode ("div", "");
3683 hc08_dirtyReg (hc08_reg_a, FALSE);
3684 hc08_dirtyReg (hc08_reg_h, FALSE);
3685 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3686 hc08_freeReg (hc08_reg_a);
3687 hc08_freeReg (hc08_reg_x);
3688 hc08_freeReg (hc08_reg_h);
3692 /* signed is a little bit more difficult */
3695 emitcode ("clr", "1,s");
3697 tlbl1 = newiTempLabel (NULL);
3698 tlbl2 = newiTempLabel (NULL);
3699 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3700 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3701 emitBranch ("bpl", tlbl1);
3702 emitcode ("inc", "1,s");
3703 rmwWithReg ("neg", hc08_reg_a);
3704 emitBranch ("bcc", tlbl2);
3705 rmwWithReg ("inc", hc08_reg_x);
3707 rmwWithReg ("neg", hc08_reg_x);
3708 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3711 if (AOP_TYPE(right)==AOP_LIT)
3713 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3714 /* AND literal negative */
3716 emitcode ("ldx", "#0x%02x", -val);
3719 emitcode ("ldx", "#0x%02x", val);
3721 hc08_useReg (hc08_reg_x);
3725 tlbl3 = newiTempLabel (NULL);
3726 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3727 emitBranch ("bpl", tlbl3);
3728 emitcode ("inc", "1,s");
3729 rmwWithReg ("neg", hc08_reg_x);
3733 emitcode ("div", "");
3734 hc08_dirtyReg (hc08_reg_x, FALSE);
3735 hc08_dirtyReg (hc08_reg_a, FALSE);
3736 hc08_dirtyReg (hc08_reg_h, FALSE);
3738 tlbl4 = newiTempLabel (NULL);
3739 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3740 emitcode ("dec", "1,s");
3742 emitBranch ("bne", tlbl4);
3744 emitBranch ("beq", tlbl4);
3745 rmwWithReg ("neg", hc08_reg_a);
3749 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3750 hc08_freeReg (hc08_reg_a);
3751 hc08_freeReg (hc08_reg_x);
3752 hc08_freeReg (hc08_reg_h);
3756 /*-----------------------------------------------------------------*/
3757 /* genMod - generates code for division */
3758 /*-----------------------------------------------------------------*/
3762 operand *left = IC_LEFT (ic);
3763 operand *right = IC_RIGHT (ic);
3764 operand *result = IC_RESULT (ic);
3766 D(emitcode ("; genMod",""));
3768 /* assign the amsops */
3769 aopOp (left, ic, FALSE);
3770 aopOp (right, ic, FALSE);
3771 aopOp (result, ic, TRUE);
3773 /* special cases first */
3774 /* if both are of size == 1 */
3775 if (AOP_SIZE (left) <= 2 &&
3776 AOP_SIZE (right) == 1)
3778 genModOneByte (left, right, result);
3782 /* should have been converted to function call */
3786 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3787 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3788 freeAsmop (result, NULL, ic, TRUE);
3791 /*-----------------------------------------------------------------*/
3792 /* genIfxJump :- will create a jump depending on the ifx */
3793 /*-----------------------------------------------------------------*/
3795 genIfxJump (iCode * ic, char *jval)
3798 symbol *tlbl = newiTempLabel (NULL);
3801 D(emitcode ("; genIfxJump",""));
3803 /* if true label then we jump if condition
3807 jlbl = IC_TRUE (ic);
3808 if (!strcmp (jval, "a"))
3810 else if (!strcmp (jval, "c"))
3817 /* false label is present */
3818 jlbl = IC_FALSE (ic);
3819 if (!strcmp (jval, "a"))
3821 else if (!strcmp (jval, "c"))
3826 emitBranch (inst, tlbl);
3827 emitBranch ("jmp", jlbl);
3830 /* mark the icode as generated */
3834 /*-----------------------------------------------------------------*/
3835 /* genCmp :- greater or less than comparison */
3836 /*-----------------------------------------------------------------*/
3838 genCmp (operand * left, operand * right,
3839 operand * result, iCode * ifx, int sign, iCode *ic)
3841 int size, offset = 0;
3842 unsigned long lit = 0L;
3844 bool needpula = FALSE;
3846 D(emitcode ("; genCmp",""));
3848 /* subtract right from left if at the
3849 end the carry flag is set then we know that
3850 left is greater than right */
3851 size = max (AOP_SIZE (left), AOP_SIZE (right));
3853 if (AOP_TYPE (right) == AOP_LIT)
3855 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3856 /* optimize if(x < 0) or if(x >= 0) */
3865 needpula = pushRegIfUsed (hc08_reg_a);
3866 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3867 emitcode ("rola", "");
3868 hc08_useReg (hc08_reg_a);
3876 && ((AOP_TYPE (right) == AOP_LIT) ||
3877 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3878 && hc08_reg_hx->isFree)
3880 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3881 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3882 hc08_freeReg (hc08_reg_hx);
3893 loadRegFromAop (hc08_reg_a, AOP (left), offset);
3894 accopWithAop (sub, AOP (right), offset);
3895 hc08_freeReg (hc08_reg_a);
3901 freeAsmop (right, NULL, ic, TRUE);
3902 freeAsmop (left, NULL, ic, TRUE);
3903 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3909 /* if the result is used in the next
3910 ifx conditional branch then generate
3911 code a little differently */
3914 pullOrFreeReg(hc08_reg_a,needpula);
3915 genIfxJump (ifx, sign ? "s" : "c");
3922 pullOrFreeReg(hc08_reg_a,needpula);
3926 /*-----------------------------------------------------------------*/
3927 /* genCmpGt :- greater than comparison */
3928 /*-----------------------------------------------------------------*/
3930 genCmpGt (iCode * ic, iCode * ifx)
3932 operand *left, *right, *result;
3933 sym_link *letype, *retype;
3936 D(emitcode ("; genCmpGt",""));
3938 result = IC_RESULT (ic);
3939 left = IC_LEFT (ic);
3940 right = IC_RIGHT (ic);
3942 letype = getSpec (operandType (left));
3943 retype = getSpec (operandType (right));
3944 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3945 /* assign the amsops */
3946 aopOp (left, ic, FALSE);
3947 aopOp (right, ic, FALSE);
3948 aopOp (result, ic, TRUE);
3950 genCmp (right, left, result, ifx, sign,ic);
3952 freeAsmop (result, NULL, ic, TRUE);
3955 /*-----------------------------------------------------------------*/
3956 /* genCmpLt - less than comparisons */
3957 /*-----------------------------------------------------------------*/
3959 genCmpLt (iCode * ic, iCode * ifx)
3961 operand *left, *right, *result;
3962 sym_link *letype, *retype;
3965 D(emitcode ("; genCmpLt",""));
3967 result = IC_RESULT (ic);
3968 left = IC_LEFT (ic);
3969 right = IC_RIGHT (ic);
3971 letype = getSpec (operandType (left));
3972 retype = getSpec (operandType (right));
3973 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3975 /* assign the amsops */
3976 aopOp (left, ic, FALSE);
3977 aopOp (right, ic, FALSE);
3978 aopOp (result, ic, TRUE);
3980 genCmp (left, right, result, ifx, sign,ic);
3982 freeAsmop (result, NULL, ic, TRUE);
3985 /*-----------------------------------------------------------------*/
3986 /* - compare and branch if not equal */
3987 /*-----------------------------------------------------------------*/
3989 gencbneshort (operand * left, operand * right, symbol * lbl)
3991 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3993 unsigned long lit = 0L;
3995 /* if the left side is a literal or
3996 if the right is in a pointer register and left
3998 if (AOP_TYPE (left) == AOP_LIT)
4004 if (AOP_TYPE (right) == AOP_LIT)
4005 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4009 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4010 accopWithAop ("cmp", AOP (right), offset);
4011 hc08_useReg (hc08_reg_a);
4012 hc08_freeReg (hc08_reg_a);
4013 emitBranch ("bne", lbl);
4019 /*-----------------------------------------------------------------*/
4020 /* gencjne - compare and jump if not equal */
4021 /*-----------------------------------------------------------------*/
4023 gencjne (operand * left, operand * right, symbol * lbl)
4025 symbol *tlbl = newiTempLabel (NULL);
4027 gencbneshort (left, right, lbl);
4029 loadRegFromConst (hc08_reg_a, one);
4030 emitBranch ("bra", tlbl);
4032 loadRegFromConst (hc08_reg_a, zero);
4035 hc08_useReg(hc08_reg_a);
4036 hc08_freeReg(hc08_reg_a);
4039 /*-----------------------------------------------------------------*/
4040 /* genCmpEq - generates code for equal to */
4041 /*-----------------------------------------------------------------*/
4043 genCmpEq (iCode * ic, iCode * ifx)
4045 operand *left, *right, *result;
4047 D(emitcode ("; genCmpEq",""));
4049 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4050 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4051 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4053 /* if literal, literal on the right or
4054 if the right is in a pointer register and left
4056 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4058 operand *t = IC_RIGHT (ic);
4059 IC_RIGHT (ic) = IC_LEFT (ic);
4063 if (ifx && !AOP_SIZE (result))
4066 tlbl = newiTempLabel (NULL);
4067 gencbneshort (left, right, tlbl);
4070 emitBranch ("jmp", IC_TRUE (ifx));
4075 symbol *lbl = newiTempLabel (NULL);
4076 emitBranch ("bra", lbl);
4078 emitBranch ("jmp", IC_FALSE (ifx));
4082 /* mark the icode as generated */
4087 gencjne (left, right, newiTempLabel (NULL));
4088 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4090 storeRegToAop (hc08_reg_a, AOP (result), 0);
4095 genIfxJump (ifx, "a");
4098 /* if the result is used in an arithmetic operation
4099 then put the result in place */
4100 if (AOP_TYPE (result) != AOP_CRY)
4104 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4105 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4106 freeAsmop (result, NULL, ic, TRUE);
4109 /*-----------------------------------------------------------------*/
4110 /* ifxForOp - returns the icode containing the ifx for operand */
4111 /*-----------------------------------------------------------------*/
4113 ifxForOp (operand * op, iCode * ic)
4115 /* if true symbol then needs to be assigned */
4116 if (IS_TRUE_SYMOP (op))
4119 /* if this has register type condition and
4120 the next instruction is ifx with the same operand
4121 and live to of the operand is upto the ifx only then */
4123 ic->next->op == IFX &&
4124 IC_COND (ic->next)->key == op->key &&
4125 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4132 genPointerGetSetOfs (iCode *ic)
4134 iCode *lic = ic->next;
4140 /* Make sure we have a next iCode */
4141 emitcode("","; checking lic");
4145 /* Make sure the result of the addition is an iCode */
4146 emitcode("","; checking IS_ITEMP");
4147 if (!IS_ITEMP (IC_RESULT (ic)))
4150 /* Make sure the next iCode is a pointer set or get */
4151 pset = POINTER_SET(lic);
4152 pget = POINTER_GET(lic);
4153 emitcode("","; pset=%d, pget=%d",pset,pget);
4157 emitcode("", "; checking pset operandsEqu");
4158 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4161 emitcode("", "; checking pget operandsEqu");
4162 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4165 emitcode("", "; checking IS_SYMOP");
4166 if (!IS_SYMOP (IC_LEFT (ic)))
4169 emitcode("", "; checking !IS_TRUE_SYMOP");
4170 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4173 sym = OP_SYMBOL (IC_LEFT (ic));
4175 emitcode("", "; checking remat");
4181 D(emitcode ("; genPointerGetOfs",""));
4182 aopOp (IC_LEFT(ic), ic, FALSE);
4183 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4184 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4186 aopOp (IC_RIGHT(ic), ic, FALSE);
4187 aopOp (IC_RESULT(lic), lic, FALSE);
4190 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4191 size = AOP_SIZE (IC_RESULT(lic));
4192 derefaop->size = size;
4197 emitcode ("lda", "%s,x",
4198 aopAdrStr (derefaop, offset, TRUE));
4199 hc08_useReg (hc08_reg_a);
4200 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4201 hc08_freeReg (hc08_reg_a);
4205 hc08_freeReg (hc08_reg_hx);
4207 freeAsmop (NULL, derefaop, ic, TRUE);
4208 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4209 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4216 D(emitcode ("; genPointerSetOfs",""));
4217 aopOp (IC_LEFT(ic), ic, FALSE);
4218 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4219 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4221 aopOp (IC_RIGHT(ic), ic, FALSE);
4222 aopOp (IC_RIGHT(lic), lic, FALSE);
4225 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4226 size = AOP_SIZE (IC_RIGHT(lic));
4227 derefaop->size = size;
4232 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4233 emitcode ("sta", "%s,x",
4234 aopAdrStr (derefaop, offset, TRUE));
4235 hc08_freeReg (hc08_reg_a);
4240 hc08_freeReg (hc08_reg_hx);
4242 freeAsmop (NULL, derefaop, ic, TRUE);
4243 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4244 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4253 /*-----------------------------------------------------------------*/
4254 /* hasInc - operand is incremented before any other use */
4255 /*-----------------------------------------------------------------*/
4257 hasInc (operand *op, iCode *ic,int osize)
4259 sym_link *type = operandType(op);
4260 sym_link *retype = getSpec (type);
4261 iCode *lic = ic->next;
4264 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4265 if (!IS_SYMOP(op)) return NULL;
4267 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4268 if (IS_AGGREGATE(type->next)) return NULL;
4269 if (osize != (isize = getSize(type->next))) return NULL;
4272 /* if operand of the form op = op + <sizeof *op> */
4273 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4274 isOperandEqual(IC_RESULT(lic),op) &&
4275 isOperandLiteral(IC_RIGHT(lic)) &&
4276 operandLitValue(IC_RIGHT(lic)) == isize) {
4279 /* if the operand used or deffed */
4280 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4283 /* if GOTO or IFX */
4284 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4290 /*-----------------------------------------------------------------*/
4291 /* genAndOp - for && operation */
4292 /*-----------------------------------------------------------------*/
4294 genAndOp (iCode * ic)
4296 operand *left, *right, *result;
4297 symbol *tlbl, *tlbl0;
4299 D(emitcode ("; genAndOp",""));
4301 /* note here that && operations that are in an
4302 if statement are taken away by backPatchLabels
4303 only those used in arthmetic operations remain */
4304 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4305 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4306 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4308 tlbl = newiTempLabel (NULL);
4309 tlbl0 = newiTempLabel (NULL);
4311 asmopToBool (AOP (left), FALSE);
4312 emitBranch ("beq", tlbl0);
4313 asmopToBool (AOP (right), FALSE);
4314 emitBranch ("beq", tlbl0);
4315 loadRegFromConst (hc08_reg_a,one);
4316 emitBranch ("bra", tlbl);
4318 loadRegFromConst (hc08_reg_a,zero);
4321 hc08_useReg (hc08_reg_a);
4322 hc08_freeReg (hc08_reg_a);
4324 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4326 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4327 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4328 freeAsmop (result, NULL, ic, TRUE);
4332 /*-----------------------------------------------------------------*/
4333 /* genOrOp - for || operation */
4334 /*-----------------------------------------------------------------*/
4336 genOrOp (iCode * ic)
4338 operand *left, *right, *result;
4339 symbol *tlbl, *tlbl0;
4341 D(emitcode ("; genOrOp",""));
4343 /* note here that || operations that are in an
4344 if statement are taken away by backPatchLabels
4345 only those used in arthmetic operations remain */
4346 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4347 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4348 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4350 tlbl = newiTempLabel (NULL);
4351 tlbl0 = newiTempLabel (NULL);
4353 asmopToBool (AOP (left), FALSE);
4354 emitBranch ("bne", tlbl0);
4355 asmopToBool (AOP (right), FALSE);
4356 emitBranch ("bne", tlbl0);
4357 loadRegFromConst (hc08_reg_a,zero);
4358 emitBranch ("bra", tlbl);
4360 loadRegFromConst (hc08_reg_a,one);
4363 hc08_useReg (hc08_reg_a);
4364 hc08_freeReg (hc08_reg_a);
4366 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4369 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4370 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4371 freeAsmop (result, NULL, ic, TRUE);
4374 /*-----------------------------------------------------------------*/
4375 /* isLiteralBit - test if lit == 2^n */
4376 /*-----------------------------------------------------------------*/
4378 isLiteralBit (unsigned long lit)
4380 unsigned long pw[32] =
4381 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4382 0x100L, 0x200L, 0x400L, 0x800L,
4383 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4384 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4385 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4386 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4387 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4390 for (idx = 0; idx < 32; idx++)
4397 /*-----------------------------------------------------------------*/
4398 /* continueIfTrue - */
4399 /*-----------------------------------------------------------------*/
4401 continueIfTrue (iCode * ic)
4404 emitBranch ("jmp", IC_TRUE (ic));
4408 /*-----------------------------------------------------------------*/
4410 /*-----------------------------------------------------------------*/
4412 jumpIfTrue (iCode * ic)
4415 emitBranch ("jmp", IC_FALSE (ic));
4419 /*-----------------------------------------------------------------*/
4420 /* jmpTrueOrFalse - */
4421 /*-----------------------------------------------------------------*/
4423 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4425 // ugly but optimized by peephole
4428 symbol *nlbl = newiTempLabel (NULL);
4429 emitBranch ("bra", nlbl);
4431 emitBranch ("jmp", IC_TRUE (ic));
4436 emitBranch ("jmp", IC_FALSE (ic));
4443 /*-----------------------------------------------------------------*/
4444 /* genAnd - code for and */
4445 /*-----------------------------------------------------------------*/
4447 genAnd (iCode * ic, iCode * ifx)
4449 operand *left, *right, *result;
4450 int size, offset = 0;
4451 unsigned long lit = 0L;
4452 unsigned long litinv;
4458 D(emitcode ("; genAnd",""));
4460 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4461 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4462 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4465 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4467 AOP_TYPE (left), AOP_TYPE (right));
4468 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4470 AOP_SIZE (left), AOP_SIZE (right));
4473 /* if left is a literal & right is not then exchange them */
4474 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4476 operand *tmp = right;
4481 /* if left is accumulator & right is not then exchange them */
4482 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4484 operand *tmp = right;
4489 size = AOP_SIZE (result);
4491 if (AOP_TYPE (right) == AOP_LIT)
4493 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4494 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4496 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4497 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4499 int bitpos = isLiteralBit(litinv)-1;
4500 emitcode ("bclr","#%d,%s",bitpos & 7,
4501 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4509 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4510 if ((AOP_TYPE (right) != AOP_LIT)
4511 || (((lit >> (offset*8)) & 0xff) != 0xff))
4512 accopWithAop ("and", AOP (right), offset);
4513 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4514 hc08_freeReg( hc08_reg_a);
4518 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4519 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4520 freeAsmop (result, NULL, ic, TRUE);
4523 /*-----------------------------------------------------------------*/
4524 /* genOr - code for or */
4525 /*-----------------------------------------------------------------*/
4527 genOr (iCode * ic, iCode * ifx)
4529 operand *left, *right, *result;
4530 int size, offset = 0;
4531 unsigned long lit = 0L;
4533 D(emitcode ("; genOr",""));
4535 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4536 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4537 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4540 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4542 AOP_TYPE (left), AOP_TYPE (right));
4543 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4545 AOP_SIZE (left), AOP_SIZE (right));
4548 /* if left is a literal & right is not then exchange them */
4549 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4551 operand *tmp = right;
4556 /* if left is accumulator & right is not then exchange them */
4557 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4559 operand *tmp = right;
4564 /* if right is bit then exchange them */
4565 if (AOP_TYPE (right) == AOP_CRY &&
4566 AOP_TYPE (left) != AOP_CRY)
4568 operand *tmp = right;
4572 if (AOP_TYPE (right) == AOP_LIT)
4573 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4575 size = AOP_SIZE (result);
4577 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4578 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4579 (AOP_TYPE (left) == AOP_DIR))
4581 int bitpos = isLiteralBit(lit)-1;
4582 emitcode ("bset","#%d,%s",bitpos & 7,
4583 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4592 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4593 accopWithAop ("ora", AOP (right), offset);
4594 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4595 hc08_freeReg( hc08_reg_a);
4600 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4601 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4602 freeAsmop (result, NULL, ic, TRUE);
4605 /*-----------------------------------------------------------------*/
4606 /* genXor - code for xclusive or */
4607 /*-----------------------------------------------------------------*/
4609 genXor (iCode * ic, iCode * ifx)
4611 operand *left, *right, *result;
4612 int size, offset = 0;
4613 unsigned long lit = 0L;
4615 D(emitcode ("; genXor",""));
4617 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4618 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4619 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4622 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4624 AOP_TYPE (left), AOP_TYPE (right));
4625 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4627 AOP_SIZE (left), AOP_SIZE (right));
4630 /* if left is a literal & right is not ||
4631 if left needs acc & right does not */
4632 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4634 operand *tmp = right;
4639 /* if left is accumulator & right is not then exchange them */
4640 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4642 operand *tmp = right;
4647 /* if right is bit then exchange them */
4648 if (AOP_TYPE (right) == AOP_CRY &&
4649 AOP_TYPE (left) != AOP_CRY)
4651 operand *tmp = right;
4655 if (AOP_TYPE (right) == AOP_LIT)
4656 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4658 size = AOP_SIZE (result);
4662 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4663 accopWithAop ("eor", AOP (right), offset);
4664 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4665 hc08_freeReg( hc08_reg_a);
4670 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4671 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4672 freeAsmop (result, NULL, ic, TRUE);
4676 emitinline (iCode * ic, char *inlin)
4682 symbol *sym, *tempsym;
4691 while (isalnum(*inlin) || (*inlin == '_'))
4695 //printf("Found possible symbol '%s'\n",symname);
4696 tempsym = newSymbol (symname, ic->level);
4697 tempsym->block = ic->block;
4698 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4707 aop = aopForSym (ic, sym, FALSE);
4708 l = aopAdrStr (aop, aop->size - 1, TRUE);
4712 if (!sym->allocreq && !sym->ismyparm)
4714 werror (E_ID_UNDEF, sym->name);
4716 " Add 'volatile' to the variable declaration so that it\n"
4717 " can be referenced within inline assembly");
4719 //printf("Replacing with '%s'\n",l);
4723 if ((2+bp-buffer)>sizeof(buffer))
4732 if ((2+bp-buffer)>sizeof(buffer))
4739 if ((2+bp-buffer)>sizeof(buffer))
4740 fprintf(stderr, "Inline assembly buffer overflow\n");
4742 //printf("%s\n",buffer);
4743 emitcode (buffer,"");
4747 /*-----------------------------------------------------------------*/
4748 /* genInline - write the inline code out */
4749 /*-----------------------------------------------------------------*/
4751 genInline (iCode * ic)
4753 char *buffer, *bp, *bp1;
4755 D(emitcode ("; genInline",""));
4757 _G.inLine += (!options.asmpeep);
4759 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4760 strcpy (buffer, IC_INLINE (ic));
4762 /* emit each line as a code */
4768 /* emitcode (bp1, ""); */
4769 emitinline (ic, bp1);
4788 /* emitcode (bp1, ""); */
4789 emitinline (ic, bp1);
4791 /* emitcode("",buffer); */
4792 _G.inLine -= (!options.asmpeep);
4795 /*-----------------------------------------------------------------*/
4796 /* genRRC - rotate right with carry */
4797 /*-----------------------------------------------------------------*/
4801 operand *left, *result;
4802 int size, offset = 0;
4803 bool needpula = FALSE;
4804 bool resultInA = FALSE;
4807 D(emitcode ("; genRRC",""));
4809 /* rotate right with carry */
4810 left = IC_LEFT (ic);
4811 result = IC_RESULT (ic);
4812 aopOp (left, ic, FALSE);
4813 aopOp (result, ic, FALSE);
4815 if ((AOP_TYPE (result) == AOP_REG)
4816 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4819 size = AOP_SIZE (result);
4823 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4827 rmwWithAop (shift, AOP (result), offset--);
4835 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4836 rmwWithReg (shift, hc08_reg_a);
4837 storeRegToAop (hc08_reg_a, AOP (result), offset--);
4838 hc08_freeReg (hc08_reg_a);
4843 if ((!hc08_reg_a->isFree) || resultInA)
4845 pushReg (hc08_reg_a, TRUE);
4849 /* now we need to put the carry into the
4850 highest order byte of the result */
4851 offset = AOP_SIZE (result) - 1;
4852 emitcode ("clra","");
4853 emitcode ("rora","");
4854 hc08_dirtyReg (hc08_reg_a, FALSE);
4857 emitcode ("ora", "1,s");
4858 emitcode ("ais", "#1");
4859 hc08_dirtyReg (hc08_reg_a, FALSE);
4863 accopWithAop ("ora", AOP (result), offset);
4864 storeRegToAop (hc08_reg_a, AOP (result), offset);
4866 pullOrFreeReg (hc08_reg_a, needpula);
4868 freeAsmop (left, NULL, ic, TRUE);
4869 freeAsmop (result, NULL, ic, TRUE);
4872 /*-----------------------------------------------------------------*/
4873 /* genRLC - generate code for rotate left with carry */
4874 /*-----------------------------------------------------------------*/
4878 operand *left, *result;
4879 int size, offset = 0;
4881 bool resultInA = FALSE;
4882 bool needpula = FALSE;
4884 D(emitcode ("; genRLC",""));
4886 /* rotate right with carry */
4887 left = IC_LEFT (ic);
4888 result = IC_RESULT (ic);
4889 aopOp (left, ic, FALSE);
4890 aopOp (result, ic, FALSE);
4892 if ((AOP_TYPE (result) == AOP_REG)
4893 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4896 size = AOP_SIZE (result);
4900 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4904 rmwWithAop (shift, AOP (result), offset--);
4912 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4913 rmwWithReg (shift, hc08_reg_a);
4914 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4915 hc08_freeReg (hc08_reg_a);
4920 if ((!hc08_reg_a->isFree) || resultInA)
4922 pushReg (hc08_reg_a, TRUE);
4926 /* now we need to put the carry into the
4927 lowest order byte of the result */
4929 emitcode ("clra","");
4930 emitcode ("rola","");
4931 hc08_dirtyReg (hc08_reg_a, FALSE);
4934 emitcode ("ora", "1,s");
4935 emitcode ("ais", "#1");
4936 hc08_dirtyReg (hc08_reg_a, FALSE);
4940 accopWithAop ("ora", AOP (result), offset);
4941 storeRegToAop (hc08_reg_a, AOP (result), offset);
4943 pullOrFreeReg (hc08_reg_a, needpula);
4945 freeAsmop (left, NULL, ic, TRUE);
4946 freeAsmop (result, NULL, ic, TRUE);
4949 /*-----------------------------------------------------------------*/
4950 /* genGetHbit - generates code get highest order bit */
4951 /*-----------------------------------------------------------------*/
4953 genGetHbit (iCode * ic)
4955 operand *left, *result;
4957 D(emitcode ("; genGetHbit",""));
4959 left = IC_LEFT (ic);
4960 result = IC_RESULT (ic);
4961 aopOp (left, ic, FALSE);
4962 aopOp (result, ic, FALSE);
4964 /* get the highest order byte into a */
4965 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
4966 emitcode ("rola", "");
4967 emitcode ("clra", "");
4968 emitcode ("rola", "");
4969 hc08_dirtyReg (hc08_reg_a, FALSE);
4970 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4972 freeAsmop (left, NULL, ic, TRUE);
4973 freeAsmop (result, NULL, ic, TRUE);
4977 /*-----------------------------------------------------------------*/
4978 /* AccRol - rotate left accumulator by known count */
4979 /*-----------------------------------------------------------------*/
4981 AccRol (int shCount)
4983 shCount &= 0x0007; // shCount : 0..7
4990 emitcode ("rola", ""); /* 1 cycle */
4993 emitcode ("rola", ""); /* 1 cycle */
4994 emitcode ("rola", ""); /* 1 cycle */
4997 emitcode ("nsa", "");
4998 emitcode ("rora", "");
5001 emitcode ("nsa", ""); /* 3 cycles */
5004 emitcode ("nsa", ""); /* 3 cycles */
5005 emitcode ("rola", ""); /* 1 cycle */
5008 emitcode ("nsa", ""); /* 3 cycles */
5009 emitcode ("rola", ""); /* 1 cycle */
5010 emitcode ("rola", ""); /* 1 cycle */
5013 emitcode ("nsa", ""); /* 3 cycles */
5014 emitcode ("rola", ""); /* 1 cycle */
5015 emitcode ("rola", ""); /* 1 cycle */
5016 emitcode ("rola", ""); /* 1 cycle */
5023 /*-----------------------------------------------------------------*/
5024 /* AccLsh - left shift accumulator by known count */
5025 /*-----------------------------------------------------------------*/
5027 AccLsh (int shCount)
5031 shCount &= 0x0007; // shCount : 0..7
5033 /* Shift counts of 4 and 5 are currently optimized for code size. */
5034 /* Falling through to the unrolled loop would be optimal for code speed. */
5035 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5039 accopWithMisc ("nsa", "");
5040 accopWithMisc ("and", "#0xf0");
5041 /* total: 5 cycles, 3 bytes */
5044 accopWithMisc ("nsa", "");
5045 accopWithMisc ("and", "#0xf0");
5046 accopWithMisc ("lsla", "");
5047 /* total: 6 cycles, 4 bytes */
5050 accopWithMisc ("rora", "");
5051 accopWithMisc ("rora", "");
5052 accopWithMisc ("rora", "");
5053 accopWithMisc ("and", "#0xc0");
5054 /* total: 5 cycles, 5 bytes */
5057 accopWithMisc ("rora", "");
5058 accopWithMisc ("clra", "");
5059 accopWithMisc ("rora", "");
5060 /* total: 3 cycles, 3 bytes */
5064 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5065 /* the fastest (shCount<6) and shortest (shCount<4). */
5066 for (i=0;i<shCount;i++)
5067 accopWithMisc ("lsla", "");
5071 /*-----------------------------------------------------------------*/
5072 /* AccSRsh - signed right shift accumulator by known count */
5073 /*-----------------------------------------------------------------*/
5075 AccSRsh (int shCount)
5079 shCount &= 0x0007; // shCount : 0..7
5083 accopWithMisc ("rola", "");
5084 accopWithMisc ("clra", "");
5085 accopWithMisc ("sbc", zero);
5086 /* total: 4 cycles, 4 bytes */
5090 for (i=0;i<shCount;i++)
5091 accopWithMisc ("asra", "");
5094 /*-----------------------------------------------------------------*/
5095 /* AccRsh - right shift accumulator by known count */
5096 /*-----------------------------------------------------------------*/
5098 AccRsh (int shCount, bool sign)
5108 shCount &= 0x0007; // shCount : 0..7
5110 /* Shift counts of 4 and 5 are currently optimized for code size. */
5111 /* Falling through to the unrolled loop would be optimal for code speed. */
5112 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5116 accopWithMisc ("nsa", "");
5117 accopWithMisc ("and", "#0x0f");
5118 /* total: 5 cycles, 3 bytes */
5121 accopWithMisc ("nsa", "");
5122 accopWithMisc ("and", "#0x0f");
5123 accopWithMisc ("lsra", "");
5124 /* total: 6 cycles, 4 bytes */
5127 accopWithMisc ("rola", "");
5128 accopWithMisc ("rola", "");
5129 accopWithMisc ("rola", "");
5130 accopWithMisc ("and", "#0x03");
5131 /* total: 5 cycles, 5 bytes */
5134 accopWithMisc ("rola", "");
5135 accopWithMisc ("clra", "");
5136 accopWithMisc ("rola", "");
5137 /* total: 3 cycles, 3 bytes */
5141 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5142 /* the fastest (shCount<6) and shortest (shCount<4). */
5143 for (i=0;i<shCount;i++)
5144 accopWithMisc ("lsra", "");
5148 /*-----------------------------------------------------------------*/
5149 /* XAccLsh - left shift register pair XA by known count */
5150 /*-----------------------------------------------------------------*/
5152 XAccLsh (int shCount)
5156 shCount &= 0x000f; // shCount : 0..15
5161 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5162 loadRegFromConst (hc08_reg_a, zero);
5166 /* if we can beat 2n cycles or bytes for some special case, do it here */
5170 /* bytes cycles reg x reg a carry
5171 ** abcd efgh ijkl mnop ?
5172 ** lsrx 1 1 0abc defg ijkl mnop h
5173 ** rora 1 1 0abc defg hijk lmno p
5174 ** tax 1 1 hijk lmno hijk lmno p
5175 ** clra 1 1 hijk lmno 0000 0000 p
5176 ** rora 1 1 hijk lmno p000 0000 0
5177 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5179 rmwWithReg ("lsr", hc08_reg_x);
5180 rmwWithReg ("ror", hc08_reg_a);
5181 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5182 loadRegFromConst (hc08_reg_a, zero);
5183 rmwWithReg ("ror", hc08_reg_a);
5190 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5191 /* the fastest and shortest. */
5192 for (i=0;i<shCount;i++)
5194 rmwWithReg ("lsl", hc08_reg_a);
5195 rmwWithReg ("rol", hc08_reg_x);
5199 /*-----------------------------------------------------------------*/
5200 /* XAccSRsh - signed right shift register pair XA by known count */
5201 /*-----------------------------------------------------------------*/
5203 XAccSRsh (int shCount)
5207 shCount &= 0x000f; // shCount : 0..7
5209 /* if we can beat 2n cycles or bytes for some special case, do it here */
5213 /* bytes cycles reg x reg a carry
5214 ** abcd efgh ijkl mnop ?
5215 ** lslx 1 1 bcde fgh0 ijkl mnop a
5216 ** clra 1 1 bcde fgh0 0000 0000 a
5217 ** rola 1 1 bcde fgh0 0000 000a 0
5218 ** nega 1 1 bcde fgh0 aaaa aaaa a
5219 ** tax 1 1 aaaa aaaa aaaa aaaa a
5220 ** total: 5 cycles, 5 bytes
5222 rmwWithReg ("lsl", hc08_reg_x);
5223 loadRegFromConst (hc08_reg_a, zero);
5224 rmwWithReg ("rol", hc08_reg_a);
5225 rmwWithReg ("neg", hc08_reg_a);
5226 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5236 /* bytes cycles reg x reg a carry
5237 ** abcd efgh ijkl mnop ?
5238 ** txa 1 1 abcd efgh abcd efgh ?
5239 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5240 ** lsla 1 1 abcd efgh ???? ???? a
5241 ** clrx 1 1 0000 0000 ???? ???? a
5242 ** rolx 1 1 0000 000a ???? ???? 0
5243 ** negx 1 1 aaaa aaaa ???? ???? a
5244 ** rora 1 1 aaaa aaaa LSBresult 0
5245 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5247 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5248 AccSRsh (shCount-8);
5249 rmwWithReg ("lsl", hc08_reg_a);
5250 loadRegFromConst (hc08_reg_x, zero);
5251 rmwWithReg ("rol", hc08_reg_x);
5252 rmwWithReg ("neg", hc08_reg_x);
5253 rmwWithReg ("ror", hc08_reg_a);
5260 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5261 /* the fastest and shortest. */
5262 for (i=0;i<shCount;i++)
5264 rmwWithReg ("asr", hc08_reg_x);
5265 rmwWithReg ("ror", hc08_reg_a);
5269 /*-----------------------------------------------------------------*/
5270 /* XAccRsh - right shift register pair XA by known count */
5271 /*-----------------------------------------------------------------*/
5273 XAccRsh (int shCount, bool sign)
5283 shCount &= 0x000f; // shCount : 0..f
5285 /* if we can beat 2n cycles or bytes for some special case, do it here */
5289 /* bytes cycles reg x reg a carry
5290 ** abcd efgh ijkl mnop ?
5291 ** clra 1 1 abcd efgh 0000 0000 a
5292 ** lslx 1 1 bcde fgh0 0000 0000 a
5293 ** rola 1 1 bcde fgh0 0000 000a 0
5294 ** clrx 1 1 0000 0000 0000 000a 0
5295 ** total: 4 cycles, 4 bytes
5297 loadRegFromConst (hc08_reg_x, zero);
5298 rmwWithReg ("lsl", hc08_reg_x);
5299 rmwWithReg ("rol", hc08_reg_a);
5300 loadRegFromConst (hc08_reg_a, zero);
5304 /* bytes cycles reg x reg a carry
5305 ** abcd efgh ijkl mnop ?
5306 ** clra 1 1 abcd efgh 0000 0000 a
5307 ** lslx 1 1 bcde fgh0 0000 0000 a
5308 ** rola 1 1 bcde fgh0 0000 000a 0
5309 ** lslx 1 1 cdef gh00 0000 000a b
5310 ** rola 1 1 cdef gh00 0000 00ab 0
5311 ** clrx 1 1 0000 0000 0000 000a 0
5312 ** total: 6 cycles, 6 bytes
5314 loadRegFromConst (hc08_reg_x, zero);
5315 rmwWithReg ("lsl", hc08_reg_x);
5316 rmwWithReg ("rol", hc08_reg_a);
5317 rmwWithReg ("lsl", hc08_reg_x);
5318 rmwWithReg ("rol", hc08_reg_a);
5319 loadRegFromConst (hc08_reg_a, zero);
5328 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5329 AccRsh (shCount-8, FALSE);
5330 loadRegFromConst (hc08_reg_x, zero);
5334 /* bytes cycles reg x reg a carry
5335 ** abcd efgh ijkl mnop ?
5336 ** lsla 1 1 abcd efgh jklm nop0 i
5337 ** txa 1 1 abcd efgh abcd efgh i
5338 ** rola 1 1 abcd efgh bcde fghi a
5339 ** clrx 1 1 0000 0000 bcde fghi a
5340 ** rolx 1 1 0000 000a bcde fghi 0
5341 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5343 rmwWithReg ("lsl", hc08_reg_a);
5344 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5345 rmwWithReg ("rol", hc08_reg_a);
5346 loadRegFromConst (hc08_reg_x, zero);
5347 rmwWithReg ("rol", hc08_reg_x);
5350 /* bytes cycles reg x reg a carry
5351 ** abcd efgh ijkl mnop ?
5352 ** lsla 1 1 abcd efgh jklm nop0 i
5353 ** rolx 1 1 bcde fghi jklm nop0 a
5354 ** rola 1 1 bcde fghi klmn op0a j
5355 ** rolx 1 1 cdef ghij klmn op0a b
5356 ** rola 1 1 cdef ghij lmno p0ab k
5357 ** and #3 2 2 cdef ghij 0000 00ab k
5358 ** psha 1 2 cdef ghij 0000 00ab k
5359 ** txa 1 1 cdef ghij cdef ghij k
5360 ** pula 1 2 0000 00ab cdef ghij k
5361 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5367 /* lslx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5368 /* the fastest and shortest. */
5369 for (i=0;i<shCount;i++)
5371 rmwWithReg ("lsl", hc08_reg_x);
5372 rmwWithReg ("rol", hc08_reg_a);
5379 /*-----------------------------------------------------------------*/
5380 /* shiftR1Left2Result - shift right one byte from left to result */
5381 /*-----------------------------------------------------------------*/
5383 shiftR1Left2Result (operand * left, int offl,
5384 operand * result, int offr,
5385 int shCount, int sign)
5387 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5388 /* shift right accumulator */
5389 AccRsh (shCount, sign);
5390 storeRegToAop (hc08_reg_a, AOP (result), offr);
5394 /*-----------------------------------------------------------------*/
5395 /* shiftL1Left2Result - shift left one byte from left to result */
5396 /*-----------------------------------------------------------------*/
5398 shiftL1Left2Result (operand * left, int offl,
5399 operand * result, int offr, int shCount)
5401 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5402 /* shift left accumulator */
5404 storeRegToAop (hc08_reg_a, AOP (result), offr);
5407 /*-----------------------------------------------------------------*/
5408 /* movLeft2Result - move byte from left to result */
5409 /*-----------------------------------------------------------------*/
5411 movLeft2Result (operand * left, int offl,
5412 operand * result, int offr, int sign)
5414 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5416 transferAopAop (AOP (left), offl, AOP (result), offr);
5421 /*-----------------------------------------------------------------*/
5422 /* shiftL2Left2Result - shift left two bytes from left to result */
5423 /*-----------------------------------------------------------------*/
5425 shiftL2Left2Result (operand * left, int offl,
5426 operand * result, int offr, int shCount)
5429 bool needpula = FALSE;
5430 bool needpulx = FALSE;
5432 needpula = pushRegIfUsed (hc08_reg_a);
5433 needpulx = pushRegIfUsed (hc08_reg_x);
5435 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5440 rmwWithReg ("lsr", hc08_reg_x);
5441 rmwWithReg ("ror", hc08_reg_a);
5442 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5443 rmwWithReg ("clr", hc08_reg_a);
5444 rmwWithReg ("ror", hc08_reg_a);
5447 for (i=0; i<shCount; i++)
5449 rmwWithReg ("lsl", hc08_reg_a);
5450 rmwWithReg ("rol", hc08_reg_x);
5453 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5455 pullOrFreeReg (hc08_reg_x, needpulx);
5456 pullOrFreeReg (hc08_reg_a, needpula);
5462 /*-----------------------------------------------------------------*/
5463 /* shiftR2Left2Result - shift right two bytes from left to result */
5464 /*-----------------------------------------------------------------*/
5466 shiftR2Left2Result (operand * left, int offl,
5467 operand * result, int offr,
5468 int shCount, int sign)
5471 bool needpula = FALSE;
5472 bool needpulx = FALSE;
5474 needpula = pushRegIfUsed (hc08_reg_a);
5475 needpulx = pushRegIfUsed (hc08_reg_x);
5477 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5478 for (i=0; i<shCount; i++)
5481 rmwWithReg ("asr", hc08_reg_x);
5483 rmwWithReg ("lsr", hc08_reg_x);
5484 rmwWithReg ("ror", hc08_reg_a);
5486 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5488 pullOrFreeReg (hc08_reg_x, needpulx);
5489 pullOrFreeReg (hc08_reg_a, needpula);
5494 /*-----------------------------------------------------------------*/
5495 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5496 /*-----------------------------------------------------------------*/
5498 shiftLLeftOrResult (operand * left, int offl,
5499 operand * result, int offr, int shCount)
5501 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5502 /* shift left accumulator */
5504 /* or with result */
5505 accopWithAop ("ora", AOP (result), offr);
5506 /* back to result */
5507 storeRegToAop (hc08_reg_a, AOP (result), offr);
5508 hc08_freeReg (hc08_reg_a);
5512 /*-----------------------------------------------------------------*/
5513 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5514 /*-----------------------------------------------------------------*/
5516 shiftRLeftOrResult (operand * left, int offl,
5517 operand * result, int offr, int shCount)
5519 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5520 /* shift left accumulator */
5521 AccRsh (shCount, FALSE);
5522 /* or with result */
5523 accopWithAop ("ora", AOP (result), offr);
5524 /* back to result */
5525 storeRegToAop (hc08_reg_a, AOP (result), offr);
5526 hc08_freeReg (hc08_reg_a);
5529 /*-----------------------------------------------------------------*/
5530 /* genlshOne - left shift a one byte quantity by known count */
5531 /*-----------------------------------------------------------------*/
5533 genlshOne (operand * result, operand * left, int shCount)
5535 D(emitcode ("; genlshOne",""));
5537 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5540 /*-----------------------------------------------------------------*/
5541 /* genlshTwo - left shift two bytes by known amount != 0 */
5542 /*-----------------------------------------------------------------*/
5544 genlshTwo (operand * result, operand * left, int shCount)
5548 D(emitcode ("; genlshTwo",""));
5551 size = getDataSize (result);
5553 /* if shCount >= 8 */
5560 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5562 storeRegToAop (hc08_reg_a, AOP (result), 1);
5564 storeConstToAop(zero, AOP (result), LSB);
5567 /* 1 <= shCount <= 7 */
5570 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5572 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5576 /*-----------------------------------------------------------------*/
5577 /* shiftLLong - shift left one long from left to result */
5578 /* offl = LSB or MSB16 */
5579 /*-----------------------------------------------------------------*/
5581 shiftLLong (operand * left, operand * result, int offr)
5584 // int size = AOP_SIZE (result);
5586 bool needpula = FALSE;
5587 bool needpulx = FALSE;
5589 needpula = pushRegIfUsed (hc08_reg_a);
5590 needpulx = pushRegIfUsed (hc08_reg_x);
5592 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5593 rmwWithReg ("lsl", hc08_reg_a);
5594 rmwWithReg ("rol", hc08_reg_x);
5595 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5599 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5600 rmwWithReg ("rol", hc08_reg_a);
5601 rmwWithReg ("rol", hc08_reg_x);
5602 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5604 else if (offr==MSB16)
5606 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5607 rmwWithReg ("rol", hc08_reg_a);
5608 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5611 pullOrFreeReg (hc08_reg_x, needpulx);
5612 pullOrFreeReg (hc08_reg_a, needpula);
5615 /*-----------------------------------------------------------------*/
5616 /* genlshFour - shift four byte by a known amount != 0 */
5617 /*-----------------------------------------------------------------*/
5619 genlshFour (operand * result, operand * left, int shCount)
5623 D(emitcode ("; genlshFour",""));
5625 size = AOP_SIZE (result);
5627 /* TODO: deal with the &result == &left case */
5629 /* if shifting more that 3 bytes */
5634 /* lowest order of left goes to the highest
5635 order of the destination */
5636 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5638 movLeft2Result (left, LSB, result, MSB32, 0);
5639 storeConstToAop (zero, AOP (result), LSB);
5640 storeConstToAop (zero, AOP (result), MSB16);
5641 storeConstToAop (zero, AOP (result), MSB24);
5645 /* more than two bytes */
5646 else if (shCount >= 16)
5648 /* lower order two bytes goes to higher order two bytes */
5650 /* if some more remaining */
5652 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5655 movLeft2Result (left, MSB16, result, MSB32, 0);
5656 movLeft2Result (left, LSB, result, MSB24, 0);
5658 storeConstToAop (zero, AOP (result), LSB);
5659 storeConstToAop (zero, AOP (result), MSB16);
5663 /* if more than 1 byte */
5664 else if (shCount >= 8)
5666 /* lower order three bytes goes to higher order three bytes */
5671 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5673 movLeft2Result (left, LSB, result, MSB16, 0);
5679 movLeft2Result (left, MSB24, result, MSB32, 0);
5680 movLeft2Result (left, MSB16, result, MSB24, 0);
5681 movLeft2Result (left, LSB, result, MSB16, 0);
5682 storeConstToAop (zero, AOP (result), LSB);
5684 else if (shCount == 1)
5685 shiftLLong (left, result, MSB16);
5688 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5689 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5690 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5691 storeConstToAop (zero, AOP (result), LSB);
5696 /* 1 <= shCount <= 7 */
5697 else if (shCount <= 2)
5699 shiftLLong (left, result, LSB);
5701 shiftLLong (result, result, LSB);
5703 /* 3 <= shCount <= 7, optimize */
5706 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5707 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5708 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5712 /*-----------------------------------------------------------------*/
5713 /* genLeftShiftLiteral - left shifting by known count */
5714 /*-----------------------------------------------------------------*/
5716 genLeftShiftLiteral (operand * left,
5721 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5724 D(emitcode ("; genLeftShiftLiteral",""));
5726 freeAsmop (right, NULL, ic, TRUE);
5728 aopOp (left, ic, FALSE);
5729 aopOp (result, ic, FALSE);
5731 // size = getSize (operandType (result));
5732 size = AOP_SIZE (result);
5735 emitcode ("; shift left ", "result %d, left %d", size,
5742 transferAopAop( AOP(left), size, AOP(result), size);
5744 else if (shCount >= (size * 8))
5747 storeConstToAop (zero, AOP (result), size);
5754 genlshOne (result, left, shCount);
5758 genlshTwo (result, left, shCount);
5762 genlshFour (result, left, shCount);
5765 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5766 "*** ack! mystery literal shift!\n");
5770 freeAsmop (left, NULL, ic, TRUE);
5771 freeAsmop (result, NULL, ic, TRUE);
5774 /*-----------------------------------------------------------------*/
5775 /* genLeftShift - generates code for left shifting */
5776 /*-----------------------------------------------------------------*/
5778 genLeftShift (iCode * ic)
5780 operand *left, *right, *result;
5782 symbol *tlbl, *tlbl1;
5787 D(emitcode ("; genLeftShift",""));
5789 right = IC_RIGHT (ic);
5790 left = IC_LEFT (ic);
5791 result = IC_RESULT (ic);
5793 aopOp (right, ic, FALSE);
5795 /* if the shift count is known then do it
5796 as efficiently as possible */
5797 if (AOP_TYPE (right) == AOP_LIT)
5799 genLeftShiftLiteral (left, right, result, ic);
5803 /* shift count is unknown then we have to form
5804 a loop get the loop count in A : Note: we take
5805 only the lower order byte since shifting
5806 more that 32 bits make no sense anyway, ( the
5807 largest size of an object can be only 32 bits ) */
5809 aopOp (left, ic, FALSE);
5810 aopOp (result, ic, FALSE);
5812 /* now move the left to the result if they are not the
5814 if (!sameRegs (AOP (left), AOP (result)))
5817 size = AOP_SIZE (result);
5821 transferAopAop (AOP (left), offset, AOP (result), offset);
5825 freeAsmop (left, NULL, ic, TRUE);
5827 tlbl = newiTempLabel (NULL);
5828 size = AOP_SIZE (result);
5830 tlbl1 = newiTempLabel (NULL);
5834 loadRegFromAop (reg, AOP (right), 0);
5835 freeAsmop (right, NULL, ic, TRUE);
5836 emitBranch ("beq", tlbl1);
5840 for (offset=0;offset<size;offset++)
5842 rmwWithAop (shift, AOP (result), offset);
5845 rmwWithReg ("dec", reg);
5846 emitBranch ("bne", tlbl);
5850 freeAsmop (result, NULL, ic, TRUE);
5853 /*-----------------------------------------------------------------*/
5854 /* genrshOne - right shift a one byte quantity by known count */
5855 /*-----------------------------------------------------------------*/
5857 genrshOne (operand * result, operand * left,
5858 int shCount, int sign)
5860 D(emitcode ("; genrshOne",""));
5862 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5863 AccRsh (shCount, sign);
5864 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5867 /*-----------------------------------------------------------------*/
5868 /* genrshTwo - right shift two bytes by known amount != 0 */
5869 /*-----------------------------------------------------------------*/
5871 genrshTwo (operand * result, operand * left,
5872 int shCount, int sign)
5874 D(emitcode ("; genrshTwo",""));
5876 /* if shCount >= 8 */
5879 if (shCount || sign)
5881 loadRegFromAop (hc08_reg_a, AOP (left), 1);
5882 AccRsh (shCount-8, sign);
5883 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5887 transferAopAop (AOP (left), 1, AOP (result), 0);
5888 storeConstToAop (zero, AOP (result), 1);
5892 /* 1 <= shCount <= 7 */
5895 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5896 XAccRsh (shCount, sign);
5897 storeRegToAop (hc08_reg_xa, AOP (result), 0);
5901 /*-----------------------------------------------------------------*/
5902 /* shiftRLong - shift right one long from left to result */
5903 /* offl = LSB or MSB16 */
5904 /*-----------------------------------------------------------------*/
5906 shiftRLong (operand * left, int offl,
5907 operand * result, int sign)
5910 // int size = AOP_SIZE (result);
5912 bool needpula = FALSE;
5913 bool needpulx = FALSE;
5915 needpula = pushRegIfUsed (hc08_reg_a);
5916 needpulx = pushRegIfUsed (hc08_reg_x);
5920 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5922 rmwWithReg ("asr", hc08_reg_x);
5924 rmwWithReg ("lsr", hc08_reg_x);
5925 rmwWithReg ("rol", hc08_reg_a);
5926 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
5928 else if (offl==MSB16)
5930 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
5932 rmwWithReg ("asr", hc08_reg_a);
5934 rmwWithReg ("lsr", hc08_reg_a);
5935 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
5938 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5939 rmwWithReg ("ror", hc08_reg_x);
5940 rmwWithReg ("ror", hc08_reg_a);
5941 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
5944 pullOrFreeReg (hc08_reg_x, needpulx);
5945 pullOrFreeReg (hc08_reg_a, needpula);
5948 /*-----------------------------------------------------------------*/
5949 /* genrshFour - shift four byte by a known amount != 0 */
5950 /*-----------------------------------------------------------------*/
5952 genrshFour (operand * result, operand * left,
5953 int shCount, int sign)
5955 /* TODO: handle cases where left == result */
5957 D(emitcode ("; genrshFour",""));
5959 /* if shifting more that 3 bytes */
5962 loadRegFromAop (hc08_reg_a, AOP (left), 3);
5963 AccRsh (shCount-24, sign);
5964 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5967 else if (shCount >= 16)
5969 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
5970 XAccRsh (shCount-16, sign);
5971 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
5974 else if (shCount >= 8)
5977 shiftRLong (left, MSB16, result, sign);
5978 else if (shCount == 8)
5980 transferAopAop (AOP (left), 1, AOP (result), 0);
5981 transferAopAop (AOP (left), 2, AOP (result), 1);
5982 loadRegFromAop (hc08_reg_a, AOP (left), 3);
5983 storeRegToAop (hc08_reg_a, AOP (result), 2);
5984 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
5986 else if (shCount == 9)
5988 shiftRLong (left, MSB16, result, sign);
5992 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
5993 XAccRsh (shCount-8, FALSE);
5994 storeRegToAop (hc08_reg_xa, AOP (result), 0);
5995 loadRegFromAop (hc08_reg_x, AOP (left), 3);
5996 loadRegFromConst (hc08_reg_a, zero);
5997 XAccRsh (shCount-8, sign);
5998 accopWithAop ("ora", AOP (result), 1);
5999 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6003 { /* 1 <= shCount <= 7 */
6006 shiftRLong (left, LSB, result, sign);
6010 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6011 XAccRsh (shCount, FALSE);
6012 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6013 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6015 accopWithAop ("ora", AOP (result), 1);
6016 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6017 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6018 XAccRsh (shCount, sign);
6019 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6024 /*-----------------------------------------------------------------*/
6025 /* genRightShiftLiteral - right shifting by known count */
6026 /*-----------------------------------------------------------------*/
6028 genRightShiftLiteral (operand * left,
6034 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6037 D(emitcode ("; genRightShiftLiteral",""));
6039 freeAsmop (right, NULL, ic, TRUE);
6041 aopOp (left, ic, FALSE);
6042 aopOp (result, ic, FALSE);
6045 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6049 size = getDataSize (left);
6050 /* test the LEFT size !!! */
6052 /* I suppose that the left size >= result size */
6055 size = getDataSize (result);
6057 transferAopAop (AOP (left), size, AOP(result), size);
6059 else if (shCount >= (size * 8))
6062 /* get sign in acc.7 */
6063 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6065 addSign (result, LSB, sign);
6072 genrshOne (result, left, shCount, sign);
6076 genrshTwo (result, left, shCount, sign);
6080 genrshFour (result, left, shCount, sign);
6086 freeAsmop (left, NULL, ic, TRUE);
6087 freeAsmop (result, NULL, ic, TRUE);
6091 /*-----------------------------------------------------------------*/
6092 /* genRightShift - generate code for right shifting */
6093 /*-----------------------------------------------------------------*/
6095 genRightShift (iCode * ic)
6097 operand *right, *left, *result;
6101 symbol *tlbl, *tlbl1;
6105 D(emitcode ("; genRightShift",""));
6107 /* if signed then we do it the hard way preserve the
6108 sign bit moving it inwards */
6109 retype = getSpec (operandType (IC_RESULT (ic)));
6110 sign = !SPEC_USIGN (retype);
6112 /* signed & unsigned types are treated the same : i.e. the
6113 signed is NOT propagated inwards : quoting from the
6114 ANSI - standard : "for E1 >> E2, is equivalent to division
6115 by 2**E2 if unsigned or if it has a non-negative value,
6116 otherwise the result is implementation defined ", MY definition
6117 is that the sign does not get propagated */
6119 right = IC_RIGHT (ic);
6120 left = IC_LEFT (ic);
6121 result = IC_RESULT (ic);
6123 aopOp (right, ic, FALSE);
6125 /* if the shift count is known then do it
6126 as efficiently as possible */
6127 if (AOP_TYPE (right) == AOP_LIT)
6129 genRightShiftLiteral (left, right, result, ic, sign);
6133 /* shift count is unknown then we have to form
6134 a loop get the loop count in X : Note: we take
6135 only the lower order byte since shifting
6136 more that 32 bits make no sense anyway, ( the
6137 largest size of an object can be only 32 bits ) */
6139 aopOp (left, ic, FALSE);
6140 aopOp (result, ic, FALSE);
6142 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6143 AOP (result) = forceStackedAop (AOP (result));
6145 size = AOP_SIZE (result);
6149 transferAopAop (AOP (left), offset, AOP (result), offset);
6153 tlbl = newiTempLabel (NULL);
6154 size = AOP_SIZE (result);
6156 tlbl1 = newiTempLabel (NULL);
6158 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6159 emitcode ("tstx", "");
6160 emitcode ("beq", "%05d$", tlbl1->key + 100);
6161 emitcode ("", "%05d$:", tlbl->key + 100);
6162 shift= sign ? "asr" : "lsr";
6163 for (offset=size-1;offset>=0;offset--)
6165 rmwWithAop (shift, AOP (result), offset);
6168 rmwWithReg ("dec", hc08_reg_x);
6169 emitcode ("bne","%05d$", tlbl->key + 100);
6170 emitcode ("", "%05d$:", tlbl1->key + 100);
6172 freeAsmop (result, NULL, ic, TRUE);
6173 freeAsmop (left, NULL, ic, TRUE);
6174 freeAsmop (right, NULL, ic, TRUE);
6177 /*-----------------------------------------------------------------*/
6178 /* genUnpackBits - generates code for unpacking bits */
6179 /*-----------------------------------------------------------------*/
6181 genUnpackBits (operand * result)
6183 int offset = 0; /* result byte offset */
6184 int rsize; /* result size */
6185 int rlen = 0; /* remaining bitfield length */
6186 sym_link *etype; /* bitfield type information */
6187 int blen; /* bitfield length */
6188 int bstr; /* bitfield starting bit within byte */
6190 D(emitcode ("; genUnpackBits",""));
6192 etype = getSpec (operandType (result));
6193 rsize = getSize (operandType (result));
6194 blen = SPEC_BLEN (etype);
6195 bstr = SPEC_BSTR (etype);
6197 /* If the bitfield length is less than a byte */
6200 emitcode ("lda", ",x");
6201 hc08_dirtyReg (hc08_reg_a, FALSE);
6202 AccRsh (bstr, FALSE);
6203 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6204 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6208 /* Bit field did not fit in a byte. Copy all
6209 but the partial byte at the end. */
6210 for (rlen=blen;rlen>=8;rlen-=8)
6212 emitcode ("lda", ",x");
6213 hc08_dirtyReg (hc08_reg_a, FALSE);
6214 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6216 emitcode ("aix", "#1");
6219 /* Handle the partial byte at the end */
6222 emitcode ("lda", ",x");
6223 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6224 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6232 storeConstToAop (zero, AOP (result), offset++);
6237 /*-----------------------------------------------------------------*/
6238 /* genDataPointerGet - generates code when ptr offset is known */
6239 /*-----------------------------------------------------------------*/
6241 genDataPointerGet (operand * left,
6245 int size, offset = 0;
6248 D(emitcode ("; genDataPointerGet",""));
6250 aopOp (result, ic, TRUE);
6251 size = AOP_SIZE (result);
6253 derefaop = aopDerefAop (AOP (left));
6254 freeAsmop (left, NULL, ic, TRUE);
6255 derefaop->size = size;
6259 transferAopAop(derefaop, offset, AOP (result), offset);
6263 freeAsmop (NULL, derefaop, ic, TRUE);
6264 freeAsmop (result, NULL, ic, TRUE);
6268 /*-----------------------------------------------------------------*/
6269 /* genNearPointerGet - emitcode for near pointer fetch */
6270 /*-----------------------------------------------------------------*/
6272 genNearPointerGet (operand * left,
6278 sym_link *retype = getSpec (operandType (result));
6280 D(emitcode ("; genNearPointerGet",""));
6282 aopOp (left, ic, FALSE);
6284 /* if left is rematerialisable and
6285 result is not bit variable type and
6286 the left is pointer to data space i.e
6287 lower 128 bytes of space */
6288 if ((AOP_TYPE (left) == AOP_IMMD)
6289 || (AOP_TYPE (left) == AOP_LIT)
6290 /* !IS_BITVAR (retype) */
6291 /* && DCL_TYPE (ltype) == POINTER */ )
6293 genDataPointerGet (left, result, ic);
6297 /* if the operand is already in hx
6298 then we do nothing else we move the value to hx */
6299 if (AOP_TYPE (left) != AOP_STR)
6301 /* if this is remateriazable */
6302 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6303 loadRegFromConst (hc08_reg_h, zero);
6306 /* so hx now contains the address */
6307 aopOp (result, ic, FALSE);
6309 /* if bit then unpack */
6310 if (IS_BITVAR (retype))
6311 genUnpackBits (result);
6314 size = AOP_SIZE (result);
6319 accopWithMisc ("lda", ",x");
6322 rmwWithReg ("inc", hc08_reg_x);
6324 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6325 hc08_freeReg (hc08_reg_a);
6329 freeAsmop (left, NULL, ic, TRUE);
6330 freeAsmop (result, NULL, ic, TRUE);
6332 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6333 aopOp (IC_RESULT (pi), pi, FALSE);
6334 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6335 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6339 hc08_freeReg (hc08_reg_hx);
6343 /*-----------------------------------------------------------------*/
6344 /* genFarPointerGet - get value from far space */
6345 /*-----------------------------------------------------------------*/
6347 genFarPointerGet (operand * left,
6348 operand * result, iCode * ic, iCode * pi)
6351 sym_link *retype = getSpec (operandType (result));
6353 D(emitcode ("; genFarPointerGet",""));
6355 aopOp (left, ic, FALSE);
6357 /* if left is rematerialisable and
6358 result is not bit variable type and
6359 the left is pointer to data space i.e
6360 lower 128 bytes of space */
6361 if (AOP_TYPE (left) == AOP_IMMD &&
6363 /* && DCL_TYPE (ltype) == POINTER */ )
6365 genDataPointerGet (left, result, ic);
6369 /* if the operand is already in hx
6370 then we do nothing else we move the value to hx */
6371 if (AOP_TYPE (left) != AOP_STR)
6373 /* if this is remateriazable */
6374 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6377 /* so hx now contains the address */
6378 aopOp (result, ic, FALSE);
6380 /* if bit then unpack */
6381 if (IS_BITVAR (retype))
6382 genUnpackBits (result);
6385 size = AOP_SIZE (result);
6390 accopWithMisc ("lda", ",x");
6393 emitcode ("aix", "#1");
6394 hc08_dirtyReg (hc08_reg_hx, FALSE);
6396 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6397 hc08_freeReg (hc08_reg_a);
6401 freeAsmop (left, NULL, ic, TRUE);
6402 freeAsmop (result, NULL, ic, TRUE);
6404 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6405 aopOp (IC_RESULT (pi), pi, FALSE);
6406 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6407 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6411 hc08_freeReg (hc08_reg_hx);
6417 /*-----------------------------------------------------------------*/
6418 /* genPointerGet - generate code for pointer get */
6419 /*-----------------------------------------------------------------*/
6421 genPointerGet (iCode * ic, iCode *pi)
6423 operand *left, *result;
6424 sym_link *type, *etype;
6427 D(emitcode ("; genPointerGet",""));
6429 left = IC_LEFT (ic);
6430 result = IC_RESULT (ic);
6432 /* depending on the type of pointer we need to
6433 move it to the correct pointer register */
6434 type = operandType (left);
6435 etype = getSpec (type);
6436 /* if left is of type of pointer then it is simple */
6437 if (IS_PTR (type) && !IS_FUNC (type->next))
6438 p_type = DCL_TYPE (type);
6441 /* we have to go by the storage class */
6442 p_type = PTR_TYPE (SPEC_OCLS (etype));
6445 /* special case when cast remat */
6446 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
6447 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6448 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6449 type = operandType (left);
6450 p_type = DCL_TYPE (type);
6452 /* now that we have the pointer type we assign
6453 the pointer values */
6460 genNearPointerGet (left, result, ic, pi);
6466 genFarPointerGet (left, result, ic, pi);
6473 /*-----------------------------------------------------------------*/
6474 /* genPackBits - generates code for packed bit storage */
6475 /*-----------------------------------------------------------------*/
6477 genPackBits (sym_link * etype,
6480 int offset = 0; /* source byte offset */
6481 int rlen = 0; /* remaining bitfield length */
6482 int blen; /* bitfield length */
6483 int bstr; /* bitfield starting bit within byte */
6484 int litval; /* source literal value (if AOP_LIT) */
6485 unsigned char mask; /* bitmask within current byte */
6487 D(emitcode ("; genPackBits",""));
6489 blen = SPEC_BLEN (etype);
6490 bstr = SPEC_BSTR (etype);
6492 /* If the bitfield length is less than a byte */
6495 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6496 (unsigned char) (0xFF >> (8 - bstr)));
6498 if (AOP_TYPE (right) == AOP_LIT)
6500 /* Case with a bitfield length <8 and literal source
6502 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6504 litval &= (~mask) & 0xff;
6506 emitcode ("lda", ",x");
6507 if ((mask|litval)!=0xff)
6508 emitcode ("and","#0x%02x", mask);
6510 emitcode ("ora","#0x%02x", litval);
6511 hc08_dirtyReg (hc08_reg_a, FALSE);
6512 emitcode ("sta", ",x");
6514 hc08_freeReg (hc08_reg_a);
6518 /* Case with a bitfield length < 8 and arbitrary source
6520 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6521 /* shift and mask source value */
6523 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6524 hc08_dirtyReg (hc08_reg_a, FALSE);
6525 pushReg (hc08_reg_a, TRUE);
6527 emitcode ("lda", ",x");
6528 emitcode ("and", "#0x%02x", mask);
6529 emitcode ("ora", "1,s");
6530 emitcode ("sta", ",x");
6531 pullReg (hc08_reg_a);
6533 hc08_freeReg (hc08_reg_a);
6537 /* Bit length is greater than 7 bits. In this case, copy */
6538 /* all except the partial byte at the end */
6539 for (rlen=blen;rlen>=8;rlen-=8)
6541 if (AOP (right)->type == AOP_DIR)
6543 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6547 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6548 emitcode ("sta", "%d,x", offset);
6553 /* If there was a partial byte at the end */
6556 mask = (((unsigned char) -1 << rlen) & 0xff);
6558 if (AOP_TYPE (right) == AOP_LIT)
6560 /* Case with partial byte and literal source
6562 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6563 litval >>= (blen-rlen);
6564 litval &= (~mask) & 0xff;
6565 emitcode ("lda", "%d,x", offset);
6566 hc08_dirtyReg (hc08_reg_a, FALSE);
6567 if ((mask|litval)!=0xff)
6568 emitcode ("and","#0x%02x", mask);
6570 emitcode ("ora","#0x%02x", litval);
6571 emitcode ("sta", "%d,x", offset);
6572 hc08_dirtyReg (hc08_reg_a, FALSE);
6573 hc08_freeReg (hc08_reg_a);
6577 /* Case with partial byte and arbitrary source
6579 loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6580 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6581 hc08_dirtyReg (hc08_reg_a, FALSE);
6582 pushReg (hc08_reg_a, TRUE);
6584 emitcode ("lda", ",x");
6585 emitcode ("and", "#0x%02x", mask);
6586 emitcode ("ora", "1,s");
6587 emitcode ("sta", ",x");
6590 hc08_freeReg (hc08_reg_a);
6593 /*-----------------------------------------------------------------*/
6594 /* genDataPointerSet - remat pointer to data space */
6595 /*-----------------------------------------------------------------*/
6597 genDataPointerSet (operand * right,
6601 int size, offset = 0;
6604 D(emitcode ("; genDataPointerSet",""));
6606 aopOp (right, ic, FALSE);
6607 size = AOP_SIZE (right);
6609 derefaop = aopDerefAop (AOP (result));
6610 freeAsmop (result, NULL, ic, TRUE);
6611 derefaop->size = size;
6615 transferAopAop (AOP (right), offset, derefaop, offset);
6619 freeAsmop (right, NULL, ic, TRUE);
6620 freeAsmop (NULL, derefaop, ic, TRUE);
6624 /*-----------------------------------------------------------------*/
6625 /* genNearPointerSet - emitcode for near pointer put */
6626 /*-----------------------------------------------------------------*/
6628 genNearPointerSet (operand * right,
6634 sym_link *retype = getSpec (operandType (right));
6635 sym_link *letype = getSpec (operandType (result));
6637 D(emitcode ("; genNearPointerSet",""));
6639 aopOp (result, ic, FALSE);
6641 /* if the result is rematerializable &
6642 in data space & not a bit variable */
6643 if (AOP_TYPE (result) == AOP_IMMD &&
6644 /* DCL_TYPE (ptype) == POINTER && */
6645 !IS_BITVAR (retype) &&
6646 !IS_BITVAR (letype))
6648 genDataPointerSet (right, result, ic);
6652 /* if the operand is already in hx
6653 then we do nothing else we move the value to hx */
6654 if (AOP_TYPE (result) != AOP_STR)
6656 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6657 loadRegFromConst (hc08_reg_h, zero);
6659 /* so hx now contains the address */
6660 aopOp (right, ic, FALSE);
6662 /* if bit then unpack */
6663 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6664 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6667 size = AOP_SIZE (right);
6672 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6673 accopWithMisc ("sta", ",x");
6676 rmwWithReg ("inc", hc08_reg_x);
6678 hc08_freeReg (hc08_reg_a);
6682 freeAsmop (result, NULL, ic, TRUE);
6683 freeAsmop (right, NULL, ic, TRUE);
6685 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6686 aopOp (IC_RESULT (pi), pi, FALSE);
6687 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6688 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6692 hc08_freeReg (hc08_reg_hx);
6697 /*-----------------------------------------------------------------*/
6698 /* genFarPointerSet - set value from far space */
6699 /*-----------------------------------------------------------------*/
6701 genFarPointerSet (operand * right,
6702 operand * result, iCode * ic, iCode * pi)
6705 sym_link *retype = getSpec (operandType (right));
6706 sym_link *letype = getSpec (operandType (result));
6708 D(emitcode ("; genFarPointerSet",""));
6710 aopOp (result, ic, FALSE);
6712 /* if the result is rematerializable &
6713 in data space & not a bit variable */
6714 if (AOP_TYPE (result) == AOP_IMMD &&
6715 /* DCL_TYPE (ptype) == POINTER && */
6716 !IS_BITVAR (retype) &&
6717 !IS_BITVAR (letype))
6719 genDataPointerSet (right, result, ic);
6723 /* if the operand is already in hx
6724 then we do nothing else we move the value to hx */
6725 if (AOP_TYPE (result) != AOP_STR)
6727 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6729 /* so hx now contains the address */
6730 aopOp (right, ic, FALSE);
6732 /* if bit then unpack */
6733 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6734 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6737 size = AOP_SIZE (right);
6742 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6743 accopWithMisc ("sta", ",x");
6746 emitcode ("aix", "#1");
6748 hc08_freeReg (hc08_reg_a);
6752 freeAsmop (result, NULL, ic, TRUE);
6753 freeAsmop (right, NULL, ic, TRUE);
6755 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6756 aopOp (IC_RESULT (pi), pi, FALSE);
6757 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6758 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6762 hc08_freeReg (hc08_reg_hx);
6768 /*-----------------------------------------------------------------*/
6769 /* genPointerSet - stores the value into a pointer location */
6770 /*-----------------------------------------------------------------*/
6772 genPointerSet (iCode * ic, iCode *pi)
6774 operand *right, *result;
6775 sym_link *type, *etype;
6778 D(emitcode ("; genPointerSet",""));
6780 right = IC_RIGHT (ic);
6781 result = IC_RESULT (ic);
6783 /* depending on the type of pointer we need to
6784 move it to the correct pointer register */
6785 type = operandType (result);
6786 etype = getSpec (type);
6787 /* if left is of type of pointer then it is simple */
6788 if (IS_PTR (type) && !IS_FUNC (type->next))
6790 p_type = DCL_TYPE (type);
6794 /* we have to go by the storage class */
6795 p_type = PTR_TYPE (SPEC_OCLS (etype));
6798 /* special case when cast remat */
6799 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
6800 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
6801 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
6802 type = operandType (result);
6803 p_type = DCL_TYPE (type);
6805 /* now that we have the pointer type we assign
6806 the pointer values */
6813 genNearPointerSet (right, result, ic, pi);
6819 genFarPointerSet (right, result, ic, pi);
6823 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6824 "genPointerSet: illegal pointer type");
6829 /*-----------------------------------------------------------------*/
6830 /* genIfx - generate code for Ifx statement */
6831 /*-----------------------------------------------------------------*/
6833 genIfx (iCode * ic, iCode * popIc)
6835 operand *cond = IC_COND (ic);
6838 D(emitcode ("; genIfx",""));
6840 aopOp (cond, ic, FALSE);
6842 /* get the value into acc */
6843 if (AOP_TYPE (cond) != AOP_CRY)
6844 asmopToBool (AOP (cond), FALSE);
6847 /* the result is now in the accumulator */
6848 freeAsmop (cond, NULL, ic, TRUE);
6850 /* if there was something to be popped then do it */
6854 /* if the condition is a bit variable */
6855 if (isbit && IS_ITEMP (cond) &&
6857 genIfxJump (ic, SPIL_LOC (cond)->rname);
6858 else if (isbit && !IS_ITEMP (cond))
6859 genIfxJump (ic, OP_SYMBOL (cond)->rname);
6861 genIfxJump (ic, "a");
6866 /*-----------------------------------------------------------------*/
6867 /* genAddrOf - generates code for address of */
6868 /*-----------------------------------------------------------------*/
6870 genAddrOf (iCode * ic)
6872 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
6875 D(emitcode ("; genAddrOf",""));
6877 aopOp (IC_RESULT (ic), ic, FALSE);
6879 /* if the operand is on the stack then we
6880 need to get the stack offset of this
6884 /* if it has an offset then we need to compute
6886 hc08_useReg (hc08_reg_hx);
6887 emitcode ("tsx", "");
6888 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
6889 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
6890 hc08_freeReg (hc08_reg_hx);
6895 /* object not on stack then we need the name */
6896 size = AOP_SIZE (IC_RESULT (ic));
6901 char s[SDCC_NAME_MAX+10];
6904 sprintf (s, "#%s", sym->rname);
6907 sprintf (s, "#>%s", sym->rname);
6910 sprintf (s, "#(%s >> %d)",
6914 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
6918 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
6922 /*-----------------------------------------------------------------*/
6923 /* genAssign - generate code for assignment */
6924 /*-----------------------------------------------------------------*/
6926 genAssign (iCode * ic)
6928 operand *result, *right;
6930 // unsigned long lit = 0L;
6932 D(emitcode("; genAssign",""));
6934 result = IC_RESULT (ic);
6935 right = IC_RIGHT (ic);
6937 /* if they are the same */
6938 if (operandsEqu (result, right)) {
6942 aopOp (right, ic, FALSE);
6943 aopOp (result, ic, TRUE);
6945 /* if they are the same registers */
6946 if (sameRegs (AOP (right), AOP (result)))
6949 if ((AOP_TYPE (right) == AOP_LIT)
6950 && (IS_AOP_HX(AOP(result))))
6952 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
6957 size = AOP_SIZE (result);
6962 transferAopAop (AOP (right), offset, AOP (result), offset);
6967 freeAsmop (right, NULL, ic, TRUE);
6968 freeAsmop (result, NULL, ic, TRUE);
6971 /*-----------------------------------------------------------------*/
6972 /* genJumpTab - genrates code for jump table */
6973 /*-----------------------------------------------------------------*/
6975 genJumpTab (iCode * ic)
6980 D(emitcode ("; genJumpTab",""));
6982 aopOp (IC_JTCOND (ic), ic, FALSE);
6983 /* get the condition into accumulator */
6984 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
6985 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
6986 /* multiply by three */
6987 pushReg (hc08_reg_a, FALSE);
6988 emitcode ("lsla", "");
6989 emitcode ("add","1,s");
6990 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
6991 loadRegFromConst (hc08_reg_h, zero);
6993 jtab = newiTempLabel (NULL);
6994 emitcode ("jmp", "%05d$,x", jtab->key + 100);
6995 emitcode ("", "%05d$:", jtab->key + 100);
6996 /* now generate the jump labels */
6997 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
6998 jtab = setNextItem (IC_JTLABELS (ic)))
6999 emitcode ("jmp", "%05d$", jtab->key + 100);
7001 hc08_dirtyReg (hc08_reg_a, TRUE);
7002 hc08_dirtyReg (hc08_reg_hx, TRUE);
7005 /*-----------------------------------------------------------------*/
7006 /* genCast - gen code for casting */
7007 /*-----------------------------------------------------------------*/
7009 genCast (iCode * ic)
7011 operand *result = IC_RESULT (ic);
7012 sym_link *ctype = operandType (IC_LEFT (ic));
7013 sym_link *rtype = operandType (IC_RIGHT (ic));
7014 operand *right = IC_RIGHT (ic);
7017 D(emitcode("; genCast",""));
7019 /* if they are equivalent then do nothing */
7020 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7023 aopOp (right, ic, FALSE);
7024 aopOp (result, ic, FALSE);
7027 /* if they are the same size : or less */
7028 if (AOP_SIZE (result) <= AOP_SIZE (right))
7031 /* if they are in the same place */
7033 if (sameRegs (AOP (right), AOP (result)))
7037 /* if they in different places then copy */
7038 size = AOP_SIZE (result);
7042 transferAopAop(AOP (right), offset, AOP (result), offset);
7049 /* if the result is of type pointer */
7054 sym_link *type = operandType (right);
7055 sym_link *etype = getSpec (type);
7057 /* pointer to generic pointer */
7058 if (IS_GENPTR (ctype))
7061 p_type = DCL_TYPE (type);
7064 if (SPEC_SCLS(etype)==S_REGISTER) {
7065 // let's assume it is a generic pointer
7068 /* we have to go by the storage class */
7069 p_type = PTR_TYPE (SPEC_OCLS (etype));
7073 /* the first two bytes are known */
7074 size = GPTRSIZE - 1;
7078 transferAopAop(AOP (right), offset, AOP (result), offset);
7081 /* the last byte depending on type */
7084 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7089 // pointerTypeToGPByte will have bitched.
7093 sprintf(gpValStr, "#0x%d", gpVal);
7094 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7100 /* just copy the pointers */
7101 size = AOP_SIZE (result);
7105 transferAopAop(AOP (right), offset, AOP (result), offset);
7111 /* so we now know that the size of destination is greater
7112 than the size of the source */
7113 /* we move to result for the size of source */
7114 size = AOP_SIZE (right);
7118 transferAopAop(AOP (right), offset, AOP (result), offset);
7122 /* now depending on the sign of the source && destination */
7123 size = AOP_SIZE (result) - AOP_SIZE (right);
7124 /* if unsigned or not an integral type */
7125 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7128 storeConstToAop (zero, AOP (result), offset++);
7132 /* we need to extend the sign :{ */
7133 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7134 accopWithMisc ("rola", "");
7135 accopWithMisc ("clra", "");
7136 accopWithMisc ("sbc", zero);
7138 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7141 /* we are done hurray !!!! */
7144 freeAsmop (right, NULL, ic, TRUE);
7145 freeAsmop (result, NULL, ic, TRUE);
7149 /*-----------------------------------------------------------------*/
7150 /* genDjnz - generate decrement & jump if not zero instrucion */
7151 /*-----------------------------------------------------------------*/
7153 genDjnz (iCode * ic, iCode * ifx)
7159 D(emitcode ("; genDjnz",""));
7161 /* if the if condition has a false label
7162 then we cannot save */
7166 /* if the minus is not of the form
7168 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7169 !IS_OP_LITERAL (IC_RIGHT (ic)))
7172 if (operandLitValue (IC_RIGHT (ic)) != 1)
7175 /* if the size of this greater than one then no
7177 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7179 aopOp (IC_RESULT (ic), ic, FALSE);
7180 if (AOP_SIZE (IC_RESULT (ic))>1)
7182 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7186 /* otherwise we can save BIG */
7187 lbl = newiTempLabel (NULL);
7188 lbl1 = newiTempLabel (NULL);
7191 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7194 emitBranch ("bra", lbl1);
7196 emitBranch ("jmp", IC_TRUE (ifx));
7199 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7204 /*-----------------------------------------------------------------*/
7205 /* genReceive - generate code for a receive iCode */
7206 /*-----------------------------------------------------------------*/
7208 genReceive (iCode * ic)
7212 D(emitcode ("; genReceive",""));
7214 aopOp (IC_RESULT (ic), ic, FALSE);
7215 size = AOP_SIZE (IC_RESULT (ic));
7220 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7221 AOP (IC_RESULT (ic)), offset);
7222 if (hc08_aop_pass[offset]->type == AOP_REG)
7223 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7228 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7231 /*-----------------------------------------------------------------*/
7232 /* genDummyRead - generate code for dummy read of volatiles */
7233 /*-----------------------------------------------------------------*/
7235 genDummyRead (iCode * ic)
7240 D(emitcode("; genDummyRead",""));
7242 right = IC_RIGHT (ic);
7244 aopOp (right, ic, FALSE);
7246 /* bit variables done */
7248 size = AOP_SIZE (right);
7253 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7254 hc08_freeReg (hc08_reg_a);
7258 freeAsmop (right, NULL, ic, TRUE);
7261 /*-----------------------------------------------------------------*/
7262 /* genCritical - generate code for start of a critical sequence */
7263 /*-----------------------------------------------------------------*/
7265 genCritical (iCode *ic)
7267 D(emitcode("; genCritical",""));
7270 aopOp (IC_RESULT (ic), ic, TRUE);
7272 emitcode ("tpa", "");
7273 hc08_dirtyReg (hc08_reg_a, FALSE);
7274 emitcode ("sei", "");
7277 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7279 pushReg (hc08_reg_a, FALSE);
7281 hc08_freeReg (hc08_reg_a);
7283 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7286 /*-----------------------------------------------------------------*/
7287 /* genEndCritical - generate code for end of a critical sequence */
7288 /*-----------------------------------------------------------------*/
7290 genEndCritical (iCode *ic)
7292 D(emitcode("; genEndCritical",""));
7296 aopOp (IC_RIGHT (ic), ic, FALSE);
7297 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7298 emitcode ("tap", "");
7299 hc08_freeReg (hc08_reg_a);
7300 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7304 pullReg (hc08_reg_a);
7305 emitcode ("tap", "");
7310 /*-----------------------------------------------------------------*/
7311 /* genhc08Code - generate code for HC08 based controllers */
7312 /*-----------------------------------------------------------------*/
7314 genhc08Code (iCode * lic)
7319 lineHead = lineCurr = NULL;
7321 /* print the allocation information */
7322 if (allocInfo && currFunc)
7323 printAllocInfo (currFunc, codeOutFile);
7324 /* if debug information required */
7325 if (options.debug && currFunc)
7327 debugFile->writeFunction(currFunc);
7329 if (IS_STATIC (currFunc->etype))
7330 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7332 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7335 /* stack pointer name */
7336 if (options.useXstack)
7341 hc08_aop_pass[0] = newAsmop (AOP_REG);
7342 hc08_aop_pass[0]->size=1;
7343 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7344 hc08_aop_pass[1] = newAsmop (AOP_REG);
7345 hc08_aop_pass[1]->size=1;
7346 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7347 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7348 hc08_aop_pass[2]->size=1;
7349 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7350 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7351 hc08_aop_pass[3]->size=1;
7352 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7354 for (ic = lic; ic; ic = ic->next)
7357 if (ic->lineno && cln != ic->lineno)
7362 emitcode ("", "C$%s$%d$%d$%d ==.",
7363 FileBaseName (ic->filename), ic->lineno,
7364 ic->level, ic->block);
7367 if (!options.noCcodeInAsm) {
7368 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7369 printCLine(ic->filename, ic->lineno));
7373 if (options.iCodeInAsm) {
7377 for (i=0; i<6; i++) {
7378 sprintf (®sInUse[i],
7379 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7382 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7384 /* if the result is marked as
7385 spilt and rematerializable or code for
7386 this has already been generated then
7388 if (resultRemat (ic) || ic->generated)
7396 for (i=A_IDX;i<=XA_IDX;i++)
7398 reg = hc08_regWithIdx(i);
7400 emitcode("","; %s = %s offset %d", reg->name,
7401 aopName(reg->aop), reg->aopofs);
7404 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7406 sym = OP_SYMBOL (IC_LEFT (ic));
7407 if (sym->accuse == ACCUSE_HX)
7409 hc08_reg_h->isFree = FALSE;
7410 hc08_reg_x->isFree = FALSE;
7412 else if (sym->accuse == ACCUSE_XA)
7414 hc08_reg_a->isFree = FALSE;
7416 hc08_reg_x->isFree = FALSE;
7419 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7421 sym = OP_SYMBOL (IC_RIGHT (ic));
7422 if (sym->accuse == ACCUSE_HX)
7424 hc08_reg_h->isFree = FALSE;
7425 hc08_reg_x->isFree = FALSE;
7427 else if (sym->accuse == ACCUSE_XA)
7429 hc08_reg_a->isFree = FALSE;
7431 hc08_reg_x->isFree = FALSE;
7436 /* depending on the operation */
7456 /* IPOP happens only when trying to restore a
7457 spilt live range, if there is an ifx statement
7458 following this pop then the if statement might
7459 be using some of the registers being popped which
7460 would destory the contents of the register so
7461 we need to check for this condition and handle it */
7463 ic->next->op == IFX &&
7464 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7465 genIfx (ic->next, ic);
7483 genEndFunction (ic);
7499 if (!genPointerGetSetOfs (ic))
7504 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7521 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7525 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7532 /* note these two are xlated by algebraic equivalence
7533 during parsing SDCC.y */
7534 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7535 "got '>=' or '<=' shouldn't have come here");
7539 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7551 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7555 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7559 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7586 case GET_VALUE_AT_ADDRESS:
7587 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7591 if (POINTER_SET (ic))
7592 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7618 addSet (&_G.sendSet, ic);
7621 case DUMMY_READ_VOLATILE:
7630 genEndCritical (ic);
7637 if (!hc08_reg_a->isFree)
7638 emitcode("","; forgot to free a");
7639 if (!hc08_reg_x->isFree)
7640 emitcode("","; forgot to free x");
7641 if (!hc08_reg_h->isFree)
7642 emitcode("","; forgot to free h");
7643 if (!hc08_reg_hx->isFree)
7644 emitcode("","; forgot to free hx");
7645 if (!hc08_reg_xa->isFree)
7646 emitcode("","; forgot to free xa");
7650 /* now we are ready to call the
7651 peep hole optimizer */
7652 if (!options.nopeep)
7653 peepHole (&lineHead);
7655 /* now do the actual printing */
7656 printLine (lineHead, codeOutFile);