1 /*-------------------------------------------------------------------------
2 SDCCgen51.c - source file for code generation for 8051
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
5 and - Jean-Louis VERN.jlvern@writeme.com (1999)
6 Bug Fixes - Wojciech Stryjewski wstryj1@tiger.lsu.edu (1999 v2.1.9a)
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 In other words, you are welcome to use, share and improve this program.
23 You are forbidden to forbid anyone else to use, share and improve
24 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
35 #include "SDCCglobl.h"
38 #ifdef HAVE_SYS_ISA_DEFS_H
39 #include <sys/isa_defs.h>
41 #ifdef HAVE_MACHINE_ENDIAN_H
42 #include <machine/endian.h>
47 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
48 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
49 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
56 #include "SDCCpeeph.h"
60 #if defined(__BORLANDC__) || defined(_MSC_VER)
61 #define STRCASECMP stricmp
63 #define STRCASECMP strcasecmp
68 /* this is the down and dirty file with all kinds of
69 kludgy & hacky stuff. This is what it is all about
70 CODE GENERATION for a specific MCU . some of the
71 routines may be reusable, will have to see */
82 extern int xa51_ptrRegReq;
83 extern int xa51_nRegs;
84 extern FILE *codeOutFile;
86 static lineNode *lineHead = NULL;
87 static lineNode *lineCurr = NULL;
94 static char *MOV="mov";
95 static char *MOVB="mov.b";
96 static char *MOVW="mov.w";
97 static char *MOVC="movc";
99 static char *R1L="r1l";
100 static char *R1="r1";
102 void bailOut (char *mesg) {
103 fprintf (stderr, "%s: bailing out\n", mesg);
107 /*-----------------------------------------------------------------*/
108 /* emitcode - writes the code into a file : for now it is simple */
109 /*-----------------------------------------------------------------*/
110 static void emitcode (char *inst, char *fmt,...) {
112 char lb[INITIAL_INLINEASM];
120 sprintf (lb, "%s\t", inst);
122 sprintf (lb, "%s", inst);
123 vsprintf (lb + (strlen (lb)), fmt, ap);
126 vsprintf (lb, fmt, ap);
128 while (isspace ((int)*lbp))
132 lineCurr = (lineCurr ?
133 connectLine (lineCurr, newLineNode (lb)) :
134 (lineHead = newLineNode (lb)));
135 lineCurr->isInline = _G.inLine;
136 lineCurr->isDebug = _G.debugLine;
140 char *getStackOffset(int stack) {
141 static char gsoBuf[1024];
142 sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
143 FUNC_ISISR(currFunc->type) ?
144 port->stack.isr_overhead : port->stack.call_overhead,
149 /*-----------------------------------------------------------------*/
150 /* newAsmop - creates a new asmOp */
151 /*-----------------------------------------------------------------*/
153 newAsmop (short type)
157 aop = Safe_calloc (1, sizeof (asmop));
162 char *aopTypeName(asmop *aop) {
165 case AOP_LIT: return "lit";
166 case AOP_REG: return "reg";
167 case AOP_DIR: return "dir";
168 case AOP_FAR: return "far";
169 case AOP_CODE: return "code";
170 case AOP_GPTR: return "gptr";
171 case AOP_STK: return "stack";
172 case AOP_IMMD: return "imm";
173 case AOP_BIT: return "bit";
178 /*-----------------------------------------------------------------*/
179 /* aopForSym - for a true symbol */
180 /*-----------------------------------------------------------------*/
181 static asmop *aopForSym(symbol *sym,
182 bool canUsePointer, bool canUseOffset) {
186 sym->aop = aop = newAsmop(0);
187 size=aop->size=getSize(sym->type);
189 // if the sym has registers
190 if (sym->nRegs && sym->regs[0]) {
192 sprintf (aop->name[0], sym->regs[0]->name);
194 sprintf (aop->name[1], sym->regs[1]->name);
201 if (!canUsePointer || !canUseOffset) {
206 emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
207 sprintf (aop->name[0], "r0l");
210 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
211 sprintf (aop->name[0], "r0");
214 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
215 sprintf (aop->name[0], "r0");
216 emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
217 sprintf (aop->name[1], "r1l");
220 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
221 sprintf (aop->name[0], "r0");
222 emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
223 sprintf (aop->name[1], "r1");
228 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
230 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
235 // if it has a spillLoc
236 if (sym->usl.spillLoc) {
237 return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
241 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
243 sprintf (aop->name[0], sym->rname);
247 // if in direct space
248 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
250 sprintf (aop->name[0], sym->rname);
252 sprintf (aop->name[1], "%s+2", sym->rname);
258 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
259 if (!canUsePointer) {
264 emitcode (MOV, "r0,#%s", sym->rname);
265 emitcode (MOVC, "r0l,[r0]");
266 sprintf (aop->name[0], "r0l");
269 emitcode (MOV, "r0,#%s", sym->rname);
270 emitcode (MOVC, "r0,[r0]");
271 sprintf (aop->name[0], "r0");
274 emitcode (MOV, "r0,#%s", sym->rname);
275 emitcode (MOVC, "r1l,[r0+2]");
276 sprintf (aop->name[1], "r1l");
277 emitcode (MOV, "r0,[r0]");
278 sprintf (aop->name[0], "r0");
281 emitcode (MOV, "r0,#%s", sym->rname);
282 emitcode (MOVC, "r1,[r0+2]");
283 sprintf (aop->name[1], "r1");
284 emitcode (MOVC, "r0,[r0]");
285 sprintf (aop->name[0], "r0");
291 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
292 sprintf (aop->name[0], "[r0]");
294 sprintf (aop->name[1], "[r0+2]");
301 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
302 if (!canUsePointer) {
307 emitcode (MOV, "r0,#%s", sym->rname);
308 emitcode (MOV, "r0l,[r0]");
309 sprintf (aop->name[0], "r0l");
312 emitcode (MOV, "r0,#%s", sym->rname);
313 emitcode (MOV, "r0,[r0]");
314 sprintf (aop->name[0], "r0");
317 emitcode (MOV, "r0,#%s", sym->rname);
318 emitcode (MOV, "r1l,[r0+2]");
319 sprintf (aop->name[1], "r1l");
320 emitcode (MOV, "r0,[r0]");
321 sprintf (aop->name[0], "r0");
324 emitcode (MOV, "r0,#%s", sym->rname);
325 emitcode (MOV, "r1,[r0+2]");
326 sprintf (aop->name[1], "r1");
327 emitcode (MOV, "r0,[r0]");
328 sprintf (aop->name[0], "r0");
333 emitcode ("mov", "r0,#%s ; aopForSym:far", sym->rname);
334 sprintf (aop->name[0], "[r0]");
336 sprintf (aop->name[1], "[r0+2]");
342 bailOut("aopForSym");
346 /*-----------------------------------------------------------------*/
347 /* aopForVal - for a value */
348 /*-----------------------------------------------------------------*/
349 static asmop *aopForVal(operand *op) {
352 if (IS_OP_LITERAL(op)) {
353 op->aop = aop = newAsmop (AOP_LIT);
354 switch ((aop->size=getSize(operandType(op))))
357 sprintf (aop->name[0], "#0x%02x",
358 SPEC_CVAL(operandType(op)).v_int & 0xff);
359 sprintf (aop->name[1], "#0");
362 sprintf (aop->name[0], "#0x%04x",
363 SPEC_CVAL(operandType(op)).v_int & 0xffff);
364 sprintf (aop->name[1], "#0");
367 // must be a generic pointer, can only be zero
368 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
369 sprintf (aop->name[0], "#0x%04x",
370 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
371 sprintf (aop->name[1], "#0");
374 sprintf (aop->name[0], "#0x%04lx",
375 SPEC_CVAL(operandType(op)).v_ulong >> 16);
376 sprintf (aop->name[1], "#0x%04x",
377 SPEC_CVAL(operandType(op)).v_ulong && 0xffff);
380 bailOut("aopForVal");
387 op->aop = aop = newAsmop (AOP_IMMD);
388 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
392 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
394 case 3: // generic pointer
395 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
396 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
401 bailOut ("aopForVal: unknown type");
405 static int aopOp(operand *op,
406 bool canUsePointer, bool canUseOffset) {
409 op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
413 op->aop=aopForVal (op);
417 bailOut("aopOp: unexpected operand");
421 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
422 if (strcmp(aop1->name[offset], aop2->name[offset])) {
428 bool aopIsDir(operand *op) {
429 return AOP_TYPE(op)==AOP_DIR;
432 bool aopIsBit(operand *op) {
433 return AOP_TYPE(op)==AOP_BIT;
436 bool aopIsPtr(operand *op) {
437 if (AOP_TYPE(op)==AOP_STK ||
438 AOP_TYPE(op)==AOP_CODE ||
439 AOP_TYPE(op)==AOP_FAR) {
446 char *opRegName(operand *op, int offset, char *opName) {
449 if (OP_SYMBOL(op)->onStack) {
450 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
453 if (IS_TRUE_SYMOP(op))
454 return OP_SYMBOL(op)->rname;
455 else if (OP_SYMBOL(op)->regs[offset])
456 return OP_SYMBOL(op)->regs[offset]->name;
458 bailOut("opRegName: unknown regs");
462 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
465 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
466 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
467 bailOut("opRegName: invalid bit value");
471 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
474 if (SPEC_LONG(OP_VALUE(op)->type)) {
475 sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
477 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
481 sprintf (opName, "#%f", SPEC_CVAL(OP_VALUE(op)->type).v_float);
484 bailOut("opRegName: unexpected noun");
488 bailOut("opRegName: unexpected operand type");
492 char * printOp (operand *op) {
493 static char line[132];
494 sym_link *optype=operandType(op);
495 bool isPtr = IS_PTR(optype);
498 symbol *sym=OP_SYMBOL(op);
499 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
500 sym=SYM_SPIL_LOC(sym);
504 if (DCL_TYPE(optype)==FPOINTER)
505 strcat (line, "far * ");
506 else if (DCL_TYPE(optype)==CPOINTER)
507 strcat (line, "code * ");
508 else if (DCL_TYPE(optype)==GPOINTER)
509 strcat (line, "gen * ");
510 else if (DCL_TYPE(optype)==POINTER)
511 strcat (line, "near * ");
513 strcat (line, "unknown * ");
515 strcat (line, nounName(sym->etype));
517 strcat (line, sym->name);
520 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
523 strcat (line, sym->regs[0]->name);
526 strcat (line, sym->regs[1]->name);
531 sprintf (line+strlen(line), "stack%+d", sym->stack);
534 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
535 strcat (line, "code");
538 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
539 strcat (line, "far");
542 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
543 strcat (line, "bit");
546 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
547 strcat (line, "dir");
550 strcat (line, "unknown");
552 } else if (IS_VALOP(op)) {
553 opRegName(op, 0, line);
554 } else if (IS_TYPOP(op)) {
557 if (DCL_TYPE(optype)==FPOINTER)
558 strcat (line, "far * ");
559 else if (DCL_TYPE(optype)==CPOINTER)
560 strcat (line, "code * ");
561 else if (DCL_TYPE(optype)==GPOINTER)
562 strcat (line, "gen * ");
563 else if (DCL_TYPE(optype)==POINTER)
564 strcat (line, "near * ");
566 strcat (line, "unknown * ");
568 // forget about static, volatile, ... for now
569 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
570 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
571 strcat (line, nounName(operandType(op)));
574 bailOut("printOp: unexpected operand type");
579 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
582 sprintf (line, "%s(%d)", op, ic->lineno);
584 strcat (line, " result=");
585 strcat (line, printOp (IC_RESULT(ic)));
588 strcat (line, " left=");
589 strcat (line, printOp (IC_LEFT(ic)));
592 strcat (line, " right=");
593 strcat (line, printOp (IC_RIGHT(ic)));
595 emitcode (";", line);
598 /*-----------------------------------------------------------------*/
599 /* toBoolean - return carry for operand!=0 */
600 /*-----------------------------------------------------------------*/
601 static char *toBoolean (operand * op) {
602 switch (AOP_SIZE(op))
606 emitcode ("cmp", "%s,#0", AOP_NAME(op));
607 emitcode ("mov", "c,z");
611 bailOut("toBoolean: unknown size");
615 /*-----------------------------------------------------------------*/
616 /* regsInCommon - two operands have some registers in common */
617 /*-----------------------------------------------------------------*/
618 static bool regsInCommon (operand * op1, operand * op2) {
622 /* if they have registers in common */
623 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
626 sym1 = OP_SYMBOL (op1);
627 sym2 = OP_SYMBOL (op2);
629 if (sym1->nRegs == 0 || sym2->nRegs == 0)
632 for (i = 0; i < sym1->nRegs; i++)
638 for (j = 0; j < sym2->nRegs; j++)
643 if (sym2->regs[j] == sym1->regs[i])
651 /*-----------------------------------------------------------------*/
652 /* resultRemat - result is rematerializable */
653 /*-----------------------------------------------------------------*/
654 static int resultRemat (iCode * ic) {
655 if (SKIP_IC (ic) || ic->op == IFX)
658 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
660 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
661 if (sym->remat && !POINTER_SET (ic))
668 /*-----------------------------------------------------------------*/
669 /* genNot - generate code for ! operation */
670 /*-----------------------------------------------------------------*/
671 static void genNot (iCode * ic) {
672 printIc("genNot:", ic, 1,1,0);
675 /*-----------------------------------------------------------------*/
676 /* genCpl - generate code for complement */
677 /*-----------------------------------------------------------------*/
678 static void genCpl (iCode * ic) {
679 printIc("genCpl", ic, 1,1,0);
682 /*-----------------------------------------------------------------*/
683 /* genUminus - unary minus code generation */
684 /*-----------------------------------------------------------------*/
685 static void genUminus (iCode * ic) {
686 printIc("genUminus", ic, 1,1,0);
689 /*-----------------------------------------------------------------*/
690 /* genIpush - genrate code for pushing this gets a little complex */
691 /*-----------------------------------------------------------------*/
692 static void genIpush (iCode * ic) {
693 printIc ("genIpush", ic, 0,1,0);
696 /*-----------------------------------------------------------------*/
697 /* genIpop - recover the registers: can happen only for spilling */
698 /*-----------------------------------------------------------------*/
699 static void genIpop (iCode * ic) {
700 printIc ("genIpop", ic, 0,1,0);
703 /*-----------------------------------------------------------------*/
704 /* genCall - generates a call statement */
705 /*-----------------------------------------------------------------*/
706 static void genCall (iCode * ic) {
707 emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
708 printOp (IC_RESULT(ic)));
711 /*-----------------------------------------------------------------*/
712 /* genPcall - generates a call by pointer statement */
713 /*-----------------------------------------------------------------*/
715 genPcall (iCode * ic)
717 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
720 /*-----------------------------------------------------------------*/
721 /* genFunction - generated code for function entry */
722 /*-----------------------------------------------------------------*/
723 static void genFunction (iCode * ic) {
724 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
725 sym_link *type=sym->type;
727 emitcode (";", "-----------------------------------------");
728 emitcode (";", " function %s", sym->name);
729 emitcode (";", "-----------------------------------------");
731 emitcode ("", "%s:", sym->rname);
733 if (IFFUNC_ISNAKED(type))
735 emitcode(";", "naked function: no prologue.");
739 /* if critical function then turn interrupts off */
740 if (IFFUNC_ISCRITICAL (type))
741 emitcode ("clr", "ea");
745 /*-----------------------------------------------------------------*/
746 /* genEndFunction - generates epilogue for functions */
747 /*-----------------------------------------------------------------*/
749 genEndFunction (iCode * ic)
751 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
753 if (IFFUNC_ISNAKED(sym->type))
755 emitcode(";", "naked function: no epilogue.");
759 printIc ("genEndFunction", ic, 0,0,0);
762 /*-----------------------------------------------------------------*/
763 /* genRet - generate code for return statement */
764 /*-----------------------------------------------------------------*/
765 static void genRet (iCode * ic) {
767 printIc ("genRet", ic, 0,1,0);
769 aopOp(IC_LEFT(ic), TRUE, TRUE);
771 switch (AOP_SIZE(IC_LEFT(ic)))
774 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
775 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
778 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
781 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
784 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
790 /*-----------------------------------------------------------------*/
791 /* genLabel - generates a label */
792 /*-----------------------------------------------------------------*/
793 static void genLabel (iCode * ic) {
794 /* special case never generate */
795 if (IC_LABEL (ic) == entryLabel)
798 emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
799 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
802 /*-----------------------------------------------------------------*/
803 /* genGoto - generates a jmp */
804 /*-----------------------------------------------------------------*/
805 static void genGoto (iCode * ic) {
806 emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
807 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
810 /*-----------------------------------------------------------------*/
811 /* genPlus - generates code for addition */
812 /*-----------------------------------------------------------------*/
813 static void genPlus (iCode * ic) {
814 printIc ("genPlus", ic, 1,1,1);
817 /*-----------------------------------------------------------------*/
818 /* genMinus - generates code for subtraction */
819 /*-----------------------------------------------------------------*/
820 static void genMinus (iCode * ic) {
821 printIc ("genMinus", ic, 1,1,1);
825 /*-----------------------------------------------------------------*/
826 /* genMult - generates code for multiplication */
827 /*-----------------------------------------------------------------*/
828 static void genMult (iCode * ic) {
829 printIc ("genMult", ic, 1,1,1);
832 /*-----------------------------------------------------------------*/
833 /* genDiv - generates code for division */
834 /*-----------------------------------------------------------------*/
835 static void genDiv (iCode * ic) {
836 printIc ("genDiv", ic, 1,1,1);
839 /*-----------------------------------------------------------------*/
840 /* genMod - generates code for division */
841 /*-----------------------------------------------------------------*/
842 static void genMod (iCode * ic) {
843 printIc ("genMod", ic, 1,1,1);
846 /*-----------------------------------------------------------------*/
847 /* genCmpGt :- greater than comparison */
848 /*-----------------------------------------------------------------*/
849 static void genCmpGt (iCode * ic) {
850 printIc ("genCmpGt", ic, 1,1,1);
852 /*-----------------------------------------------------------------*/
853 /* genCmpGt :- greater than comparison */
854 /*-----------------------------------------------------------------*/
855 static void genCmpLe (iCode * ic) {
856 printIc ("genCmpLe", ic, 1,1,1);
858 /*-----------------------------------------------------------------*/
859 /* genCmpGt :- greater than comparison */
860 /*-----------------------------------------------------------------*/
861 static void genCmpGe (iCode * ic) {
862 printIc ("genCmpGe", ic, 1,1,1);
864 /*-----------------------------------------------------------------*/
865 /* genCmpGt :- greater than comparison */
866 /*-----------------------------------------------------------------*/
867 static void genCmpNe (iCode * ic) {
868 printIc ("genCmpNe", ic, 1,1,1);
870 /*-----------------------------------------------------------------*/
871 /* genCmpLt - less than comparisons */
872 /*-----------------------------------------------------------------*/
873 static void genCmpLt (iCode * ic) {
874 printIc ("genCmpLt", ic, 1,1,1);
876 /*-----------------------------------------------------------------*/
877 /* genCmpEq - generates code for equal to */
878 /*-----------------------------------------------------------------*/
879 static void genCmpEq (iCode * ic) {
880 printIc ("genCmpEq", ic, 1,1,1);
883 /*-----------------------------------------------------------------*/
884 /* ifxForOp - returns the icode containing the ifx for operand */
885 /*-----------------------------------------------------------------*/
886 static iCode *ifxForOp (operand * op, iCode * ic) {
887 /* if true symbol then needs to be assigned */
888 if (IS_TRUE_SYMOP (op))
891 /* if this has register type condition and
892 the next instruction is ifx with the same operand
893 and live to of the operand is upto the ifx only then */
895 ic->next->op == IFX &&
896 IC_COND (ic->next)->key == op->key &&
897 OP_SYMBOL (op)->liveTo <= ic->next->seq)
903 /*-----------------------------------------------------------------*/
904 /* hasInc - operand is incremented before any other use */
905 /*-----------------------------------------------------------------*/
906 static iCode *hasInc (operand *op, iCode *ic, int osize) {
907 sym_link *type = operandType(op);
908 sym_link *retype = getSpec (type);
909 iCode *lic = ic->next;
912 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
913 if (!IS_SYMOP(op)) return NULL;
915 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
916 if (IS_AGGREGATE(type->next)) return NULL;
917 if (osize != (isize = getSize(type->next))) return NULL;
920 /* if operand of the form op = op + <sizeof *op> */
921 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
922 isOperandEqual(IC_RESULT(lic),op) &&
923 isOperandLiteral(IC_RIGHT(lic)) &&
924 operandLitValue(IC_RIGHT(lic)) == isize) {
927 /* if the operand used or deffed */
928 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
932 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
938 /*-----------------------------------------------------------------*/
939 /* genAndOp - for && operation */
940 /*-----------------------------------------------------------------*/
941 static void genAndOp (iCode * ic) {
942 printIc ("genAndOp(&&)", ic, 1,1,1);
945 /*-----------------------------------------------------------------*/
946 /* genOrOp - for || operation */
947 /*-----------------------------------------------------------------*/
948 static void genOrOp (iCode * ic) {
949 printIc ("genOrOp(||)", ic, 1,1,1);
952 /*-----------------------------------------------------------------*/
953 /* genAnd - code for and */
954 /*-----------------------------------------------------------------*/
955 static void genAnd (iCode * ic, iCode * ifx) {
956 printIc ("genAnd", ic, 1,1,1);
959 /*-----------------------------------------------------------------*/
960 /* genOr - code for or */
961 /*-----------------------------------------------------------------*/
962 static void genOr (iCode * ic, iCode * ifx) {
963 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
964 int size=aopOp(result, TRUE, TRUE);
967 printIc ("genOr", ic, 1,1,1);
969 /* if left is a literal, then exchange them */
970 if (IS_LITERAL(operandType(left))) {
971 operand *tmp = right;
976 if (aopIsBit(result)) {
977 if (IS_LITERAL(operandType(right))) {
978 if (operandLitValue(right)) {
979 emitcode ("setb", AOP_NAME(result)[0]);
982 aopOp(left, TRUE, TRUE);
983 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
988 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
989 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
996 if (!aopEqual(result->aop, left->aop, 0)) {
997 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
999 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1001 if (!aopEqual(result->aop, left->aop, 1)) {
1002 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1004 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1009 /*-----------------------------------------------------------------*/
1010 /* genXor - code for xclusive or */
1011 /*-----------------------------------------------------------------*/
1012 static void genXor (iCode * ic, iCode * ifx) {
1013 printIc ("genXor", ic, 1,1,1);
1016 /*-----------------------------------------------------------------*/
1017 /* genInline - write the inline code out */
1018 /*-----------------------------------------------------------------*/
1019 static void genInline (iCode * ic) {
1021 printIc ("genInline", ic, 0,0,0);
1023 emitcode ("", IC_INLINE(ic));
1026 /*-----------------------------------------------------------------*/
1027 /* genRRC - rotate right with carry */
1028 /*-----------------------------------------------------------------*/
1029 static void genRRC (iCode * ic) {
1030 printIc ("genRRC", ic, 1,1,0);
1033 /*-----------------------------------------------------------------*/
1034 /* genRLC - generate code for rotate left with carry */
1035 /*-----------------------------------------------------------------*/
1036 static void genRLC (iCode * ic) {
1037 printIc ("genRLC", ic, 1,1,0);
1040 /*-----------------------------------------------------------------*/
1041 /* genGetHbit - generates code get highest order bit */
1042 /*-----------------------------------------------------------------*/
1043 static void genGetHbit (iCode * ic) {
1044 printIc ("genGetHbit", ic, 1,1,0);
1047 /*-----------------------------------------------------------------*/
1048 /* genLeftShift - generates code for left shifting */
1049 /*-----------------------------------------------------------------*/
1050 static void genLeftShift (iCode * ic) {
1051 printIc ("genLeftShift", ic, 1,1,1);
1054 /*-----------------------------------------------------------------*/
1055 /* genRightShift - generate code for right shifting */
1056 /*-----------------------------------------------------------------*/
1057 static void genRightShift (iCode * ic) {
1058 printIc ("genRightShift", ic, 1,1,1);
1061 /*-----------------------------------------------------------------*/
1062 /* genPointerGet - generate code for pointer get */
1063 /*-----------------------------------------------------------------*/
1064 static void genPointerGet (iCode * ic, iCode *pi) {
1065 char *instr, *scratchReg;
1066 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1069 printIc ("genPointerGet", ic, 1,1,0);
1071 if (!IS_PTR(operandType(left))) {
1072 bailOut ("genPointerGet: pointer required");
1075 aopOp(left,FALSE,FALSE);
1076 size=aopOp(result,TRUE,aopIsDir(left));
1078 if (IS_GENPTR(operandType(left))) {
1079 emitcode (";", "INLINE\t_gptrget ; %s %s = [%s %s]",
1080 AOP_NAME(result)[0], AOP_NAME(result)[1],
1081 AOP_NAME(left)[0], AOP_NAME(left)[1]);
1085 switch (AOP_TYPE(left))
1095 if (AOP_TYPE(result)==AOP_STK) {
1096 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1097 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1099 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1106 if (AOP_TYPE(result)==AOP_STK) {
1107 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1108 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1110 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1116 bailOut ("genPointerGet");
1119 /*-----------------------------------------------------------------*/
1120 /* genPointerSet - stores the value into a pointer location */
1121 /*-----------------------------------------------------------------*/
1122 static void genPointerSet (iCode * ic, iCode *pi) {
1124 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1127 printIc ("genPointerSet", ic, 1,0,1);
1129 if (!IS_PTR(operandType(result))) {
1130 bailOut ("genPointerSet: pointer required");
1133 aopOp(result,FALSE,FALSE);
1134 size=aopOp(right,FALSE, FALSE);
1136 if (IS_GENPTR(operandType(result))) {
1137 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1138 AOP_NAME(result)[0], AOP_NAME(result)[1],
1139 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1143 switch (AOP_TYPE(right))
1152 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1157 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0], AOP_NAME(right)[1]);
1161 bailOut ("genPointerSet");
1164 /*-----------------------------------------------------------------*/
1165 /* genIfx - generate code for Ifx statement */
1166 /*-----------------------------------------------------------------*/
1167 static void genIfx (iCode * ic, iCode * popIc) {
1171 symbol *jlbl, *tlbl;
1172 operand *cond=IC_COND(ic);
1174 emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s",
1176 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1177 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1179 size=aopOp(cond,TRUE,TRUE);
1189 switch (AOP_TYPE(cond) )
1192 emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$",
1193 AOP_NAME(cond)[0], jlbl->key+100);
1199 tlbl=newiTempLabel(NULL);
1205 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1206 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1209 // generic pointer, just consider the pointer part
1211 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1212 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1215 emitcode ("jmp", "%05d$", jlbl->key+100);
1216 emitcode ("", "%05d$:", tlbl->key+100);
1222 /*-----------------------------------------------------------------*/
1223 /* genAddrOf - generates code for address of */
1224 /*-----------------------------------------------------------------*/
1225 static void genAddrOf (iCode * ic) {
1227 operand *left=IC_LEFT(ic);
1229 printIc ("genAddrOf", ic, 1,1,0);
1231 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1233 if (isOperandOnStack(left)) {
1234 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1235 getStackOffset(OP_SYMBOL(left)->stack));
1237 // this must be a generic pointer
1238 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1243 if (isOperandInDirSpace(left) ||
1244 isOperandInFarSpace(left) ||
1245 isOperandInCodeSpace(left)) {
1246 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1247 OP_SYMBOL(left)->rname);
1249 // this must be a generic pointer
1250 int space=0; // dir space
1251 if (isOperandInFarSpace(left)) {
1253 } else if (isOperandInCodeSpace(left)) {
1256 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1261 bailOut("genAddrOf");
1264 /*-----------------------------------------------------------------*/
1265 /* genAssign - generate code for assignment */
1266 /*-----------------------------------------------------------------*/
1267 static void genAssign (iCode * ic) {
1268 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1272 printIc ("genAssign", ic, 1,0,1);
1274 if (!IS_SYMOP(result)) {
1275 bailOut("genAssign: result is not a symbol");
1278 aopOp(result, TRUE, TRUE);
1279 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1280 size=AOP_SIZE(result);
1282 /* if result is a bit */
1283 if (AOP_TYPE(result) == AOP_BIT) {
1284 /* if right is literal, we know what the value is */
1285 if (AOP_TYPE(right) == AOP_LIT) {
1286 if (operandLitValue(right)) {
1287 emitcode ("setb", AOP_NAME(result)[0]);
1289 emitcode ("clr", AOP_NAME(result)[0]);
1293 /* if right is also a bit */
1294 if (AOP_TYPE(right) == AOP_BIT) {
1295 emitcode ("mov", "c,%s", AOP_NAME(right));
1296 emitcode ("mov", "%s,c", AOP_NAME(result));
1300 emitcode ("mov", "%s,%s", AOP_NAME(result), toBoolean(right));
1310 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1317 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1322 /*-----------------------------------------------------------------*/
1323 /* genJumpTab - genrates code for jump table */
1324 /*-----------------------------------------------------------------*/
1325 static void genJumpTab (iCode * ic) {
1326 printIc ("genJumpTab", ic, 0,0,0);
1329 /*-----------------------------------------------------------------*/
1330 /* genCast - gen code for casting */
1331 /*-----------------------------------------------------------------*/
1332 static void genCast (iCode * ic) {
1333 printIc ("genCast", ic, 1,1,1);
1336 /*-----------------------------------------------------------------*/
1337 /* genDjnz - generate decrement & jump if not zero instrucion */
1338 /*-----------------------------------------------------------------*/
1339 static bool genDjnz (iCode * ic, iCode * ifx) {
1345 /* if the if condition has a false label
1346 then we cannot save */
1350 /* if the minus is not of the form
1352 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1353 !IS_OP_LITERAL (IC_RIGHT (ic)))
1356 if (operandLitValue (IC_RIGHT (ic)) != 1)
1359 /* if the size of this greater than two then no
1361 if (getSize (operandType (IC_RESULT (ic))) > 2)
1364 printIc ("genDjnz", ic, 1,1,1);
1366 /* otherwise we can save BIG */
1367 lbl = newiTempLabel (NULL);
1368 lbl1 = newiTempLabel (NULL);
1370 aopOp (IC_RESULT (ic), FALSE, TRUE);
1372 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1373 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1374 emitcode ("br", "%05d$", lbl1->key + 100);
1375 emitcode ("", "%05d$:", lbl->key + 100);
1376 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1377 emitcode ("", "%05d$:", lbl1->key + 100);
1381 bailOut("genDjnz: aop type");
1385 /*-----------------------------------------------------------------*/
1386 /* genReceive - generate code for a receive iCode */
1387 /*-----------------------------------------------------------------*/
1388 static void genReceive (iCode * ic) {
1389 printIc ("genReceive", ic, 1,0,0);
1392 /*-----------------------------------------------------------------*/
1393 /* gen51Code - generate code for 8051 based controllers */
1394 /*-----------------------------------------------------------------*/
1395 void genXA51Code (iCode * lic) {
1399 lineHead = lineCurr = NULL;
1401 /* print the allocation information */
1403 printAllocInfo (currFunc, codeOutFile);
1405 /* if debug information required */
1406 if (options.debug && currFunc)
1408 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1410 if (IS_STATIC (currFunc->etype))
1411 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1413 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1417 for (ic = lic; ic; ic = ic->next) {
1418 if (ic->lineno && cln != ic->lineno) {
1419 if (options.debug) {
1421 emitcode ("", "C$%s$%d$%d$%d ==.",
1422 FileBaseName (ic->filename), ic->lineno,
1423 ic->level, ic->block);
1426 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1427 printCLine(ic->filename, ic->lineno));
1430 /* if the result is marked as
1431 spilt and rematerializable or code for
1432 this has already been generated then
1434 if (resultRemat (ic) || ic->generated)
1437 /* depending on the operation */
1457 /* IPOP happens only when trying to restore a
1458 spilt live range, if there is an ifx statement
1459 following this pop then the if statement might
1460 be using some of the registers being popped which
1461 would destory the contents of the register so
1462 we need to check for this condition and handle it */
1464 ic->next->op == IFX &&
1465 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1466 genIfx (ic->next, ic);
1484 genEndFunction (ic);
1504 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1553 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1557 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1561 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1588 case GET_VALUE_AT_ADDRESS:
1589 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
1593 if (POINTER_SET (ic))
1594 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1620 addSet (&_G.sendSet, ic);
1629 /* now we are ready to call the
1630 peep hole optimizer */
1631 if (!options.nopeep)
1632 peepHole (&lineHead);
1634 /* now do the actual printing */
1635 printLine (lineHead, codeOutFile);