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 */
83 extern int xa51_ptrRegReq;
84 extern int xa51_nRegs;
85 extern FILE *codeOutFile;
87 static lineNode *lineHead = NULL;
88 static lineNode *lineCurr = NULL;
95 static char *MOV="mov";
96 static char *MOVB="mov.b";
97 static char *MOVW="mov.w";
98 static char *MOVC="movc";
100 static char *R1L="r1l";
101 static char *R1="r1";
103 void bailOut (char *mesg) {
104 fprintf (stderr, "%s: bailing out\n", mesg);
108 /*-----------------------------------------------------------------*/
109 /* emitcode - writes the code into a file : for now it is simple */
110 /*-----------------------------------------------------------------*/
111 static void emitcode (char *inst, char *fmt,...) {
113 char lb[INITIAL_INLINEASM];
121 sprintf (lb, "%s\t", inst);
123 sprintf (lb, "%s", inst);
124 vsprintf (lb + (strlen (lb)), fmt, ap);
127 vsprintf (lb, fmt, ap);
129 while (isspace ((int)*lbp))
133 lineCurr = (lineCurr ?
134 connectLine (lineCurr, newLineNode (lb)) :
135 (lineHead = newLineNode (lb)));
136 lineCurr->isInline = _G.inLine;
137 lineCurr->isDebug = _G.debugLine;
141 char *getStackOffset(int stack) {
142 static char gsoBuf[1024];
143 sprintf (gsoBuf, "r7+(%d%+d%+d%+d)", stack,
144 FUNC_ISISR(currFunc->type) ?
145 port->stack.isr_overhead : port->stack.call_overhead,
146 currFunc->stack, _G.nRegsSaved);
150 /*-----------------------------------------------------------------*/
151 /* newAsmop - creates a new asmOp */
152 /*-----------------------------------------------------------------*/
154 newAsmop (short type)
158 aop = Safe_calloc (1, sizeof (asmop));
163 char *aopTypeName(asmop *aop) {
166 case AOP_LIT: return "lit";
167 case AOP_REG: return "reg";
168 case AOP_DIR: return "dir";
169 case AOP_FAR: return "far";
170 case AOP_CODE: return "code";
171 case AOP_GPTR: return "gptr";
172 case AOP_STK: return "stack";
173 case AOP_IMMD: return "imm";
174 case AOP_BIT: return "bit";
179 /*-----------------------------------------------------------------*/
180 /* aopForSym - for a true symbol */
181 /*-----------------------------------------------------------------*/
182 static asmop *aopForSym(symbol *sym,
183 bool canUsePointer, bool canUseOffset) {
187 sym->aop = aop = newAsmop(0);
188 size=aop->size=getSize(sym->type);
190 // if the sym has registers
191 if (sym->nRegs && sym->regs[0]) {
193 sprintf (aop->name[0], sym->regs[0]->name);
195 sprintf (aop->name[1], sym->regs[1]->name);
202 if (!canUsePointer || !canUseOffset) {
207 emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
208 sprintf (aop->name[0], "r0l");
211 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
212 sprintf (aop->name[0], "r0");
215 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
216 sprintf (aop->name[0], "r0");
217 emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
218 sprintf (aop->name[1], "r1l");
221 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
222 sprintf (aop->name[0], "r0");
223 emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
224 sprintf (aop->name[1], "r1");
229 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
231 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
236 // if it has a spillLoc
237 if (sym->usl.spillLoc) {
238 return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
242 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
244 sprintf (aop->name[0], sym->rname);
248 // if in direct space
249 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
251 sprintf (aop->name[0], sym->rname);
253 sprintf (aop->name[1], "%s+2", sym->rname);
259 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
260 if (!canUsePointer) {
265 emitcode (MOV, "r0,#%s", sym->rname);
266 emitcode (MOVC, "r0l,[r0]");
267 sprintf (aop->name[0], "r0l");
270 emitcode (MOV, "r0,#%s", sym->rname);
271 emitcode (MOVC, "r0,[r0]");
272 sprintf (aop->name[0], "r0");
275 emitcode (MOV, "r0,#%s", sym->rname);
276 emitcode (MOVC, "r1l,[r0+2]");
277 sprintf (aop->name[1], "r1l");
278 emitcode (MOV, "r0,[r0]");
279 sprintf (aop->name[0], "r0");
282 emitcode (MOV, "r0,#%s", sym->rname);
283 emitcode (MOVC, "r1,[r0+2]");
284 sprintf (aop->name[1], "r1");
285 emitcode (MOVC, "r0,[r0]");
286 sprintf (aop->name[0], "r0");
292 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
293 sprintf (aop->name[0], "[r0]");
295 sprintf (aop->name[1], "[r0+2]");
302 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
303 if (!canUsePointer) {
308 emitcode (MOV, "r0,#%s", sym->rname);
309 emitcode (MOV, "r0l,[r0]");
310 sprintf (aop->name[0], "r0l");
313 emitcode (MOV, "r0,#%s", sym->rname);
314 emitcode (MOV, "r0,[r0]");
315 sprintf (aop->name[0], "r0");
318 emitcode (MOV, "r0,#%s", sym->rname);
319 emitcode (MOV, "r1l,[r0+2]");
320 sprintf (aop->name[1], "r1l");
321 emitcode (MOV, "r0,[r0]");
322 sprintf (aop->name[0], "r0");
325 emitcode (MOV, "r0,#%s", sym->rname);
326 emitcode (MOV, "r1,[r0+2]");
327 sprintf (aop->name[1], "r1");
328 emitcode (MOV, "r0,[r0]");
329 sprintf (aop->name[0], "r0");
334 emitcode ("mov", "r0,#%s ; aopForSym:far", sym->rname);
335 sprintf (aop->name[0], "[r0]");
337 sprintf (aop->name[1], "[r0+2]");
343 bailOut("aopForSym");
347 /*-----------------------------------------------------------------*/
348 /* aopForVal - for a value */
349 /*-----------------------------------------------------------------*/
350 static asmop *aopForVal(operand *op) {
353 if (IS_OP_LITERAL(op)) {
354 op->aop = aop = newAsmop (AOP_LIT);
355 switch ((aop->size=getSize(operandType(op))))
358 sprintf (aop->name[0], "#0x%02x",
359 SPEC_CVAL(operandType(op)).v_int & 0xff);
360 sprintf (aop->name[1], "#0");
363 sprintf (aop->name[0], "#0x%04x",
364 SPEC_CVAL(operandType(op)).v_int & 0xffff);
365 sprintf (aop->name[1], "#0");
368 // must be a generic pointer, can only be zero
369 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
370 sprintf (aop->name[0], "#0x%04x",
371 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
372 sprintf (aop->name[1], "#0");
375 sprintf (aop->name[0], "#0x%04lx",
376 SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
377 sprintf (aop->name[1], "#0x%04lx",
378 SPEC_CVAL(operandType(op)).v_ulong >> 16);
381 bailOut("aopForVal");
388 op->aop = aop = newAsmop (AOP_IMMD);
389 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
393 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
395 case 3: // generic pointer
396 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
397 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
402 bailOut ("aopForVal: unknown type");
406 static int aopOp(operand *op,
407 bool canUsePointer, bool canUseOffset) {
410 op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
414 op->aop=aopForVal (op);
418 bailOut("aopOp: unexpected operand");
422 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
423 if (strcmp(aop1->name[offset], aop2->name[offset])) {
429 bool aopIsDir(operand *op) {
430 return AOP_TYPE(op)==AOP_DIR;
433 bool aopIsBit(operand *op) {
434 return AOP_TYPE(op)==AOP_BIT;
437 bool aopIsPtr(operand *op) {
438 if (AOP_TYPE(op)==AOP_STK ||
439 AOP_TYPE(op)==AOP_CODE ||
440 AOP_TYPE(op)==AOP_FAR) {
447 char *opRegName(operand *op, int offset, char *opName) {
450 if (OP_SYMBOL(op)->onStack) {
451 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
454 if (IS_TRUE_SYMOP(op))
455 return OP_SYMBOL(op)->rname;
456 else if (OP_SYMBOL(op)->regs[offset])
457 return OP_SYMBOL(op)->regs[offset]->name;
459 bailOut("opRegName: unknown regs");
463 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
466 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
467 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
468 bailOut("opRegName: invalid bit value");
472 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
475 if (SPEC_LONG(OP_VALUE(op)->type)) {
476 sprintf (opName, "#0x%02lx", SPEC_CVAL(OP_VALUE(op)->type).v_long);
478 sprintf (opName, "#0x%02x", SPEC_CVAL(OP_VALUE(op)->type).v_int);
482 sprintf (opName, "#%f", SPEC_CVAL(OP_VALUE(op)->type).v_float);
485 bailOut("opRegName: unexpected noun");
489 bailOut("opRegName: unexpected operand type");
493 char * printOp (operand *op) {
494 static char line[132];
495 sym_link *optype=operandType(op);
496 bool isPtr = IS_PTR(optype);
499 symbol *sym=OP_SYMBOL(op);
500 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
501 sym=SYM_SPIL_LOC(sym);
505 if (DCL_TYPE(optype)==FPOINTER)
506 strcat (line, "far * ");
507 else if (DCL_TYPE(optype)==CPOINTER)
508 strcat (line, "code * ");
509 else if (DCL_TYPE(optype)==GPOINTER)
510 strcat (line, "gen * ");
511 else if (DCL_TYPE(optype)==POINTER)
512 strcat (line, "near * ");
514 strcat (line, "unknown * ");
516 strcat (line, nounName(sym->etype));
518 strcat (line, sym->name);
521 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
524 strcat (line, sym->regs[0]->name);
527 strcat (line, sym->regs[1]->name);
532 sprintf (line+strlen(line), "stack%+d", sym->stack);
535 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
536 strcat (line, "code");
539 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
540 strcat (line, "far");
543 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
544 strcat (line, "bit");
547 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
548 strcat (line, "dir");
551 strcat (line, "unknown");
553 } else if (IS_VALOP(op)) {
554 opRegName(op, 0, line);
555 } else if (IS_TYPOP(op)) {
558 if (DCL_TYPE(optype)==FPOINTER)
559 strcat (line, "far * ");
560 else if (DCL_TYPE(optype)==CPOINTER)
561 strcat (line, "code * ");
562 else if (DCL_TYPE(optype)==GPOINTER)
563 strcat (line, "gen * ");
564 else if (DCL_TYPE(optype)==POINTER)
565 strcat (line, "near * ");
567 strcat (line, "unknown * ");
569 // forget about static, volatile, ... for now
570 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
571 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
572 strcat (line, nounName(operandType(op)));
575 bailOut("printOp: unexpected operand type");
580 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
583 sprintf (line, "%s(%d)", op, ic->lineno);
585 strcat (line, " result=");
586 strcat (line, printOp (IC_RESULT(ic)));
589 strcat (line, " left=");
590 strcat (line, printOp (IC_LEFT(ic)));
593 strcat (line, " right=");
594 strcat (line, printOp (IC_RIGHT(ic)));
596 emitcode (";", line);
599 /*-----------------------------------------------------------------*/
600 /* toBoolean - return carry for operand!=0 */
601 /*-----------------------------------------------------------------*/
602 static char *toBoolean (operand * op) {
603 symbol *tlbl=newiTempLabel(NULL);
605 switch (AOP_SIZE(op))
609 emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
610 "This needs a second thought");
612 emitcode ("", "%05d$:", tlbl->key+100);
616 bailOut("toBoolean: unknown size");
620 /*-----------------------------------------------------------------*/
621 /* regsInCommon - two operands have some registers in common */
622 /*-----------------------------------------------------------------*/
623 static bool regsInCommon (operand * op1, operand * op2) {
627 /* if they have registers in common */
628 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
631 sym1 = OP_SYMBOL (op1);
632 sym2 = OP_SYMBOL (op2);
634 if (sym1->nRegs == 0 || sym2->nRegs == 0)
637 for (i = 0; i < sym1->nRegs; i++)
643 for (j = 0; j < sym2->nRegs; j++)
648 if (sym2->regs[j] == sym1->regs[i])
656 /*-----------------------------------------------------------------*/
657 /* resultRemat - result is rematerializable */
658 /*-----------------------------------------------------------------*/
659 static int resultRemat (iCode * ic) {
660 if (SKIP_IC (ic) || ic->op == IFX)
663 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
665 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
666 if (sym->remat && !POINTER_SET (ic))
673 /*-----------------------------------------------------------------*/
674 /* genNot - generate code for ! operation */
675 /*-----------------------------------------------------------------*/
676 static void genNot (iCode * ic) {
677 printIc("genNot:", ic, 1,1,0);
680 /*-----------------------------------------------------------------*/
681 /* genCpl - generate code for complement */
682 /*-----------------------------------------------------------------*/
683 static void genCpl (iCode * ic) {
684 printIc("genCpl", ic, 1,1,0);
687 /*-----------------------------------------------------------------*/
688 /* genUminus - unary minus code generation */
689 /*-----------------------------------------------------------------*/
690 static void genUminus (iCode * ic) {
691 printIc("genUminus", ic, 1,1,0);
694 /*-----------------------------------------------------------------*/
695 /* genIpush - genrate code for pushing this gets a little complex */
696 /*-----------------------------------------------------------------*/
697 static void genIpush (iCode * ic) {
698 printIc ("genIpush", ic, 0,1,0);
701 /*-----------------------------------------------------------------*/
702 /* genIpop - recover the registers: can happen only for spilling */
703 /*-----------------------------------------------------------------*/
704 static void genIpop (iCode * ic) {
705 printIc ("genIpop", ic, 0,1,0);
708 /*-----------------------------------------------------------------*/
709 /* genCall - generates a call statement */
710 /*-----------------------------------------------------------------*/
711 static void genCall (iCode * ic) {
712 emitcode (";", "genCall %s result=%s", OP_SYMBOL(IC_LEFT(ic))->name,
713 printOp (IC_RESULT(ic)));
716 /*-----------------------------------------------------------------*/
717 /* genPcall - generates a call by pointer statement */
718 /*-----------------------------------------------------------------*/
720 genPcall (iCode * ic)
722 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
725 /*-----------------------------------------------------------------*/
726 /* genFunction - generated code for function entry */
727 /*-----------------------------------------------------------------*/
728 static void genFunction (iCode * ic) {
729 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
730 sym_link *type=sym->type;
732 emitcode (";", "genFunction %s", sym->rname);
734 /* print the allocation information */
735 printAllocInfo (currFunc, codeOutFile);
737 emitcode ("", "%s:", sym->rname);
739 if (IFFUNC_ISNAKED(type))
741 emitcode(";", "naked function: no prologue.");
745 /* adjust the stack for locals used in this function */
747 emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
751 /*-----------------------------------------------------------------*/
752 /* genEndFunction - generates epilogue for functions */
753 /*-----------------------------------------------------------------*/
755 genEndFunction (iCode * ic)
757 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
759 printIc ("genEndFunction", ic, 0,0,0);
761 if (IFFUNC_ISNAKED(sym->type)) {
762 emitcode(";", "naked function: no epilogue.");
766 /* readjust the stock for locals used in this function */
768 emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
771 if (IFFUNC_ISISR(sym->type)) {
772 emitcode ("reti", "");
774 emitcode ("ret", "");
778 /*-----------------------------------------------------------------*/
779 /* genRet - generate code for return statement */
780 /*-----------------------------------------------------------------*/
781 static void genRet (iCode * ic) {
783 printIc ("genRet", ic, 0,1,0);
785 aopOp(IC_LEFT(ic), TRUE, TRUE);
787 switch (AOP_SIZE(IC_LEFT(ic)))
790 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
791 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
794 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
797 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
800 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
806 /*-----------------------------------------------------------------*/
807 /* genLabel - generates a label */
808 /*-----------------------------------------------------------------*/
809 static void genLabel (iCode * ic) {
810 /* special case never generate */
811 if (IC_LABEL (ic) == entryLabel)
814 emitcode (";", "genLabel %s", IC_LABEL(ic)->name);
815 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
818 /*-----------------------------------------------------------------*/
819 /* genGoto - generates a jmp */
820 /*-----------------------------------------------------------------*/
821 static void genGoto (iCode * ic) {
822 emitcode (";", "genGoto %s", IC_LABEL(ic)->name);
823 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
826 /*-----------------------------------------------------------------*/
827 /* genPlus - generates code for addition */
828 /*-----------------------------------------------------------------*/
829 static void genPlus (iCode * ic) {
830 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
834 printIc ("genPlus", ic, 1,1,1);
836 size=aopOp(result, TRUE, TRUE);
838 /* if left is a literal, then exchange them */
839 if (IS_LITERAL(operandType(left))) {
840 operand *tmp = right;
845 if (aopIsBit(result)) {
846 if (IS_LITERAL(operandType(right))) {
847 if (operandLitValue(right)) {
848 emitcode ("setb", AOP_NAME(result)[0]);
851 aopOp(left, TRUE, TRUE);
852 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
855 bailOut("genPlus: unfinished genPlus bit");
858 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
859 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
866 if (!aopEqual(result->aop, left->aop, 0)) {
867 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
869 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
871 if (!aopEqual(result->aop, left->aop, 1)) {
872 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
877 emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
883 /*-----------------------------------------------------------------*/
884 /* genMinus - generates code for subtraction */
885 /*-----------------------------------------------------------------*/
886 static void genMinus (iCode * ic) {
887 printIc ("genMinus", ic, 1,1,1);
891 /*-----------------------------------------------------------------*/
892 /* genMult - generates code for multiplication */
893 /*-----------------------------------------------------------------*/
894 static void genMult (iCode * ic) {
895 printIc ("genMult", ic, 1,1,1);
898 /*-----------------------------------------------------------------*/
899 /* genDiv - generates code for division */
900 /*-----------------------------------------------------------------*/
901 static void genDiv (iCode * ic) {
902 printIc ("genDiv", ic, 1,1,1);
905 /*-----------------------------------------------------------------*/
906 /* genMod - generates code for division */
907 /*-----------------------------------------------------------------*/
908 static void genMod (iCode * ic) {
909 printIc ("genMod", ic, 1,1,1);
912 /*-----------------------------------------------------------------*/
913 /* genCmpGt :- greater than comparison */
914 /*-----------------------------------------------------------------*/
915 static void genCmpGt (iCode * ic) {
916 printIc ("genCmpGt", ic, 1,1,1);
918 /*-----------------------------------------------------------------*/
919 /* genCmpGt :- greater than comparison */
920 /*-----------------------------------------------------------------*/
921 static void genCmpLe (iCode * ic) {
922 printIc ("genCmpLe", ic, 1,1,1);
924 /*-----------------------------------------------------------------*/
925 /* genCmpGt :- greater than comparison */
926 /*-----------------------------------------------------------------*/
927 static void genCmpGe (iCode * ic) {
928 printIc ("genCmpGe", ic, 1,1,1);
930 /*-----------------------------------------------------------------*/
931 /* genCmpGt :- greater than comparison */
932 /*-----------------------------------------------------------------*/
933 static void genCmpNe (iCode * ic) {
934 printIc ("genCmpNe", ic, 1,1,1);
936 /*-----------------------------------------------------------------*/
937 /* genCmpLt - less than comparisons */
938 /*-----------------------------------------------------------------*/
939 static void genCmpLt (iCode * ic) {
940 printIc ("genCmpLt", ic, 1,1,1);
942 /*-----------------------------------------------------------------*/
943 /* genCmpEq - generates code for equal to */
944 /*-----------------------------------------------------------------*/
945 static void genCmpEq (iCode * ic) {
946 printIc ("genCmpEq", ic, 1,1,1);
949 /*-----------------------------------------------------------------*/
950 /* ifxForOp - returns the icode containing the ifx for operand */
951 /*-----------------------------------------------------------------*/
952 static iCode *ifxForOp (operand * op, iCode * ic) {
953 /* if true symbol then needs to be assigned */
954 if (IS_TRUE_SYMOP (op))
957 /* if this has register type condition and
958 the next instruction is ifx with the same operand
959 and live to of the operand is upto the ifx only then */
961 ic->next->op == IFX &&
962 IC_COND (ic->next)->key == op->key &&
963 OP_SYMBOL (op)->liveTo <= ic->next->seq)
969 /*-----------------------------------------------------------------*/
970 /* hasInc - operand is incremented before any other use */
971 /*-----------------------------------------------------------------*/
972 static iCode *hasInc (operand *op, iCode *ic, int osize) {
973 sym_link *type = operandType(op);
974 sym_link *retype = getSpec (type);
975 iCode *lic = ic->next;
978 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
979 if (!IS_SYMOP(op)) return NULL;
981 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
982 if (IS_AGGREGATE(type->next)) return NULL;
983 if (osize != (isize = getSize(type->next))) return NULL;
986 /* if operand of the form op = op + <sizeof *op> */
987 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
988 isOperandEqual(IC_RESULT(lic),op) &&
989 isOperandLiteral(IC_RIGHT(lic)) &&
990 operandLitValue(IC_RIGHT(lic)) == isize) {
993 /* if the operand used or deffed */
994 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
998 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1004 /*-----------------------------------------------------------------*/
1005 /* genAndOp - for && operation */
1006 /*-----------------------------------------------------------------*/
1007 static void genAndOp (iCode * ic) {
1008 printIc ("genAndOp(&&)", ic, 1,1,1);
1011 /*-----------------------------------------------------------------*/
1012 /* genOrOp - for || operation */
1013 /*-----------------------------------------------------------------*/
1014 static void genOrOp (iCode * ic) {
1015 printIc ("genOrOp(||)", ic, 1,1,1);
1018 /*-----------------------------------------------------------------*/
1019 /* genAnd - code for and */
1020 /*-----------------------------------------------------------------*/
1021 static void genAnd (iCode * ic, iCode * ifx) {
1022 printIc ("genAnd", ic, 1,1,1);
1025 /*-----------------------------------------------------------------*/
1026 /* genOr - code for or */
1027 /*-----------------------------------------------------------------*/
1028 static void genOr (iCode * ic, iCode * ifx) {
1029 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1033 printIc ("genOr", ic, 1,1,1);
1035 size=aopOp(result, TRUE, TRUE);
1037 /* if left is a literal, then exchange them */
1038 if (IS_LITERAL(operandType(left))) {
1039 operand *tmp = right;
1044 if (aopIsBit(result)) {
1045 if (IS_LITERAL(operandType(right))) {
1046 if (operandLitValue(right)) {
1047 emitcode ("setb", AOP_NAME(result)[0]);
1050 aopOp(left, TRUE, TRUE);
1051 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1056 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1057 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1064 if (!aopEqual(result->aop, left->aop, 0)) {
1065 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1067 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1069 if (!aopEqual(result->aop, left->aop, 1)) {
1070 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1072 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1077 /*-----------------------------------------------------------------*/
1078 /* genXor - code for xclusive or */
1079 /*-----------------------------------------------------------------*/
1080 static void genXor (iCode * ic, iCode * ifx) {
1081 printIc ("genXor", ic, 1,1,1);
1084 /*-----------------------------------------------------------------*/
1085 /* genInline - write the inline code out */
1086 /*-----------------------------------------------------------------*/
1087 static void genInline (iCode * ic) {
1089 printIc ("genInline", ic, 0,0,0);
1091 emitcode ("", IC_INLINE(ic));
1094 /*-----------------------------------------------------------------*/
1095 /* genRRC - rotate right with carry */
1096 /*-----------------------------------------------------------------*/
1097 static void genRRC (iCode * ic) {
1098 printIc ("genRRC", ic, 1,1,0);
1101 /*-----------------------------------------------------------------*/
1102 /* genRLC - generate code for rotate left with carry */
1103 /*-----------------------------------------------------------------*/
1104 static void genRLC (iCode * ic) {
1105 printIc ("genRLC", ic, 1,1,0);
1108 /*-----------------------------------------------------------------*/
1109 /* genGetHbit - generates code get highest order bit */
1110 /*-----------------------------------------------------------------*/
1111 static void genGetHbit (iCode * ic) {
1112 printIc ("genGetHbit", ic, 1,1,0);
1115 /*-----------------------------------------------------------------*/
1116 /* genLeftShift - generates code for left shifting */
1117 /*-----------------------------------------------------------------*/
1118 static void genLeftShift (iCode * ic) {
1119 printIc ("genLeftShift", ic, 1,1,1);
1122 /*-----------------------------------------------------------------*/
1123 /* genRightShift - generate code for right shifting */
1124 /*-----------------------------------------------------------------*/
1125 static void genRightShift (iCode * ic) {
1126 printIc ("genRightShift", ic, 1,1,1);
1129 /*-----------------------------------------------------------------*/
1130 /* genPointerGet - generate code for pointer get */
1131 /*-----------------------------------------------------------------*/
1132 static void genPointerGet (iCode * ic, iCode *pi) {
1133 char *instr, *scratchReg;
1134 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1137 printIc ("genPointerGet", ic, 1,1,0);
1139 if (!IS_PTR(operandType(left))) {
1140 bailOut ("genPointerGet: pointer required");
1143 aopOp(left,FALSE,FALSE);
1144 size=aopOp(result,TRUE,aopIsDir(left));
1146 if (IS_GENPTR(operandType(left))) {
1147 symbol *tlbl1=newiTempLabel(NULL);
1148 symbol *tlbl2=newiTempLabel(NULL);
1149 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1150 emitcode ("bne", "%05d$", tlbl1->key+100);
1152 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1154 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1156 emitcode ("br", "%05d$", tlbl2->key+100);
1157 emitcode ("", "%05d$:", tlbl1->key+100);
1159 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1160 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1162 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1164 emitcode ("", "%05d$:", tlbl2->key+100);
1168 switch (AOP_TYPE(left))
1178 if (AOP_TYPE(result)==AOP_STK) {
1179 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1180 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1183 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1186 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1194 if (AOP_TYPE(result)==AOP_STK) {
1195 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1196 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1199 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1202 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1209 bailOut ("genPointerGet");
1212 /*-----------------------------------------------------------------*/
1213 /* genPointerSet - stores the value into a pointer location */
1214 /*-----------------------------------------------------------------*/
1215 static void genPointerSet (iCode * ic, iCode *pi) {
1217 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1220 printIc ("genPointerSet", ic, 1,0,1);
1222 if (!IS_PTR(operandType(result))) {
1223 bailOut ("genPointerSet: pointer required");
1226 aopOp(result,FALSE,FALSE);
1227 size=aopOp(right,FALSE, FALSE);
1229 if (IS_GENPTR(operandType(result))) {
1230 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1231 AOP_NAME(result)[0], AOP_NAME(result)[1],
1232 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1236 switch (AOP_TYPE(right))
1246 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1249 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1256 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1257 AOP_NAME(right)[1]);
1259 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1260 AOP_NAME(right)[1]);
1265 bailOut ("genPointerSet");
1268 /*-----------------------------------------------------------------*/
1269 /* genIfx - generate code for Ifx statement */
1270 /*-----------------------------------------------------------------*/
1271 static void genIfx (iCode * ic, iCode * popIc) {
1275 symbol *jlbl, *tlbl;
1276 operand *cond=IC_COND(ic);
1278 emitcode (";", "genIfx cond=%s trueLabel:%s falseLabel:%s",
1280 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1281 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1283 size=aopOp(cond,TRUE,TRUE);
1293 switch (AOP_TYPE(cond) )
1296 emitcode (trueOrFalse ? "jb" : "jbc", "%s,%05d$",
1297 AOP_NAME(cond)[0], jlbl->key+100);
1303 tlbl=newiTempLabel(NULL);
1309 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1310 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1313 // generic pointer, forget the generic part
1315 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1316 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1319 emitcode ("jmp", "%05d$", jlbl->key+100);
1320 emitcode ("", "%05d$:", tlbl->key+100);
1326 /*-----------------------------------------------------------------*/
1327 /* genAddrOf - generates code for address of */
1328 /*-----------------------------------------------------------------*/
1329 static void genAddrOf (iCode * ic) {
1331 operand *left=IC_LEFT(ic);
1333 printIc ("genAddrOf", ic, 1,1,0);
1335 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1337 if (isOperandOnStack(left)) {
1338 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1339 getStackOffset(OP_SYMBOL(left)->stack));
1341 // this must be a generic pointer
1342 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1347 if (isOperandInDirSpace(left) ||
1348 isOperandInFarSpace(left) ||
1349 isOperandInCodeSpace(left)) {
1350 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1351 OP_SYMBOL(left)->rname);
1353 // this must be a generic pointer
1354 int space=0; // dir space
1355 if (isOperandInFarSpace(left)) {
1357 } else if (isOperandInCodeSpace(left)) {
1360 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1365 bailOut("genAddrOf");
1368 /*-----------------------------------------------------------------*/
1369 /* genAssign - generate code for assignment */
1370 /*-----------------------------------------------------------------*/
1371 static void genAssign (iCode * ic) {
1372 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1376 printIc ("genAssign", ic, 1,0,1);
1378 if (!IS_SYMOP(result)) {
1379 bailOut("genAssign: result is not a symbol");
1382 aopOp(result, TRUE, TRUE);
1383 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1384 size=AOP_SIZE(result);
1386 /* if result is a bit */
1387 if (AOP_TYPE(result) == AOP_BIT) {
1388 /* if right is literal, we know what the value is */
1389 if (AOP_TYPE(right) == AOP_LIT) {
1390 if (operandLitValue(right)) {
1391 emitcode ("setb", AOP_NAME(result)[0]);
1393 emitcode ("clr", AOP_NAME(result)[0]);
1397 /* if right is also a bit */
1398 if (AOP_TYPE(right) == AOP_BIT) {
1399 emitcode ("mov", "c,%s", AOP_NAME(right));
1400 emitcode ("mov", "%s,c", AOP_NAME(result));
1404 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1414 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1421 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1426 /*-----------------------------------------------------------------*/
1427 /* genJumpTab - genrates code for jump table */
1428 /*-----------------------------------------------------------------*/
1429 static void genJumpTab (iCode * ic) {
1430 printIc ("genJumpTab", ic, 0,0,0);
1433 /*-----------------------------------------------------------------*/
1434 /* genCast - gen code for casting */
1435 /*-----------------------------------------------------------------*/
1436 static void genCast (iCode * ic) {
1437 printIc ("genCast", ic, 1,1,1);
1440 /*-----------------------------------------------------------------*/
1441 /* genDjnz - generate decrement & jump if not zero instrucion */
1442 /*-----------------------------------------------------------------*/
1443 static bool genDjnz (iCode * ic, iCode * ifx) {
1449 /* if the if condition has a false label
1450 then we cannot save */
1454 /* if the minus is not of the form
1456 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1457 !IS_OP_LITERAL (IC_RIGHT (ic)))
1460 if (operandLitValue (IC_RIGHT (ic)) != 1)
1463 /* if the size of this greater than two then no
1465 if (getSize (operandType (IC_RESULT (ic))) > 2)
1468 printIc ("genDjnz", ic, 1,1,1);
1470 /* otherwise we can save BIG */
1471 lbl = newiTempLabel (NULL);
1472 lbl1 = newiTempLabel (NULL);
1474 aopOp (IC_RESULT (ic), FALSE, TRUE);
1476 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1477 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1478 emitcode ("br", "%05d$", lbl1->key + 100);
1479 emitcode ("", "%05d$:", lbl->key + 100);
1480 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1481 emitcode ("", "%05d$:", lbl1->key + 100);
1485 bailOut("genDjnz: aop type");
1489 /*-----------------------------------------------------------------*/
1490 /* genReceive - generate code for a receive iCode */
1491 /*-----------------------------------------------------------------*/
1492 static void genReceive (iCode * ic) {
1493 printIc ("genReceive", ic, 1,0,0);
1496 /*-----------------------------------------------------------------*/
1497 /* gen51Code - generate code for 8051 based controllers */
1498 /*-----------------------------------------------------------------*/
1499 void genXA51Code (iCode * lic) {
1503 lineHead = lineCurr = NULL;
1505 /* if debug information required */
1506 if (options.debug && currFunc)
1508 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1510 if (IS_STATIC (currFunc->etype))
1511 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1513 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1517 for (ic = lic; ic; ic = ic->next) {
1518 if (ic->lineno && cln != ic->lineno) {
1519 if (options.debug) {
1521 emitcode ("", "C$%s$%d$%d$%d ==.",
1522 FileBaseName (ic->filename), ic->lineno,
1523 ic->level, ic->block);
1526 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1527 printCLine(ic->filename, ic->lineno));
1530 /* if the result is marked as
1531 spilt and rematerializable or code for
1532 this has already been generated then
1534 if (resultRemat (ic) || ic->generated)
1537 /* depending on the operation */
1557 /* IPOP happens only when trying to restore a
1558 spilt live range, if there is an ifx statement
1559 following this pop then the if statement might
1560 be using some of the registers being popped which
1561 would destory the contents of the register so
1562 we need to check for this condition and handle it */
1564 ic->next->op == IFX &&
1565 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1566 genIfx (ic->next, ic);
1584 genEndFunction (ic);
1604 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1653 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1657 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1661 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1688 case GET_VALUE_AT_ADDRESS:
1689 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_LEFT(ic)))));
1693 if (POINTER_SET (ic))
1694 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1720 addSet (&_G.sendSet, ic);
1729 /* now we are ready to call the
1730 peep hole optimizer */
1731 if (!options.nopeep)
1732 peepHole (&lineHead);
1734 /* now do the actual printing */
1735 printLine (lineHead, codeOutFile);