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);
4971 hc08_freeReg (hc08_reg_a);
4973 freeAsmop (left, NULL, ic, TRUE);
4974 freeAsmop (result, NULL, ic, TRUE);
4977 /*-----------------------------------------------------------------*/
4978 /* genSwap - generates code to swap nibbles or bytes */
4979 /*-----------------------------------------------------------------*/
4981 genSwap (iCode * ic)
4983 operand *left, *result;
4985 D(emitcode ("; genSwap",""));
4987 left = IC_LEFT (ic);
4988 result = IC_RESULT (ic);
4989 aopOp (left, ic, FALSE);
4990 aopOp (result, ic, FALSE);
4992 switch (AOP_SIZE (left))
4994 case 1: /* swap nibbles in byte */
4995 loadRegFromAop (hc08_reg_a, AOP (left), 0);
4996 emitcode ("nsa", "");
4997 hc08_dirtyReg (hc08_reg_a, FALSE);
4998 storeRegToAop (hc08_reg_a, AOP (result), 0);
4999 hc08_freeReg (hc08_reg_a);
5001 case 2: /* swap bytes in a word */
5002 if (operandsEqu (left, result))
5004 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5005 hc08_useReg (hc08_reg_a);
5006 transferAopAop (AOP (left), 1, AOP (result), 0);
5007 storeRegToAop (hc08_reg_a, AOP (result), 1);
5008 hc08_freeReg (hc08_reg_a);
5012 transferAopAop (AOP (left), 0, AOP (result), 1);
5013 transferAopAop (AOP (left), 1, AOP (result), 0);
5017 wassertl(FALSE, "unsupported SWAP operand size");
5020 freeAsmop (left, NULL, ic, TRUE);
5021 freeAsmop (result, NULL, ic, TRUE);
5025 /*-----------------------------------------------------------------*/
5026 /* AccRol - rotate left accumulator by known count */
5027 /*-----------------------------------------------------------------*/
5029 AccRol (int shCount)
5031 shCount &= 0x0007; // shCount : 0..7
5038 emitcode ("rola", ""); /* 1 cycle */
5041 emitcode ("rola", ""); /* 1 cycle */
5042 emitcode ("rola", ""); /* 1 cycle */
5045 emitcode ("nsa", "");
5046 emitcode ("rora", "");
5049 emitcode ("nsa", ""); /* 3 cycles */
5052 emitcode ("nsa", ""); /* 3 cycles */
5053 emitcode ("rola", ""); /* 1 cycle */
5056 emitcode ("nsa", ""); /* 3 cycles */
5057 emitcode ("rola", ""); /* 1 cycle */
5058 emitcode ("rola", ""); /* 1 cycle */
5061 emitcode ("nsa", ""); /* 3 cycles */
5062 emitcode ("rola", ""); /* 1 cycle */
5063 emitcode ("rola", ""); /* 1 cycle */
5064 emitcode ("rola", ""); /* 1 cycle */
5071 /*-----------------------------------------------------------------*/
5072 /* AccLsh - left shift accumulator by known count */
5073 /*-----------------------------------------------------------------*/
5075 AccLsh (int shCount)
5079 shCount &= 0x0007; // shCount : 0..7
5081 /* Shift counts of 4 and 5 are currently optimized for code size. */
5082 /* Falling through to the unrolled loop would be optimal for code speed. */
5083 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5087 accopWithMisc ("nsa", "");
5088 accopWithMisc ("and", "#0xf0");
5089 /* total: 5 cycles, 3 bytes */
5092 accopWithMisc ("nsa", "");
5093 accopWithMisc ("and", "#0xf0");
5094 accopWithMisc ("lsla", "");
5095 /* total: 6 cycles, 4 bytes */
5098 accopWithMisc ("rora", "");
5099 accopWithMisc ("rora", "");
5100 accopWithMisc ("rora", "");
5101 accopWithMisc ("and", "#0xc0");
5102 /* total: 5 cycles, 5 bytes */
5105 accopWithMisc ("rora", "");
5106 accopWithMisc ("clra", "");
5107 accopWithMisc ("rora", "");
5108 /* total: 3 cycles, 3 bytes */
5112 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5113 /* the fastest (shCount<6) and shortest (shCount<4). */
5114 for (i=0;i<shCount;i++)
5115 accopWithMisc ("lsla", "");
5119 /*-----------------------------------------------------------------*/
5120 /* AccSRsh - signed right shift accumulator by known count */
5121 /*-----------------------------------------------------------------*/
5123 AccSRsh (int shCount)
5127 shCount &= 0x0007; // shCount : 0..7
5131 accopWithMisc ("rola", "");
5132 accopWithMisc ("clra", "");
5133 accopWithMisc ("sbc", zero);
5134 /* total: 4 cycles, 4 bytes */
5138 for (i=0;i<shCount;i++)
5139 accopWithMisc ("asra", "");
5142 /*-----------------------------------------------------------------*/
5143 /* AccRsh - right shift accumulator by known count */
5144 /*-----------------------------------------------------------------*/
5146 AccRsh (int shCount, bool sign)
5156 shCount &= 0x0007; // shCount : 0..7
5158 /* Shift counts of 4 and 5 are currently optimized for code size. */
5159 /* Falling through to the unrolled loop would be optimal for code speed. */
5160 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5164 accopWithMisc ("nsa", "");
5165 accopWithMisc ("and", "#0x0f");
5166 /* total: 5 cycles, 3 bytes */
5169 accopWithMisc ("nsa", "");
5170 accopWithMisc ("and", "#0x0f");
5171 accopWithMisc ("lsra", "");
5172 /* total: 6 cycles, 4 bytes */
5175 accopWithMisc ("rola", "");
5176 accopWithMisc ("rola", "");
5177 accopWithMisc ("rola", "");
5178 accopWithMisc ("and", "#0x03");
5179 /* total: 5 cycles, 5 bytes */
5182 accopWithMisc ("rola", "");
5183 accopWithMisc ("clra", "");
5184 accopWithMisc ("rola", "");
5185 /* total: 3 cycles, 3 bytes */
5189 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5190 /* the fastest (shCount<6) and shortest (shCount<4). */
5191 for (i=0;i<shCount;i++)
5192 accopWithMisc ("lsra", "");
5196 /*-----------------------------------------------------------------*/
5197 /* XAccLsh - left shift register pair XA by known count */
5198 /*-----------------------------------------------------------------*/
5200 XAccLsh (int shCount)
5204 shCount &= 0x000f; // shCount : 0..15
5209 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5210 loadRegFromConst (hc08_reg_a, zero);
5214 /* if we can beat 2n cycles or bytes for some special case, do it here */
5218 /* bytes cycles reg x reg a carry
5219 ** abcd efgh ijkl mnop ?
5220 ** lsrx 1 1 0abc defg ijkl mnop h
5221 ** rora 1 1 0abc defg hijk lmno p
5222 ** tax 1 1 hijk lmno hijk lmno p
5223 ** clra 1 1 hijk lmno 0000 0000 p
5224 ** rora 1 1 hijk lmno p000 0000 0
5225 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5227 rmwWithReg ("lsr", hc08_reg_x);
5228 rmwWithReg ("ror", hc08_reg_a);
5229 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5230 loadRegFromConst (hc08_reg_a, zero);
5231 rmwWithReg ("ror", hc08_reg_a);
5238 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5239 /* the fastest and shortest. */
5240 for (i=0;i<shCount;i++)
5242 rmwWithReg ("lsl", hc08_reg_a);
5243 rmwWithReg ("rol", hc08_reg_x);
5247 /*-----------------------------------------------------------------*/
5248 /* XAccSRsh - signed right shift register pair XA by known count */
5249 /*-----------------------------------------------------------------*/
5251 XAccSRsh (int shCount)
5255 shCount &= 0x000f; // shCount : 0..7
5257 /* if we can beat 2n cycles or bytes for some special case, do it here */
5261 /* bytes cycles reg x reg a carry
5262 ** abcd efgh ijkl mnop ?
5263 ** lslx 1 1 bcde fgh0 ijkl mnop a
5264 ** clra 1 1 bcde fgh0 0000 0000 a
5265 ** rola 1 1 bcde fgh0 0000 000a 0
5266 ** nega 1 1 bcde fgh0 aaaa aaaa a
5267 ** tax 1 1 aaaa aaaa aaaa aaaa a
5268 ** total: 5 cycles, 5 bytes
5270 rmwWithReg ("lsl", hc08_reg_x);
5271 loadRegFromConst (hc08_reg_a, zero);
5272 rmwWithReg ("rol", hc08_reg_a);
5273 rmwWithReg ("neg", hc08_reg_a);
5274 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5284 /* bytes cycles reg x reg a carry
5285 ** abcd efgh ijkl mnop ?
5286 ** txa 1 1 abcd efgh abcd efgh ?
5287 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5288 ** lsla 1 1 abcd efgh ???? ???? a
5289 ** clrx 1 1 0000 0000 ???? ???? a
5290 ** rolx 1 1 0000 000a ???? ???? 0
5291 ** negx 1 1 aaaa aaaa ???? ???? a
5292 ** rora 1 1 aaaa aaaa LSBresult 0
5293 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5295 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5296 AccSRsh (shCount-8);
5297 rmwWithReg ("lsl", hc08_reg_a);
5298 loadRegFromConst (hc08_reg_x, zero);
5299 rmwWithReg ("rol", hc08_reg_x);
5300 rmwWithReg ("neg", hc08_reg_x);
5301 rmwWithReg ("ror", hc08_reg_a);
5308 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5309 /* the fastest and shortest. */
5310 for (i=0;i<shCount;i++)
5312 rmwWithReg ("asr", hc08_reg_x);
5313 rmwWithReg ("ror", hc08_reg_a);
5317 /*-----------------------------------------------------------------*/
5318 /* XAccRsh - right shift register pair XA by known count */
5319 /*-----------------------------------------------------------------*/
5321 XAccRsh (int shCount, bool sign)
5331 shCount &= 0x000f; // shCount : 0..f
5333 /* if we can beat 2n cycles or bytes for some special case, do it here */
5337 /* bytes cycles reg x reg a carry
5338 ** abcd efgh ijkl mnop ?
5339 ** clra 1 1 abcd efgh 0000 0000 a
5340 ** lslx 1 1 bcde fgh0 0000 0000 a
5341 ** rola 1 1 bcde fgh0 0000 000a 0
5342 ** clrx 1 1 0000 0000 0000 000a 0
5343 ** total: 4 cycles, 4 bytes
5345 loadRegFromConst (hc08_reg_x, zero);
5346 rmwWithReg ("lsl", hc08_reg_x);
5347 rmwWithReg ("rol", hc08_reg_a);
5348 loadRegFromConst (hc08_reg_a, zero);
5352 /* bytes cycles reg x reg a carry
5353 ** abcd efgh ijkl mnop ?
5354 ** clra 1 1 abcd efgh 0000 0000 a
5355 ** lslx 1 1 bcde fgh0 0000 0000 a
5356 ** rola 1 1 bcde fgh0 0000 000a 0
5357 ** lslx 1 1 cdef gh00 0000 000a b
5358 ** rola 1 1 cdef gh00 0000 00ab 0
5359 ** clrx 1 1 0000 0000 0000 000a 0
5360 ** total: 6 cycles, 6 bytes
5362 loadRegFromConst (hc08_reg_x, zero);
5363 rmwWithReg ("lsl", hc08_reg_x);
5364 rmwWithReg ("rol", hc08_reg_a);
5365 rmwWithReg ("lsl", hc08_reg_x);
5366 rmwWithReg ("rol", hc08_reg_a);
5367 loadRegFromConst (hc08_reg_a, zero);
5376 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5377 AccRsh (shCount-8, FALSE);
5378 loadRegFromConst (hc08_reg_x, zero);
5382 /* bytes cycles reg x reg a carry
5383 ** abcd efgh ijkl mnop ?
5384 ** lsla 1 1 abcd efgh jklm nop0 i
5385 ** txa 1 1 abcd efgh abcd efgh i
5386 ** rola 1 1 abcd efgh bcde fghi a
5387 ** clrx 1 1 0000 0000 bcde fghi a
5388 ** rolx 1 1 0000 000a bcde fghi 0
5389 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5391 rmwWithReg ("lsl", hc08_reg_a);
5392 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5393 rmwWithReg ("rol", hc08_reg_a);
5394 loadRegFromConst (hc08_reg_x, zero);
5395 rmwWithReg ("rol", hc08_reg_x);
5398 /* bytes cycles reg x reg a carry
5399 ** abcd efgh ijkl mnop ?
5400 ** lsla 1 1 abcd efgh jklm nop0 i
5401 ** rolx 1 1 bcde fghi jklm nop0 a
5402 ** rola 1 1 bcde fghi klmn op0a j
5403 ** rolx 1 1 cdef ghij klmn op0a b
5404 ** rola 1 1 cdef ghij lmno p0ab k
5405 ** and #3 2 2 cdef ghij 0000 00ab k
5406 ** psha 1 2 cdef ghij 0000 00ab k
5407 ** txa 1 1 cdef ghij cdef ghij k
5408 ** pula 1 2 0000 00ab cdef ghij k
5409 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5415 /* lslx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5416 /* the fastest and shortest. */
5417 for (i=0;i<shCount;i++)
5419 rmwWithReg ("lsl", hc08_reg_x);
5420 rmwWithReg ("rol", hc08_reg_a);
5427 /*-----------------------------------------------------------------*/
5428 /* shiftR1Left2Result - shift right one byte from left to result */
5429 /*-----------------------------------------------------------------*/
5431 shiftR1Left2Result (operand * left, int offl,
5432 operand * result, int offr,
5433 int shCount, int sign)
5435 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5436 /* shift right accumulator */
5437 AccRsh (shCount, sign);
5438 storeRegToAop (hc08_reg_a, AOP (result), offr);
5442 /*-----------------------------------------------------------------*/
5443 /* shiftL1Left2Result - shift left one byte from left to result */
5444 /*-----------------------------------------------------------------*/
5446 shiftL1Left2Result (operand * left, int offl,
5447 operand * result, int offr, int shCount)
5449 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5450 /* shift left accumulator */
5452 storeRegToAop (hc08_reg_a, AOP (result), offr);
5455 /*-----------------------------------------------------------------*/
5456 /* movLeft2Result - move byte from left to result */
5457 /*-----------------------------------------------------------------*/
5459 movLeft2Result (operand * left, int offl,
5460 operand * result, int offr, int sign)
5462 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5464 transferAopAop (AOP (left), offl, AOP (result), offr);
5469 /*-----------------------------------------------------------------*/
5470 /* shiftL2Left2Result - shift left two bytes from left to result */
5471 /*-----------------------------------------------------------------*/
5473 shiftL2Left2Result (operand * left, int offl,
5474 operand * result, int offr, int shCount)
5477 bool needpula = FALSE;
5478 bool needpulx = FALSE;
5480 needpula = pushRegIfUsed (hc08_reg_a);
5481 needpulx = pushRegIfUsed (hc08_reg_x);
5483 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5488 rmwWithReg ("lsr", hc08_reg_x);
5489 rmwWithReg ("ror", hc08_reg_a);
5490 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5491 rmwWithReg ("clr", hc08_reg_a);
5492 rmwWithReg ("ror", hc08_reg_a);
5495 for (i=0; i<shCount; i++)
5497 rmwWithReg ("lsl", hc08_reg_a);
5498 rmwWithReg ("rol", hc08_reg_x);
5501 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5503 pullOrFreeReg (hc08_reg_x, needpulx);
5504 pullOrFreeReg (hc08_reg_a, needpula);
5510 /*-----------------------------------------------------------------*/
5511 /* shiftR2Left2Result - shift right two bytes from left to result */
5512 /*-----------------------------------------------------------------*/
5514 shiftR2Left2Result (operand * left, int offl,
5515 operand * result, int offr,
5516 int shCount, int sign)
5519 bool needpula = FALSE;
5520 bool needpulx = FALSE;
5522 needpula = pushRegIfUsed (hc08_reg_a);
5523 needpulx = pushRegIfUsed (hc08_reg_x);
5525 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5526 for (i=0; i<shCount; i++)
5529 rmwWithReg ("asr", hc08_reg_x);
5531 rmwWithReg ("lsr", hc08_reg_x);
5532 rmwWithReg ("ror", hc08_reg_a);
5534 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5536 pullOrFreeReg (hc08_reg_x, needpulx);
5537 pullOrFreeReg (hc08_reg_a, needpula);
5542 /*-----------------------------------------------------------------*/
5543 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5544 /*-----------------------------------------------------------------*/
5546 shiftLLeftOrResult (operand * left, int offl,
5547 operand * result, int offr, int shCount)
5549 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5550 /* shift left accumulator */
5552 /* or with result */
5553 accopWithAop ("ora", AOP (result), offr);
5554 /* back to result */
5555 storeRegToAop (hc08_reg_a, AOP (result), offr);
5556 hc08_freeReg (hc08_reg_a);
5560 /*-----------------------------------------------------------------*/
5561 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5562 /*-----------------------------------------------------------------*/
5564 shiftRLeftOrResult (operand * left, int offl,
5565 operand * result, int offr, int shCount)
5567 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5568 /* shift left accumulator */
5569 AccRsh (shCount, FALSE);
5570 /* or with result */
5571 accopWithAop ("ora", AOP (result), offr);
5572 /* back to result */
5573 storeRegToAop (hc08_reg_a, AOP (result), offr);
5574 hc08_freeReg (hc08_reg_a);
5577 /*-----------------------------------------------------------------*/
5578 /* genlshOne - left shift a one byte quantity by known count */
5579 /*-----------------------------------------------------------------*/
5581 genlshOne (operand * result, operand * left, int shCount)
5583 D(emitcode ("; genlshOne",""));
5585 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5588 /*-----------------------------------------------------------------*/
5589 /* genlshTwo - left shift two bytes by known amount != 0 */
5590 /*-----------------------------------------------------------------*/
5592 genlshTwo (operand * result, operand * left, int shCount)
5596 D(emitcode ("; genlshTwo",""));
5599 size = getDataSize (result);
5601 /* if shCount >= 8 */
5608 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5610 storeRegToAop (hc08_reg_a, AOP (result), 1);
5612 storeConstToAop(zero, AOP (result), LSB);
5615 /* 1 <= shCount <= 7 */
5618 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5620 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5624 /*-----------------------------------------------------------------*/
5625 /* shiftLLong - shift left one long from left to result */
5626 /* offl = LSB or MSB16 */
5627 /*-----------------------------------------------------------------*/
5629 shiftLLong (operand * left, operand * result, int offr)
5632 // int size = AOP_SIZE (result);
5634 bool needpula = FALSE;
5635 bool needpulx = FALSE;
5637 needpula = pushRegIfUsed (hc08_reg_a);
5638 needpulx = pushRegIfUsed (hc08_reg_x);
5640 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5641 rmwWithReg ("lsl", hc08_reg_a);
5642 rmwWithReg ("rol", hc08_reg_x);
5643 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5647 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5648 rmwWithReg ("rol", hc08_reg_a);
5649 rmwWithReg ("rol", hc08_reg_x);
5650 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5652 else if (offr==MSB16)
5654 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5655 rmwWithReg ("rol", hc08_reg_a);
5656 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5659 pullOrFreeReg (hc08_reg_x, needpulx);
5660 pullOrFreeReg (hc08_reg_a, needpula);
5663 /*-----------------------------------------------------------------*/
5664 /* genlshFour - shift four byte by a known amount != 0 */
5665 /*-----------------------------------------------------------------*/
5667 genlshFour (operand * result, operand * left, int shCount)
5671 D(emitcode ("; genlshFour",""));
5673 size = AOP_SIZE (result);
5675 /* TODO: deal with the &result == &left case */
5677 /* if shifting more that 3 bytes */
5682 /* lowest order of left goes to the highest
5683 order of the destination */
5684 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5686 movLeft2Result (left, LSB, result, MSB32, 0);
5687 storeConstToAop (zero, AOP (result), LSB);
5688 storeConstToAop (zero, AOP (result), MSB16);
5689 storeConstToAop (zero, AOP (result), MSB24);
5693 /* more than two bytes */
5694 else if (shCount >= 16)
5696 /* lower order two bytes goes to higher order two bytes */
5698 /* if some more remaining */
5700 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5703 movLeft2Result (left, MSB16, result, MSB32, 0);
5704 movLeft2Result (left, LSB, result, MSB24, 0);
5706 storeConstToAop (zero, AOP (result), LSB);
5707 storeConstToAop (zero, AOP (result), MSB16);
5711 /* if more than 1 byte */
5712 else if (shCount >= 8)
5714 /* lower order three bytes goes to higher order three bytes */
5719 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5721 movLeft2Result (left, LSB, result, MSB16, 0);
5727 movLeft2Result (left, MSB24, result, MSB32, 0);
5728 movLeft2Result (left, MSB16, result, MSB24, 0);
5729 movLeft2Result (left, LSB, result, MSB16, 0);
5730 storeConstToAop (zero, AOP (result), LSB);
5732 else if (shCount == 1)
5733 shiftLLong (left, result, MSB16);
5736 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5737 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5738 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5739 storeConstToAop (zero, AOP (result), LSB);
5744 /* 1 <= shCount <= 7 */
5745 else if (shCount <= 2)
5747 shiftLLong (left, result, LSB);
5749 shiftLLong (result, result, LSB);
5751 /* 3 <= shCount <= 7, optimize */
5754 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5755 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5756 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5760 /*-----------------------------------------------------------------*/
5761 /* genLeftShiftLiteral - left shifting by known count */
5762 /*-----------------------------------------------------------------*/
5764 genLeftShiftLiteral (operand * left,
5769 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5772 D(emitcode ("; genLeftShiftLiteral",""));
5774 freeAsmop (right, NULL, ic, TRUE);
5776 aopOp (left, ic, FALSE);
5777 aopOp (result, ic, FALSE);
5779 // size = getSize (operandType (result));
5780 size = AOP_SIZE (result);
5783 emitcode ("; shift left ", "result %d, left %d", size,
5790 transferAopAop( AOP(left), size, AOP(result), size);
5792 else if (shCount >= (size * 8))
5795 storeConstToAop (zero, AOP (result), size);
5802 genlshOne (result, left, shCount);
5806 genlshTwo (result, left, shCount);
5810 genlshFour (result, left, shCount);
5813 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5814 "*** ack! mystery literal shift!\n");
5818 freeAsmop (left, NULL, ic, TRUE);
5819 freeAsmop (result, NULL, ic, TRUE);
5822 /*-----------------------------------------------------------------*/
5823 /* genLeftShift - generates code for left shifting */
5824 /*-----------------------------------------------------------------*/
5826 genLeftShift (iCode * ic)
5828 operand *left, *right, *result;
5830 symbol *tlbl, *tlbl1;
5835 D(emitcode ("; genLeftShift",""));
5837 right = IC_RIGHT (ic);
5838 left = IC_LEFT (ic);
5839 result = IC_RESULT (ic);
5841 aopOp (right, ic, FALSE);
5843 /* if the shift count is known then do it
5844 as efficiently as possible */
5845 if (AOP_TYPE (right) == AOP_LIT)
5847 genLeftShiftLiteral (left, right, result, ic);
5851 /* shift count is unknown then we have to form
5852 a loop get the loop count in A : Note: we take
5853 only the lower order byte since shifting
5854 more that 32 bits make no sense anyway, ( the
5855 largest size of an object can be only 32 bits ) */
5857 aopOp (left, ic, FALSE);
5858 aopOp (result, ic, FALSE);
5860 /* now move the left to the result if they are not the
5862 if (!sameRegs (AOP (left), AOP (result)))
5865 size = AOP_SIZE (result);
5869 transferAopAop (AOP (left), offset, AOP (result), offset);
5873 freeAsmop (left, NULL, ic, TRUE);
5875 tlbl = newiTempLabel (NULL);
5876 size = AOP_SIZE (result);
5878 tlbl1 = newiTempLabel (NULL);
5882 loadRegFromAop (reg, AOP (right), 0);
5883 freeAsmop (right, NULL, ic, TRUE);
5884 emitBranch ("beq", tlbl1);
5888 for (offset=0;offset<size;offset++)
5890 rmwWithAop (shift, AOP (result), offset);
5893 rmwWithReg ("dec", reg);
5894 emitBranch ("bne", tlbl);
5898 freeAsmop (result, NULL, ic, TRUE);
5901 /*-----------------------------------------------------------------*/
5902 /* genrshOne - right shift a one byte quantity by known count */
5903 /*-----------------------------------------------------------------*/
5905 genrshOne (operand * result, operand * left,
5906 int shCount, int sign)
5908 D(emitcode ("; genrshOne",""));
5910 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5911 AccRsh (shCount, sign);
5912 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5915 /*-----------------------------------------------------------------*/
5916 /* genrshTwo - right shift two bytes by known amount != 0 */
5917 /*-----------------------------------------------------------------*/
5919 genrshTwo (operand * result, operand * left,
5920 int shCount, int sign)
5922 D(emitcode ("; genrshTwo",""));
5924 /* if shCount >= 8 */
5927 if (shCount || sign)
5929 loadRegFromAop (hc08_reg_a, AOP (left), 1);
5930 AccRsh (shCount-8, sign);
5931 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
5935 transferAopAop (AOP (left), 1, AOP (result), 0);
5936 storeConstToAop (zero, AOP (result), 1);
5940 /* 1 <= shCount <= 7 */
5943 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5944 XAccRsh (shCount, sign);
5945 storeRegToAop (hc08_reg_xa, AOP (result), 0);
5949 /*-----------------------------------------------------------------*/
5950 /* shiftRLong - shift right one long from left to result */
5951 /* offl = LSB or MSB16 */
5952 /*-----------------------------------------------------------------*/
5954 shiftRLong (operand * left, int offl,
5955 operand * result, int sign)
5958 // int size = AOP_SIZE (result);
5960 bool needpula = FALSE;
5961 bool needpulx = FALSE;
5963 needpula = pushRegIfUsed (hc08_reg_a);
5964 needpulx = pushRegIfUsed (hc08_reg_x);
5968 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5970 rmwWithReg ("asr", hc08_reg_x);
5972 rmwWithReg ("lsr", hc08_reg_x);
5973 rmwWithReg ("rol", hc08_reg_a);
5974 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
5976 else if (offl==MSB16)
5978 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
5980 rmwWithReg ("asr", hc08_reg_a);
5982 rmwWithReg ("lsr", hc08_reg_a);
5983 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
5986 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5987 rmwWithReg ("ror", hc08_reg_x);
5988 rmwWithReg ("ror", hc08_reg_a);
5989 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
5992 pullOrFreeReg (hc08_reg_x, needpulx);
5993 pullOrFreeReg (hc08_reg_a, needpula);
5996 /*-----------------------------------------------------------------*/
5997 /* genrshFour - shift four byte by a known amount != 0 */
5998 /*-----------------------------------------------------------------*/
6000 genrshFour (operand * result, operand * left,
6001 int shCount, int sign)
6003 /* TODO: handle cases where left == result */
6005 D(emitcode ("; genrshFour",""));
6007 /* if shifting more that 3 bytes */
6010 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6011 AccRsh (shCount-24, sign);
6012 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6015 else if (shCount >= 16)
6017 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6018 XAccRsh (shCount-16, sign);
6019 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6022 else if (shCount >= 8)
6025 shiftRLong (left, MSB16, result, sign);
6026 else if (shCount == 8)
6028 transferAopAop (AOP (left), 1, AOP (result), 0);
6029 transferAopAop (AOP (left), 2, AOP (result), 1);
6030 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6031 storeRegToAop (hc08_reg_a, AOP (result), 2);
6032 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6034 else if (shCount == 9)
6036 shiftRLong (left, MSB16, result, sign);
6040 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6041 XAccRsh (shCount-8, FALSE);
6042 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6043 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6044 loadRegFromConst (hc08_reg_a, zero);
6045 XAccRsh (shCount-8, sign);
6046 accopWithAop ("ora", AOP (result), 1);
6047 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6051 { /* 1 <= shCount <= 7 */
6054 shiftRLong (left, LSB, result, sign);
6058 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6059 XAccRsh (shCount, FALSE);
6060 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6061 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6063 accopWithAop ("ora", AOP (result), 1);
6064 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6065 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6066 XAccRsh (shCount, sign);
6067 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6072 /*-----------------------------------------------------------------*/
6073 /* genRightShiftLiteral - right shifting by known count */
6074 /*-----------------------------------------------------------------*/
6076 genRightShiftLiteral (operand * left,
6082 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6085 D(emitcode ("; genRightShiftLiteral",""));
6087 freeAsmop (right, NULL, ic, TRUE);
6089 aopOp (left, ic, FALSE);
6090 aopOp (result, ic, FALSE);
6093 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6097 size = getDataSize (left);
6098 /* test the LEFT size !!! */
6100 /* I suppose that the left size >= result size */
6103 size = getDataSize (result);
6105 transferAopAop (AOP (left), size, AOP(result), size);
6107 else if (shCount >= (size * 8))
6110 /* get sign in acc.7 */
6111 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6113 addSign (result, LSB, sign);
6120 genrshOne (result, left, shCount, sign);
6124 genrshTwo (result, left, shCount, sign);
6128 genrshFour (result, left, shCount, sign);
6134 freeAsmop (left, NULL, ic, TRUE);
6135 freeAsmop (result, NULL, ic, TRUE);
6139 /*-----------------------------------------------------------------*/
6140 /* genRightShift - generate code for right shifting */
6141 /*-----------------------------------------------------------------*/
6143 genRightShift (iCode * ic)
6145 operand *right, *left, *result;
6149 symbol *tlbl, *tlbl1;
6153 D(emitcode ("; genRightShift",""));
6155 /* if signed then we do it the hard way preserve the
6156 sign bit moving it inwards */
6157 retype = getSpec (operandType (IC_RESULT (ic)));
6158 sign = !SPEC_USIGN (retype);
6160 /* signed & unsigned types are treated the same : i.e. the
6161 signed is NOT propagated inwards : quoting from the
6162 ANSI - standard : "for E1 >> E2, is equivalent to division
6163 by 2**E2 if unsigned or if it has a non-negative value,
6164 otherwise the result is implementation defined ", MY definition
6165 is that the sign does not get propagated */
6167 right = IC_RIGHT (ic);
6168 left = IC_LEFT (ic);
6169 result = IC_RESULT (ic);
6171 aopOp (right, ic, FALSE);
6173 /* if the shift count is known then do it
6174 as efficiently as possible */
6175 if (AOP_TYPE (right) == AOP_LIT)
6177 genRightShiftLiteral (left, right, result, ic, sign);
6181 /* shift count is unknown then we have to form
6182 a loop get the loop count in X : Note: we take
6183 only the lower order byte since shifting
6184 more that 32 bits make no sense anyway, ( the
6185 largest size of an object can be only 32 bits ) */
6187 aopOp (left, ic, FALSE);
6188 aopOp (result, ic, FALSE);
6190 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6191 AOP (result) = forceStackedAop (AOP (result));
6193 size = AOP_SIZE (result);
6197 transferAopAop (AOP (left), offset, AOP (result), offset);
6201 tlbl = newiTempLabel (NULL);
6202 size = AOP_SIZE (result);
6204 tlbl1 = newiTempLabel (NULL);
6206 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6207 emitcode ("tstx", "");
6208 emitcode ("beq", "%05d$", tlbl1->key + 100);
6209 emitcode ("", "%05d$:", tlbl->key + 100);
6210 shift= sign ? "asr" : "lsr";
6211 for (offset=size-1;offset>=0;offset--)
6213 rmwWithAop (shift, AOP (result), offset);
6216 rmwWithReg ("dec", hc08_reg_x);
6217 emitcode ("bne","%05d$", tlbl->key + 100);
6218 emitcode ("", "%05d$:", tlbl1->key + 100);
6220 freeAsmop (result, NULL, ic, TRUE);
6221 freeAsmop (left, NULL, ic, TRUE);
6222 freeAsmop (right, NULL, ic, TRUE);
6225 /*-----------------------------------------------------------------*/
6226 /* genUnpackBits - generates code for unpacking bits */
6227 /*-----------------------------------------------------------------*/
6229 genUnpackBits (operand * result)
6231 int offset = 0; /* result byte offset */
6232 int rsize; /* result size */
6233 int rlen = 0; /* remaining bitfield length */
6234 sym_link *etype; /* bitfield type information */
6235 int blen; /* bitfield length */
6236 int bstr; /* bitfield starting bit within byte */
6238 D(emitcode ("; genUnpackBits",""));
6240 etype = getSpec (operandType (result));
6241 rsize = getSize (operandType (result));
6242 blen = SPEC_BLEN (etype);
6243 bstr = SPEC_BSTR (etype);
6245 /* If the bitfield length is less than a byte */
6248 emitcode ("lda", ",x");
6249 hc08_dirtyReg (hc08_reg_a, FALSE);
6250 AccRsh (bstr, FALSE);
6251 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6252 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6256 /* Bit field did not fit in a byte. Copy all
6257 but the partial byte at the end. */
6258 for (rlen=blen;rlen>=8;rlen-=8)
6260 emitcode ("lda", ",x");
6261 hc08_dirtyReg (hc08_reg_a, FALSE);
6262 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6264 emitcode ("aix", "#1");
6267 /* Handle the partial byte at the end */
6270 emitcode ("lda", ",x");
6271 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6272 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6280 storeConstToAop (zero, AOP (result), offset++);
6285 /*-----------------------------------------------------------------*/
6286 /* genDataPointerGet - generates code when ptr offset is known */
6287 /*-----------------------------------------------------------------*/
6289 genDataPointerGet (operand * left,
6293 int size, offset = 0;
6296 D(emitcode ("; genDataPointerGet",""));
6298 aopOp (result, ic, TRUE);
6299 size = AOP_SIZE (result);
6301 derefaop = aopDerefAop (AOP (left));
6302 freeAsmop (left, NULL, ic, TRUE);
6303 derefaop->size = size;
6307 transferAopAop(derefaop, offset, AOP (result), offset);
6311 freeAsmop (NULL, derefaop, ic, TRUE);
6312 freeAsmop (result, NULL, ic, TRUE);
6316 /*-----------------------------------------------------------------*/
6317 /* genNearPointerGet - emitcode for near pointer fetch */
6318 /*-----------------------------------------------------------------*/
6320 genNearPointerGet (operand * left,
6326 sym_link *retype = getSpec (operandType (result));
6328 D(emitcode ("; genNearPointerGet",""));
6330 aopOp (left, ic, FALSE);
6332 /* if left is rematerialisable and
6333 result is not bit variable type and
6334 the left is pointer to data space i.e
6335 lower 128 bytes of space */
6336 if ((AOP_TYPE (left) == AOP_IMMD)
6337 || (AOP_TYPE (left) == AOP_LIT)
6338 /* !IS_BITVAR (retype) */
6339 /* && DCL_TYPE (ltype) == POINTER */ )
6341 genDataPointerGet (left, result, ic);
6345 /* if the operand is already in hx
6346 then we do nothing else we move the value to hx */
6347 if (AOP_TYPE (left) != AOP_STR)
6349 /* if this is remateriazable */
6350 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6351 loadRegFromConst (hc08_reg_h, zero);
6354 /* so hx now contains the address */
6355 aopOp (result, ic, FALSE);
6357 /* if bit then unpack */
6358 if (IS_BITVAR (retype))
6359 genUnpackBits (result);
6362 size = AOP_SIZE (result);
6367 accopWithMisc ("lda", ",x");
6370 rmwWithReg ("inc", hc08_reg_x);
6372 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6373 hc08_freeReg (hc08_reg_a);
6377 freeAsmop (left, NULL, ic, TRUE);
6378 freeAsmop (result, NULL, ic, TRUE);
6380 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6381 aopOp (IC_RESULT (pi), pi, FALSE);
6382 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6383 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6387 hc08_freeReg (hc08_reg_hx);
6391 /*-----------------------------------------------------------------*/
6392 /* genFarPointerGet - get value from far space */
6393 /*-----------------------------------------------------------------*/
6395 genFarPointerGet (operand * left,
6396 operand * result, iCode * ic, iCode * pi)
6399 sym_link *retype = getSpec (operandType (result));
6401 D(emitcode ("; genFarPointerGet",""));
6403 aopOp (left, ic, FALSE);
6405 /* if left is rematerialisable and
6406 result is not bit variable type and
6407 the left is pointer to data space i.e
6408 lower 128 bytes of space */
6409 if (AOP_TYPE (left) == AOP_IMMD &&
6411 /* && DCL_TYPE (ltype) == POINTER */ )
6413 genDataPointerGet (left, result, ic);
6417 /* if the operand is already in hx
6418 then we do nothing else we move the value to hx */
6419 if (AOP_TYPE (left) != AOP_STR)
6421 /* if this is remateriazable */
6422 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6425 /* so hx now contains the address */
6426 aopOp (result, ic, FALSE);
6428 /* if bit then unpack */
6429 if (IS_BITVAR (retype))
6430 genUnpackBits (result);
6433 size = AOP_SIZE (result);
6438 accopWithMisc ("lda", ",x");
6441 emitcode ("aix", "#1");
6442 hc08_dirtyReg (hc08_reg_hx, FALSE);
6444 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6445 hc08_freeReg (hc08_reg_a);
6449 freeAsmop (left, NULL, ic, TRUE);
6450 freeAsmop (result, NULL, ic, TRUE);
6452 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6453 aopOp (IC_RESULT (pi), pi, FALSE);
6454 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6455 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6459 hc08_freeReg (hc08_reg_hx);
6465 /*-----------------------------------------------------------------*/
6466 /* genPointerGet - generate code for pointer get */
6467 /*-----------------------------------------------------------------*/
6469 genPointerGet (iCode * ic, iCode *pi)
6471 operand *left, *result;
6472 sym_link *type, *etype;
6475 D(emitcode ("; genPointerGet",""));
6477 left = IC_LEFT (ic);
6478 result = IC_RESULT (ic);
6480 /* depending on the type of pointer we need to
6481 move it to the correct pointer register */
6482 type = operandType (left);
6483 etype = getSpec (type);
6484 /* if left is of type of pointer then it is simple */
6485 if (IS_PTR (type) && !IS_FUNC (type->next))
6486 p_type = DCL_TYPE (type);
6489 /* we have to go by the storage class */
6490 p_type = PTR_TYPE (SPEC_OCLS (etype));
6493 /* special case when cast remat */
6494 if (p_type == GPOINTER && IS_SYMOP(left) && OP_SYMBOL(left)->remat &&
6495 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6496 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6497 type = operandType (left);
6498 p_type = DCL_TYPE (type);
6500 /* now that we have the pointer type we assign
6501 the pointer values */
6508 genNearPointerGet (left, result, ic, pi);
6514 genFarPointerGet (left, result, ic, pi);
6521 /*-----------------------------------------------------------------*/
6522 /* genPackBits - generates code for packed bit storage */
6523 /*-----------------------------------------------------------------*/
6525 genPackBits (sym_link * etype,
6528 int offset = 0; /* source byte offset */
6529 int rlen = 0; /* remaining bitfield length */
6530 int blen; /* bitfield length */
6531 int bstr; /* bitfield starting bit within byte */
6532 int litval; /* source literal value (if AOP_LIT) */
6533 unsigned char mask; /* bitmask within current byte */
6535 D(emitcode ("; genPackBits",""));
6537 blen = SPEC_BLEN (etype);
6538 bstr = SPEC_BSTR (etype);
6540 /* If the bitfield length is less than a byte */
6543 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6544 (unsigned char) (0xFF >> (8 - bstr)));
6546 if (AOP_TYPE (right) == AOP_LIT)
6548 /* Case with a bitfield length <8 and literal source
6550 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6552 litval &= (~mask) & 0xff;
6554 emitcode ("lda", ",x");
6555 if ((mask|litval)!=0xff)
6556 emitcode ("and","#0x%02x", mask);
6558 emitcode ("ora","#0x%02x", litval);
6559 hc08_dirtyReg (hc08_reg_a, FALSE);
6560 emitcode ("sta", ",x");
6562 hc08_freeReg (hc08_reg_a);
6566 /* Case with a bitfield length < 8 and arbitrary source
6568 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6569 /* shift and mask source value */
6571 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6572 hc08_dirtyReg (hc08_reg_a, FALSE);
6573 pushReg (hc08_reg_a, TRUE);
6575 emitcode ("lda", ",x");
6576 emitcode ("and", "#0x%02x", mask);
6577 emitcode ("ora", "1,s");
6578 emitcode ("sta", ",x");
6579 pullReg (hc08_reg_a);
6581 hc08_freeReg (hc08_reg_a);
6585 /* Bit length is greater than 7 bits. In this case, copy */
6586 /* all except the partial byte at the end */
6587 for (rlen=blen;rlen>=8;rlen-=8)
6589 if (AOP (right)->type == AOP_DIR)
6591 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6595 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6596 emitcode ("sta", "%d,x", offset);
6601 /* If there was a partial byte at the end */
6604 mask = (((unsigned char) -1 << rlen) & 0xff);
6606 if (AOP_TYPE (right) == AOP_LIT)
6608 /* Case with partial byte and literal source
6610 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6611 litval >>= (blen-rlen);
6612 litval &= (~mask) & 0xff;
6613 emitcode ("lda", "%d,x", offset);
6614 hc08_dirtyReg (hc08_reg_a, FALSE);
6615 if ((mask|litval)!=0xff)
6616 emitcode ("and","#0x%02x", mask);
6618 emitcode ("ora","#0x%02x", litval);
6619 emitcode ("sta", "%d,x", offset);
6620 hc08_dirtyReg (hc08_reg_a, FALSE);
6621 hc08_freeReg (hc08_reg_a);
6625 /* Case with partial byte and arbitrary source
6627 loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6628 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6629 hc08_dirtyReg (hc08_reg_a, FALSE);
6630 pushReg (hc08_reg_a, TRUE);
6632 emitcode ("lda", ",x");
6633 emitcode ("and", "#0x%02x", mask);
6634 emitcode ("ora", "1,s");
6635 emitcode ("sta", ",x");
6638 hc08_freeReg (hc08_reg_a);
6641 /*-----------------------------------------------------------------*/
6642 /* genDataPointerSet - remat pointer to data space */
6643 /*-----------------------------------------------------------------*/
6645 genDataPointerSet (operand * right,
6649 int size, offset = 0;
6652 D(emitcode ("; genDataPointerSet",""));
6654 aopOp (right, ic, FALSE);
6655 size = AOP_SIZE (right);
6657 derefaop = aopDerefAop (AOP (result));
6658 freeAsmop (result, NULL, ic, TRUE);
6659 derefaop->size = size;
6663 transferAopAop (AOP (right), offset, derefaop, offset);
6667 freeAsmop (right, NULL, ic, TRUE);
6668 freeAsmop (NULL, derefaop, ic, TRUE);
6672 /*-----------------------------------------------------------------*/
6673 /* genNearPointerSet - emitcode for near pointer put */
6674 /*-----------------------------------------------------------------*/
6676 genNearPointerSet (operand * right,
6682 sym_link *retype = getSpec (operandType (right));
6683 sym_link *letype = getSpec (operandType (result));
6685 D(emitcode ("; genNearPointerSet",""));
6687 aopOp (result, ic, FALSE);
6689 /* if the result is rematerializable &
6690 in data space & not a bit variable */
6691 if (AOP_TYPE (result) == AOP_IMMD &&
6692 /* DCL_TYPE (ptype) == POINTER && */
6693 !IS_BITVAR (retype) &&
6694 !IS_BITVAR (letype))
6696 genDataPointerSet (right, result, ic);
6700 /* if the operand is already in hx
6701 then we do nothing else we move the value to hx */
6702 if (AOP_TYPE (result) != AOP_STR)
6704 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6705 loadRegFromConst (hc08_reg_h, zero);
6707 /* so hx now contains the address */
6708 aopOp (right, ic, FALSE);
6710 /* if bit then unpack */
6711 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6712 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6715 size = AOP_SIZE (right);
6720 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6721 accopWithMisc ("sta", ",x");
6724 rmwWithReg ("inc", hc08_reg_x);
6726 hc08_freeReg (hc08_reg_a);
6730 freeAsmop (result, NULL, ic, TRUE);
6731 freeAsmop (right, NULL, ic, TRUE);
6733 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6734 aopOp (IC_RESULT (pi), pi, FALSE);
6735 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6736 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6740 hc08_freeReg (hc08_reg_hx);
6745 /*-----------------------------------------------------------------*/
6746 /* genFarPointerSet - set value from far space */
6747 /*-----------------------------------------------------------------*/
6749 genFarPointerSet (operand * right,
6750 operand * result, iCode * ic, iCode * pi)
6753 sym_link *retype = getSpec (operandType (right));
6754 sym_link *letype = getSpec (operandType (result));
6756 D(emitcode ("; genFarPointerSet",""));
6758 aopOp (result, ic, FALSE);
6760 /* if the result is rematerializable &
6761 in data space & not a bit variable */
6762 if (AOP_TYPE (result) == AOP_IMMD &&
6763 /* DCL_TYPE (ptype) == POINTER && */
6764 !IS_BITVAR (retype) &&
6765 !IS_BITVAR (letype))
6767 genDataPointerSet (right, result, ic);
6771 /* if the operand is already in hx
6772 then we do nothing else we move the value to hx */
6773 if (AOP_TYPE (result) != AOP_STR)
6775 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6777 /* so hx now contains the address */
6778 aopOp (right, ic, FALSE);
6780 /* if bit then unpack */
6781 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6782 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6785 size = AOP_SIZE (right);
6790 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6791 accopWithMisc ("sta", ",x");
6794 emitcode ("aix", "#1");
6796 hc08_freeReg (hc08_reg_a);
6800 freeAsmop (result, NULL, ic, TRUE);
6801 freeAsmop (right, NULL, ic, TRUE);
6803 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6804 aopOp (IC_RESULT (pi), pi, FALSE);
6805 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6806 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6810 hc08_freeReg (hc08_reg_hx);
6816 /*-----------------------------------------------------------------*/
6817 /* genPointerSet - stores the value into a pointer location */
6818 /*-----------------------------------------------------------------*/
6820 genPointerSet (iCode * ic, iCode *pi)
6822 operand *right, *result;
6823 sym_link *type, *etype;
6826 D(emitcode ("; genPointerSet",""));
6828 right = IC_RIGHT (ic);
6829 result = IC_RESULT (ic);
6831 /* depending on the type of pointer we need to
6832 move it to the correct pointer register */
6833 type = operandType (result);
6834 etype = getSpec (type);
6835 /* if left is of type of pointer then it is simple */
6836 if (IS_PTR (type) && !IS_FUNC (type->next))
6838 p_type = DCL_TYPE (type);
6842 /* we have to go by the storage class */
6843 p_type = PTR_TYPE (SPEC_OCLS (etype));
6846 /* special case when cast remat */
6847 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
6848 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
6849 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
6850 type = operandType (result);
6851 p_type = DCL_TYPE (type);
6853 /* now that we have the pointer type we assign
6854 the pointer values */
6861 genNearPointerSet (right, result, ic, pi);
6867 genFarPointerSet (right, result, ic, pi);
6871 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
6872 "genPointerSet: illegal pointer type");
6877 /*-----------------------------------------------------------------*/
6878 /* genIfx - generate code for Ifx statement */
6879 /*-----------------------------------------------------------------*/
6881 genIfx (iCode * ic, iCode * popIc)
6883 operand *cond = IC_COND (ic);
6886 D(emitcode ("; genIfx",""));
6888 aopOp (cond, ic, FALSE);
6890 /* get the value into acc */
6891 if (AOP_TYPE (cond) != AOP_CRY)
6892 asmopToBool (AOP (cond), FALSE);
6895 /* the result is now in the accumulator */
6896 freeAsmop (cond, NULL, ic, TRUE);
6898 /* if there was something to be popped then do it */
6902 /* if the condition is a bit variable */
6903 if (isbit && IS_ITEMP (cond) &&
6905 genIfxJump (ic, SPIL_LOC (cond)->rname);
6906 else if (isbit && !IS_ITEMP (cond))
6907 genIfxJump (ic, OP_SYMBOL (cond)->rname);
6909 genIfxJump (ic, "a");
6914 /*-----------------------------------------------------------------*/
6915 /* genAddrOf - generates code for address of */
6916 /*-----------------------------------------------------------------*/
6918 genAddrOf (iCode * ic)
6920 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
6923 D(emitcode ("; genAddrOf",""));
6925 aopOp (IC_RESULT (ic), ic, FALSE);
6927 /* if the operand is on the stack then we
6928 need to get the stack offset of this
6932 /* if it has an offset then we need to compute
6934 hc08_useReg (hc08_reg_hx);
6935 emitcode ("tsx", "");
6936 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
6937 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
6938 hc08_freeReg (hc08_reg_hx);
6943 /* object not on stack then we need the name */
6944 size = AOP_SIZE (IC_RESULT (ic));
6949 char s[SDCC_NAME_MAX+10];
6952 sprintf (s, "#%s", sym->rname);
6955 sprintf (s, "#>%s", sym->rname);
6958 sprintf (s, "#(%s >> %d)",
6962 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
6966 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
6970 /*-----------------------------------------------------------------*/
6971 /* genAssign - generate code for assignment */
6972 /*-----------------------------------------------------------------*/
6974 genAssign (iCode * ic)
6976 operand *result, *right;
6978 // unsigned long lit = 0L;
6980 D(emitcode("; genAssign",""));
6982 result = IC_RESULT (ic);
6983 right = IC_RIGHT (ic);
6985 /* if they are the same */
6986 if (operandsEqu (result, right)) {
6990 aopOp (right, ic, FALSE);
6991 aopOp (result, ic, TRUE);
6993 /* if they are the same registers */
6994 if (sameRegs (AOP (right), AOP (result)))
6997 if ((AOP_TYPE (right) == AOP_LIT)
6998 && (IS_AOP_HX(AOP(result))))
7000 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7005 size = AOP_SIZE (result);
7010 transferAopAop (AOP (right), offset, AOP (result), offset);
7015 freeAsmop (right, NULL, ic, TRUE);
7016 freeAsmop (result, NULL, ic, TRUE);
7019 /*-----------------------------------------------------------------*/
7020 /* genJumpTab - genrates code for jump table */
7021 /*-----------------------------------------------------------------*/
7023 genJumpTab (iCode * ic)
7028 D(emitcode ("; genJumpTab",""));
7030 aopOp (IC_JTCOND (ic), ic, FALSE);
7031 /* get the condition into accumulator */
7032 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7033 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7034 /* multiply by three */
7035 pushReg (hc08_reg_a, FALSE);
7036 emitcode ("lsla", "");
7037 emitcode ("add","1,s");
7038 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7039 loadRegFromConst (hc08_reg_h, zero);
7041 jtab = newiTempLabel (NULL);
7042 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7043 emitcode ("", "%05d$:", jtab->key + 100);
7044 /* now generate the jump labels */
7045 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7046 jtab = setNextItem (IC_JTLABELS (ic)))
7047 emitcode ("jmp", "%05d$", jtab->key + 100);
7049 hc08_dirtyReg (hc08_reg_a, TRUE);
7050 hc08_dirtyReg (hc08_reg_hx, TRUE);
7053 /*-----------------------------------------------------------------*/
7054 /* genCast - gen code for casting */
7055 /*-----------------------------------------------------------------*/
7057 genCast (iCode * ic)
7059 operand *result = IC_RESULT (ic);
7060 sym_link *ctype = operandType (IC_LEFT (ic));
7061 sym_link *rtype = operandType (IC_RIGHT (ic));
7062 operand *right = IC_RIGHT (ic);
7065 D(emitcode("; genCast",""));
7067 /* if they are equivalent then do nothing */
7068 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7071 aopOp (right, ic, FALSE);
7072 aopOp (result, ic, FALSE);
7075 /* if they are the same size : or less */
7076 if (AOP_SIZE (result) <= AOP_SIZE (right))
7079 /* if they are in the same place */
7081 if (sameRegs (AOP (right), AOP (result)))
7085 /* if they in different places then copy */
7086 size = AOP_SIZE (result);
7090 transferAopAop(AOP (right), offset, AOP (result), offset);
7097 /* if the result is of type pointer */
7102 sym_link *type = operandType (right);
7103 sym_link *etype = getSpec (type);
7105 /* pointer to generic pointer */
7106 if (IS_GENPTR (ctype))
7109 p_type = DCL_TYPE (type);
7112 if (SPEC_SCLS(etype)==S_REGISTER) {
7113 // let's assume it is a generic pointer
7116 /* we have to go by the storage class */
7117 p_type = PTR_TYPE (SPEC_OCLS (etype));
7121 /* the first two bytes are known */
7122 size = GPTRSIZE - 1;
7126 transferAopAop(AOP (right), offset, AOP (result), offset);
7129 /* the last byte depending on type */
7132 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7137 // pointerTypeToGPByte will have bitched.
7141 sprintf(gpValStr, "#0x%d", gpVal);
7142 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7148 /* just copy the pointers */
7149 size = AOP_SIZE (result);
7153 transferAopAop(AOP (right), offset, AOP (result), offset);
7159 /* so we now know that the size of destination is greater
7160 than the size of the source */
7161 /* we move to result for the size of source */
7162 size = AOP_SIZE (right);
7166 transferAopAop(AOP (right), offset, AOP (result), offset);
7170 /* now depending on the sign of the source && destination */
7171 size = AOP_SIZE (result) - AOP_SIZE (right);
7172 /* if unsigned or not an integral type */
7173 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7176 storeConstToAop (zero, AOP (result), offset++);
7180 /* we need to extend the sign :{ */
7181 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7182 accopWithMisc ("rola", "");
7183 accopWithMisc ("clra", "");
7184 accopWithMisc ("sbc", zero);
7186 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7189 /* we are done hurray !!!! */
7192 freeAsmop (right, NULL, ic, TRUE);
7193 freeAsmop (result, NULL, ic, TRUE);
7197 /*-----------------------------------------------------------------*/
7198 /* genDjnz - generate decrement & jump if not zero instrucion */
7199 /*-----------------------------------------------------------------*/
7201 genDjnz (iCode * ic, iCode * ifx)
7207 D(emitcode ("; genDjnz",""));
7209 /* if the if condition has a false label
7210 then we cannot save */
7214 /* if the minus is not of the form
7216 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7217 !IS_OP_LITERAL (IC_RIGHT (ic)))
7220 if (operandLitValue (IC_RIGHT (ic)) != 1)
7223 /* dbnz doesn't support extended mode */
7224 if (isOperandInFarSpace (IC_RESULT (ic)))
7227 /* if the size of this greater than one then no
7229 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7231 aopOp (IC_RESULT (ic), ic, FALSE);
7232 if (AOP_SIZE (IC_RESULT (ic))>1)
7234 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7238 /* otherwise we can save BIG */
7239 lbl = newiTempLabel (NULL);
7240 lbl1 = newiTempLabel (NULL);
7243 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7246 emitBranch ("bra", lbl1);
7248 emitBranch ("jmp", IC_TRUE (ifx));
7251 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7256 /*-----------------------------------------------------------------*/
7257 /* genReceive - generate code for a receive iCode */
7258 /*-----------------------------------------------------------------*/
7260 genReceive (iCode * ic)
7264 D(emitcode ("; genReceive",""));
7266 aopOp (IC_RESULT (ic), ic, FALSE);
7267 size = AOP_SIZE (IC_RESULT (ic));
7272 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7273 AOP (IC_RESULT (ic)), offset);
7274 if (hc08_aop_pass[offset]->type == AOP_REG)
7275 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7280 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7283 /*-----------------------------------------------------------------*/
7284 /* genDummyRead - generate code for dummy read of volatiles */
7285 /*-----------------------------------------------------------------*/
7287 genDummyRead (iCode * ic)
7292 D(emitcode("; genDummyRead",""));
7294 right = IC_RIGHT (ic);
7296 aopOp (right, ic, FALSE);
7298 /* bit variables done */
7300 size = AOP_SIZE (right);
7305 loadRegFromAop (hc08_reg_a, AOP (right), offset);
7306 hc08_freeReg (hc08_reg_a);
7310 freeAsmop (right, NULL, ic, TRUE);
7313 /*-----------------------------------------------------------------*/
7314 /* genCritical - generate code for start of a critical sequence */
7315 /*-----------------------------------------------------------------*/
7317 genCritical (iCode *ic)
7319 D(emitcode("; genCritical",""));
7322 aopOp (IC_RESULT (ic), ic, TRUE);
7324 emitcode ("tpa", "");
7325 hc08_dirtyReg (hc08_reg_a, FALSE);
7326 emitcode ("sei", "");
7329 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7331 pushReg (hc08_reg_a, FALSE);
7333 hc08_freeReg (hc08_reg_a);
7335 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7338 /*-----------------------------------------------------------------*/
7339 /* genEndCritical - generate code for end of a critical sequence */
7340 /*-----------------------------------------------------------------*/
7342 genEndCritical (iCode *ic)
7344 D(emitcode("; genEndCritical",""));
7348 aopOp (IC_RIGHT (ic), ic, FALSE);
7349 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7350 emitcode ("tap", "");
7351 hc08_freeReg (hc08_reg_a);
7352 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7356 pullReg (hc08_reg_a);
7357 emitcode ("tap", "");
7362 /*-----------------------------------------------------------------*/
7363 /* genhc08Code - generate code for HC08 based controllers */
7364 /*-----------------------------------------------------------------*/
7366 genhc08Code (iCode * lic)
7371 lineHead = lineCurr = NULL;
7373 /* print the allocation information */
7374 if (allocInfo && currFunc)
7375 printAllocInfo (currFunc, codeOutFile);
7376 /* if debug information required */
7377 if (options.debug && currFunc)
7379 debugFile->writeFunction(currFunc);
7381 if (IS_STATIC (currFunc->etype))
7382 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7384 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7387 /* stack pointer name */
7388 if (options.useXstack)
7393 hc08_aop_pass[0] = newAsmop (AOP_REG);
7394 hc08_aop_pass[0]->size=1;
7395 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7396 hc08_aop_pass[1] = newAsmop (AOP_REG);
7397 hc08_aop_pass[1]->size=1;
7398 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7399 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7400 hc08_aop_pass[2]->size=1;
7401 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7402 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7403 hc08_aop_pass[3]->size=1;
7404 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7406 for (ic = lic; ic; ic = ic->next)
7409 if (ic->lineno && cln != ic->lineno)
7414 emitcode ("", "C$%s$%d$%d$%d ==.",
7415 FileBaseName (ic->filename), ic->lineno,
7416 ic->level, ic->block);
7419 if (!options.noCcodeInAsm) {
7420 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7421 printCLine(ic->filename, ic->lineno));
7425 if (options.iCodeInAsm) {
7429 for (i=0; i<6; i++) {
7430 sprintf (®sInUse[i],
7431 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7434 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7436 /* if the result is marked as
7437 spilt and rematerializable or code for
7438 this has already been generated then
7440 if (resultRemat (ic) || ic->generated)
7448 for (i=A_IDX;i<=XA_IDX;i++)
7450 reg = hc08_regWithIdx(i);
7452 emitcode("","; %s = %s offset %d", reg->name,
7453 aopName(reg->aop), reg->aopofs);
7456 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7458 sym = OP_SYMBOL (IC_LEFT (ic));
7459 if (sym->accuse == ACCUSE_HX)
7461 hc08_reg_h->isFree = FALSE;
7462 hc08_reg_x->isFree = FALSE;
7464 else if (sym->accuse == ACCUSE_XA)
7466 hc08_reg_a->isFree = FALSE;
7468 hc08_reg_x->isFree = FALSE;
7471 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7473 sym = OP_SYMBOL (IC_RIGHT (ic));
7474 if (sym->accuse == ACCUSE_HX)
7476 hc08_reg_h->isFree = FALSE;
7477 hc08_reg_x->isFree = FALSE;
7479 else if (sym->accuse == ACCUSE_XA)
7481 hc08_reg_a->isFree = FALSE;
7483 hc08_reg_x->isFree = FALSE;
7488 /* depending on the operation */
7508 /* IPOP happens only when trying to restore a
7509 spilt live range, if there is an ifx statement
7510 following this pop then the if statement might
7511 be using some of the registers being popped which
7512 would destory the contents of the register so
7513 we need to check for this condition and handle it */
7515 ic->next->op == IFX &&
7516 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7517 genIfx (ic->next, ic);
7535 genEndFunction (ic);
7551 if (!genPointerGetSetOfs (ic))
7556 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7573 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7577 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7584 /* note these two are xlated by algebraic equivalence
7585 during parsing SDCC.y */
7586 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7587 "got '>=' or '<=' shouldn't have come here");
7591 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7603 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7607 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7611 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7638 case GET_VALUE_AT_ADDRESS:
7639 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7643 if (POINTER_SET (ic))
7644 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7670 addSet (&_G.sendSet, ic);
7673 case DUMMY_READ_VOLATILE:
7682 genEndCritical (ic);
7693 if (!hc08_reg_a->isFree)
7694 emitcode("","; forgot to free a");
7695 if (!hc08_reg_x->isFree)
7696 emitcode("","; forgot to free x");
7697 if (!hc08_reg_h->isFree)
7698 emitcode("","; forgot to free h");
7699 if (!hc08_reg_hx->isFree)
7700 emitcode("","; forgot to free hx");
7701 if (!hc08_reg_xa->isFree)
7702 emitcode("","; forgot to free xa");
7706 /* now we are ready to call the
7707 peep hole optimizer */
7708 if (!options.nopeep)
7709 peepHole (&lineHead);
7711 /* now do the actual printing */
7712 printLine (lineHead, codeOutFile);