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;
75 static asmop *hc08_aop_pass[4];
77 extern int hc08_ptrRegReq;
78 extern int hc08_nRegs;
79 extern FILE *codeOutFile;
80 //static void saveRBank (int, iCode *, bool);
81 static bool operandsEqu (operand * op1, operand * op2);
82 static void loadRegFromConst (regs *reg, char *c);
83 static char *aopName (asmop *aop);
84 static asmop * newAsmop (short type);
85 static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
86 #define RESULTONSTACK(x) \
87 (IC_RESULT(x) && IC_RESULT(x)->aop && \
88 IC_RESULT(x)->aop->type == AOP_STK )
90 #define IS_AOP_HX(x) \
91 (((x)->type == AOP_REG) \
92 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
93 && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
95 #define IS_AOP_XA(x) \
96 (((x)->type == AOP_REG) \
97 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
98 && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
100 #define IS_AOP_A(x) \
101 (((x)->type == AOP_REG) \
102 && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
103 && ((x)->size == 1) )
105 #define IS_AOP_X(x) \
106 (((x)->type == AOP_REG) \
107 && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
108 && ((x)->size == 1) )
110 #define IS_AOP_H(x) \
111 (((x)->type == AOP_REG) \
112 && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
113 && ((x)->size == 1) )
115 #define CLRC emitcode("clc","")
117 static lineNode *lineHead = NULL;
118 static lineNode *lineCurr = NULL;
121 static unsigned char SLMask[] =
122 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
123 0xE0, 0xC0, 0x80, 0x00};
124 static unsigned char SRMask[] =
125 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
126 0x07, 0x03, 0x01, 0x00};
134 #define AOP(op) op->aop
135 #define AOP_TYPE(op) AOP(op)->type
136 #define AOP_SIZE(op) AOP(op)->size
137 #define AOP_OP(aop) aop->op
140 /*-----------------------------------------------------------------*/
141 /* emitcode - writes the code into a file : for now it is simple */
142 /*-----------------------------------------------------------------*/
144 emitcode (char *inst, char *fmt,...)
147 char lb[INITIAL_INLINEASM];
155 sprintf (lb, "%s\t", inst);
157 sprintf (lb, "%s", inst);
158 vsprintf (lb + (strlen (lb)), fmt, ap);
161 vsprintf (lb, fmt, ap);
163 while (isspace (*lbp))
167 lineCurr = (lineCurr ?
168 connectLine (lineCurr, newLineNode (lb)) :
169 (lineHead = newLineNode (lb)));
170 lineCurr->isInline = _G.inLine;
171 lineCurr->isDebug = _G.debugLine;
172 lineCurr->ic = _G.current_iCode;
174 //printf("%s\n", lb);
179 emitBranch (char *branchop, symbol *tlbl)
181 emitcode (branchop, "%05d$", (tlbl->key + 100));
185 emitLabel (symbol *tlbl)
187 emitcode ("", "%05d$:", (tlbl->key +100));
192 /*--------------------------------------------------------------------------*/
193 /* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If */
194 /* freesrc is true, sreg is marked free and available for */
195 /* reuse. sreg and dreg must be of equal size */
196 /*--------------------------------------------------------------------------*/
198 transferRegReg (regs *sreg, regs *dreg, bool freesrc)
204 /* Nothing to do if no destination. */
208 /* But it's definately an error if there's no source. */
211 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
212 "NULL sreg in transferRegReg");
216 D(emitcode ("", "; transferRegReg(%s,%s)",
217 sreg->name, dreg->name));
230 case H_IDX: /* H to A */
231 emitcode ("pshh", "");
232 emitcode ("pula", "");
234 case X_IDX: /* X to A */
235 emitcode ("txa", "");
244 case A_IDX: /* A to H */
245 emitcode ("psha", "");
246 emitcode ("pulh", "");
248 case X_IDX: /* X to H */
249 emitcode ("pshx", "");
250 emitcode ("pulh", "");
259 case A_IDX: /* A to X */
260 emitcode ("tax", "");
262 case H_IDX: /* H to X */
263 emitcode ("pshh", "");
264 emitcode ("pulx", "");
273 case XA_IDX: /* XA to HX */
274 emitcode ("pshx", "");
275 emitcode ("pulh", "");
276 emitcode ("tax", "");
285 case HX_IDX: /* HX to XA */
286 emitcode ("txa", "");
287 emitcode ("pshh", "");
288 emitcode ("pulx", "");
298 wassertl (!error, "bad combo in transferRegReg");
303 dreg->aop = sreg->aop;
304 dreg->aopofs = sreg->aopofs;
305 dreg->isFree = FALSE;
309 /*--------------------------------------------------------------------------*/
310 /* pushReg - Push register reg onto the stack. If freereg is true, reg is */
311 /* marked free and available for reuse. */
312 /*--------------------------------------------------------------------------*/
314 pushReg (regs *reg, bool freereg)
316 int regidx = reg->rIdx;
321 emitcode ("psha", "");
325 emitcode ("pshx", "");
329 emitcode ("pshh", "");
333 emitcode ("pshx", "");
334 emitcode ("pshh", "");
338 emitcode ("psha", "");
339 emitcode ("pshx", "");
347 return -_G.stackOfs-_G.stackPushes;
350 /*--------------------------------------------------------------------------*/
351 /* pullReg - Pull register reg off the stack. */
352 /*--------------------------------------------------------------------------*/
356 int regidx = reg->rIdx;
361 emitcode ("pula", "");
365 emitcode ("pulx", "");
369 emitcode ("pulh", "");
373 emitcode ("pulx", "");
374 emitcode ("pulh", "");
378 emitcode ("pula", "");
379 emitcode ("pulx", "");
386 hc08_dirtyReg(reg, FALSE);
389 /*--------------------------------------------------------------------------*/
390 /* pullNull - Discard n bytes off the top of the stack */
391 /*--------------------------------------------------------------------------*/
397 emitcode("ais","#%d",n);
402 /*--------------------------------------------------------------------------*/
403 /* pushRegIfUsed - Push register reg if marked in use. Returns true if the */
404 /* push was performed, false otherwise. */
405 /*--------------------------------------------------------------------------*/
407 pushRegIfUsed (regs *reg)
418 /*--------------------------------------------------------------------------*/
419 /* pullOrFreeReg - If needpull is true, register reg is pulled from the */
420 /* stack. Otherwise register reg is marked as free. */
421 /*--------------------------------------------------------------------------*/
423 pullOrFreeReg (regs *reg, bool needpull)
431 /*--------------------------------------------------------------------------*/
432 /* adjustStack - Adjust the stack pointer by n bytes. */
433 /*--------------------------------------------------------------------------*/
442 emitcode ("ais","#127");
447 emitcode ("ais","#-128");
452 emitcode ("ais", "#%d", n);
459 /*--------------------------------------------------------------------------*/
460 /* aopName - Return a string with debugging information about an asmop. */
461 /*--------------------------------------------------------------------------*/
465 static char buffer[256];
469 return "(asmop*)NULL";
474 sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
477 sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
480 sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
483 sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
486 sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
489 sprintf (buf, "REG(%s,%s,%s,%s)",
490 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
491 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
492 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
493 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
500 sprintf (buf,"?%d", aop->type);
508 /*--------------------------------------------------------------------------*/
509 /* loadRegFromAop - Load register reg from logical offset loffset of aop. */
510 /*--------------------------------------------------------------------------*/
512 loadRegFromAop (regs *reg, asmop *aop, int loffset)
514 int regidx = reg->rIdx;
516 if (aop->stacked && aop->stk_aop[loffset])
518 loadRegFromAop (reg, aop->stk_aop[loffset], 0);
523 printf("loadRegFromAop called\n");
526 printf(" reg = NULL\n");
529 printf(" reg = %s\n", reg->name);
532 printf(" aop = NULL\n");
535 printf(" aop->type = %d\n", aop->type);
536 printf(" loffset = %d\n", loffset);
539 printf(" aop has operand link\n");
541 printf(" aop missing operand link\n");
543 printf(" reg has operand link\n");
545 printf(" reg missing operand link\n");
548 D(emitcode ("", "; loadRegFromAop (%s, %s, %d)",
549 reg->name, aopName (aop), loffset));
551 /* If operand is volatile, we cannot optimize. */
552 if (!aop->op || isOperandVolatile (aop->op, FALSE))
556 /* If this register already has this offset of the operand
557 then we need only mark it as in use. */
558 if (reg->aop && reg->aop->op && aop->op
559 && operandsEqu(reg->aop->op,aop->op)
560 && (reg->aopofs == loffset))
563 D(emitcode ("","; already had correct value for %s", reg->name));
567 /* TODO: check to see if we can transfer from another register */
569 if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
570 && operandsEqu(hc08_reg_h->aop->op,aop->op)
571 && (hc08_reg_h->aopofs == loffset))
573 D(emitcode ("","; found correct value for %s in h", reg->name));
574 transferRegReg (hc08_reg_h, reg, FALSE);
580 if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
581 && operandsEqu(hc08_reg_x->aop->op,aop->op)
582 && (hc08_reg_x->aopofs == loffset))
584 D(emitcode ("","; found correct value for %s in x", reg->name));
585 transferRegReg (hc08_reg_x, reg, FALSE);
590 if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
591 && operandsEqu(hc08_reg_a->aop->op,aop->op)
592 && (hc08_reg_a->aopofs == loffset))
594 D(emitcode ("","; found correct value for %s in a", reg->name));
595 transferRegReg (hc08_reg_a, reg, FALSE);
605 if (aop->type == AOP_REG)
607 if (loffset < aop->size)
608 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
610 emitcode ("clra", ""); /* TODO: handle sign extension */
613 emitcode ("lda","%s", aopAdrStr (aop, loffset, FALSE));
616 if (aop->type == AOP_REG)
618 if (loffset < aop->size)
619 transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
621 emitcode ("clrx", ""); /* TODO: handle sign extension */
624 emitcode ("ldx","%s", aopAdrStr (aop, loffset, FALSE));
627 if (hc08_reg_a->isFree)
629 loadRegFromAop (hc08_reg_a, aop, loffset);
630 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
632 else if (hc08_reg_x->isFree)
634 loadRegFromAop (hc08_reg_x, aop, loffset);
635 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
639 pushReg (hc08_reg_a, TRUE);
640 loadRegFromAop (hc08_reg_a, aop, loffset);
641 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
642 pullReg (hc08_reg_a);
648 else if (IS_AOP_XA(aop))
649 transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
650 else if ((aop->type == AOP_DIR))
652 if (aop->size>(loffset+1))
653 emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
656 loadRegFromAop (hc08_reg_x, aop, loffset);
657 loadRegFromConst (hc08_reg_h, zero);
660 else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
662 emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
667 needpula = pushRegIfUsed (hc08_reg_a);
668 loadRegFromAop (hc08_reg_a, aop, loffset+1);
669 loadRegFromAop (hc08_reg_x, aop, loffset);
670 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
671 pullOrFreeReg (hc08_reg_a, needpula);
677 else if (IS_AOP_HX(aop))
678 transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
681 loadRegFromAop (hc08_reg_a, aop, loffset);
682 loadRegFromAop (hc08_reg_x, aop, loffset+1);
687 // ignore caching for now
690 reg->aopofs = loffset;
695 /*--------------------------------------------------------------------------*/
696 /* forceStackedAop - Reserve space on the stack for asmop aop; when */
697 /* freeAsmop is called with aop, the stacked data will */
698 /* be copied to the original aop location and */
699 /*--------------------------------------------------------------------------*/
701 forceStackedAop (asmop *aop)
704 asmop *newaop = newAsmop (aop->type);
705 memcpy (newaop, aop, sizeof(*newaop));
707 D(emitcode("", "; forcedStackAop %s", aopName(aop)));
708 for (loffset=0; loffset < newaop->size; loffset++)
710 asmop *aopsof = newAsmop (AOP_SOF);
712 aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
713 aopsof->op = aop->op;
714 newaop->stk_aop[loffset] = aopsof;
721 /*--------------------------------------------------------------------------*/
722 /* storeRegToAop - Store register reg to logical offset loffset of aop. */
723 /*--------------------------------------------------------------------------*/
725 storeRegToAop (regs *reg, asmop *aop, int loffset)
727 int regidx = reg->rIdx;
733 D(emitcode ("", "; storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
734 reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
736 if ((reg->rIdx == HX_IDX) && aop->stacked
737 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
739 storeRegToAop (hc08_reg_h, aop, loffset+1);
740 storeRegToAop (hc08_reg_x, aop, loffset);
744 if ((reg->rIdx == XA_IDX) && aop->stacked
745 && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
747 storeRegToAop (hc08_reg_x, aop, loffset+1);
748 storeRegToAop (hc08_reg_a, aop, loffset);
752 if (aop->stacked && aop->stk_aop[loffset])
754 storeRegToAop (reg, aop->stk_aop[loffset], 0);
758 if (aop->type == AOP_STR)
761 transferRegReg (reg, hc08_reg_x, FALSE);
763 transferRegReg (reg, hc08_reg_h, FALSE);
767 if (aop->type == AOP_DUMMY)
773 if ((aop->type == AOP_REG) && (loffset < aop->size))
774 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
776 emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
779 if ((aop->type == AOP_REG) && (loffset < aop->size))
780 transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
782 emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
785 if (hc08_reg_a->isFree)
787 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
788 storeRegToAop (hc08_reg_a, aop, loffset);
789 hc08_freeReg (hc08_reg_a);
791 else if (hc08_reg_x->isFree)
793 transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
794 storeRegToAop (hc08_reg_x, aop, loffset);
795 hc08_freeReg (hc08_reg_x);
799 pushReg (hc08_reg_a, TRUE);
800 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
801 storeRegToAop (hc08_reg_a, aop, loffset);
802 pullReg (hc08_reg_a);
806 if ((aop->type == AOP_DIR) )
808 emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
810 else if (IS_AOP_XA(aop))
811 transferRegReg(reg, hc08_reg_xa, FALSE);
812 else if (IS_AOP_HX(aop))
817 needpula = pushRegIfUsed (hc08_reg_a);
818 transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
819 storeRegToAop (hc08_reg_a, aop, loffset+1);
820 storeRegToAop (hc08_reg_x, aop, loffset);
821 pullOrFreeReg (hc08_reg_a, needpula);
826 transferRegReg(reg, hc08_reg_hx, FALSE);
827 else if (IS_AOP_XA(aop))
831 storeRegToAop (hc08_reg_a, aop, loffset);
832 storeRegToAop (hc08_reg_x, aop, loffset+1);
837 /* Disable the register tracking for now */
839 //if (!reg->aop || (reg->aop && (reg->aop != aop)))
842 for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
844 otherreg=hc08_regWithIdx(otheridx);
845 if (otherreg && otherreg->aop
846 && otherreg->aop->op && aop->op
847 && operandsEqu(otherreg->aop->op,aop->op)
848 && (otherreg->aopofs == loffset))
850 D(emitcode("","; marking %s stale", otherreg->name));
854 if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
856 hc08_reg_hx->aop = NULL;
857 D(emitcode("","; marking hx stale"));
859 if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
861 hc08_reg_xa->aop = NULL;
862 D(emitcode("","; marking xa stale"));
866 reg->aopofs = loffset;
871 /*--------------------------------------------------------------------------*/
872 /* loadRegFromConst - Load register reg from constant c. */
873 /*--------------------------------------------------------------------------*/
875 loadRegFromConst (regs *reg, char *c)
881 emitcode ("clra", "");
883 emitcode ("lda", "%s", c);
887 emitcode ("clrx", "");
889 emitcode ("ldx", "%s", c);
893 emitcode ("clrh", "");
894 else if (hc08_reg_a->isFree)
896 loadRegFromConst (hc08_reg_a, c);
897 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
899 else if (hc08_reg_x->isFree)
901 loadRegFromConst (hc08_reg_x, c);
902 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
906 pushReg (hc08_reg_a, TRUE);
907 loadRegFromConst (hc08_reg_a, c);
908 transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
909 pullReg (hc08_reg_a);
913 emitcode ("ldhx", "%s", c);
916 emitcode ("lda", "%s", c);
917 emitcode ("ldx", "%s >> 8", c);
920 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
921 "Bad rIdx in loadRegFromConst");
928 /*--------------------------------------------------------------------------*/
929 /* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
930 /*--------------------------------------------------------------------------*/
932 storeConstToAop (char *c, asmop *aop, int loffset)
934 if (aop->stacked && aop->stk_aop[loffset])
936 storeConstToAop (c, aop->stk_aop[loffset], 0);
944 emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
946 emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
949 if (loffset>(aop->size-1))
951 loadRegFromConst (aop->aopu.aop_reg[loffset], c);
956 if (hc08_reg_a->isFree)
958 loadRegFromConst (hc08_reg_a, c);
959 storeRegToAop( hc08_reg_a, aop, loffset);
960 hc08_freeReg (hc08_reg_a);
962 else if (hc08_reg_x->isFree)
964 loadRegFromConst (hc08_reg_x, c);
965 storeRegToAop( hc08_reg_x, aop, loffset);
966 hc08_freeReg (hc08_reg_x);
970 pushReg (hc08_reg_a, TRUE);
971 loadRegFromConst (hc08_reg_a, c);
972 storeRegToAop( hc08_reg_a, aop, loffset);
973 pullReg (hc08_reg_a);
979 /*--------------------------------------------------------------------------*/
980 /* storeRegSignToUpperAop - If isSigned is true, the sign bit of register */
981 /* reg is extended to fill logical offsets loffset */
982 /* and above of asmop aop. Otherwise, logical */
983 /* offsets loffset and above of asmop aop are */
984 /* zeroed. reg must be an 8-bit register. */
985 /*--------------------------------------------------------------------------*/
987 storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
989 // int regidx = reg->rIdx;
990 int size = aop->size;
999 storeConstToAop(zero, aop, loffset++);
1004 transferRegReg (reg, hc08_reg_a, FALSE);
1005 emitcode ("rola","");
1006 emitcode ("clra","");
1007 emitcode ("sbc", "#0");
1008 hc08_useReg (hc08_reg_a);
1009 while (loffset<size)
1010 storeRegToAop (hc08_reg_a, aop, loffset++);
1011 hc08_freeReg (hc08_reg_a);
1015 /*--------------------------------------------------------------------------*/
1016 /* storeRegToFullAop - Store register reg to asmop aop with appropriate */
1017 /* padding and/or truncation as needed. If isSigned is */
1018 /* true, sign extension will take place in the padding. */
1019 /*--------------------------------------------------------------------------*/
1021 storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
1023 int regidx = reg->rIdx;
1024 int size = aop->size;
1031 storeRegToAop (reg, aop, 0);
1032 storeRegSignToUpperAop (reg, aop, 1, isSigned);
1037 storeRegToAop (hc08_reg_x, aop, 0);
1041 storeRegToAop (reg, aop, 0);
1042 storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
1048 storeRegToAop (hc08_reg_a, aop, 0);
1052 storeRegToAop (reg, aop, 0);
1053 storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
1059 /*--------------------------------------------------------------------------*/
1060 /* transferAopAop - Transfer the value at logical offset srcofs of asmop */
1061 /* srcaop to logical offset dstofs of asmop dstofs. */
1062 /*--------------------------------------------------------------------------*/
1064 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
1066 bool needpula = FALSE;
1069 bool keepreg = FALSE;
1071 if (srcaop->stacked && srcaop->stk_aop[srcofs])
1073 transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
1077 if (dstaop->stacked && dstaop->stk_aop[srcofs])
1079 transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
1083 // D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
1084 // aopName (srcaop), srcofs, aopName (dstaop), dstofs));
1085 // D(emitcode ("", "; srcaop->type = %d", srcaop->type));
1086 // D(emitcode ("", "; dstaop->type = %d", dstaop->type));
1088 if (dstofs >= dstaop->size)
1091 if ((dstaop->type == AOP_DIR)
1092 && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
1094 emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
1095 aopAdrStr(dstaop, dstofs, FALSE));
1099 if (dstaop->type == AOP_REG)
1101 regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
1102 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1104 reg = dstaop->aopu.aop_reg[dstofs];
1109 if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
1111 regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
1112 if ((regIdx == A_IDX) || (regIdx == X_IDX))
1114 reg = srcaop->aopu.aop_reg[srcofs];
1121 if (hc08_reg_a->isFree)
1123 else if (hc08_reg_x->isFree)
1127 pushReg (hc08_reg_a, TRUE);
1133 loadRegFromAop (reg, srcaop, srcofs);
1134 storeRegToAop (reg, dstaop, dstofs);
1137 pullOrFreeReg (hc08_reg_a, needpula);
1141 /*--------------------------------------------------------------------------*/
1142 /* accopWithMisc - Emit accumulator modifying instruction accop with the */
1143 /* parameter param. */
1144 /*--------------------------------------------------------------------------*/
1146 accopWithMisc (char *accop, char *param)
1148 emitcode (accop, "%s", param);
1149 hc08_dirtyReg (hc08_reg_a, FALSE);
1152 /*--------------------------------------------------------------------------*/
1153 /* accopWithAop - Emit accumulator modifying instruction accop with the */
1154 /* byte at logical offset loffset of asmop aop. */
1155 /* Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub */
1156 /*--------------------------------------------------------------------------*/
1158 accopWithAop (char *accop, asmop *aop, int loffset)
1160 if (aop->stacked && aop->stk_aop[loffset])
1162 accopWithAop (accop, aop->stk_aop[loffset], 0);
1166 if (aop->type == AOP_DUMMY)
1169 if (aop->type == AOP_REG)
1171 pushReg (aop->aopu.aop_reg[loffset], FALSE);
1172 emitcode (accop, "1,s");
1176 emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
1178 hc08_dirtyReg (hc08_reg_a, FALSE);
1182 /*--------------------------------------------------------------------------*/
1183 /* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
1184 /* byte at logical offset loffset of asmop aop. Register reg */
1185 /* must be 8-bit. */
1186 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1187 /*--------------------------------------------------------------------------*/
1189 rmwWithReg (char *rmwop, regs *reg)
1192 char *rmwaop = rmwbuf;
1194 if (reg->rIdx == A_IDX)
1196 sprintf(rmwaop,"%sa", rmwop);
1197 emitcode (rmwaop, "");
1198 hc08_dirtyReg (hc08_reg_a, FALSE);
1200 else if (reg->rIdx == X_IDX)
1202 sprintf(rmwaop,"%sx", rmwop);
1203 emitcode (rmwaop, "");
1204 hc08_dirtyReg (hc08_reg_a, FALSE);
1206 else if (hc08_reg_a->isFree)
1208 transferRegReg(reg, hc08_reg_a, FALSE);
1209 sprintf(rmwaop,"%sa", rmwop);
1210 emitcode (rmwaop, "");
1211 hc08_dirtyReg (hc08_reg_a, FALSE);
1212 transferRegReg(hc08_reg_a, reg, TRUE);
1216 pushReg (reg, FALSE);
1217 emitcode (rmwop, "1,s");
1219 hc08_dirtyReg (reg, FALSE);
1223 /*--------------------------------------------------------------------------*/
1224 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
1225 /* logical offset loffset of asmop aop. */
1226 /* Supports: com, dec, inc, lsl, lsr, neg, rol, ror */
1227 /*--------------------------------------------------------------------------*/
1229 rmwWithAop (char *rmwop, asmop *aop, int loffset)
1231 bool needpula = FALSE;
1233 if (aop->stacked && aop->stk_aop[loffset])
1235 rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
1242 rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
1245 needpula = pushRegIfUsed (hc08_reg_a);
1246 loadRegFromAop (hc08_reg_a, aop, loffset);
1247 rmwWithReg (rmwop, hc08_reg_a);
1248 storeRegToAop (hc08_reg_a, aop, loffset);
1249 pullOrFreeReg (hc08_reg_a, needpula);
1254 emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
1260 /*-----------------------------------------------------------------*/
1261 /* newAsmop - creates a new asmOp */
1262 /*-----------------------------------------------------------------*/
1264 newAsmop (short type)
1268 aop = Safe_calloc (1, sizeof (asmop));
1275 /*-----------------------------------------------------------------*/
1276 /* pointerCode - returns the code for a pointer type */
1277 /*-----------------------------------------------------------------*/
1279 pointerCode (sym_link * etype)
1282 return PTR_TYPE (SPEC_OCLS (etype));
1287 /*-----------------------------------------------------------------*/
1288 /* aopForSym - for a true symbol */
1289 /*-----------------------------------------------------------------*/
1291 aopForSym (iCode * ic, symbol * sym, bool result)
1296 wassertl (ic != NULL, "Got a null iCode");
1297 wassertl (sym != NULL, "Got a null symbol");
1299 // printf("in aopForSym for symbol %s\n", sym->name);
1301 space = SPEC_OCLS (sym->etype);
1303 /* if already has one */
1309 /* special case for a function */
1310 if (IS_FUNC (sym->type))
1312 sym->aop = aop = newAsmop (AOP_IMMD);
1313 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
1314 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
1315 aop->size = FPTRSIZE;
1319 /* if it is in direct space */
1320 if (IN_DIRSPACE (space))
1322 sym->aop = aop = newAsmop (AOP_DIR);
1323 aop->aopu.aop_dir = sym->rname;
1324 aop->size = getSize (sym->type);
1328 /* if it is in far space */
1329 if (IN_FARSPACE (space))
1331 sym->aop = aop = newAsmop (AOP_EXT);
1332 aop->aopu.aop_dir = sym->rname;
1333 aop->size = getSize (sym->type);
1337 if (IN_STACK (sym->etype))
1339 sym->aop = aop = newAsmop (AOP_SOF);
1340 aop->aopu.aop_dir = sym->rname;
1341 aop->size = getSize (sym->type);
1342 aop->aopu.aop_stk = sym->stack;
1348 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1349 "aopForSym should never reach here");
1353 /* if it is in code space */
1354 if (IN_CODESPACE (space))
1360 /*-----------------------------------------------------------------*/
1361 /* aopForRemat - rematerialzes an object */
1362 /*-----------------------------------------------------------------*/
1364 aopForRemat (symbol * sym)
1366 iCode *ic = sym->rematiCode;
1374 val += (int) operandLitValue (IC_RIGHT (ic));
1375 else if (ic->op == '-')
1376 val -= (int) operandLitValue (IC_RIGHT (ic));
1377 else if (IS_CAST_ICODE(ic)) {
1378 sym_link *from_type = operandType(IC_RIGHT(ic));
1379 aop->aopu.aop_immd.from_cast_remat = 1;
1380 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
1381 ptr_type = DCL_TYPE(from_type);
1382 if (ptr_type == IPOINTER) {
1389 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
1392 if (ic->op == ADDRESS_OF)
1395 sprintf (buffer, "(%s %c 0x%04x)",
1396 OP_SYMBOL (IC_LEFT (ic))->rname,
1397 val >= 0 ? '+' : '-',
1398 abs (val) & 0xffff);
1400 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
1402 aop = newAsmop (AOP_IMMD);
1403 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
1404 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
1405 /* set immd2 field if required */
1406 if (aop->aopu.aop_immd.from_cast_remat)
1408 sprintf(buffer,"#0x%02x",ptr_type);
1409 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
1410 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
1413 else if (ic->op == '=')
1415 val += (int) operandLitValue (IC_RIGHT (ic));
1417 sprintf (buffer, "0x%04x", val);
1418 aop = newAsmop (AOP_LIT);
1419 aop->aopu.aop_lit = constVal (buffer);
1422 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1423 "unexpected rematerialization");
1430 /*-----------------------------------------------------------------*/
1431 /* regsInCommon - two operands have some registers in common */
1432 /*-----------------------------------------------------------------*/
1434 regsInCommon (operand * op1, operand * op2)
1436 symbol *sym1, *sym2;
1439 /* if they have registers in common */
1440 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1443 sym1 = OP_SYMBOL (op1);
1444 sym2 = OP_SYMBOL (op2);
1446 if (sym1->nRegs == 0 || sym2->nRegs == 0)
1449 for (i = 0; i < sym1->nRegs; i++)
1455 for (j = 0; j < sym2->nRegs; j++)
1460 if (sym2->regs[j] == sym1->regs[i])
1468 /*-----------------------------------------------------------------*/
1469 /* operandsEqu - equivalent */
1470 /*-----------------------------------------------------------------*/
1472 operandsEqu (operand * op1, operand * op2)
1474 symbol *sym1, *sym2;
1476 /* if they not symbols */
1477 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
1480 sym1 = OP_SYMBOL (op1);
1481 sym2 = OP_SYMBOL (op2);
1483 /* if both are itemps & one is spilt
1484 and the other is not then false */
1485 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
1486 sym1->isspilt != sym2->isspilt)
1489 /* if they are the same */
1493 if (strcmp (sym1->rname, sym2->rname) == 0)
1497 /* if left is a tmp & right is not */
1498 if (IS_ITEMP (op1) &&
1501 (sym1->usl.spillLoc == sym2))
1504 if (IS_ITEMP (op2) &&
1508 (sym2->usl.spillLoc == sym1))
1514 /*-----------------------------------------------------------------*/
1515 /* sameRegs - two asmops have the same registers */
1516 /*-----------------------------------------------------------------*/
1518 sameRegs (asmop * aop1, asmop * aop2)
1525 // if (aop1->size != aop2->size)
1528 if (aop1->type == aop2->type)
1533 for (i = 0; i < aop1->size; i++)
1534 if (aop1->aopu.aop_reg[i] !=
1535 aop2->aopu.aop_reg[i])
1539 return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
1542 return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
1549 /*-----------------------------------------------------------------*/
1550 /* aopOp - allocates an asmop for an operand : */
1551 /*-----------------------------------------------------------------*/
1553 aopOp (operand * op, iCode * ic, bool result)
1562 // Is this a pointer set result?
1564 if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
1568 // printf("checking literal\n");
1569 /* if this a literal */
1570 if (IS_OP_LITERAL (op))
1572 op->aop = aop = newAsmop (AOP_LIT);
1573 aop->aopu.aop_lit = op->operand.valOperand;
1574 aop->size = getSize (operandType (op));
1576 aop->isaddr = op->isaddr;
1580 // printf("checking pre-existing\n");
1581 /* if already has a asmop then continue */
1585 op->aop->isaddr = op->isaddr;
1589 // printf("checking underlying sym\n");
1590 /* if the underlying symbol has a aop */
1591 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
1593 op->aop = aop = Safe_calloc(1, sizeof(*aop));
1594 memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
1595 //op->aop = aop = OP_SYMBOL (op)->aop;
1596 aop->size = getSize( operandType (op));
1597 //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
1598 //printf (" with size = %d\n", aop->size);
1601 aop->isaddr = op->isaddr;
1602 /* if (aop->isaddr & IS_ITEMP (op))
1604 aop->psize=aop->size;
1605 aop->size = getSize( operandType (op)->next);
1610 // printf("checking true sym\n");
1611 /* if this is a true symbol */
1612 if (IS_TRUE_SYMOP (op))
1614 op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
1616 aop->isaddr = op->isaddr;
1617 //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
1618 //printf (" with size = %d\n", aop->size);
1622 /* this is a temporary : this has
1628 e) can be a return use only */
1630 sym = OP_SYMBOL (op);
1632 // printf("checking conditional\n");
1633 /* if the type is a conditional */
1634 if (sym->regType == REG_CND)
1636 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
1639 aop->isaddr = op->isaddr;
1643 // printf("checking spilt\n");
1644 /* if it is spilt then two situations
1646 b) has a spill location */
1647 if (sym->isspilt || sym->nRegs == 0)
1650 // printf("checking remat\n");
1651 /* rematerialize it NOW */
1654 sym->aop = op->aop = aop =
1656 aop->size = getSize (sym->type);
1658 aop->isaddr = op->isaddr;
1659 /* if (aop->isaddr & IS_ITEMP (op))
1661 aop->psize=aop->size;
1662 aop->size = getSize( operandType (op)->next);
1667 // printf("checking accuse\n");
1670 aop = op->aop = sym->aop = newAsmop (AOP_REG);
1671 aop->size = getSize (sym->type);
1672 switch (sym->accuse)
1675 aop->aopu.aop_reg[0] = hc08_reg_a;
1676 aop->aopu.aop_reg[1] = hc08_reg_x;
1679 aop->aopu.aop_reg[0] = hc08_reg_x;
1680 aop->aopu.aop_reg[1] = hc08_reg_h;
1684 aop->isaddr = op->isaddr;
1688 // printf("checking ruonly\n");
1694 aop = op->aop = sym->aop = newAsmop (AOP_STR);
1695 aop->size = getSize (sym->type);
1696 for (i = 0; i < fReturnSizeHC08; i++)
1697 aop->aopu.aop_str[i] = fReturn2[i];
1699 aop->isaddr = op->isaddr;
1703 /* else spill location */
1704 if (sym->usl.spillLoc)
1706 if (sym->usl.spillLoc->aop
1707 && sym->usl.spillLoc->aop->size != getSize (sym->type))
1709 /* force a new aop if sizes differ */
1710 sym->usl.spillLoc->aop = NULL;
1711 //printf ("forcing new aop\n");
1713 sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
1714 aop->size = getSize (sym->type);
1716 aop->isaddr = op->isaddr;
1717 //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
1718 //printf (" with size = %d\n", aop->size);
1722 /* else must be a dummy iTemp */
1723 sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
1724 aop->size = getSize (sym->type);
1728 // printf("assuming register\n");
1729 /* must be in a register */
1730 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1731 aop->size = sym->nRegs;
1732 for (i = 0; i < sym->nRegs; i++)
1733 aop->aopu.aop_reg[i] = sym->regs[i];
1735 aop->isaddr = op->isaddr;
1739 /*-----------------------------------------------------------------*/
1740 /* freeAsmop - free up the asmop given to an operand */
1741 /*----------------------------------------------------------------*/
1743 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1765 D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
1768 for (loffset=0; loffset<aop->size; loffset++)
1769 if (aop->stk_aop[loffset])
1771 transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
1774 pullNull (stackAdjust);
1778 /* all other cases just dealloc */
1784 OP_SYMBOL (op)->aop = NULL;
1785 /* if the symbol has a spill */
1787 SPIL_LOC (op)->aop = NULL;
1793 /*-----------------------------------------------------------------*/
1794 /* aopDerefAop - treating the aop parameter as a pointer, return */
1795 /* an asmop for the object it references */
1796 /*-----------------------------------------------------------------*/
1798 aopDerefAop (asmop *aop)
1803 asmop *newaop = NULL;
1804 sym_link *type, *etype;
1807 D(emitcode ("", "; aopDerefAop(%s)", aopName(aop)));
1811 type = operandType (aop->op);
1812 etype = getSpec (type);
1813 /* if op is of type of pointer then it is simple */
1814 if (IS_PTR (type) && !IS_FUNC (type->next))
1815 p_type = DCL_TYPE (type);
1818 /* we have to go by the storage class */
1819 p_type = PTR_TYPE (SPEC_OCLS (etype));
1828 if (p_type == POINTER)
1829 newaop = newAsmop (AOP_DIR);
1831 newaop = newAsmop (AOP_EXT);
1832 newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
1835 adr = (int) floatFromVal (aop->aopu.aop_lit);
1836 if (p_type == POINTER)
1841 newaop = newAsmop (AOP_DIR);
1842 sprintf (s, "0x%02x",adr);
1846 newaop = newAsmop (AOP_EXT);
1847 sprintf (s, "0x%04x",adr);
1849 rs = Safe_calloc (1, strlen (s) + 1);
1851 newaop->aopu.aop_dir = rs;
1854 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1855 "unsupported asmop");
1865 /*-----------------------------------------------------------------*/
1866 /* aopAdrStr - for referencing the address of the aop */
1867 /*-----------------------------------------------------------------*/
1869 aopAdrStr (asmop * aop, int loffset, bool bit16)
1873 int offset = aop->size - 1 - loffset;
1876 /* offset is greater than
1878 if (loffset > (aop->size - 1) &&
1879 aop->type != AOP_LIT)
1882 /* depending on type */
1890 if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
1891 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
1893 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
1897 sprintf (s, "#(%s >> %d)",
1898 aop->aopu.aop_immd.aop_immd1,
1902 aop->aopu.aop_immd.aop_immd1);
1906 aop->aopu.aop_immd.aop_immd1);
1907 rs = Safe_calloc (1, strlen (s) + 1);
1913 sprintf (s, "*(%s + %d)",
1917 sprintf (s, "*%s", aop->aopu.aop_dir);
1918 rs = Safe_calloc (1, strlen (s) + 1);
1924 sprintf (s, "(%s + %d)",
1928 sprintf (s, "%s", aop->aopu.aop_dir);
1929 rs = Safe_calloc (1, strlen (s) + 1);
1934 return aop->aopu.aop_reg[loffset]->name;
1938 return aopLiteralLong (aop->aopu.aop_lit, /*loffset*/ 0, 2);
1940 return aopLiteral (aop->aopu.aop_lit, loffset);
1944 return aop->aopu.aop_str[loffset];
1947 sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
1949 rs = Safe_calloc (1, strlen (s) + 1);
1955 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1956 "aopAdrStr got unsupported aop->type");
1965 /*-----------------------------------------------------------------*/
1966 /* opIsGptr: returns non-zero if the passed operand is */
1967 /* a generic pointer type. */
1968 /*-----------------------------------------------------------------*/
1970 opIsGptr (operand * op)
1972 sym_link *type = operandType (op);
1974 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1982 /*-----------------------------------------------------------------*/
1983 /* getDataSize - get the operand data size */
1984 /*-----------------------------------------------------------------*/
1986 getDataSize (operand * op)
1989 size = AOP_SIZE (op);
1993 /*-----------------------------------------------------------------*/
1994 /* outAcc - output Acc */
1995 /*-----------------------------------------------------------------*/
1997 outAcc (operand * result)
2000 size = getDataSize (result);
2003 storeRegToAop (hc08_reg_a, AOP (result), 0);
2006 /* unsigned or positive */
2009 storeConstToAop (zero, AOP (result), offset++);
2014 /*-----------------------------------------------------------------*/
2015 /* outBitC - output a bit C */
2016 /*-----------------------------------------------------------------*/
2018 outBitC (operand * result)
2022 /* if the result is bit */
2023 if (AOP_TYPE (result) == AOP_CRY)
2024 aopPut (AOP (result), "c", 0);
2028 emitcode ("clra", "");
2029 emitcode ("rola", "");
2034 /*-----------------------------------------------------------------*/
2035 /* outBitNV - output a bit N^V */
2036 /*-----------------------------------------------------------------*/
2038 outBitNV (operand * result)
2040 symbol *tlbl, *tlbl1;
2042 tlbl = newiTempLabel (NULL);
2043 tlbl1 = newiTempLabel (NULL);
2045 emitBranch ("blt", tlbl);
2046 loadRegFromConst (hc08_reg_a, zero);
2047 emitBranch ("bra", tlbl1);
2049 loadRegFromConst (hc08_reg_a, one);
2055 /*-----------------------------------------------------------------*/
2056 /* asmopToBool - Emit code to convert an asmop to a boolean. */
2057 /* Result left in A (0=FALSE, 1=TRUE) if ResultInA, */
2058 /* otherwise result left in Z flag (1=FALSE, 0=TRUE) */
2059 /*-----------------------------------------------------------------*/
2061 asmopToBool (asmop *aop, bool resultInA)
2063 symbol *tlbl, *tlbl1;
2064 int size = aop->size;
2065 bool needpula = FALSE;
2066 bool flagsonly = TRUE;
2071 hc08_freeReg(hc08_reg_a);
2078 emitcode ("tsta", "");
2081 else if (IS_AOP_X(aop))
2082 emitcode ("tstx", "");
2083 else if (IS_AOP_H(aop))
2085 if (hc08_reg_a->isFree)
2087 transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
2088 emitcode ("tsta", "");
2090 hc08_freeReg(hc08_reg_a);
2092 else if (hc08_reg_x->isFree)
2094 transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
2095 emitcode ("tstx", "");
2096 hc08_freeReg(hc08_reg_x);
2100 emitcode ("pshh", "");
2101 emitcode ("tst", "1,s");
2102 emitcode ("ais", "#1");
2105 else if (IS_AOP_HX(aop))
2106 emitcode ("cphx", zero);
2107 else if (IS_AOP_XA(aop))
2109 symbol *tlbl = newiTempLabel (NULL);
2110 emitcode ("tsta", "");
2111 emitcode ("bne", "%05d$", (tlbl->key + 100));
2112 emitcode ("tstx", "");
2113 emitcode ("", "%05d$:", (tlbl->key + 100));
2117 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2118 "Bad rIdx in asmToBool");
2126 needpula = pushRegIfUsed (hc08_reg_a);
2127 loadRegFromAop (hc08_reg_a, aop, 0);
2128 for (offset=1; offset<size; offset++)
2129 accopWithAop ("ora", aop, offset);
2131 pullReg (hc08_reg_a);
2134 hc08_freeReg (hc08_reg_a);
2143 loadRegFromAop (hc08_reg_a, aop, 0);
2144 hc08_freeReg (hc08_reg_a);
2148 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2153 if (hc08_reg_a->isFree)
2155 loadRegFromAop (hc08_reg_a, aop, 0);
2156 accopWithAop ("ora", aop, 1);
2157 hc08_freeReg (hc08_reg_a);
2162 tlbl = newiTempLabel (NULL);
2163 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
2164 emitcode ("bne", "%05d$", (tlbl->key + 100));
2165 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
2166 emitcode ("", "%05d$:", (tlbl->key + 100));
2172 needpula = pushRegIfUsed (hc08_reg_a);
2173 loadRegFromAop (hc08_reg_a, aop, 0);
2174 for (offset=1; offset<size; offset++)
2175 accopWithAop ("ora", aop, offset);
2177 pullReg (hc08_reg_a);
2180 hc08_freeReg (hc08_reg_a);
2188 tlbl = newiTempLabel (NULL);
2192 tlbl1 = newiTempLabel (NULL);
2193 emitBranch ("bne", tlbl1);
2194 loadRegFromConst (hc08_reg_a, zero);
2195 emitBranch ("bra", tlbl);
2197 loadRegFromConst (hc08_reg_a, one);
2201 emitBranch ("beq", tlbl);
2202 loadRegFromConst (hc08_reg_a, one);
2205 hc08_useReg (hc08_reg_a);
2211 /*-----------------------------------------------------------------*/
2212 /* genNot - generate code for ! operation */
2213 /*-----------------------------------------------------------------*/
2217 D(emitcode ("; genNot",""));
2219 /* assign asmOps to operand & result */
2220 aopOp (IC_LEFT (ic), ic, FALSE);
2221 aopOp (IC_RESULT (ic), ic, TRUE);
2223 asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
2224 emitcode ("eor", one);
2225 storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
2227 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2228 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2232 /*-----------------------------------------------------------------*/
2233 /* genCpl - generate code for complement */
2234 /*-----------------------------------------------------------------*/
2240 regs* reg = hc08_reg_a;
2244 D(emitcode ("; genCpl",""));
2246 /* assign asmOps to operand & result */
2247 aopOp (IC_LEFT (ic), ic, FALSE);
2248 aopOp (IC_RESULT (ic), ic, TRUE);
2250 size = AOP_SIZE (IC_RESULT (ic));
2253 loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
2254 rmwWithReg ("com", reg);
2256 storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
2260 /* release the aops */
2261 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2262 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2265 /*-----------------------------------------------------------------*/
2266 /* genUminusFloat - unary minus for floating points */
2267 /*-----------------------------------------------------------------*/
2269 genUminusFloat (operand * op, operand * result)
2271 int size, offset = 0;
2274 D(emitcode ("; genUminusFloat",""));
2276 /* for this we just copy and then flip the bit */
2278 size = AOP_SIZE (op) - 1;
2284 needpula = pushRegIfUsed (hc08_reg_a);
2285 loadRegFromAop (hc08_reg_a, AOP (op), offset);
2286 emitcode ("eor", "#0x80");
2287 hc08_useReg (hc08_reg_a);
2288 storeRegToAop (hc08_reg_a, AOP (result), offset);
2289 pullOrFreeReg (hc08_reg_a, needpula);
2292 transferAopAop (AOP (op), offset, AOP (result), offset);
2298 /*-----------------------------------------------------------------*/
2299 /* genUminus - unary minus code generation */
2300 /*-----------------------------------------------------------------*/
2302 genUminus (iCode * ic)
2305 sym_link *optype, *rtype;
2310 D(emitcode ("; genUminus",""));
2313 aopOp (IC_LEFT (ic), ic, FALSE);
2314 aopOp (IC_RESULT (ic), ic, TRUE);
2316 optype = operandType (IC_LEFT (ic));
2317 rtype = operandType (IC_RESULT (ic));
2319 /* if float then do float stuff */
2320 if (IS_FLOAT (optype))
2322 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
2326 /* otherwise subtract from zero */
2327 size = AOP_SIZE (IC_LEFT (ic));
2332 if (!IS_AOP_A (AOP (IC_LEFT (ic))))
2333 needpula = pushRegIfUsed (hc08_reg_a);
2336 loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
2337 emitcode ("nega", "");
2338 hc08_freeReg (hc08_reg_a);
2339 storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)),
2340 SPEC_USIGN (operandType (IC_LEFT (ic))));
2341 pullOrFreeReg (hc08_reg_a, needpula);
2345 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2346 result = forceStackedAop (AOP (IC_RESULT (ic)));
2348 result = AOP (IC_RESULT (ic));
2350 needpula = pushRegIfUsed (hc08_reg_a);
2354 loadRegFromConst (hc08_reg_a, zero);
2355 accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
2356 storeRegToAop (hc08_reg_a, result, offset++);
2359 storeRegSignToUpperAop (hc08_reg_a, result, offset,
2360 SPEC_USIGN (operandType (IC_LEFT (ic))));
2361 pullOrFreeReg (hc08_reg_a, needpula);
2363 if (IS_AOP_XA (AOP (IC_RESULT (ic))))
2364 freeAsmop (NULL, result, ic, TRUE);
2370 /* release the aops */
2371 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2372 freeAsmop (IC_LEFT (ic), NULL, ic, FALSE);
2375 /*-----------------------------------------------------------------*/
2376 /* saveRegisters - will look for a call and save the registers */
2377 /*-----------------------------------------------------------------*/
2379 saveRegisters (iCode * lic)
2386 for (ic = lic; ic; ic = ic->next)
2387 if (ic->op == CALL || ic->op == PCALL)
2392 fprintf (stderr, "found parameter push with no function call\n");
2396 /* if the registers have been saved already or don't need to be then
2400 if (IS_SYMOP(IC_LEFT(ic)) &&
2401 (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
2402 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
2405 /* safe the registers in use at this time but skip the
2406 ones for the result */
2407 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2408 hc08_rUmaskForOp (IC_RESULT(ic)));
2411 for (i = 0; i < hc08_nRegs; i++)
2413 if (bitVectBitValue (rsave, i))
2414 pushReg ( hc08_regWithIdx (i), FALSE);
2418 /*-----------------------------------------------------------------*/
2419 /* unsaveRegisters - pop the pushed registers */
2420 /*-----------------------------------------------------------------*/
2422 unsaveRegisters (iCode * ic)
2427 /* restore the registers in use at this time but skip the
2428 ones for the result */
2429 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2430 hc08_rUmaskForOp (IC_RESULT(ic)));
2432 for (i = hc08_nRegs; i >= 0; i--)
2434 if (bitVectBitValue (rsave, i))
2435 pullReg ( hc08_regWithIdx (i));
2441 /*-----------------------------------------------------------------*/
2443 /*-----------------------------------------------------------------*/
2445 pushSide (operand * oper, int size)
2450 loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
2451 pushReg ( hc08_reg_a, TRUE);
2455 /*-----------------------------------------------------------------*/
2456 /* assignResultValue - */
2457 /*-----------------------------------------------------------------*/
2459 assignResultValue (operand * oper)
2461 int size = AOP_SIZE (oper);
2465 transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
2466 if (hc08_aop_pass[offset]->type == AOP_REG)
2467 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
2474 /*-----------------------------------------------------------------*/
2475 /* genIpush - genrate code for pushing this gets a little complex */
2476 /*-----------------------------------------------------------------*/
2478 genIpush (iCode * ic)
2480 int size, offset = 0;
2483 D(emitcode ("; genIpush",""));
2485 /* if this is not a parm push : ie. it is spill push
2486 and spill push is always done on the local stack */
2490 /* and the item is spilt then do nothing */
2491 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2494 aopOp (IC_LEFT (ic), ic, FALSE);
2495 size = AOP_SIZE (IC_LEFT (ic));
2497 /* push it on the stack */
2500 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2501 pushReg ( hc08_reg_a, TRUE);
2507 /* this is a paramter push: in this case we call
2508 the routine to find the call and save those
2509 registers that need to be saved */
2512 /* then do the push */
2513 aopOp (IC_LEFT (ic), ic, FALSE);
2516 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2517 size = AOP_SIZE (IC_LEFT (ic));
2520 // l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
2521 if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
2523 if ((size==2) && hc08_reg_hx->isFree)
2525 loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
2526 pushReg (hc08_reg_hx, TRUE);
2533 // printf("loading %d\n", offset);
2534 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
2535 // printf("pushing \n");
2536 pushReg (hc08_reg_a, TRUE);
2540 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2543 /*-----------------------------------------------------------------*/
2544 /* genIpop - recover the registers: can happen only for spilling */
2545 /*-----------------------------------------------------------------*/
2547 genIpop (iCode * ic)
2551 D(emitcode ("; genIpop",""));
2553 /* if the temp was not pushed then */
2554 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
2557 aopOp (IC_LEFT (ic), ic, FALSE);
2558 size = AOP_SIZE (IC_LEFT (ic));
2562 pullReg (hc08_reg_a);
2563 storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
2565 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2569 /*-----------------------------------------------------------------*/
2570 /* genSend - gen code for SEND */
2571 /*-----------------------------------------------------------------*/
2572 static void genSend(set *sendSet)
2576 for (sic = setFirstItem (_G.sendSet); sic;
2577 sic = setNextItem (_G.sendSet)) {
2578 int size, offset = 0;
2579 aopOp (IC_LEFT (sic), sic, FALSE);
2580 size = AOP_SIZE (IC_LEFT (sic));
2585 transferAopAop( AOP (IC_LEFT (sic)), offset,
2586 hc08_aop_pass[offset+(sic->argreg-1)], 0);
2590 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2594 /*-----------------------------------------------------------------*/
2595 /* genCall - generates a call statement */
2596 /*-----------------------------------------------------------------*/
2598 genCall (iCode * ic)
2601 // bool restoreBank = FALSE;
2602 // bool swapBanks = FALSE;
2604 D(emitcode("; genCall",""));
2606 dtype = operandType (IC_LEFT (ic));
2607 /* if send set is not empty the assign */
2610 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2611 genSend(reverseSet(_G.sendSet));
2613 genSend(_G.sendSet);
2619 /* if caller saves & we have not saved then */
2625 emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2626 OP_SYMBOL (IC_LEFT (ic))->rname :
2627 OP_SYMBOL (IC_LEFT (ic))->name));
2630 /* if we need assign a result value */
2631 if ((IS_ITEMP (IC_RESULT (ic)) &&
2632 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2633 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2634 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2635 IS_TRUE_SYMOP (IC_RESULT (ic)))
2639 aopOp (IC_RESULT (ic), ic, FALSE);
2642 assignResultValue (IC_RESULT (ic));
2644 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2647 /* adjust the stack for parameters if
2651 pullNull (ic->parmBytes);
2654 /* if we had saved some registers then unsave them */
2655 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2656 unsaveRegisters (ic);
2660 /*-----------------------------------------------------------------*/
2661 /* -10l - generates a call by pointer statement */
2662 /*-----------------------------------------------------------------*/
2664 genPcall (iCode * ic)
2667 symbol *rlbl = newiTempLabel (NULL);
2668 symbol *tlbl = newiTempLabel (NULL);
2669 // bool restoreBank=FALSE;
2670 // bool swapBanks = FALSE;
2672 D(emitcode("; genPCall",""));
2674 /* if caller saves & we have not saved then */
2678 /* if we are calling a not _naked function that is not using
2679 the same register bank then we need to save the
2680 destination registers on the stack */
2681 dtype = operandType (IC_LEFT (ic))->next;
2683 /* now push the calling address */
2684 emitBranch ("bsr", tlbl);
2685 emitBranch ("bra", rlbl);
2688 /* Push the function's address */
2689 aopOp (IC_LEFT (ic), ic, FALSE);
2690 pushSide (IC_LEFT (ic), FPTRSIZE);
2691 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2693 /* if send set is not empty the assign */
2696 genSend(reverseSet(_G.sendSet));
2702 emitcode ("rts", "");
2707 /* if we need assign a result value */
2708 if ((IS_ITEMP (IC_RESULT (ic)) &&
2709 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2710 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2711 IS_TRUE_SYMOP (IC_RESULT (ic)))
2715 aopOp (IC_RESULT (ic), ic, FALSE);
2718 assignResultValue (IC_RESULT (ic));
2720 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2723 /* adjust the stack for parameters if
2727 pullNull (ic->parmBytes);
2730 /* if we hade saved some registers then
2732 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2733 unsaveRegisters (ic);
2736 /*-----------------------------------------------------------------*/
2737 /* resultRemat - result is rematerializable */
2738 /*-----------------------------------------------------------------*/
2740 resultRemat (iCode * ic)
2742 if (SKIP_IC (ic) || ic->op == IFX)
2745 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2747 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2748 if (sym->remat && !POINTER_SET (ic))
2755 #if defined(__BORLANDC__) || defined(_MSC_VER)
2756 #define STRCASECMP stricmp
2758 #define STRCASECMP strcasecmp
2761 /*-----------------------------------------------------------------*/
2762 /* inExcludeList - return 1 if the string is in exclude Reg list */
2763 /*-----------------------------------------------------------------*/
2765 regsCmp(void *p1, void *p2)
2767 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2771 inExcludeList (char *s)
2773 const char *p = setFirstItem(options.excludeRegsSet);
2775 if (p == NULL || STRCASECMP(p, "none") == 0)
2779 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2782 /*-----------------------------------------------------------------*/
2783 /* genFunction - generated code for function entry */
2784 /*-----------------------------------------------------------------*/
2786 genFunction (iCode * ic)
2790 int calleesaves_saved_register = -1;
2794 /* create the function header */
2795 emitcode (";", "-----------------------------------------");
2796 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2797 emitcode (";", "-----------------------------------------");
2799 emitcode ("", "%s:", sym->rname);
2800 ftype = operandType (IC_LEFT (ic));
2802 if (IFFUNC_ISNAKED(ftype))
2804 emitcode(";", "naked function: no prologue.");
2810 /* if this is an interrupt service routine then
2812 if (IFFUNC_ISISR (sym->type))
2815 if (!inExcludeList ("h"))
2816 emitcode ("pshh", "");
2820 /* if callee-save to be used for this function
2821 then save the registers being used in this function */
2822 if (IFFUNC_CALLEESAVES(sym->type))
2826 /* if any registers used */
2829 /* save the registers used */
2830 for (i = 0; i < sym->regsUsed->size; i++)
2832 if (bitVectBitValue (sym->regsUsed, i))
2834 /* remember one saved register for later usage */
2835 if (calleesaves_saved_register < 0)
2836 calleesaves_saved_register = i;
2837 pushReg (hc08_regWithIdx (i), FALSE);
2845 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2850 /* adjust the stack for the function */
2856 // werror (W_STACK_OVERFLOW, sym->name);
2860 _G.stackOfs = sym->stack;
2863 /* if critical function then turn interrupts off */
2864 if (IFFUNC_ISCRITICAL (ftype))
2866 if (IFFUNC_ARGS (ftype))
2868 /* Function was passed parameters, so make sure A is preserved */
2869 pushReg (hc08_reg_a, FALSE);
2870 pushReg (hc08_reg_a, FALSE);
2871 emitcode ("tpa", "");
2872 emitcode ("sta", "2,s");
2873 emitcode ("sei", "");
2874 pullReg (hc08_reg_a);
2878 /* No passed parameters, so A can be freely modified */
2879 emitcode ("tpa", "");
2880 pushReg (hc08_reg_a, TRUE);
2881 emitcode ("sei", "");
2887 /*-----------------------------------------------------------------*/
2888 /* genEndFunction - generates epilogue for functions */
2889 /*-----------------------------------------------------------------*/
2891 genEndFunction (iCode * ic)
2893 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2895 if (IFFUNC_ISNAKED(sym->type))
2897 emitcode(";", "naked function: no epilogue.");
2901 if (IFFUNC_ISCRITICAL (sym->type))
2903 if (!IS_VOID(sym->type->next))
2905 /* Function has return value, so make sure A is preserved */
2906 pushReg (hc08_reg_a, FALSE);
2907 emitcode ("lda", "2,s");
2908 emitcode ("tap", "");
2909 pullReg (hc08_reg_a);
2914 /* Function returns void, so A can be freely modified */
2915 pullReg (hc08_reg_a);
2916 emitcode ("tap", "");
2920 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2926 _G.stackPushes += sym->stack;
2927 adjustStack (sym->stack);
2931 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2935 if (IFFUNC_ISISR (sym->type))
2938 if (!inExcludeList ("h"))
2939 emitcode ("pulh", "");
2942 /* if debug then send end of function */
2943 if (options.debug && currFunc)
2946 emitcode ("", "C$%s$%d$%d$%d ==.",
2947 FileBaseName (ic->filename), currFunc->lastLine,
2948 ic->level, ic->block);
2949 if (IS_STATIC (currFunc->etype))
2950 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2952 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2956 emitcode ("rti", "");
2960 if (IFFUNC_CALLEESAVES(sym->type))
2964 /* if any registers used */
2967 /* save the registers used */
2968 for (i = sym->regsUsed->size; i >= 0; i--)
2970 if (bitVectBitValue (sym->regsUsed, i) ||
2971 (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
2972 emitcode ("pop", "%s", hc08_regWithIdx (i)->dname);
2978 /* if debug then send end of function */
2979 if (options.debug && currFunc)
2982 emitcode ("", "C$%s$%d$%d$%d ==.",
2983 FileBaseName (ic->filename), currFunc->lastLine,
2984 ic->level, ic->block);
2985 if (IS_STATIC (currFunc->etype))
2986 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2988 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2992 emitcode ("rts", "");
2997 /*-----------------------------------------------------------------*/
2998 /* genRet - generate code for return statement */
2999 /*-----------------------------------------------------------------*/
3003 int size, offset = 0;
3006 D(emitcode ("; genRet",""));
3008 /* if we have no return value then
3009 just generate the "ret" */
3013 /* we have something to return then
3014 move the return value into place */
3015 aopOp (IC_LEFT (ic), ic, FALSE);
3016 size = AOP_SIZE (IC_LEFT (ic));
3022 transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
3029 /* 4 byte return: store value in the global return variable */
3033 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
3034 STA (fReturn2[offset--], FALSE);
3035 hc08_freeReg (hc08_reg_a);
3039 /* 2 byte return: store value in x:a */
3040 loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
3041 hc08_freeReg (hc08_reg_xa);
3044 /* 1 byte return: store value in a */
3045 loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
3046 hc08_freeReg (hc08_reg_a);
3051 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3054 /* generate a jump to the return label
3055 if the next is not the return statement */
3056 if (!(ic->next && ic->next->op == LABEL &&
3057 IC_LABEL (ic->next) == returnLabel))
3059 emitcode ("jmp", "%05d$", (returnLabel->key + 100));
3063 /*-----------------------------------------------------------------*/
3064 /* genLabel - generates a label */
3065 /*-----------------------------------------------------------------*/
3067 genLabel (iCode * ic)
3072 /* For the high level labels we cannot depend on any */
3073 /* register's contents. Amnesia time. */
3074 for (i=A_IDX;i<=XA_IDX;i++)
3076 reg = hc08_regWithIdx(i);
3081 /* special case never generate */
3082 if (IC_LABEL (ic) == entryLabel)
3085 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
3089 /*-----------------------------------------------------------------*/
3090 /* genGoto - generates a jmp */
3091 /*-----------------------------------------------------------------*/
3093 genGoto (iCode * ic)
3095 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
3099 /*-----------------------------------------------------------------*/
3100 /* findLabelBackwards: walks back through the iCode chain looking */
3101 /* for the given label. Returns number of iCode instructions */
3102 /* between that label and given ic. */
3103 /* Returns zero if label not found. */
3104 /*-----------------------------------------------------------------*/
3106 findLabelBackwards (iCode * ic, int key)
3115 /* If we have any pushes or pops, we cannot predict the distance.
3116 I don't like this at all, this should be dealt with in the
3118 if (ic->op == IPUSH || ic->op == IPOP) {
3122 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3132 /*-----------------------------------------------------------------*/
3133 /* genPlusIncr :- does addition with increment if possible */
3134 /*-----------------------------------------------------------------*/
3136 genPlusIncr (iCode * ic)
3144 unsigned int size = getDataSize (IC_RESULT (ic));
3146 symbol *tlbl = NULL;
3148 left = IC_LEFT (ic);
3149 result = IC_RESULT (ic);
3151 /* will try to generate an increment */
3152 /* if the right side is not a literal
3154 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3157 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3159 D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
3161 if ((IS_AOP_HX (AOP (left)) ||
3162 ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
3164 && (icount>=-128) && (icount<=127) && (size==2))
3166 if (!IS_AOP_HX (AOP (left)))
3168 needpulx = pushRegIfUsed (hc08_reg_x);
3169 needpulh = pushRegIfUsed (hc08_reg_h);
3176 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3177 emitcode ("aix","#%d", icount);
3178 hc08_dirtyReg (hc08_reg_hx, FALSE);
3179 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3180 pullOrFreeReg (hc08_reg_h, needpulh);
3181 pullOrFreeReg (hc08_reg_x, needpulx);
3185 D(emitcode ("", "; icount = %d, sameRegs=%d", icount,
3186 sameRegs (AOP (left), AOP (result))));
3188 if ((icount > 255) || (icount<0))
3191 if (!sameRegs (AOP (left), AOP (result)))
3194 D(emitcode ("; genPlusIncr",""));
3197 tlbl = newiTempLabel (NULL);
3202 rmwWithAop ("inc", AOP (result), 0);
3204 emitBranch ("bne", tlbl);
3208 if (!IS_AOP_A (AOP (result)) && !IS_AOP_XA (AOP (result)))
3209 needpula = pushRegIfUsed (hc08_reg_a);
3212 loadRegFromAop (hc08_reg_a, AOP (result), 0);
3213 accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
3214 hc08_useReg (hc08_reg_a);
3215 storeRegToAop (hc08_reg_a, AOP (result), 0);
3216 hc08_freeReg (hc08_reg_a);
3218 emitBranch ("bcc", tlbl);
3220 for (offset=1; offset<size; offset++)
3222 rmwWithAop ("inc", AOP (result), offset);
3223 if ((offset+1)<size)
3224 emitBranch ("bne", tlbl);
3230 pullOrFreeReg (hc08_reg_a, needpula);
3237 /*-----------------------------------------------------------------*/
3238 /* genPlus - generates code for addition */
3239 /*-----------------------------------------------------------------*/
3241 genPlus (iCode * ic)
3243 int size, offset = 0;
3245 asmop *leftOp, *rightOp;
3247 /* special cases :- */
3249 D(emitcode ("; genPlus",""));
3251 aopOp (IC_LEFT (ic), ic, FALSE);
3252 aopOp (IC_RIGHT (ic), ic, FALSE);
3253 aopOp (IC_RESULT (ic), ic, TRUE);
3255 /* we want registers on the left and literals on the right */
3256 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3257 (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
3259 operand *t = IC_RIGHT (ic);
3260 IC_RIGHT (ic) = IC_LEFT (ic);
3265 /* if I can do an increment instead
3266 of add then GOOD for ME */
3267 if (genPlusIncr (ic) == TRUE)
3270 D(emitcode("","; left size = %d", getDataSize (IC_LEFT(ic))));
3271 D(emitcode("","; right size = %d", getDataSize (IC_RIGHT(ic))));
3272 D(emitcode("","; result size = %d", getDataSize (IC_RESULT(ic))));
3274 size = getDataSize (IC_RESULT (ic));
3276 leftOp = AOP(IC_LEFT(ic));
3277 rightOp = AOP(IC_RIGHT(ic));
3283 loadRegFromAop (hc08_reg_a, leftOp, offset);
3284 accopWithAop(add, rightOp, offset);
3285 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3286 hc08_freeReg (hc08_reg_a);
3287 add = "adc"; /* further adds must propagate carry */
3291 // adjustArithmeticResult (ic);
3294 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3295 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
3296 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3299 /*-----------------------------------------------------------------*/
3300 /* genMinusDec :- does subtraction with deccrement if possible */
3301 /*-----------------------------------------------------------------*/
3303 genMinusDec (iCode * ic)
3305 unsigned int icount;
3310 unsigned int size = getDataSize (IC_RESULT (ic));
3314 left = IC_LEFT (ic);
3315 result = IC_RESULT (ic);
3317 /* will try to generate an increment */
3318 /* if the right side is not a literal
3320 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3323 icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3325 if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
3326 && (icount>=-127) && (icount<=128) && (size==2))
3328 if (!IS_AOP_HX (AOP (left)))
3330 needpulx = pushRegIfUsed (hc08_reg_x);
3331 needpulh = pushRegIfUsed (hc08_reg_h);
3338 loadRegFromAop (hc08_reg_hx, AOP(left), 0);
3339 emitcode ("aix","#%d", -icount);
3340 hc08_dirtyReg (hc08_reg_hx, FALSE);
3341 storeRegToAop (hc08_reg_hx, AOP(result), 0);
3342 pullOrFreeReg (hc08_reg_h, needpulh);
3343 pullOrFreeReg (hc08_reg_x, needpulx);
3347 if ((icount > 1) || (icount<0))
3350 if (!sameRegs (AOP (left), AOP (result)))
3356 D(emitcode ("; genMinusDec",""));
3358 rmwWithAop ("dec", AOP (result), 0);
3363 /*-----------------------------------------------------------------*/
3364 /* addSign - complete with sign */
3365 /*-----------------------------------------------------------------*/
3367 addSign (operand * result, int offset, int sign)
3369 int size = (getDataSize (result) - offset);
3374 emitcode ("rola", "");
3375 emitcode ("clra", "");
3376 emitcode ("sbc", zero);
3378 storeRegToAop (hc08_reg_a, AOP (result), offset++);
3382 storeConstToAop (zero, AOP (result), offset++);
3387 /*-----------------------------------------------------------------*/
3388 /* genMinus - generates code for subtraction */
3389 /*-----------------------------------------------------------------*/
3391 genMinus (iCode * ic)
3394 int size, offset = 0;
3396 asmop *leftOp, *rightOp;
3398 D(emitcode ("; genMinus",""));
3400 aopOp (IC_LEFT (ic), ic, FALSE);
3401 aopOp (IC_RIGHT (ic), ic, FALSE);
3402 aopOp (IC_RESULT (ic), ic, TRUE);
3404 /* special cases :- */
3405 /* if I can do an decrement instead
3406 of subtract then GOOD for ME */
3407 if (genMinusDec (ic) == TRUE)
3410 size = getDataSize (IC_RESULT (ic));
3413 leftOp = AOP(IC_LEFT(ic));
3414 rightOp = AOP(IC_RIGHT(ic));
3420 loadRegFromAop ( hc08_reg_a, leftOp, offset);
3421 accopWithAop(sub, rightOp, offset);
3422 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
3427 // adjustArithmeticResult (ic);
3430 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3431 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3432 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3437 /*-----------------------------------------------------------------*/
3438 /* genMultOneByte : 8*8=8/16 bit multiplication */
3439 /*-----------------------------------------------------------------*/
3441 genMultOneByte (operand * left,
3445 /* sym_link *opetype = operandType (result); */
3446 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3447 int size=AOP_SIZE(result);
3448 bool negLiteral = FALSE;
3450 D(emitcode ("; genMultOneByte",""));
3452 if (size<1 || size>2) {
3453 // this should never happen
3454 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3455 AOP_SIZE(result), __FILE__, lineno);
3459 /* (if two literals: the value is computed before) */
3460 /* if one literal, literal on the right */
3461 if (AOP_TYPE (left) == AOP_LIT)
3466 //D(emitcode (";", "swapped left and right"));
3470 || (SPEC_USIGN(operandType(left)) &&
3471 SPEC_USIGN(operandType(right))))
3473 // just an unsigned 8*8=8/16 multiply
3474 //D(emitcode (";","unsigned"));
3476 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3477 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3478 emitcode ("mul", "");
3479 hc08_dirtyReg (hc08_reg_xa, FALSE);
3480 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3481 hc08_freeReg (hc08_reg_xa);
3486 // we have to do a signed multiply
3489 //D(emitcode (";", "signed"));
3491 emitcode ("clr", "1,s");
3493 tlbl1 = newiTempLabel (NULL);
3494 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3495 emitcode ("tsta","");
3496 emitBranch ("bpl", tlbl1);
3497 emitcode ("inc", "1,s");
3498 rmwWithReg ("neg", hc08_reg_a);
3501 if (AOP_TYPE(right)==AOP_LIT)
3503 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3504 /* AND literal negative */
3506 emitcode ("ldx", "#0x%02x", -val);
3509 emitcode ("ldx", "#0x%02x", val);
3511 hc08_useReg (hc08_reg_x);
3515 tlbl2 = newiTempLabel (NULL);
3516 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3517 emitcode ("tstx", "");
3518 emitBranch ("bpl", tlbl2);
3519 emitcode ("inc", "1,s");
3520 rmwWithReg ("neg", hc08_reg_x);
3524 emitcode ("mul", "");
3525 hc08_dirtyReg (hc08_reg_xa, FALSE);
3527 tlbl3 = newiTempLabel (NULL);
3528 emitcode ("dec", "1,s");
3530 emitBranch ("bne", tlbl3);
3532 emitBranch ("beq", tlbl3);
3534 rmwWithReg ("neg", hc08_reg_a);
3537 tlbl4 = newiTempLabel (NULL);
3538 emitBranch ("bcc", tlbl4);
3539 rmwWithReg ("inc", hc08_reg_x);
3541 rmwWithReg ("neg", hc08_reg_x);
3546 storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
3547 hc08_freeReg (hc08_reg_xa);
3551 /*-----------------------------------------------------------------*/
3552 /* genMult - generates code for multiplication */
3553 /*-----------------------------------------------------------------*/
3555 genMult (iCode * ic)
3557 operand *left = IC_LEFT (ic);
3558 operand *right = IC_RIGHT (ic);
3559 operand *result = IC_RESULT (ic);
3561 D(emitcode ("; genMult",""));
3563 /* assign the amsops */
3564 aopOp (left, ic, FALSE);
3565 aopOp (right, ic, FALSE);
3566 aopOp (result, ic, TRUE);
3568 /* special cases first */
3569 /* if both are of size == 1 */
3570 // if (getSize(operandType(left)) == 1 &&
3571 // getSize(operandType(right)) == 1)
3572 if (AOP_SIZE (left) == 1 &&
3573 AOP_SIZE (right) == 1)
3575 genMultOneByte (left, right, result);
3579 /* should have been converted to function call */
3580 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3581 getSize(OP_SYMBOL(right)->type));
3582 fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
3587 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3588 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3589 freeAsmop (result, NULL, ic, TRUE);
3592 /*-----------------------------------------------------------------*/
3593 /* genDivOneByte : 8 bit division */
3594 /*-----------------------------------------------------------------*/
3596 genDivOneByte (operand * left,
3600 sym_link *opetype = operandType (result);
3602 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3604 bool negLiteral = FALSE;
3606 D(emitcode ("; genDivOneByte",""));
3608 size = AOP_SIZE (result);
3609 /* signed or unsigned */
3610 if (SPEC_USIGN (opetype))
3612 /* unsigned is easy */
3613 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3614 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3615 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3616 emitcode ("div", "");
3617 hc08_dirtyReg (hc08_reg_a, FALSE);
3618 hc08_dirtyReg (hc08_reg_h, FALSE);
3619 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
3620 hc08_freeReg (hc08_reg_a);
3621 hc08_freeReg (hc08_reg_x);
3622 hc08_freeReg (hc08_reg_h);
3626 /* signed is a little bit more difficult */
3629 emitcode ("clr", "1,s");
3631 tlbl1 = newiTempLabel (NULL);
3632 tlbl2 = newiTempLabel (NULL);
3633 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3634 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3635 emitBranch ("bpl", tlbl1);
3636 emitcode ("inc", "1,s");
3637 rmwWithReg ("neg", hc08_reg_a);
3638 emitBranch ("bcc", tlbl2);
3639 rmwWithReg ("inc", hc08_reg_x);
3641 rmwWithReg ("neg", hc08_reg_x);
3642 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3645 if (AOP_TYPE(right)==AOP_LIT)
3647 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3648 /* AND literal negative */
3650 emitcode ("ldx", "#0x%02x", -val);
3653 emitcode ("ldx", "#0x%02x", val);
3655 hc08_useReg (hc08_reg_x);
3659 tlbl3 = newiTempLabel (NULL);
3660 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3661 emitBranch ("bpl", tlbl3);
3662 emitcode ("inc", "1,s");
3663 rmwWithReg ("neg", hc08_reg_x);
3667 emitcode ("div", "");
3668 hc08_dirtyReg (hc08_reg_x, FALSE);
3669 hc08_dirtyReg (hc08_reg_a, FALSE);
3670 hc08_dirtyReg (hc08_reg_h, FALSE);
3672 tlbl4 = newiTempLabel (NULL);
3673 emitcode ("dec", "1,s");
3675 emitBranch ("bne", tlbl4);
3677 emitBranch ("beq", tlbl4);
3678 rmwWithReg ("neg", hc08_reg_a);
3682 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3683 hc08_freeReg (hc08_reg_a);
3684 hc08_freeReg (hc08_reg_x);
3685 hc08_freeReg (hc08_reg_h);
3690 /*-----------------------------------------------------------------*/
3691 /* genDiv - generates code for division */
3692 /*-----------------------------------------------------------------*/
3696 operand *left = IC_LEFT (ic);
3697 operand *right = IC_RIGHT (ic);
3698 operand *result = IC_RESULT (ic);
3700 D(emitcode ("; genDiv",""));
3702 /* assign the amsops */
3703 aopOp (left, ic, FALSE);
3704 aopOp (right, ic, FALSE);
3705 aopOp (result, ic, TRUE);
3707 /* special cases first */
3708 /* if both are of size == 1 */
3709 if (AOP_SIZE (left) <= 2 &&
3710 AOP_SIZE (right) == 1)
3712 genDivOneByte (left, right, result);
3716 /* should have been converted to function call */
3719 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3720 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3721 freeAsmop (result, NULL, ic, TRUE);
3724 /*-----------------------------------------------------------------*/
3725 /* genModOneByte : 8 bit modulus */
3726 /*-----------------------------------------------------------------*/
3728 genModOneByte (operand * left,
3732 sym_link *opetype = operandType (result);
3734 symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
3736 bool negLiteral = FALSE;
3738 D(emitcode ("; genModOneByte",""));
3740 size = AOP_SIZE (result);
3741 /* signed or unsigned */
3742 if (SPEC_USIGN (opetype))
3744 /* unsigned is easy */
3745 loadRegFromAop (hc08_reg_h, AOP (left), 1);
3746 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3747 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3748 emitcode ("div", "");
3749 hc08_dirtyReg (hc08_reg_a, FALSE);
3750 hc08_dirtyReg (hc08_reg_h, FALSE);
3751 storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
3752 hc08_freeReg (hc08_reg_a);
3753 hc08_freeReg (hc08_reg_x);
3754 hc08_freeReg (hc08_reg_h);
3758 /* signed is a little bit more difficult */
3761 emitcode ("clr", "1,s");
3763 tlbl1 = newiTempLabel (NULL);
3764 tlbl2 = newiTempLabel (NULL);
3765 loadRegFromAop (hc08_reg_a, AOP (left), 0);
3766 loadRegFromAop (hc08_reg_x, AOP (left), 1);
3767 emitBranch ("bpl", tlbl1);
3768 emitcode ("inc", "1,s");
3769 rmwWithReg ("neg", hc08_reg_a);
3770 emitBranch ("bcc", tlbl2);
3771 rmwWithReg ("inc", hc08_reg_x);
3773 rmwWithReg ("neg", hc08_reg_x);
3774 transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
3777 if (AOP_TYPE(right)==AOP_LIT)
3779 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3780 /* AND literal negative */
3782 emitcode ("ldx", "#0x%02x", -val);
3785 emitcode ("ldx", "#0x%02x", val);
3787 hc08_useReg (hc08_reg_x);
3791 tlbl3 = newiTempLabel (NULL);
3792 loadRegFromAop (hc08_reg_x, AOP (right), 0);
3793 emitBranch ("bpl", tlbl3);
3794 emitcode ("inc", "1,s");
3795 rmwWithReg ("neg", hc08_reg_x);
3799 emitcode ("div", "");
3800 hc08_dirtyReg (hc08_reg_x, FALSE);
3801 hc08_dirtyReg (hc08_reg_a, FALSE);
3802 hc08_dirtyReg (hc08_reg_h, FALSE);
3804 tlbl4 = newiTempLabel (NULL);
3805 transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
3806 emitcode ("dec", "1,s");
3808 emitBranch ("bne", tlbl4);
3810 emitBranch ("beq", tlbl4);
3811 rmwWithReg ("neg", hc08_reg_a);
3815 storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
3816 hc08_freeReg (hc08_reg_a);
3817 hc08_freeReg (hc08_reg_x);
3818 hc08_freeReg (hc08_reg_h);
3822 /*-----------------------------------------------------------------*/
3823 /* genMod - generates code for division */
3824 /*-----------------------------------------------------------------*/
3828 operand *left = IC_LEFT (ic);
3829 operand *right = IC_RIGHT (ic);
3830 operand *result = IC_RESULT (ic);
3832 D(emitcode ("; genMod",""));
3834 /* assign the amsops */
3835 aopOp (left, ic, FALSE);
3836 aopOp (right, ic, FALSE);
3837 aopOp (result, ic, TRUE);
3839 /* special cases first */
3840 /* if both are of size == 1 */
3841 if (AOP_SIZE (left) <= 2 &&
3842 AOP_SIZE (right) == 1)
3844 genModOneByte (left, right, result);
3848 /* should have been converted to function call */
3852 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3853 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3854 freeAsmop (result, NULL, ic, TRUE);
3857 /*-----------------------------------------------------------------*/
3858 /* genIfxJump :- will create a jump depending on the ifx */
3859 /*-----------------------------------------------------------------*/
3861 genIfxJump (iCode * ic, char *jval)
3864 symbol *tlbl = newiTempLabel (NULL);
3867 D(emitcode ("; genIfxJump",""));
3869 /* if true label then we jump if condition
3873 jlbl = IC_TRUE (ic);
3874 if (!strcmp (jval, "a"))
3876 else if (!strcmp (jval, "c"))
3883 /* false label is present */
3884 jlbl = IC_FALSE (ic);
3885 if (!strcmp (jval, "a"))
3887 else if (!strcmp (jval, "c"))
3892 emitBranch (inst, tlbl);
3893 emitBranch ("jmp", jlbl);
3896 /* mark the icode as generated */
3900 /*-----------------------------------------------------------------*/
3901 /* genCmp :- greater or less than comparison */
3902 /*-----------------------------------------------------------------*/
3904 genCmp (operand * left, operand * right,
3905 operand * result, iCode * ifx, int sign, iCode *ic)
3907 int size, offset = 0;
3908 unsigned long lit = 0L;
3910 bool needpula = FALSE;
3912 D(emitcode ("; genCmp",""));
3914 /* subtract right from left if at the
3915 end the carry flag is set then we know that
3916 left is greater than right */
3917 size = max (AOP_SIZE (left), AOP_SIZE (right));
3919 if (AOP_TYPE (right) == AOP_LIT)
3921 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3922 /* optimize if(x < 0) or if(x >= 0) */
3931 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
3932 emitcode ("rola", "");
3933 hc08_useReg (hc08_reg_a);
3941 && ((AOP_TYPE (right) == AOP_LIT) ||
3942 ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
3943 && hc08_reg_hx->isFree)
3945 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
3946 emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
3947 hc08_freeReg (hc08_reg_hx);
3958 loadRegFromAop (hc08_reg_a, AOP (left), offset);
3959 accopWithAop (sub, AOP (right), offset);
3960 hc08_freeReg (hc08_reg_a);
3966 freeAsmop (right, NULL, ic, TRUE);
3967 freeAsmop (left, NULL, ic, TRUE);
3968 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3974 /* if the result is used in the next
3975 ifx conditional branch then generate
3976 code a little differently */
3979 pullOrFreeReg(hc08_reg_a,needpula);
3980 genIfxJump (ifx, sign ? "s" : "c");
3987 pullOrFreeReg(hc08_reg_a,needpula);
3991 /*-----------------------------------------------------------------*/
3992 /* genCmpGt :- greater than comparison */
3993 /*-----------------------------------------------------------------*/
3995 genCmpGt (iCode * ic, iCode * ifx)
3997 operand *left, *right, *result;
3998 sym_link *letype, *retype;
4001 D(emitcode ("; genCmpGt",""));
4003 result = IC_RESULT (ic);
4004 left = IC_LEFT (ic);
4005 right = IC_RIGHT (ic);
4007 letype = getSpec (operandType (left));
4008 retype = getSpec (operandType (right));
4009 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4010 /* assign the amsops */
4011 aopOp (left, ic, FALSE);
4012 aopOp (right, ic, FALSE);
4013 aopOp (result, ic, TRUE);
4015 genCmp (right, left, result, ifx, sign,ic);
4017 freeAsmop (result, NULL, ic, TRUE);
4020 /*-----------------------------------------------------------------*/
4021 /* genCmpLt - less than comparisons */
4022 /*-----------------------------------------------------------------*/
4024 genCmpLt (iCode * ic, iCode * ifx)
4026 operand *left, *right, *result;
4027 sym_link *letype, *retype;
4030 D(emitcode ("; genCmpLt",""));
4032 result = IC_RESULT (ic);
4033 left = IC_LEFT (ic);
4034 right = IC_RIGHT (ic);
4036 letype = getSpec (operandType (left));
4037 retype = getSpec (operandType (right));
4038 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4040 /* assign the amsops */
4041 aopOp (left, ic, FALSE);
4042 aopOp (right, ic, FALSE);
4043 aopOp (result, ic, TRUE);
4045 genCmp (left, right, result, ifx, sign,ic);
4047 freeAsmop (result, NULL, ic, TRUE);
4050 /*-----------------------------------------------------------------*/
4051 /* - compare and branch if not equal */
4052 /*-----------------------------------------------------------------*/
4054 gencbneshort (operand * left, operand * right, symbol * lbl)
4056 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4058 unsigned long lit = 0L;
4060 /* if the left side is a literal or
4061 if the right is in a pointer register and left
4063 if (AOP_TYPE (left) == AOP_LIT)
4069 if (AOP_TYPE (right) == AOP_LIT)
4070 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4074 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4075 accopWithAop ("cmp", AOP (right), offset);
4076 hc08_useReg (hc08_reg_a);
4077 hc08_freeReg (hc08_reg_a);
4078 emitBranch ("bne", lbl);
4084 /*-----------------------------------------------------------------*/
4085 /* gencjne - compare and jump if not equal */
4086 /*-----------------------------------------------------------------*/
4088 gencjne (operand * left, operand * right, symbol * lbl)
4090 symbol *tlbl = newiTempLabel (NULL);
4092 gencbneshort (left, right, lbl);
4094 loadRegFromConst (hc08_reg_a, one);
4095 emitBranch ("bra", tlbl);
4097 loadRegFromConst (hc08_reg_a, zero);
4100 hc08_useReg(hc08_reg_a);
4101 hc08_freeReg(hc08_reg_a);
4104 /*-----------------------------------------------------------------*/
4105 /* genCmpEq - generates code for equal to */
4106 /*-----------------------------------------------------------------*/
4108 genCmpEq (iCode * ic, iCode * ifx)
4110 operand *left, *right, *result;
4112 D(emitcode ("; genCmpEq",""));
4114 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4115 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4116 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4118 /* if literal, literal on the right or
4119 if the right is in a pointer register and left
4121 if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4123 operand *t = IC_RIGHT (ic);
4124 IC_RIGHT (ic) = IC_LEFT (ic);
4128 if (ifx && !AOP_SIZE (result))
4131 tlbl = newiTempLabel (NULL);
4132 gencbneshort (left, right, tlbl);
4135 emitBranch ("jmp", IC_TRUE (ifx));
4140 symbol *lbl = newiTempLabel (NULL);
4141 emitBranch ("bra", lbl);
4143 emitBranch ("jmp", IC_FALSE (ifx));
4147 /* mark the icode as generated */
4152 gencjne (left, right, newiTempLabel (NULL));
4153 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4155 storeRegToAop (hc08_reg_a, AOP (result), 0);
4160 genIfxJump (ifx, "a");
4163 /* if the result is used in an arithmetic operation
4164 then put the result in place */
4165 if (AOP_TYPE (result) != AOP_CRY)
4169 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4170 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4171 freeAsmop (result, NULL, ic, TRUE);
4174 /*-----------------------------------------------------------------*/
4175 /* ifxForOp - returns the icode containing the ifx for operand */
4176 /*-----------------------------------------------------------------*/
4178 ifxForOp (operand * op, iCode * ic)
4180 /* if true symbol then needs to be assigned */
4181 if (IS_TRUE_SYMOP (op))
4184 /* if this has register type condition and
4185 the next instruction is ifx with the same operand
4186 and live to of the operand is upto the ifx only then */
4188 ic->next->op == IFX &&
4189 IC_COND (ic->next)->key == op->key &&
4190 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4197 genPointerGetSetOfs (iCode *ic)
4199 iCode *lic = ic->next;
4205 /* Make sure we have a next iCode */
4206 D(emitcode("","; checking lic"));
4210 /* Make sure the result of the addition is an iCode */
4211 D(emitcode("","; checking IS_ITEMP"));
4212 if (!IS_ITEMP (IC_RESULT (ic)))
4215 /* Make sure the next iCode is a pointer set or get */
4216 pset = POINTER_SET(lic);
4217 pget = POINTER_GET(lic);
4218 D(emitcode("","; pset=%d, pget=%d",pset,pget));
4222 D(emitcode("", "; checking pset operandsEqu"));
4223 if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
4226 D(emitcode("", "; checking pget operandsEqu"));
4227 if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
4230 D(emitcode("", "; checking IS_SYMOP"));
4231 if (!IS_SYMOP (IC_LEFT (ic)))
4234 D(emitcode("", "; checking !IS_TRUE_SYMOP"));
4235 if (IS_TRUE_SYMOP (IC_LEFT (ic)))
4238 sym = OP_SYMBOL (IC_LEFT (ic));
4240 D(emitcode("", "; checking remat"));
4247 D(emitcode ("; genPointerGetOfs",""));
4248 aopOp (IC_LEFT(ic), ic, FALSE);
4249 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4250 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4252 aopOp (IC_RIGHT(ic), ic, FALSE);
4253 aopOp (IC_RESULT(lic), lic, FALSE);
4255 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4257 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4259 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4260 loadRegFromConst (hc08_reg_h, zero);
4264 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4265 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4266 emitcode ("rola","");
4267 emitcode ("clra","");
4268 emitcode ("sbc", "#0");
4269 hc08_useReg (hc08_reg_a);
4270 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4274 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4275 size = AOP_SIZE (IC_RESULT(lic));
4276 derefaop->size = size;
4281 emitcode ("lda", "%s,x",
4282 aopAdrStr (derefaop, offset, TRUE));
4283 hc08_useReg (hc08_reg_a);
4284 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
4285 hc08_freeReg (hc08_reg_a);
4289 hc08_freeReg (hc08_reg_hx);
4291 freeAsmop (NULL, derefaop, ic, TRUE);
4292 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4293 freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
4300 D(emitcode ("; genPointerSetOfs",""));
4301 aopOp (IC_LEFT(ic), ic, FALSE);
4302 derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
4303 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
4305 aopOp (IC_RIGHT(ic), ic, FALSE);
4306 aopOp (IC_RIGHT(lic), lic, FALSE);
4308 if (AOP_SIZE (IC_RIGHT (ic)) == 1)
4310 if (SPEC_USIGN (getSpec (operandType (IC_RIGHT (ic)))))
4312 loadRegFromAop (hc08_reg_x, AOP (IC_RIGHT (ic)), 0);
4313 loadRegFromConst (hc08_reg_h, zero);
4317 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
4318 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
4319 emitcode ("rola","");
4320 emitcode ("clra","");
4321 emitcode ("sbc", "#0");
4322 hc08_useReg (hc08_reg_a);
4323 transferRegReg (hc08_reg_a, hc08_reg_h, FALSE);
4327 loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
4328 size = AOP_SIZE (IC_RIGHT(lic));
4329 derefaop->size = size;
4334 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
4335 emitcode ("sta", "%s,x",
4336 aopAdrStr (derefaop, offset, TRUE));
4337 hc08_freeReg (hc08_reg_a);
4342 hc08_freeReg (hc08_reg_hx);
4344 freeAsmop (NULL, derefaop, ic, TRUE);
4345 freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
4346 freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
4355 /*-----------------------------------------------------------------*/
4356 /* hasInc - operand is incremented before any other use */
4357 /*-----------------------------------------------------------------*/
4359 hasInc (operand *op, iCode *ic,int osize)
4361 sym_link *type = operandType(op);
4362 sym_link *retype = getSpec (type);
4363 iCode *lic = ic->next;
4366 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4367 if (!IS_SYMOP(op)) return NULL;
4369 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4370 if (IS_AGGREGATE(type->next)) return NULL;
4371 if (osize != (isize = getSize(type->next))) return NULL;
4374 /* if operand of the form op = op + <sizeof *op> */
4375 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4376 isOperandEqual(IC_RESULT(lic),op) &&
4377 isOperandLiteral(IC_RIGHT(lic)) &&
4378 operandLitValue(IC_RIGHT(lic)) == isize) {
4381 /* if the operand used or deffed */
4382 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4385 /* if GOTO or IFX */
4386 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
4392 /*-----------------------------------------------------------------*/
4393 /* genAndOp - for && operation */
4394 /*-----------------------------------------------------------------*/
4396 genAndOp (iCode * ic)
4398 operand *left, *right, *result;
4399 symbol *tlbl, *tlbl0;
4401 D(emitcode ("; genAndOp",""));
4403 /* note here that && operations that are in an
4404 if statement are taken away by backPatchLabels
4405 only those used in arthmetic operations remain */
4406 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4407 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4408 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4410 tlbl = newiTempLabel (NULL);
4411 tlbl0 = newiTempLabel (NULL);
4413 asmopToBool (AOP (left), FALSE);
4414 emitBranch ("beq", tlbl0);
4415 asmopToBool (AOP (right), FALSE);
4416 emitBranch ("beq", tlbl0);
4417 loadRegFromConst (hc08_reg_a,one);
4418 emitBranch ("bra", tlbl);
4420 loadRegFromConst (hc08_reg_a,zero);
4423 hc08_useReg (hc08_reg_a);
4424 hc08_freeReg (hc08_reg_a);
4426 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4428 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4429 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4430 freeAsmop (result, NULL, ic, TRUE);
4434 /*-----------------------------------------------------------------*/
4435 /* genOrOp - for || operation */
4436 /*-----------------------------------------------------------------*/
4438 genOrOp (iCode * ic)
4440 operand *left, *right, *result;
4441 symbol *tlbl, *tlbl0;
4443 D(emitcode ("; genOrOp",""));
4445 /* note here that || operations that are in an
4446 if statement are taken away by backPatchLabels
4447 only those used in arthmetic operations remain */
4448 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4449 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4450 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4452 tlbl = newiTempLabel (NULL);
4453 tlbl0 = newiTempLabel (NULL);
4455 asmopToBool (AOP (left), FALSE);
4456 emitBranch ("bne", tlbl0);
4457 asmopToBool (AOP (right), FALSE);
4458 emitBranch ("bne", tlbl0);
4459 loadRegFromConst (hc08_reg_a,zero);
4460 emitBranch ("bra", tlbl);
4462 loadRegFromConst (hc08_reg_a,one);
4465 hc08_useReg (hc08_reg_a);
4466 hc08_freeReg (hc08_reg_a);
4468 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
4471 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4472 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4473 freeAsmop (result, NULL, ic, TRUE);
4476 /*-----------------------------------------------------------------*/
4477 /* isLiteralBit - test if lit == 2^n */
4478 /*-----------------------------------------------------------------*/
4480 isLiteralBit (unsigned long lit)
4482 unsigned long pw[32] =
4483 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4484 0x100L, 0x200L, 0x400L, 0x800L,
4485 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4486 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4487 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4488 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4489 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4492 for (idx = 0; idx < 32; idx++)
4499 /*-----------------------------------------------------------------*/
4500 /* continueIfTrue - */
4501 /*-----------------------------------------------------------------*/
4503 continueIfTrue (iCode * ic)
4506 emitBranch ("jmp", IC_TRUE (ic));
4510 /*-----------------------------------------------------------------*/
4512 /*-----------------------------------------------------------------*/
4514 jumpIfTrue (iCode * ic)
4517 emitBranch ("jmp", IC_FALSE (ic));
4521 /*-----------------------------------------------------------------*/
4522 /* jmpTrueOrFalse - */
4523 /*-----------------------------------------------------------------*/
4525 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4527 // ugly but optimized by peephole
4530 symbol *nlbl = newiTempLabel (NULL);
4531 emitBranch ("bra", nlbl);
4533 emitBranch ("jmp", IC_TRUE (ic));
4538 emitBranch ("jmp", IC_FALSE (ic));
4545 /*-----------------------------------------------------------------*/
4546 /* genAnd - code for and */
4547 /*-----------------------------------------------------------------*/
4549 genAnd (iCode * ic, iCode * ifx)
4551 operand *left, *right, *result;
4552 int size, offset = 0;
4553 unsigned long lit = 0L;
4554 unsigned long litinv;
4560 D(emitcode ("; genAnd",""));
4562 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4563 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4564 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4567 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4569 AOP_TYPE (left), AOP_TYPE (right)));
4570 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4572 AOP_SIZE (left), AOP_SIZE (right)));
4575 /* if left is a literal & right is not then exchange them */
4576 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4578 operand *tmp = right;
4583 /* if left is accumulator & right is not then exchange them */
4584 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4586 operand *tmp = right;
4592 if (AOP_TYPE (result) == AOP_CRY)
4595 wassertl (ifx, "AOP_CPY result without ifx");
4597 tlbl = newiTempLabel (NULL);
4598 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4602 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4603 if ((AOP_TYPE (right) == AOP_LIT)
4604 && (((lit >> (offset*8)) & 0xff) == 0xff))
4605 emitcode ("tsta","");
4607 accopWithAop ("and", AOP (right), offset);
4608 hc08_freeReg( hc08_reg_a);
4610 emitBranch ("bne", tlbl);
4614 genIfxJump (ifx, "a");
4620 size = AOP_SIZE (result);
4622 if (AOP_TYPE (right) == AOP_LIT)
4624 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4625 litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
4627 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4628 (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
4630 int bitpos = isLiteralBit(litinv)-1;
4631 emitcode ("bclr","#%d,%s",bitpos & 7,
4632 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4640 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4641 if ((AOP_TYPE (right) != AOP_LIT)
4642 || (((lit >> (offset*8)) & 0xff) != 0xff))
4643 accopWithAop ("and", AOP (right), offset);
4644 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4645 hc08_freeReg( hc08_reg_a);
4649 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4650 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4651 freeAsmop (result, NULL, ic, TRUE);
4654 /*-----------------------------------------------------------------*/
4655 /* genOr - code for or */
4656 /*-----------------------------------------------------------------*/
4658 genOr (iCode * ic, iCode * ifx)
4660 operand *left, *right, *result;
4661 int size, offset = 0;
4662 unsigned long lit = 0L;
4664 D(emitcode ("; genOr",""));
4666 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4667 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4668 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4671 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4673 AOP_TYPE (left), AOP_TYPE (right)));
4674 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4676 AOP_SIZE (left), AOP_SIZE (right)));
4679 /* if left is a literal & right is not then exchange them */
4680 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4682 operand *tmp = right;
4687 /* if left is accumulator & right is not then exchange them */
4688 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4690 operand *tmp = right;
4695 if (AOP_TYPE (result) == AOP_CRY)
4698 wassertl (ifx, "AOP_CPY result without ifx");
4700 tlbl = newiTempLabel (NULL);
4701 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4705 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4706 if ((AOP_TYPE (right) == AOP_LIT)
4707 && (((lit >> (offset*8)) & 0xff) == 0))
4708 emitcode ("tsta","");
4710 accopWithAop ("ora", AOP (right), offset);
4711 hc08_freeReg( hc08_reg_a);
4713 emitBranch ("bne", tlbl);
4717 genIfxJump (ifx, "a");
4723 if (AOP_TYPE (right) == AOP_LIT)
4724 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4726 size = AOP_SIZE (result);
4728 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4729 (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
4730 (AOP_TYPE (left) == AOP_DIR))
4732 int bitpos = isLiteralBit(lit)-1;
4733 emitcode ("bset","#%d,%s",bitpos & 7,
4734 aopAdrStr (AOP (left), bitpos >> 3, FALSE));
4741 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4742 accopWithAop ("ora", AOP (right), offset);
4743 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4744 hc08_freeReg( hc08_reg_a);
4749 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4750 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4751 freeAsmop (result, NULL, ic, TRUE);
4754 /*-----------------------------------------------------------------*/
4755 /* genXor - code for xclusive or */
4756 /*-----------------------------------------------------------------*/
4758 genXor (iCode * ic, iCode * ifx)
4760 operand *left, *right, *result;
4761 int size, offset = 0;
4762 unsigned long lit = 0L;
4764 D(emitcode ("; genXor",""));
4766 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4767 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4768 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4771 D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4773 AOP_TYPE (left), AOP_TYPE (right)));
4774 D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4776 AOP_SIZE (left), AOP_SIZE (right)));
4779 /* if left is a literal & right is not ||
4780 if left needs acc & right does not */
4781 if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
4783 operand *tmp = right;
4788 /* if left is accumulator & right is not then exchange them */
4789 if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
4791 operand *tmp = right;
4796 if (AOP_TYPE (result) == AOP_CRY)
4799 wassertl (ifx, "AOP_CPY result without ifx");
4801 tlbl = newiTempLabel (NULL);
4802 size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
4806 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4807 if ((AOP_TYPE (right) == AOP_LIT)
4808 && (((lit >> (offset*8)) & 0xff) == 0))
4809 emitcode ("tsta","");
4811 accopWithAop ("eor", AOP (right), offset);
4812 hc08_freeReg( hc08_reg_a);
4814 emitBranch ("bne", tlbl);
4818 genIfxJump (ifx, "a");
4824 if (AOP_TYPE (right) == AOP_LIT)
4825 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4827 size = AOP_SIZE (result);
4831 loadRegFromAop (hc08_reg_a, AOP (left), offset);
4832 accopWithAop ("eor", AOP (right), offset);
4833 storeRegToAop (hc08_reg_a, AOP (result), offset++);
4834 hc08_freeReg( hc08_reg_a);
4838 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4839 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4840 freeAsmop (result, NULL, ic, TRUE);
4844 emitinline (iCode * ic, char *inlin)
4850 symbol *sym, *tempsym;
4859 while (isalnum(*inlin) || (*inlin == '_'))
4863 //printf("Found possible symbol '%s'\n",symname);
4864 tempsym = newSymbol (symname, ic->level);
4865 tempsym->block = ic->block;
4866 sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
4875 aop = aopForSym (ic, sym, FALSE);
4876 l = aopAdrStr (aop, aop->size - 1, TRUE);
4880 if (!sym->allocreq && !sym->ismyparm)
4882 werror (E_ID_UNDEF, sym->name);
4884 " Add 'volatile' to the variable declaration so that it\n"
4885 " can be referenced within inline assembly");
4887 //printf("Replacing with '%s'\n",l);
4891 if ((2+bp-buffer)>sizeof(buffer))
4900 if ((2+bp-buffer)>sizeof(buffer))
4907 if ((2+bp-buffer)>sizeof(buffer))
4908 fprintf(stderr, "Inline assembly buffer overflow\n");
4910 //printf("%s\n",buffer);
4911 emitcode (buffer,"");
4915 /*-----------------------------------------------------------------*/
4916 /* genInline - write the inline code out */
4917 /*-----------------------------------------------------------------*/
4919 genInline (iCode * ic)
4921 char *buffer, *bp, *bp1;
4923 D(emitcode ("; genInline",""));
4925 _G.inLine += (!options.asmpeep);
4927 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
4928 strcpy (buffer, IC_INLINE (ic));
4930 /* emit each line as a code */
4936 /* emitcode (bp1, ""); */
4937 emitinline (ic, bp1);
4956 /* emitcode (bp1, ""); */
4957 emitinline (ic, bp1);
4959 /* emitcode("",buffer); */
4960 _G.inLine -= (!options.asmpeep);
4963 /*-----------------------------------------------------------------*/
4964 /* genRRC - rotate right with carry */
4965 /*-----------------------------------------------------------------*/
4969 operand *left, *result;
4970 int size, offset = 0;
4971 bool needpula = FALSE;
4972 bool resultInA = FALSE;
4975 D(emitcode ("; genRRC",""));
4977 /* rotate right with carry */
4978 left = IC_LEFT (ic);
4979 result = IC_RESULT (ic);
4980 aopOp (left, ic, FALSE);
4981 aopOp (result, ic, FALSE);
4983 if ((AOP_TYPE (result) == AOP_REG)
4984 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
4987 size = AOP_SIZE (result);
4991 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4995 rmwWithAop (shift, AOP (result), offset--);
5003 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5004 rmwWithReg (shift, hc08_reg_a);
5005 storeRegToAop (hc08_reg_a, AOP (result), offset--);
5006 hc08_freeReg (hc08_reg_a);
5011 if ((!hc08_reg_a->isFree) || resultInA)
5013 pushReg (hc08_reg_a, TRUE);
5017 /* now we need to put the carry into the
5018 highest order byte of the result */
5019 offset = AOP_SIZE (result) - 1;
5020 emitcode ("clra","");
5021 emitcode ("rora","");
5022 hc08_dirtyReg (hc08_reg_a, FALSE);
5025 emitcode ("ora", "1,s");
5026 emitcode ("ais", "#1");
5027 hc08_dirtyReg (hc08_reg_a, FALSE);
5031 accopWithAop ("ora", AOP (result), offset);
5032 storeRegToAop (hc08_reg_a, AOP (result), offset);
5034 pullOrFreeReg (hc08_reg_a, needpula);
5036 freeAsmop (left, NULL, ic, TRUE);
5037 freeAsmop (result, NULL, ic, TRUE);
5040 /*-----------------------------------------------------------------*/
5041 /* genRLC - generate code for rotate left with carry */
5042 /*-----------------------------------------------------------------*/
5046 operand *left, *result;
5047 int size, offset = 0;
5049 bool resultInA = FALSE;
5050 bool needpula = FALSE;
5052 D(emitcode ("; genRLC",""));
5054 /* rotate right with carry */
5055 left = IC_LEFT (ic);
5056 result = IC_RESULT (ic);
5057 aopOp (left, ic, FALSE);
5058 aopOp (result, ic, FALSE);
5060 if ((AOP_TYPE (result) == AOP_REG)
5061 && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
5064 size = AOP_SIZE (result);
5068 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
5072 rmwWithAop (shift, AOP (result), offset--);
5080 loadRegFromAop (hc08_reg_a, AOP (left), offset);
5081 rmwWithReg (shift, hc08_reg_a);
5082 storeRegToAop (hc08_reg_a, AOP (result), offset++);
5083 hc08_freeReg (hc08_reg_a);
5088 if ((!hc08_reg_a->isFree) || resultInA)
5090 pushReg (hc08_reg_a, TRUE);
5094 /* now we need to put the carry into the
5095 lowest order byte of the result */
5097 emitcode ("clra","");
5098 emitcode ("rola","");
5099 hc08_dirtyReg (hc08_reg_a, FALSE);
5102 emitcode ("ora", "1,s");
5103 emitcode ("ais", "#1");
5104 hc08_dirtyReg (hc08_reg_a, FALSE);
5108 accopWithAop ("ora", AOP (result), offset);
5109 storeRegToAop (hc08_reg_a, AOP (result), offset);
5111 pullOrFreeReg (hc08_reg_a, needpula);
5113 freeAsmop (left, NULL, ic, TRUE);
5114 freeAsmop (result, NULL, ic, TRUE);
5117 /*-----------------------------------------------------------------*/
5118 /* genGetHbit - generates code get highest order bit */
5119 /*-----------------------------------------------------------------*/
5121 genGetHbit (iCode * ic)
5123 operand *left, *result;
5125 D(emitcode ("; genGetHbit",""));
5127 left = IC_LEFT (ic);
5128 result = IC_RESULT (ic);
5129 aopOp (left, ic, FALSE);
5130 aopOp (result, ic, FALSE);
5132 /* get the highest order byte into a */
5133 loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
5134 emitcode ("rola", "");
5135 emitcode ("clra", "");
5136 emitcode ("rola", "");
5137 hc08_dirtyReg (hc08_reg_a, FALSE);
5138 storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
5139 hc08_freeReg (hc08_reg_a);
5141 freeAsmop (left, NULL, ic, TRUE);
5142 freeAsmop (result, NULL, ic, TRUE);
5145 /*-----------------------------------------------------------------*/
5146 /* genSwap - generates code to swap nibbles or bytes */
5147 /*-----------------------------------------------------------------*/
5149 genSwap (iCode * ic)
5151 operand *left, *result;
5153 D(emitcode ("; genSwap",""));
5155 left = IC_LEFT (ic);
5156 result = IC_RESULT (ic);
5157 aopOp (left, ic, FALSE);
5158 aopOp (result, ic, FALSE);
5160 switch (AOP_SIZE (left))
5162 case 1: /* swap nibbles in byte */
5163 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5164 emitcode ("nsa", "");
5165 hc08_dirtyReg (hc08_reg_a, FALSE);
5166 storeRegToAop (hc08_reg_a, AOP (result), 0);
5167 hc08_freeReg (hc08_reg_a);
5169 case 2: /* swap bytes in a word */
5170 if (operandsEqu (left, result))
5172 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5173 hc08_useReg (hc08_reg_a);
5174 transferAopAop (AOP (left), 1, AOP (result), 0);
5175 storeRegToAop (hc08_reg_a, AOP (result), 1);
5176 hc08_freeReg (hc08_reg_a);
5180 transferAopAop (AOP (left), 0, AOP (result), 1);
5181 transferAopAop (AOP (left), 1, AOP (result), 0);
5185 wassertl(FALSE, "unsupported SWAP operand size");
5188 freeAsmop (left, NULL, ic, TRUE);
5189 freeAsmop (result, NULL, ic, TRUE);
5193 /*-----------------------------------------------------------------*/
5194 /* AccRol - rotate left accumulator by known count */
5195 /*-----------------------------------------------------------------*/
5197 AccRol (int shCount)
5199 shCount &= 0x0007; // shCount : 0..7
5206 emitcode ("rola", ""); /* 1 cycle */
5209 emitcode ("rola", ""); /* 1 cycle */
5210 emitcode ("rola", ""); /* 1 cycle */
5213 emitcode ("nsa", "");
5214 emitcode ("rora", "");
5217 emitcode ("nsa", ""); /* 3 cycles */
5220 emitcode ("nsa", ""); /* 3 cycles */
5221 emitcode ("rola", ""); /* 1 cycle */
5224 emitcode ("nsa", ""); /* 3 cycles */
5225 emitcode ("rola", ""); /* 1 cycle */
5226 emitcode ("rola", ""); /* 1 cycle */
5229 emitcode ("nsa", ""); /* 3 cycles */
5230 emitcode ("rola", ""); /* 1 cycle */
5231 emitcode ("rola", ""); /* 1 cycle */
5232 emitcode ("rola", ""); /* 1 cycle */
5239 /*-----------------------------------------------------------------*/
5240 /* AccLsh - left shift accumulator by known count */
5241 /*-----------------------------------------------------------------*/
5243 AccLsh (int shCount)
5247 shCount &= 0x0007; // shCount : 0..7
5249 /* Shift counts of 4 and 5 are currently optimized for code size. */
5250 /* Falling through to the unrolled loop would be optimal for code speed. */
5251 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5255 accopWithMisc ("nsa", "");
5256 accopWithMisc ("and", "#0xf0");
5257 /* total: 5 cycles, 3 bytes */
5260 accopWithMisc ("nsa", "");
5261 accopWithMisc ("and", "#0xf0");
5262 accopWithMisc ("lsla", "");
5263 /* total: 6 cycles, 4 bytes */
5266 accopWithMisc ("rora", "");
5267 accopWithMisc ("rora", "");
5268 accopWithMisc ("rora", "");
5269 accopWithMisc ("and", "#0xc0");
5270 /* total: 5 cycles, 5 bytes */
5273 accopWithMisc ("rora", "");
5274 accopWithMisc ("clra", "");
5275 accopWithMisc ("rora", "");
5276 /* total: 3 cycles, 3 bytes */
5280 /* lsla is only 1 cycle and byte, so an unrolled loop is often */
5281 /* the fastest (shCount<6) and shortest (shCount<4). */
5282 for (i=0;i<shCount;i++)
5283 accopWithMisc ("lsla", "");
5287 /*-----------------------------------------------------------------*/
5288 /* AccSRsh - signed right shift accumulator by known count */
5289 /*-----------------------------------------------------------------*/
5291 AccSRsh (int shCount)
5295 shCount &= 0x0007; // shCount : 0..7
5299 accopWithMisc ("rola", "");
5300 accopWithMisc ("clra", "");
5301 accopWithMisc ("sbc", zero);
5302 /* total: 4 cycles, 4 bytes */
5306 for (i=0;i<shCount;i++)
5307 accopWithMisc ("asra", "");
5310 /*-----------------------------------------------------------------*/
5311 /* AccRsh - right shift accumulator by known count */
5312 /*-----------------------------------------------------------------*/
5314 AccRsh (int shCount, bool sign)
5324 shCount &= 0x0007; // shCount : 0..7
5326 /* Shift counts of 4 and 5 are currently optimized for code size. */
5327 /* Falling through to the unrolled loop would be optimal for code speed. */
5328 /* For shift counts of 6 and 7, the unrolled loop is never optimal. */
5332 accopWithMisc ("nsa", "");
5333 accopWithMisc ("and", "#0x0f");
5334 /* total: 5 cycles, 3 bytes */
5337 accopWithMisc ("nsa", "");
5338 accopWithMisc ("and", "#0x0f");
5339 accopWithMisc ("lsra", "");
5340 /* total: 6 cycles, 4 bytes */
5343 accopWithMisc ("rola", "");
5344 accopWithMisc ("rola", "");
5345 accopWithMisc ("rola", "");
5346 accopWithMisc ("and", "#0x03");
5347 /* total: 5 cycles, 5 bytes */
5350 accopWithMisc ("rola", "");
5351 accopWithMisc ("clra", "");
5352 accopWithMisc ("rola", "");
5353 /* total: 3 cycles, 3 bytes */
5357 /* lsra is only 1 cycle and byte, so an unrolled loop is often */
5358 /* the fastest (shCount<6) and shortest (shCount<4). */
5359 for (i=0;i<shCount;i++)
5360 accopWithMisc ("lsra", "");
5364 /*-----------------------------------------------------------------*/
5365 /* XAccLsh - left shift register pair XA by known count */
5366 /*-----------------------------------------------------------------*/
5368 XAccLsh (int shCount)
5372 shCount &= 0x000f; // shCount : 0..15
5377 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5378 loadRegFromConst (hc08_reg_a, zero);
5382 /* if we can beat 2n cycles or bytes for some special case, do it here */
5386 /* bytes cycles reg x reg a carry
5387 ** abcd efgh ijkl mnop ?
5388 ** lsrx 1 1 0abc defg ijkl mnop h
5389 ** rora 1 1 0abc defg hijk lmno p
5390 ** tax 1 1 hijk lmno hijk lmno p
5391 ** clra 1 1 hijk lmno 0000 0000 p
5392 ** rora 1 1 hijk lmno p000 0000 0
5393 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5395 rmwWithReg ("lsr", hc08_reg_x);
5396 rmwWithReg ("ror", hc08_reg_a);
5397 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5398 loadRegFromConst (hc08_reg_a, zero);
5399 rmwWithReg ("ror", hc08_reg_a);
5406 /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often */
5407 /* the fastest and shortest. */
5408 for (i=0;i<shCount;i++)
5410 rmwWithReg ("lsl", hc08_reg_a);
5411 rmwWithReg ("rol", hc08_reg_x);
5415 /*-----------------------------------------------------------------*/
5416 /* XAccSRsh - signed right shift register pair XA by known count */
5417 /*-----------------------------------------------------------------*/
5419 XAccSRsh (int shCount)
5423 shCount &= 0x000f; // shCount : 0..7
5425 /* if we can beat 2n cycles or bytes for some special case, do it here */
5429 /* bytes cycles reg x reg a carry
5430 ** abcd efgh ijkl mnop ?
5431 ** lslx 1 1 bcde fgh0 ijkl mnop a
5432 ** clra 1 1 bcde fgh0 0000 0000 a
5433 ** rola 1 1 bcde fgh0 0000 000a 0
5434 ** nega 1 1 bcde fgh0 aaaa aaaa a
5435 ** tax 1 1 aaaa aaaa aaaa aaaa a
5436 ** total: 5 cycles, 5 bytes
5438 rmwWithReg ("lsl", hc08_reg_x);
5439 loadRegFromConst (hc08_reg_a, zero);
5440 rmwWithReg ("rol", hc08_reg_a);
5441 rmwWithReg ("neg", hc08_reg_a);
5442 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5452 /* bytes cycles reg x reg a carry
5453 ** abcd efgh ijkl mnop ?
5454 ** txa 1 1 abcd efgh abcd efgh ?
5455 ** (AccSRsh) <8 <8 abcd efgh LSBresult ?
5456 ** lsla 1 1 abcd efgh ???? ???? a
5457 ** clrx 1 1 0000 0000 ???? ???? a
5458 ** rolx 1 1 0000 000a ???? ???? 0
5459 ** negx 1 1 aaaa aaaa ???? ???? a
5460 ** rora 1 1 aaaa aaaa LSBresult 0
5461 ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
5463 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5464 AccSRsh (shCount-8);
5465 rmwWithReg ("lsl", hc08_reg_a);
5466 loadRegFromConst (hc08_reg_x, zero);
5467 rmwWithReg ("rol", hc08_reg_x);
5468 rmwWithReg ("neg", hc08_reg_x);
5469 rmwWithReg ("ror", hc08_reg_a);
5476 /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often */
5477 /* the fastest and shortest. */
5478 for (i=0;i<shCount;i++)
5480 rmwWithReg ("asr", hc08_reg_x);
5481 rmwWithReg ("ror", hc08_reg_a);
5485 /*-----------------------------------------------------------------*/
5486 /* XAccRsh - right shift register pair XA by known count */
5487 /*-----------------------------------------------------------------*/
5489 XAccRsh (int shCount, bool sign)
5499 shCount &= 0x000f; // shCount : 0..f
5501 /* if we can beat 2n cycles or bytes for some special case, do it here */
5505 /* bytes cycles reg x reg a carry
5506 ** abcd efgh ijkl mnop ?
5507 ** clra 1 1 abcd efgh 0000 0000 a
5508 ** lslx 1 1 bcde fgh0 0000 0000 a
5509 ** rola 1 1 bcde fgh0 0000 000a 0
5510 ** clrx 1 1 0000 0000 0000 000a 0
5511 ** total: 4 cycles, 4 bytes
5513 loadRegFromConst (hc08_reg_x, zero);
5514 rmwWithReg ("lsl", hc08_reg_x);
5515 rmwWithReg ("rol", hc08_reg_a);
5516 loadRegFromConst (hc08_reg_a, zero);
5520 /* bytes cycles reg x reg a carry
5521 ** abcd efgh ijkl mnop ?
5522 ** clra 1 1 abcd efgh 0000 0000 a
5523 ** lslx 1 1 bcde fgh0 0000 0000 a
5524 ** rola 1 1 bcde fgh0 0000 000a 0
5525 ** lslx 1 1 cdef gh00 0000 000a b
5526 ** rola 1 1 cdef gh00 0000 00ab 0
5527 ** clrx 1 1 0000 0000 0000 00ab 0
5528 ** total: 6 cycles, 6 bytes
5530 loadRegFromConst (hc08_reg_x, zero);
5531 rmwWithReg ("lsl", hc08_reg_x);
5532 rmwWithReg ("rol", hc08_reg_a);
5533 rmwWithReg ("lsl", hc08_reg_x);
5534 rmwWithReg ("rol", hc08_reg_a);
5535 loadRegFromConst (hc08_reg_a, zero);
5544 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5545 AccRsh (shCount-8, FALSE);
5546 loadRegFromConst (hc08_reg_x, zero);
5550 /* bytes cycles reg x reg a carry
5551 ** abcd efgh ijkl mnop ?
5552 ** lsla 1 1 abcd efgh jklm nop0 i
5553 ** txa 1 1 abcd efgh abcd efgh i
5554 ** rola 1 1 abcd efgh bcde fghi a
5555 ** clrx 1 1 0000 0000 bcde fghi a
5556 ** rolx 1 1 0000 000a bcde fghi 0
5557 ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
5559 rmwWithReg ("lsl", hc08_reg_a);
5560 transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
5561 rmwWithReg ("rol", hc08_reg_a);
5562 loadRegFromConst (hc08_reg_x, zero);
5563 rmwWithReg ("rol", hc08_reg_x);
5566 /* bytes cycles reg x reg a carry
5567 ** abcd efgh ijkl mnop ?
5568 ** lsla 1 1 abcd efgh jklm nop0 i
5569 ** rolx 1 1 bcde fghi jklm nop0 a
5570 ** rola 1 1 bcde fghi klmn op0a j
5571 ** rolx 1 1 cdef ghij klmn op0a b
5572 ** rola 1 1 cdef ghij lmno p0ab k
5573 ** and #3 2 2 cdef ghij 0000 00ab k
5574 ** psha 1 2 cdef ghij 0000 00ab k
5575 ** txa 1 1 cdef ghij cdef ghij k
5576 ** pula 1 2 0000 00ab cdef ghij k
5577 ** total: 12 cycles, 10 bytes (beats 12 bytes)
5583 /* lsrx/rora is only 2 cycles and bytes, so an unrolled loop is often */
5584 /* the fastest and shortest. */
5585 for (i=0;i<shCount;i++)
5587 rmwWithReg ("lsr", hc08_reg_x);
5588 rmwWithReg ("ror", hc08_reg_a);
5595 /*-----------------------------------------------------------------*/
5596 /* shiftR1Left2Result - shift right one byte from left to result */
5597 /*-----------------------------------------------------------------*/
5599 shiftR1Left2Result (operand * left, int offl,
5600 operand * result, int offr,
5601 int shCount, int sign)
5603 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5604 /* shift right accumulator */
5605 AccRsh (shCount, sign);
5606 storeRegToAop (hc08_reg_a, AOP (result), offr);
5610 /*-----------------------------------------------------------------*/
5611 /* shiftL1Left2Result - shift left one byte from left to result */
5612 /*-----------------------------------------------------------------*/
5614 shiftL1Left2Result (operand * left, int offl,
5615 operand * result, int offr, int shCount)
5617 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5618 /* shift left accumulator */
5620 storeRegToAop (hc08_reg_a, AOP (result), offr);
5623 /*-----------------------------------------------------------------*/
5624 /* movLeft2Result - move byte from left to result */
5625 /*-----------------------------------------------------------------*/
5627 movLeft2Result (operand * left, int offl,
5628 operand * result, int offr, int sign)
5630 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5632 transferAopAop (AOP (left), offl, AOP (result), offr);
5637 /*-----------------------------------------------------------------*/
5638 /* shiftL2Left2Result - shift left two bytes from left to result */
5639 /*-----------------------------------------------------------------*/
5641 shiftL2Left2Result (operand * left, int offl,
5642 operand * result, int offr, int shCount)
5645 bool needpula = FALSE;
5646 bool needpulx = FALSE;
5648 if (!IS_AOP_XA (AOP (left)) && !IS_AOP_A (AOP (left)))
5649 needpula = pushRegIfUsed (hc08_reg_a);
5652 if (!IS_AOP_XA (AOP (left)))
5653 needpulx = pushRegIfUsed (hc08_reg_x);
5657 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5662 rmwWithReg ("lsr", hc08_reg_x);
5663 rmwWithReg ("ror", hc08_reg_a);
5664 transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
5665 rmwWithReg ("clr", hc08_reg_a);
5666 rmwWithReg ("ror", hc08_reg_a);
5669 for (i=0; i<shCount; i++)
5671 rmwWithReg ("lsl", hc08_reg_a);
5672 rmwWithReg ("rol", hc08_reg_x);
5675 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5677 pullOrFreeReg (hc08_reg_x, needpulx);
5678 pullOrFreeReg (hc08_reg_a, needpula);
5684 /*-----------------------------------------------------------------*/
5685 /* shiftR2Left2Result - shift right two bytes from left to result */
5686 /*-----------------------------------------------------------------*/
5688 shiftR2Left2Result (operand * left, int offl,
5689 operand * result, int offr,
5690 int shCount, int sign)
5693 bool needpula = FALSE;
5694 bool needpulx = FALSE;
5696 needpula = pushRegIfUsed (hc08_reg_a);
5697 needpulx = pushRegIfUsed (hc08_reg_x);
5699 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
5700 for (i=0; i<shCount; i++)
5703 rmwWithReg ("asr", hc08_reg_x);
5705 rmwWithReg ("lsr", hc08_reg_x);
5706 rmwWithReg ("ror", hc08_reg_a);
5708 storeRegToAop (hc08_reg_xa, AOP (result), offl);
5710 pullOrFreeReg (hc08_reg_x, needpulx);
5711 pullOrFreeReg (hc08_reg_a, needpula);
5716 /*-----------------------------------------------------------------*/
5717 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5718 /*-----------------------------------------------------------------*/
5720 shiftLLeftOrResult (operand * left, int offl,
5721 operand * result, int offr, int shCount)
5723 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5724 /* shift left accumulator */
5726 /* or with result */
5727 accopWithAop ("ora", AOP (result), offr);
5728 /* back to result */
5729 storeRegToAop (hc08_reg_a, AOP (result), offr);
5730 hc08_freeReg (hc08_reg_a);
5734 /*-----------------------------------------------------------------*/
5735 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5736 /*-----------------------------------------------------------------*/
5738 shiftRLeftOrResult (operand * left, int offl,
5739 operand * result, int offr, int shCount)
5741 loadRegFromAop (hc08_reg_a, AOP (left), offl);
5742 /* shift left accumulator */
5743 AccRsh (shCount, FALSE);
5744 /* or with result */
5745 accopWithAop ("ora", AOP (result), offr);
5746 /* back to result */
5747 storeRegToAop (hc08_reg_a, AOP (result), offr);
5748 hc08_freeReg (hc08_reg_a);
5751 /*-----------------------------------------------------------------*/
5752 /* genlshOne - left shift a one byte quantity by known count */
5753 /*-----------------------------------------------------------------*/
5755 genlshOne (operand * result, operand * left, int shCount)
5757 D(emitcode ("; genlshOne",""));
5759 shiftL1Left2Result (left, LSB, result, LSB, shCount);
5762 /*-----------------------------------------------------------------*/
5763 /* genlshTwo - left shift two bytes by known amount != 0 */
5764 /*-----------------------------------------------------------------*/
5766 genlshTwo (operand * result, operand * left, int shCount)
5770 D(emitcode ("; genlshTwo",""));
5773 size = getDataSize (result);
5775 /* if shCount >= 8 */
5782 loadRegFromAop (hc08_reg_a, AOP (left), 0);
5784 storeRegToAop (hc08_reg_a, AOP (result), 1);
5786 storeConstToAop(zero, AOP (result), LSB);
5789 /* 1 <= shCount <= 7 */
5792 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
5794 storeRegToFullAop (hc08_reg_xa, AOP (result), 0);
5798 /*-----------------------------------------------------------------*/
5799 /* shiftLLong - shift left one long from left to result */
5800 /* offl = LSB or MSB16 */
5801 /*-----------------------------------------------------------------*/
5803 shiftLLong (operand * left, operand * result, int offr)
5806 // int size = AOP_SIZE (result);
5808 bool needpula = FALSE;
5809 bool needpulx = FALSE;
5811 needpula = pushRegIfUsed (hc08_reg_a);
5812 needpulx = pushRegIfUsed (hc08_reg_x);
5814 loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
5815 rmwWithReg ("lsl", hc08_reg_a);
5816 rmwWithReg ("rol", hc08_reg_x);
5817 storeRegToAop (hc08_reg_xa, AOP (result), offr);
5821 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
5822 rmwWithReg ("rol", hc08_reg_a);
5823 rmwWithReg ("rol", hc08_reg_x);
5824 storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
5826 else if (offr==MSB16)
5828 loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
5829 rmwWithReg ("rol", hc08_reg_a);
5830 storeRegToAop (hc08_reg_a, AOP (result), offr+2);
5833 pullOrFreeReg (hc08_reg_x, needpulx);
5834 pullOrFreeReg (hc08_reg_a, needpula);
5837 /*-----------------------------------------------------------------*/
5838 /* genlshFour - shift four byte by a known amount != 0 */
5839 /*-----------------------------------------------------------------*/
5841 genlshFour (operand * result, operand * left, int shCount)
5845 D(emitcode ("; genlshFour",""));
5847 size = AOP_SIZE (result);
5849 /* TODO: deal with the &result == &left case */
5851 /* if shifting more that 3 bytes */
5856 /* lowest order of left goes to the highest
5857 order of the destination */
5858 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
5860 movLeft2Result (left, LSB, result, MSB32, 0);
5861 storeConstToAop (zero, AOP (result), LSB);
5862 storeConstToAop (zero, AOP (result), MSB16);
5863 storeConstToAop (zero, AOP (result), MSB24);
5867 /* more than two bytes */
5868 else if (shCount >= 16)
5870 /* lower order two bytes goes to higher order two bytes */
5872 /* if some more remaining */
5874 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
5877 movLeft2Result (left, MSB16, result, MSB32, 0);
5878 movLeft2Result (left, LSB, result, MSB24, 0);
5880 storeConstToAop (zero, AOP (result), LSB);
5881 storeConstToAop (zero, AOP (result), MSB16);
5885 /* if more than 1 byte */
5886 else if (shCount >= 8)
5888 /* lower order three bytes goes to higher order three bytes */
5893 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5895 movLeft2Result (left, LSB, result, MSB16, 0);
5901 movLeft2Result (left, MSB24, result, MSB32, 0);
5902 movLeft2Result (left, MSB16, result, MSB24, 0);
5903 movLeft2Result (left, LSB, result, MSB16, 0);
5904 storeConstToAop (zero, AOP (result), LSB);
5906 else if (shCount == 1)
5907 shiftLLong (left, result, MSB16);
5910 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
5911 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
5912 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
5913 storeConstToAop (zero, AOP (result), LSB);
5918 /* 1 <= shCount <= 7 */
5919 else if (shCount <= 2)
5921 shiftLLong (left, result, LSB);
5923 shiftLLong (result, result, LSB);
5925 /* 3 <= shCount <= 7, optimize */
5928 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
5929 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
5930 shiftL2Left2Result (left, LSB, result, LSB, shCount);
5934 /*-----------------------------------------------------------------*/
5935 /* genLeftShiftLiteral - left shifting by known count */
5936 /*-----------------------------------------------------------------*/
5938 genLeftShiftLiteral (operand * left,
5943 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
5946 D(emitcode ("; genLeftShiftLiteral",""));
5948 freeAsmop (right, NULL, ic, TRUE);
5950 aopOp (left, ic, FALSE);
5951 aopOp (result, ic, FALSE);
5953 // size = getSize (operandType (result));
5954 size = AOP_SIZE (result);
5957 D(emitcode ("; shift left ", "result %d, left %d", size,
5964 transferAopAop( AOP(left), size, AOP(result), size);
5966 else if (shCount >= (size * 8))
5969 storeConstToAop (zero, AOP (result), size);
5976 genlshOne (result, left, shCount);
5980 genlshTwo (result, left, shCount);
5984 genlshFour (result, left, shCount);
5987 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
5988 "*** ack! mystery literal shift!\n");
5992 freeAsmop (left, NULL, ic, TRUE);
5993 freeAsmop (result, NULL, ic, TRUE);
5996 /*-----------------------------------------------------------------*/
5997 /* genLeftShift - generates code for left shifting */
5998 /*-----------------------------------------------------------------*/
6000 genLeftShift (iCode * ic)
6002 operand *left, *right, *result;
6004 symbol *tlbl, *tlbl1;
6009 D(emitcode ("; genLeftShift",""));
6011 right = IC_RIGHT (ic);
6012 left = IC_LEFT (ic);
6013 result = IC_RESULT (ic);
6015 aopOp (right, ic, FALSE);
6017 /* if the shift count is known then do it
6018 as efficiently as possible */
6019 if (AOP_TYPE (right) == AOP_LIT)
6021 genLeftShiftLiteral (left, right, result, ic);
6025 /* shift count is unknown then we have to form
6026 a loop get the loop count in A : Note: we take
6027 only the lower order byte since shifting
6028 more that 32 bits make no sense anyway, ( the
6029 largest size of an object can be only 32 bits ) */
6031 aopOp (left, ic, FALSE);
6032 aopOp (result, ic, FALSE);
6034 /* now move the left to the result if they are not the
6036 if (!sameRegs (AOP (left), AOP (result)))
6039 size = AOP_SIZE (result);
6043 transferAopAop (AOP (left), offset, AOP (result), offset);
6047 freeAsmop (left, NULL, ic, TRUE);
6049 tlbl = newiTempLabel (NULL);
6050 size = AOP_SIZE (result);
6052 tlbl1 = newiTempLabel (NULL);
6056 loadRegFromAop (reg, AOP (right), 0);
6057 freeAsmop (right, NULL, ic, TRUE);
6058 emitBranch ("beq", tlbl1);
6062 for (offset=0;offset<size;offset++)
6064 rmwWithAop (shift, AOP (result), offset);
6067 rmwWithReg ("dec", reg);
6068 emitBranch ("bne", tlbl);
6072 freeAsmop (result, NULL, ic, TRUE);
6075 /*-----------------------------------------------------------------*/
6076 /* genrshOne - right shift a one byte quantity by known count */
6077 /*-----------------------------------------------------------------*/
6079 genrshOne (operand * result, operand * left,
6080 int shCount, int sign)
6082 D(emitcode ("; genrshOne",""));
6084 loadRegFromAop (hc08_reg_a, AOP (left), 0);
6085 AccRsh (shCount, sign);
6086 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6089 /*-----------------------------------------------------------------*/
6090 /* genrshTwo - right shift two bytes by known amount != 0 */
6091 /*-----------------------------------------------------------------*/
6093 genrshTwo (operand * result, operand * left,
6094 int shCount, int sign)
6096 D(emitcode ("; genrshTwo",""));
6098 /* if shCount >= 8 */
6101 if (shCount || sign)
6103 loadRegFromAop (hc08_reg_a, AOP (left), 1);
6104 AccRsh (shCount-8, sign);
6105 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6109 transferAopAop (AOP (left), 1, AOP (result), 0);
6110 storeConstToAop (zero, AOP (result), 1);
6114 /* 1 <= shCount <= 7 */
6117 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6118 XAccRsh (shCount, sign);
6119 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6123 /*-----------------------------------------------------------------*/
6124 /* shiftRLong - shift right one long from left to result */
6125 /* offl = LSB or MSB16 */
6126 /*-----------------------------------------------------------------*/
6128 shiftRLong (operand * left, int offl,
6129 operand * result, int sign)
6132 // int size = AOP_SIZE (result);
6134 bool needpula = FALSE;
6135 bool needpulx = FALSE;
6137 needpula = pushRegIfUsed (hc08_reg_a);
6138 needpulx = pushRegIfUsed (hc08_reg_x);
6142 loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
6144 rmwWithReg ("asr", hc08_reg_x);
6146 rmwWithReg ("lsr", hc08_reg_x);
6147 rmwWithReg ("rol", hc08_reg_a);
6148 storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
6150 else if (offl==MSB16)
6152 loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
6154 rmwWithReg ("asr", hc08_reg_a);
6156 rmwWithReg ("lsr", hc08_reg_a);
6157 storeRegToAop (hc08_reg_a, AOP (result), MSB24);
6160 loadRegFromAop (hc08_reg_xa, AOP (left), offl);
6161 rmwWithReg ("ror", hc08_reg_x);
6162 rmwWithReg ("ror", hc08_reg_a);
6163 storeRegToAop (hc08_reg_xa, AOP (result), LSB);
6166 pullOrFreeReg (hc08_reg_x, needpulx);
6167 pullOrFreeReg (hc08_reg_a, needpula);
6170 /*-----------------------------------------------------------------*/
6171 /* genrshFour - shift four byte by a known amount != 0 */
6172 /*-----------------------------------------------------------------*/
6174 genrshFour (operand * result, operand * left,
6175 int shCount, int sign)
6177 /* TODO: handle cases where left == result */
6179 D(emitcode ("; genrshFour",""));
6181 /* if shifting more that 3 bytes */
6184 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6185 AccRsh (shCount-24, sign);
6186 storeRegToFullAop (hc08_reg_a, AOP (result), sign);
6189 else if (shCount >= 16)
6191 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6192 XAccRsh (shCount-16, sign);
6193 storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
6196 else if (shCount >= 8)
6199 shiftRLong (left, MSB16, result, sign);
6200 else if (shCount == 8)
6202 transferAopAop (AOP (left), 1, AOP (result), 0);
6203 transferAopAop (AOP (left), 2, AOP (result), 1);
6204 loadRegFromAop (hc08_reg_a, AOP (left), 3);
6205 storeRegToAop (hc08_reg_a, AOP (result), 2);
6206 storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
6208 else if (shCount == 9)
6210 shiftRLong (left, MSB16, result, sign);
6214 loadRegFromAop (hc08_reg_xa, AOP (left), 1);
6215 XAccRsh (shCount-8, FALSE);
6216 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6217 loadRegFromAop (hc08_reg_x, AOP (left), 3);
6218 loadRegFromConst (hc08_reg_a, zero);
6219 XAccRsh (shCount-8, sign);
6220 accopWithAop ("ora", AOP (result), 1);
6221 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6225 { /* 1 <= shCount <= 7 */
6228 shiftRLong (left, LSB, result, sign);
6232 loadRegFromAop (hc08_reg_xa, AOP (left), 0);
6233 XAccRsh (shCount, FALSE);
6234 storeRegToAop (hc08_reg_xa, AOP (result), 0);
6235 loadRegFromAop (hc08_reg_a, AOP (left), 2);
6237 accopWithAop ("ora", AOP (result), 1);
6238 storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
6239 loadRegFromAop (hc08_reg_xa, AOP (left), 2);
6240 XAccRsh (shCount, sign);
6241 storeRegToAop (hc08_reg_xa, AOP (result), 2);
6246 /*-----------------------------------------------------------------*/
6247 /* genRightShiftLiteral - right shifting by known count */
6248 /*-----------------------------------------------------------------*/
6250 genRightShiftLiteral (operand * left,
6256 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6259 D(emitcode ("; genRightShiftLiteral",""));
6261 freeAsmop (right, NULL, ic, TRUE);
6263 aopOp (left, ic, FALSE);
6264 aopOp (result, ic, FALSE);
6267 D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6271 size = getDataSize (left);
6272 /* test the LEFT size !!! */
6274 /* I suppose that the left size >= result size */
6277 size = getDataSize (result);
6279 transferAopAop (AOP (left), size, AOP(result), size);
6281 else if (shCount >= (size * 8))
6284 /* get sign in acc.7 */
6285 loadRegFromAop (hc08_reg_a, AOP (left), size -1);
6287 addSign (result, LSB, sign);
6294 genrshOne (result, left, shCount, sign);
6298 genrshTwo (result, left, shCount, sign);
6302 genrshFour (result, left, shCount, sign);
6308 freeAsmop (left, NULL, ic, TRUE);
6309 freeAsmop (result, NULL, ic, TRUE);
6313 /*-----------------------------------------------------------------*/
6314 /* genRightShift - generate code for right shifting */
6315 /*-----------------------------------------------------------------*/
6317 genRightShift (iCode * ic)
6319 operand *right, *left, *result;
6323 symbol *tlbl, *tlbl1;
6327 D(emitcode ("; genRightShift",""));
6329 /* if signed then we do it the hard way preserve the
6330 sign bit moving it inwards */
6331 retype = getSpec (operandType (IC_RESULT (ic)));
6332 sign = !SPEC_USIGN (retype);
6334 /* signed & unsigned types are treated the same : i.e. the
6335 signed is NOT propagated inwards : quoting from the
6336 ANSI - standard : "for E1 >> E2, is equivalent to division
6337 by 2**E2 if unsigned or if it has a non-negative value,
6338 otherwise the result is implementation defined ", MY definition
6339 is that the sign does not get propagated */
6341 right = IC_RIGHT (ic);
6342 left = IC_LEFT (ic);
6343 result = IC_RESULT (ic);
6345 aopOp (right, ic, FALSE);
6347 /* if the shift count is known then do it
6348 as efficiently as possible */
6349 if (AOP_TYPE (right) == AOP_LIT)
6351 genRightShiftLiteral (left, right, result, ic, sign);
6355 /* shift count is unknown then we have to form
6356 a loop get the loop count in X : Note: we take
6357 only the lower order byte since shifting
6358 more that 32 bits make no sense anyway, ( the
6359 largest size of an object can be only 32 bits ) */
6361 aopOp (left, ic, FALSE);
6362 aopOp (result, ic, FALSE);
6364 if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
6365 AOP (result) = forceStackedAop (AOP (result));
6367 size = AOP_SIZE (result);
6371 transferAopAop (AOP (left), offset, AOP (result), offset);
6375 tlbl = newiTempLabel (NULL);
6376 size = AOP_SIZE (result);
6378 tlbl1 = newiTempLabel (NULL);
6380 loadRegFromAop (hc08_reg_x, AOP (right), 0);
6381 emitcode ("tstx", "");
6382 emitcode ("beq", "%05d$", tlbl1->key + 100);
6383 emitcode ("", "%05d$:", tlbl->key + 100);
6384 shift= sign ? "asr" : "lsr";
6385 for (offset=size-1;offset>=0;offset--)
6387 rmwWithAop (shift, AOP (result), offset);
6390 rmwWithReg ("dec", hc08_reg_x);
6391 emitcode ("bne","%05d$", tlbl->key + 100);
6392 emitcode ("", "%05d$:", tlbl1->key + 100);
6394 freeAsmop (result, NULL, ic, TRUE);
6395 freeAsmop (left, NULL, ic, TRUE);
6396 freeAsmop (right, NULL, ic, TRUE);
6399 /*-----------------------------------------------------------------*/
6400 /* genUnpackBits - generates code for unpacking bits */
6401 /*-----------------------------------------------------------------*/
6403 genUnpackBits (operand * result)
6405 int offset = 0; /* result byte offset */
6406 int rsize; /* result size */
6407 int rlen = 0; /* remaining bitfield length */
6408 sym_link *etype; /* bitfield type information */
6409 int blen; /* bitfield length */
6410 int bstr; /* bitfield starting bit within byte */
6412 D(emitcode ("; genUnpackBits",""));
6414 etype = getSpec (operandType (result));
6415 rsize = getSize (operandType (result));
6416 blen = SPEC_BLEN (etype);
6417 bstr = SPEC_BSTR (etype);
6419 /* If the bitfield length is less than a byte */
6422 emitcode ("lda", ",x");
6423 hc08_dirtyReg (hc08_reg_a, FALSE);
6424 AccRsh (bstr, FALSE);
6425 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
6426 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6430 /* Bit field did not fit in a byte. Copy all
6431 but the partial byte at the end. */
6432 for (rlen=blen;rlen>=8;rlen-=8)
6434 emitcode ("lda", ",x");
6435 hc08_dirtyReg (hc08_reg_a, FALSE);
6436 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6438 emitcode ("aix", "#1");
6441 /* Handle the partial byte at the end */
6444 emitcode ("lda", ",x");
6445 emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
6446 storeRegToAop (hc08_reg_a, AOP (result), offset++);
6454 storeConstToAop (zero, AOP (result), offset++);
6459 /*-----------------------------------------------------------------*/
6460 /* genDataPointerGet - generates code when ptr offset is known */
6461 /*-----------------------------------------------------------------*/
6463 genDataPointerGet (operand * left,
6467 int size, offset = 0;
6470 D(emitcode ("; genDataPointerGet",""));
6472 aopOp (result, ic, TRUE);
6473 size = AOP_SIZE (result);
6475 derefaop = aopDerefAop (AOP (left));
6476 freeAsmop (left, NULL, ic, TRUE);
6477 derefaop->size = size;
6481 transferAopAop(derefaop, offset, AOP (result), offset);
6485 freeAsmop (NULL, derefaop, ic, TRUE);
6486 freeAsmop (result, NULL, ic, TRUE);
6490 /*-----------------------------------------------------------------*/
6491 /* genNearPointerGet - emitcode for near pointer fetch */
6492 /*-----------------------------------------------------------------*/
6494 genNearPointerGet (operand * left,
6500 sym_link *retype = getSpec (operandType (result));
6502 D(emitcode ("; genNearPointerGet",""));
6504 aopOp (left, ic, FALSE);
6506 /* if left is rematerialisable and
6507 result is not bit variable type and
6508 the left is pointer to data space i.e
6509 lower 128 bytes of space */
6510 if ((AOP_TYPE (left) == AOP_IMMD)
6511 || (AOP_TYPE (left) == AOP_LIT)
6512 /* !IS_BITVAR (retype) */
6513 /* && DCL_TYPE (ltype) == POINTER */ )
6515 genDataPointerGet (left, result, ic);
6519 /* if the operand is already in hx
6520 then we do nothing else we move the value to hx */
6521 if (AOP_TYPE (left) != AOP_STR)
6523 /* if this is remateriazable */
6524 loadRegFromAop (hc08_reg_x, AOP (left), 0);
6525 loadRegFromConst (hc08_reg_h, zero);
6528 /* so hx now contains the address */
6529 aopOp (result, ic, FALSE);
6531 /* if bit then unpack */
6532 if (IS_BITVAR (retype))
6533 genUnpackBits (result);
6536 size = AOP_SIZE (result);
6541 accopWithMisc ("lda", ",x");
6544 rmwWithReg ("inc", hc08_reg_x);
6546 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6547 hc08_freeReg (hc08_reg_a);
6551 freeAsmop (left, NULL, ic, TRUE);
6552 freeAsmop (result, NULL, ic, TRUE);
6554 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6555 aopOp (IC_RESULT (pi), pi, FALSE);
6556 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6557 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6561 hc08_freeReg (hc08_reg_hx);
6565 /*-----------------------------------------------------------------*/
6566 /* genFarPointerGet - get value from far space */
6567 /*-----------------------------------------------------------------*/
6569 genFarPointerGet (operand * left,
6570 operand * result, iCode * ic, iCode * pi)
6573 sym_link *retype = getSpec (operandType (result));
6575 D(emitcode ("; genFarPointerGet",""));
6577 aopOp (left, ic, FALSE);
6579 /* if left is rematerialisable and
6580 result is not bit variable type and
6581 the left is pointer to data space i.e
6582 lower 128 bytes of space */
6583 if (AOP_TYPE (left) == AOP_IMMD &&
6585 /* && DCL_TYPE (ltype) == POINTER */ )
6587 genDataPointerGet (left, result, ic);
6591 /* if the operand is already in hx
6592 then we do nothing else we move the value to hx */
6593 if (AOP_TYPE (left) != AOP_STR)
6595 /* if this is remateriazable */
6596 loadRegFromAop (hc08_reg_hx, AOP (left), 0);
6599 /* so hx now contains the address */
6600 aopOp (result, ic, FALSE);
6602 /* if bit then unpack */
6603 if (IS_BITVAR (retype))
6604 genUnpackBits (result);
6607 size = AOP_SIZE (result);
6612 accopWithMisc ("lda", ",x");
6615 emitcode ("aix", "#1");
6616 hc08_dirtyReg (hc08_reg_hx, FALSE);
6618 storeRegToAop (hc08_reg_a, AOP (result), offset--);
6619 hc08_freeReg (hc08_reg_a);
6623 freeAsmop (left, NULL, ic, TRUE);
6624 freeAsmop (result, NULL, ic, TRUE);
6626 if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
6627 aopOp (IC_RESULT (pi), pi, FALSE);
6628 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6629 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6633 hc08_freeReg (hc08_reg_hx);
6639 /*-----------------------------------------------------------------*/
6640 /* genPointerGet - generate code for pointer get */
6641 /*-----------------------------------------------------------------*/
6643 genPointerGet (iCode * ic, iCode *pi)
6645 operand *left, *result;
6646 sym_link *type, *etype;
6649 D(emitcode ("; genPointerGet",""));
6651 left = IC_LEFT (ic);
6652 result = IC_RESULT (ic);
6654 /* depending on the type of pointer we need to
6655 move it to the correct pointer register */
6656 type = operandType (left);
6657 etype = getSpec (type);
6658 /* if left is of type of pointer then it is simple */
6659 if (IS_PTR (type) && !IS_FUNC (type->next))
6660 p_type = DCL_TYPE (type);
6663 /* we have to go by the storage class */
6664 p_type = PTR_TYPE (SPEC_OCLS (etype));
6667 /* special case when cast remat */
6668 if (p_type == GPOINTER && IS_SYMOP(left) && OP_SYMBOL(left)->remat &&
6669 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
6670 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
6671 type = operandType (left);
6672 p_type = DCL_TYPE (type);
6674 /* now that we have the pointer type we assign
6675 the pointer values */
6682 genNearPointerGet (left, result, ic, pi);
6688 genFarPointerGet (left, result, ic, pi);
6695 /*-----------------------------------------------------------------*/
6696 /* genPackBits - generates code for packed bit storage */
6697 /*-----------------------------------------------------------------*/
6699 genPackBits (sym_link * etype,
6702 int offset = 0; /* source byte offset */
6703 int rlen = 0; /* remaining bitfield length */
6704 int blen; /* bitfield length */
6705 int bstr; /* bitfield starting bit within byte */
6706 int litval; /* source literal value (if AOP_LIT) */
6707 unsigned char mask; /* bitmask within current byte */
6709 D(emitcode ("; genPackBits",""));
6711 blen = SPEC_BLEN (etype);
6712 bstr = SPEC_BSTR (etype);
6714 /* If the bitfield length is less than a byte */
6717 mask = ((unsigned char) (0xFF << (blen + bstr)) |
6718 (unsigned char) (0xFF >> (8 - bstr)));
6720 if (AOP_TYPE (right) == AOP_LIT)
6722 /* Case with a bitfield length <8 and literal source
6724 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6726 litval &= (~mask) & 0xff;
6728 emitcode ("lda", ",x");
6729 if ((mask|litval)!=0xff)
6730 emitcode ("and","#0x%02x", mask);
6732 emitcode ("ora","#0x%02x", litval);
6733 hc08_dirtyReg (hc08_reg_a, FALSE);
6734 emitcode ("sta", ",x");
6736 hc08_freeReg (hc08_reg_a);
6740 /* Case with a bitfield length < 8 and arbitrary source
6742 loadRegFromAop (hc08_reg_a, AOP (right), 0);
6743 /* shift and mask source value */
6745 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6746 hc08_dirtyReg (hc08_reg_a, FALSE);
6747 pushReg (hc08_reg_a, TRUE);
6749 emitcode ("lda", ",x");
6750 emitcode ("and", "#0x%02x", mask);
6751 emitcode ("ora", "1,s");
6752 emitcode ("sta", ",x");
6753 pullReg (hc08_reg_a);
6755 hc08_freeReg (hc08_reg_a);
6759 /* Bit length is greater than 7 bits. In this case, copy */
6760 /* all except the partial byte at the end */
6761 for (rlen=blen;rlen>=8;rlen-=8)
6763 if (AOP (right)->type == AOP_DIR)
6765 emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
6769 loadRegFromAop (hc08_reg_a, AOP (right), offset);
6770 emitcode ("sta", "%d,x", offset);
6775 /* If there was a partial byte at the end */
6778 mask = (((unsigned char) -1 << rlen) & 0xff);
6780 if (AOP_TYPE (right) == AOP_LIT)
6782 /* Case with partial byte and literal source
6784 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6785 litval >>= (blen-rlen);
6786 litval &= (~mask) & 0xff;
6787 emitcode ("lda", "%d,x", offset);
6788 hc08_dirtyReg (hc08_reg_a, FALSE);
6789 if ((mask|litval)!=0xff)
6790 emitcode ("and","#0x%02x", mask);
6792 emitcode ("ora","#0x%02x", litval);
6793 emitcode ("sta", "%d,x", offset);
6794 hc08_dirtyReg (hc08_reg_a, FALSE);
6795 hc08_freeReg (hc08_reg_a);
6799 /* Case with partial byte and arbitrary source
6801 loadRegFromAop (hc08_reg_a, AOP (right), offset++);
6802 emitcode ("and", "#0x%02x", (~mask) & 0xff);
6803 hc08_dirtyReg (hc08_reg_a, FALSE);
6804 pushReg (hc08_reg_a, TRUE);
6806 emitcode ("lda", ",x");
6807 emitcode ("and", "#0x%02x", mask);
6808 emitcode ("ora", "1,s");
6809 emitcode ("sta", ",x");
6810 pullReg (hc08_reg_a);
6813 hc08_freeReg (hc08_reg_a);
6816 /*-----------------------------------------------------------------*/
6817 /* genDataPointerSet - remat pointer to data space */
6818 /*-----------------------------------------------------------------*/
6820 genDataPointerSet (operand * right,
6824 int size, offset = 0;
6827 D(emitcode ("; genDataPointerSet",""));
6829 aopOp (right, ic, FALSE);
6830 size = AOP_SIZE (right);
6832 derefaop = aopDerefAop (AOP (result));
6833 freeAsmop (result, NULL, ic, TRUE);
6834 derefaop->size = size;
6838 transferAopAop (AOP (right), offset, derefaop, offset);
6842 freeAsmop (right, NULL, ic, TRUE);
6843 freeAsmop (NULL, derefaop, ic, TRUE);
6847 /*-----------------------------------------------------------------*/
6848 /* genNearPointerSet - emitcode for near pointer put */
6849 /*-----------------------------------------------------------------*/
6851 genNearPointerSet (operand * right,
6857 sym_link *retype = getSpec (operandType (right));
6858 sym_link *letype = getSpec (operandType (result));
6860 D(emitcode ("; genNearPointerSet",""));
6862 aopOp (result, ic, FALSE);
6864 /* if the result is rematerializable &
6865 in data space & not a bit variable */
6866 if (AOP_TYPE (result) == AOP_IMMD &&
6867 /* DCL_TYPE (ptype) == POINTER && */
6868 !IS_BITVAR (retype) &&
6869 !IS_BITVAR (letype))
6871 genDataPointerSet (right, result, ic);
6875 /* if the operand is already in hx
6876 then we do nothing else we move the value to hx */
6877 if (AOP_TYPE (result) != AOP_STR)
6879 loadRegFromAop (hc08_reg_x, AOP (result), 0);
6880 loadRegFromConst (hc08_reg_h, zero);
6882 /* so hx now contains the address */
6883 aopOp (right, ic, FALSE);
6885 /* if bit then unpack */
6886 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6887 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6890 size = AOP_SIZE (right);
6895 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6896 accopWithMisc ("sta", ",x");
6899 rmwWithReg ("inc", hc08_reg_x);
6901 hc08_freeReg (hc08_reg_a);
6905 freeAsmop (result, NULL, ic, TRUE);
6906 freeAsmop (right, NULL, ic, TRUE);
6908 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6909 aopOp (IC_RESULT (pi), pi, FALSE);
6910 storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
6911 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6915 hc08_freeReg (hc08_reg_hx);
6920 /*-----------------------------------------------------------------*/
6921 /* genFarPointerSet - set value from far space */
6922 /*-----------------------------------------------------------------*/
6924 genFarPointerSet (operand * right,
6925 operand * result, iCode * ic, iCode * pi)
6928 sym_link *retype = getSpec (operandType (right));
6929 sym_link *letype = getSpec (operandType (result));
6931 D(emitcode ("; genFarPointerSet",""));
6933 aopOp (result, ic, FALSE);
6935 /* if the result is rematerializable &
6936 in data space & not a bit variable */
6937 if (AOP_TYPE (result) == AOP_IMMD &&
6938 /* DCL_TYPE (ptype) == POINTER && */
6939 !IS_BITVAR (retype) &&
6940 !IS_BITVAR (letype))
6942 genDataPointerSet (right, result, ic);
6946 /* if the operand is already in hx
6947 then we do nothing else we move the value to hx */
6948 if (AOP_TYPE (result) != AOP_STR)
6950 loadRegFromAop (hc08_reg_hx, AOP (result), 0);
6952 /* so hx now contains the address */
6953 aopOp (right, ic, FALSE);
6955 /* if bit then unpack */
6956 if (IS_BITVAR (retype) || IS_BITVAR (letype))
6957 genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
6960 size = AOP_SIZE (right);
6965 loadRegFromAop (hc08_reg_a, AOP (right), offset--);
6966 accopWithMisc ("sta", ",x");
6969 emitcode ("aix", "#1");
6971 hc08_freeReg (hc08_reg_a);
6975 freeAsmop (result, NULL, ic, TRUE);
6976 freeAsmop (right, NULL, ic, TRUE);
6978 if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
6979 aopOp (IC_RESULT (pi), pi, FALSE);
6980 storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
6981 freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
6985 hc08_freeReg (hc08_reg_hx);
6991 /*-----------------------------------------------------------------*/
6992 /* genPointerSet - stores the value into a pointer location */
6993 /*-----------------------------------------------------------------*/
6995 genPointerSet (iCode * ic, iCode *pi)
6997 operand *right, *result;
6998 sym_link *type, *etype;
7001 D(emitcode ("; genPointerSet",""));
7003 right = IC_RIGHT (ic);
7004 result = IC_RESULT (ic);
7006 /* depending on the type of pointer we need to
7007 move it to the correct pointer register */
7008 type = operandType (result);
7009 etype = getSpec (type);
7010 /* if left is of type of pointer then it is simple */
7011 if (IS_PTR (type) && !IS_FUNC (type->next))
7013 p_type = DCL_TYPE (type);
7017 /* we have to go by the storage class */
7018 p_type = PTR_TYPE (SPEC_OCLS (etype));
7021 /* special case when cast remat */
7022 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
7023 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
7024 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
7025 type = operandType (result);
7026 p_type = DCL_TYPE (type);
7028 /* now that we have the pointer type we assign
7029 the pointer values */
7036 genNearPointerSet (right, result, ic, pi);
7042 genFarPointerSet (right, result, ic, pi);
7046 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7047 "genPointerSet: illegal pointer type");
7052 /*-----------------------------------------------------------------*/
7053 /* genIfx - generate code for Ifx statement */
7054 /*-----------------------------------------------------------------*/
7056 genIfx (iCode * ic, iCode * popIc)
7058 operand *cond = IC_COND (ic);
7061 D(emitcode ("; genIfx",""));
7063 aopOp (cond, ic, FALSE);
7065 /* get the value into acc */
7066 if (AOP_TYPE (cond) != AOP_CRY)
7067 asmopToBool (AOP (cond), FALSE);
7070 /* the result is now in the accumulator */
7071 freeAsmop (cond, NULL, ic, TRUE);
7073 /* if there was something to be popped then do it */
7077 /* if the condition is a bit variable */
7078 if (isbit && IS_ITEMP (cond) &&
7080 genIfxJump (ic, SPIL_LOC (cond)->rname);
7081 else if (isbit && !IS_ITEMP (cond))
7082 genIfxJump (ic, OP_SYMBOL (cond)->rname);
7084 genIfxJump (ic, "a");
7089 /*-----------------------------------------------------------------*/
7090 /* genAddrOf - generates code for address of */
7091 /*-----------------------------------------------------------------*/
7093 genAddrOf (iCode * ic)
7095 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
7098 D(emitcode ("; genAddrOf",""));
7100 aopOp (IC_RESULT (ic), ic, FALSE);
7102 /* if the operand is on the stack then we
7103 need to get the stack offset of this
7107 /* if it has an offset then we need to compute
7109 hc08_useReg (hc08_reg_hx);
7110 emitcode ("tsx", "");
7111 emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
7112 storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
7113 hc08_freeReg (hc08_reg_hx);
7118 /* object not on stack then we need the name */
7119 size = AOP_SIZE (IC_RESULT (ic));
7124 char s[SDCC_NAME_MAX+10];
7127 sprintf (s, "#%s", sym->rname);
7130 sprintf (s, "#>%s", sym->rname);
7133 sprintf (s, "#(%s >> %d)",
7137 storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
7141 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7145 /*-----------------------------------------------------------------*/
7146 /* genAssign - generate code for assignment */
7147 /*-----------------------------------------------------------------*/
7149 genAssign (iCode * ic)
7151 operand *result, *right;
7153 // unsigned long lit = 0L;
7155 D(emitcode("; genAssign",""));
7157 result = IC_RESULT (ic);
7158 right = IC_RIGHT (ic);
7160 /* if they are the same */
7161 if (operandsEqu (result, right)) {
7165 aopOp (right, ic, FALSE);
7166 aopOp (result, ic, TRUE);
7168 /* if they are the same registers */
7169 if (sameRegs (AOP (right), AOP (result)))
7172 if ((AOP_TYPE (right) == AOP_LIT)
7173 && (IS_AOP_HX(AOP(result))))
7175 loadRegFromAop(hc08_reg_hx, AOP (right), 0);
7180 size = AOP_SIZE (result);
7185 transferAopAop (AOP (right), offset, AOP (result), offset);
7190 freeAsmop (right, NULL, ic, TRUE);
7191 freeAsmop (result, NULL, ic, TRUE);
7194 /*-----------------------------------------------------------------*/
7195 /* genJumpTab - genrates code for jump table */
7196 /*-----------------------------------------------------------------*/
7198 genJumpTab (iCode * ic)
7203 D(emitcode ("; genJumpTab",""));
7205 aopOp (IC_JTCOND (ic), ic, FALSE);
7206 /* get the condition into accumulator */
7207 loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
7208 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
7209 /* multiply by three */
7210 pushReg (hc08_reg_a, FALSE);
7211 emitcode ("lsla", "");
7212 emitcode ("add","1,s");
7213 transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
7214 loadRegFromConst (hc08_reg_h, zero);
7215 pullReg (hc08_reg_a);
7217 jtab = newiTempLabel (NULL);
7218 emitcode ("jmp", "%05d$,x", jtab->key + 100);
7219 emitcode ("", "%05d$:", jtab->key + 100);
7220 /* now generate the jump labels */
7221 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
7222 jtab = setNextItem (IC_JTLABELS (ic)))
7223 emitcode ("jmp", "%05d$", jtab->key + 100);
7225 hc08_dirtyReg (hc08_reg_a, TRUE);
7226 hc08_dirtyReg (hc08_reg_hx, TRUE);
7229 /*-----------------------------------------------------------------*/
7230 /* genCast - gen code for casting */
7231 /*-----------------------------------------------------------------*/
7233 genCast (iCode * ic)
7235 operand *result = IC_RESULT (ic);
7236 sym_link *ctype = operandType (IC_LEFT (ic));
7237 sym_link *rtype = operandType (IC_RIGHT (ic));
7238 operand *right = IC_RIGHT (ic);
7241 D(emitcode("; genCast",""));
7243 /* if they are equivalent then do nothing */
7244 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
7247 aopOp (right, ic, FALSE);
7248 aopOp (result, ic, FALSE);
7251 /* if they are the same size : or less */
7252 if (AOP_SIZE (result) <= AOP_SIZE (right))
7255 /* if they are in the same place */
7257 if (sameRegs (AOP (right), AOP (result)))
7261 /* if they in different places then copy */
7262 size = AOP_SIZE (result);
7266 transferAopAop(AOP (right), offset, AOP (result), offset);
7273 /* if the result is of type pointer */
7278 sym_link *type = operandType (right);
7279 sym_link *etype = getSpec (type);
7281 /* pointer to generic pointer */
7282 if (IS_GENPTR (ctype))
7285 p_type = DCL_TYPE (type);
7288 if (SPEC_SCLS(etype)==S_REGISTER) {
7289 // let's assume it is a generic pointer
7292 /* we have to go by the storage class */
7293 p_type = PTR_TYPE (SPEC_OCLS (etype));
7297 /* the first two bytes are known */
7298 size = GPTRSIZE - 1;
7302 transferAopAop(AOP (right), offset, AOP (result), offset);
7305 /* the last byte depending on type */
7308 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
7313 // pointerTypeToGPByte will have bitched.
7317 sprintf(gpValStr, "#0x%d", gpVal);
7318 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
7324 /* just copy the pointers */
7325 size = AOP_SIZE (result);
7329 transferAopAop(AOP (right), offset, AOP (result), offset);
7335 /* so we now know that the size of destination is greater
7336 than the size of the source */
7337 /* we move to result for the size of source */
7338 size = AOP_SIZE (right);
7342 transferAopAop(AOP (right), offset, AOP (result), offset);
7346 /* now depending on the sign of the source && destination */
7347 size = AOP_SIZE (result) - AOP_SIZE (right);
7348 /* if unsigned or not an integral type */
7349 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
7352 storeConstToAop (zero, AOP (result), offset++);
7356 /* we need to extend the sign :{ */
7357 loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
7358 accopWithMisc ("rola", "");
7359 accopWithMisc ("clra", "");
7360 accopWithMisc ("sbc", zero);
7362 storeRegToAop (hc08_reg_a, AOP (result), offset++);
7365 /* we are done hurray !!!! */
7368 freeAsmop (right, NULL, ic, TRUE);
7369 freeAsmop (result, NULL, ic, TRUE);
7373 /*-----------------------------------------------------------------*/
7374 /* genDjnz - generate decrement & jump if not zero instrucion */
7375 /*-----------------------------------------------------------------*/
7377 genDjnz (iCode * ic, iCode * ifx)
7383 D(emitcode ("; genDjnz",""));
7385 /* if the if condition has a false label
7386 then we cannot save */
7390 /* if the minus is not of the form
7392 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
7393 !IS_OP_LITERAL (IC_RIGHT (ic)))
7396 if (operandLitValue (IC_RIGHT (ic)) != 1)
7399 /* dbnz doesn't support extended mode */
7400 if (isOperandInFarSpace (IC_RESULT (ic)))
7403 /* if the size of this greater than one then no
7405 // if (getSize (operandType (IC_RESULT (ic))) > 1)
7407 aopOp (IC_RESULT (ic), ic, FALSE);
7408 if (AOP_SIZE (IC_RESULT (ic))>1)
7410 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7414 /* otherwise we can save BIG */
7415 lbl = newiTempLabel (NULL);
7416 lbl1 = newiTempLabel (NULL);
7419 emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
7422 emitBranch ("bra", lbl1);
7424 emitBranch ("jmp", IC_TRUE (ifx));
7427 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7432 /*-----------------------------------------------------------------*/
7433 /* genReceive - generate code for a receive iCode */
7434 /*-----------------------------------------------------------------*/
7436 genReceive (iCode * ic)
7440 D(emitcode ("; genReceive",""));
7442 aopOp (IC_RESULT (ic), ic, FALSE);
7443 size = AOP_SIZE (IC_RESULT (ic));
7448 transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
7449 AOP (IC_RESULT (ic)), offset);
7450 if (hc08_aop_pass[offset]->type == AOP_REG)
7451 hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
7456 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7459 /*-----------------------------------------------------------------*/
7460 /* genDummyRead - generate code for dummy read of volatiles */
7461 /*-----------------------------------------------------------------*/
7463 genDummyRead (iCode * ic)
7468 D(emitcode("; genDummyRead",""));
7471 if (op && IS_SYMOP (op))
7474 aopOp (op, ic, FALSE);
7476 size = AOP_SIZE (op);
7481 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7482 hc08_freeReg (hc08_reg_a);
7486 freeAsmop (op, NULL, ic, TRUE);
7489 if (op && IS_SYMOP (op))
7492 aopOp (op, ic, FALSE);
7494 size = AOP_SIZE (op);
7499 loadRegFromAop (hc08_reg_a, AOP (op), offset);
7500 hc08_freeReg (hc08_reg_a);
7504 freeAsmop (op, NULL, ic, TRUE);
7508 /*-----------------------------------------------------------------*/
7509 /* genCritical - generate code for start of a critical sequence */
7510 /*-----------------------------------------------------------------*/
7512 genCritical (iCode *ic)
7514 D(emitcode("; genCritical",""));
7517 aopOp (IC_RESULT (ic), ic, TRUE);
7519 emitcode ("tpa", "");
7520 hc08_dirtyReg (hc08_reg_a, FALSE);
7521 emitcode ("sei", "");
7524 storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), 0);
7526 pushReg (hc08_reg_a, FALSE);
7528 hc08_freeReg (hc08_reg_a);
7530 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
7533 /*-----------------------------------------------------------------*/
7534 /* genEndCritical - generate code for end of a critical sequence */
7535 /*-----------------------------------------------------------------*/
7537 genEndCritical (iCode *ic)
7539 D(emitcode("; genEndCritical",""));
7543 aopOp (IC_RIGHT (ic), ic, FALSE);
7544 loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (ic)), 0);
7545 emitcode ("tap", "");
7546 hc08_freeReg (hc08_reg_a);
7547 freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
7551 pullReg (hc08_reg_a);
7552 emitcode ("tap", "");
7557 /*-----------------------------------------------------------------*/
7558 /* genhc08Code - generate code for HC08 based controllers */
7559 /*-----------------------------------------------------------------*/
7561 genhc08Code (iCode * lic)
7566 lineHead = lineCurr = NULL;
7568 /* print the allocation information */
7569 if (allocInfo && currFunc)
7570 printAllocInfo (currFunc, codeOutFile);
7571 /* if debug information required */
7572 if (options.debug && currFunc)
7574 debugFile->writeFunction(currFunc);
7576 if (IS_STATIC (currFunc->etype))
7577 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
7579 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
7582 /* stack pointer name */
7583 if (options.useXstack)
7588 hc08_aop_pass[0] = newAsmop (AOP_REG);
7589 hc08_aop_pass[0]->size=1;
7590 hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
7591 hc08_aop_pass[1] = newAsmop (AOP_REG);
7592 hc08_aop_pass[1]->size=1;
7593 hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
7594 hc08_aop_pass[2] = newAsmop (AOP_DIR);
7595 hc08_aop_pass[2]->size=1;
7596 hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
7597 hc08_aop_pass[3] = newAsmop (AOP_DIR);
7598 hc08_aop_pass[3]->size=1;
7599 hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
7601 for (ic = lic; ic; ic = ic->next)
7603 _G.current_iCode = ic;
7605 if (ic->lineno && cln != ic->lineno)
7610 emitcode ("", "C$%s$%d$%d$%d ==.",
7611 FileBaseName (ic->filename), ic->lineno,
7612 ic->level, ic->block);
7615 if (!options.noCcodeInAsm) {
7616 emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
7617 printCLine(ic->filename, ic->lineno));
7621 if (options.iCodeInAsm) {
7625 for (i=0; i<6; i++) {
7626 sprintf (®sInUse[i],
7627 "%c", ic->riu & (1<<i) ? i+'0' : '-');
7630 emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
7632 /* if the result is marked as
7633 spilt and rematerializable or code for
7634 this has already been generated then
7636 if (resultRemat (ic) || ic->generated)
7644 for (i=A_IDX;i<=XA_IDX;i++)
7646 reg = hc08_regWithIdx(i);
7648 emitcode("","; %s = %s offset %d", reg->name,
7649 aopName(reg->aop), reg->aopofs);
7652 if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
7654 sym = OP_SYMBOL (IC_LEFT (ic));
7655 if (sym->accuse == ACCUSE_HX)
7657 hc08_reg_h->isFree = FALSE;
7658 hc08_reg_x->isFree = FALSE;
7660 else if (sym->accuse == ACCUSE_XA)
7662 hc08_reg_a->isFree = FALSE;
7664 hc08_reg_x->isFree = FALSE;
7667 if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
7669 sym = OP_SYMBOL (IC_RIGHT (ic));
7670 if (sym->accuse == ACCUSE_HX)
7672 hc08_reg_h->isFree = FALSE;
7673 hc08_reg_x->isFree = FALSE;
7675 else if (sym->accuse == ACCUSE_XA)
7677 hc08_reg_a->isFree = FALSE;
7679 hc08_reg_x->isFree = FALSE;
7684 /* depending on the operation */
7704 /* IPOP happens only when trying to restore a
7705 spilt live range, if there is an ifx statement
7706 following this pop then the if statement might
7707 be using some of the registers being popped which
7708 would destory the contents of the register so
7709 we need to check for this condition and handle it */
7711 ic->next->op == IFX &&
7712 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
7713 genIfx (ic->next, ic);
7731 genEndFunction (ic);
7747 if (!genPointerGetSetOfs (ic))
7752 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
7769 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
7773 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
7780 /* note these two are xlated by algebraic equivalence
7781 during parsing SDCC.y */
7782 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
7783 "got '>=' or '<=' shouldn't have come here");
7787 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
7799 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
7803 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
7807 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
7834 case GET_VALUE_AT_ADDRESS:
7835 genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
7839 if (POINTER_SET (ic))
7840 genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
7866 addSet (&_G.sendSet, ic);
7869 case DUMMY_READ_VOLATILE:
7878 genEndCritical (ic);
7889 if (!hc08_reg_a->isFree)
7890 D(emitcode("","; forgot to free a"));
7891 if (!hc08_reg_x->isFree)
7892 D(emitcode("","; forgot to free x"));
7893 if (!hc08_reg_h->isFree)
7894 D(emitcode("","; forgot to free h"));
7895 if (!hc08_reg_hx->isFree)
7896 D(emitcode("","; forgot to free hx"));
7897 if (!hc08_reg_xa->isFree)
7898 D(emitcode("","; forgot to free xa"));
7902 /* now we are ready to call the
7903 peep hole optimizer */
7904 if (!options.nopeep)
7905 peepHole (&lineHead);
7907 /* now do the actual printing */
7908 printLine (lineHead, codeOutFile);