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 */
84 extern int xa51_ptrRegReq;
85 extern int xa51_nRegs;
86 extern FILE *codeOutFile;
88 static lineNode *lineHead = NULL;
89 static lineNode *lineCurr = NULL;
96 static char *MOV="mov";
97 static char *MOVB="mov.b";
98 static char *MOVW="mov.w";
99 static char *MOVC="movc";
100 static char *MOVCB="movc.b";
101 static char *MOVCW="movc.w";
103 static char *R1L="r1l";
104 static char *R1="r1";
106 void bailOut (char *mesg) {
107 fprintf (stderr, "%s: bailing out\n", mesg);
111 /*-----------------------------------------------------------------*/
112 /* emitcode - writes the code into a file : for now it is simple */
113 /*-----------------------------------------------------------------*/
114 static void emitcode (char *inst, char *fmt,...) {
116 char lb[INITIAL_INLINEASM];
124 sprintf (lb, "%s\t", inst);
126 sprintf (lb, "%s", inst);
127 vsprintf (lb + (strlen (lb)), fmt, ap);
130 vsprintf (lb, fmt, ap);
132 while (isspace ((int)*lbp))
136 lineCurr = (lineCurr ?
137 connectLine (lineCurr, newLineNode (lb)) :
138 (lineHead = newLineNode (lb)));
139 lineCurr->isInline = _G.inLine;
140 lineCurr->isDebug = _G.debugLine;
144 char *getStackOffset(int stack) {
145 static char gsoBuf[1024];
146 sprintf (gsoBuf, "r7+(%d%+d%+d%+d)", stack,
147 FUNC_ISISR(currFunc->type) ?
148 port->stack.isr_overhead : port->stack.call_overhead,
149 currFunc->stack, _G.nRegsSaved);
153 /*-----------------------------------------------------------------*/
154 /* newAsmop - creates a new asmOp */
155 /*-----------------------------------------------------------------*/
157 newAsmop (short type)
161 aop = Safe_calloc (1, sizeof (asmop));
166 char *aopTypeName(asmop *aop) {
169 case AOP_LIT: return "lit";
170 case AOP_REG: return "reg";
171 case AOP_DIR: return "dir";
172 case AOP_FAR: return "far";
173 case AOP_CODE: return "code";
174 case AOP_GPTR: return "gptr";
175 case AOP_STK: return "stack";
176 case AOP_IMMD: return "imm";
177 case AOP_BIT: return "bit";
182 /*-----------------------------------------------------------------*/
183 /* aopForSym - for a true symbol */
184 /*-----------------------------------------------------------------*/
185 static asmop *aopForSym(symbol *sym,
186 bool canUsePointer, bool canUseOffset) {
190 sym->aop = aop = newAsmop(0);
191 size=aop->size=getSize(sym->type);
193 // if the sym has registers
194 if (sym->nRegs && sym->regs[0]) {
196 sprintf (aop->name[0], sym->regs[0]->name);
198 sprintf (aop->name[1], sym->regs[1]->name);
205 if (!canUsePointer || !canUseOffset) {
210 emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
211 sprintf (aop->name[0], "r0l");
214 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
215 sprintf (aop->name[0], "r0");
218 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
219 sprintf (aop->name[0], "r0");
220 emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
221 sprintf (aop->name[1], "r1l");
224 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
225 sprintf (aop->name[0], "r0");
226 emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
227 sprintf (aop->name[1], "r1");
232 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
234 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
239 // if it has a spillLoc
240 if (sym->usl.spillLoc) {
241 return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
245 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
247 sprintf (aop->name[0], sym->rname);
251 // if in direct space
252 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
254 sprintf (aop->name[0], sym->rname);
256 sprintf (aop->name[1], "%s+2", sym->rname);
262 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
263 if (!canUsePointer) {
268 emitcode (MOV, "r0,#%s", sym->rname);
269 emitcode (MOVC, "r0l,[r0]");
270 sprintf (aop->name[0], "r0l");
273 emitcode (MOV, "r0,#%s", sym->rname);
274 emitcode (MOVC, "r0,[r0]");
275 sprintf (aop->name[0], "r0");
278 emitcode (MOV, "r0,#%s", sym->rname);
279 emitcode (MOVC, "r1l,[r0+2]");
280 sprintf (aop->name[1], "r1l");
281 emitcode (MOV, "r0,[r0]");
282 sprintf (aop->name[0], "r0");
285 emitcode (MOV, "r0,#%s", sym->rname);
286 emitcode (MOVC, "r1,[r0+2]");
287 sprintf (aop->name[1], "r1");
288 emitcode (MOVC, "r0,[r0]");
289 sprintf (aop->name[0], "r0");
295 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
296 sprintf (aop->name[0], "[r0]");
298 sprintf (aop->name[1], "[r0+2]");
305 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
306 if (!canUsePointer) {
311 emitcode (MOV, "r0,#%s", sym->rname);
312 emitcode (MOV, "r0l,[r0]");
313 sprintf (aop->name[0], "r0l");
316 emitcode (MOV, "r0,#%s", sym->rname);
317 emitcode (MOV, "r0,[r0]");
318 sprintf (aop->name[0], "r0");
321 emitcode (MOV, "r0,#%s", sym->rname);
322 emitcode (MOV, "r1l,[r0+2]");
323 sprintf (aop->name[1], "r1l");
324 emitcode (MOV, "r0,[r0]");
325 sprintf (aop->name[0], "r0");
328 emitcode (MOV, "r0,#%s", sym->rname);
329 emitcode (MOV, "r1,[r0+2]");
330 sprintf (aop->name[1], "r1");
331 emitcode (MOV, "r0,[r0]");
332 sprintf (aop->name[0], "r0");
337 emitcode ("mov", "r0,#%s ; aopForSym:far", sym->rname);
338 sprintf (aop->name[0], "[r0]");
340 sprintf (aop->name[1], "[r0+2]");
346 bailOut("aopForSym");
350 /*-----------------------------------------------------------------*/
351 /* aopForVal - for a value */
352 /*-----------------------------------------------------------------*/
353 static asmop *aopForVal(operand *op) {
356 if (IS_OP_LITERAL(op)) {
357 op->aop = aop = newAsmop (AOP_LIT);
358 switch ((aop->size=getSize(operandType(op))))
361 sprintf (aop->name[0], "#0x%02x",
362 SPEC_CVAL(operandType(op)).v_int & 0xff);
363 sprintf (aop->name[1], "#0");
366 sprintf (aop->name[0], "#0x%04x",
367 SPEC_CVAL(operandType(op)).v_int & 0xffff);
368 sprintf (aop->name[1], "#0");
371 // must be a generic pointer, can only be zero
372 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
373 sprintf (aop->name[0], "#0x%04x",
374 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
375 sprintf (aop->name[1], "#0");
378 sprintf (aop->name[0], "#0x%04lx",
379 SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
380 sprintf (aop->name[1], "#0x%04lx",
381 SPEC_CVAL(operandType(op)).v_ulong >> 16);
384 bailOut("aopForVal");
391 op->aop = aop = newAsmop (AOP_IMMD);
392 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
396 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
398 case 3: // generic pointer
399 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
400 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
405 bailOut ("aopForVal: unknown type");
409 static int aopOp(operand *op,
410 bool canUsePointer, bool canUseOffset) {
413 op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
417 op->aop=aopForVal (op);
421 bailOut("aopOp: unexpected operand");
425 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
426 if (strcmp(aop1->name[offset], aop2->name[offset])) {
432 bool aopIsDir(operand *op) {
433 return AOP_TYPE(op)==AOP_DIR;
436 bool aopIsBit(operand *op) {
437 return AOP_TYPE(op)==AOP_BIT;
440 bool aopIsPtr(operand *op) {
441 if (AOP_TYPE(op)==AOP_STK ||
442 AOP_TYPE(op)==AOP_CODE ||
443 AOP_TYPE(op)==AOP_FAR) {
450 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
453 if (OP_SYMBOL(op)->onStack) {
454 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
457 if (IS_TRUE_SYMOP(op))
458 return OP_SYMBOL(op)->rname;
459 else if (OP_SYMBOL(op)->regs[offset])
460 return OP_SYMBOL(op)->regs[offset]->name;
462 bailOut("opRegName: unknown regs");
466 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
469 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
470 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
471 bailOut("opRegName: invalid bit value");
475 sprintf (opName, "#%s0x%02x", decorate?"(char)":"",
476 SPEC_CVAL(OP_VALUE(op)->type).v_int);
479 if (SPEC_LONG(OP_VALUE(op)->type)) {
480 sprintf (opName, "#%s0x%02lx", decorate?"(long)":"",
481 SPEC_CVAL(OP_VALUE(op)->type).v_long);
483 sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
484 SPEC_CVAL(OP_VALUE(op)->type).v_int);
488 sprintf (opName, "#%s%f", decorate?"(float)":"",
489 SPEC_CVAL(OP_VALUE(op)->type).v_float);
492 bailOut("opRegName: unexpected noun");
496 bailOut("opRegName: unexpected operand type");
500 char * printOp (operand *op) {
501 static char line[132];
502 sym_link *optype=operandType(op);
503 bool isPtr = IS_PTR(optype);
506 symbol *sym=OP_SYMBOL(op);
507 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
508 sym=SYM_SPIL_LOC(sym);
512 if (DCL_TYPE(optype)==FPOINTER)
513 strcat (line, "far * ");
514 else if (DCL_TYPE(optype)==CPOINTER)
515 strcat (line, "code * ");
516 else if (DCL_TYPE(optype)==GPOINTER)
517 strcat (line, "gen * ");
518 else if (DCL_TYPE(optype)==POINTER)
519 strcat (line, "near * ");
521 strcat (line, "unknown * ");
523 strcat (line, nounName(sym->etype));
525 strcat (line, sym->name);
528 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
531 strcat (line, sym->regs[0]->name);
534 strcat (line, sym->regs[1]->name);
539 sprintf (line+strlen(line), "stack%+d", sym->stack);
542 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
543 strcat (line, "code");
546 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
547 strcat (line, "far");
550 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
551 strcat (line, "bit");
554 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
555 strcat (line, "dir");
558 strcat (line, "unknown");
560 } else if (IS_VALOP(op)) {
561 opRegName(op, 0, line, 1);
562 } else if (IS_TYPOP(op)) {
565 if (DCL_TYPE(optype)==FPOINTER)
566 strcat (line, "far * ");
567 else if (DCL_TYPE(optype)==CPOINTER)
568 strcat (line, "code * ");
569 else if (DCL_TYPE(optype)==GPOINTER)
570 strcat (line, "gen * ");
571 else if (DCL_TYPE(optype)==POINTER)
572 strcat (line, "near * ");
574 strcat (line, "unknown * ");
576 // forget about static, volatile, ... for now
577 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
578 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
579 strcat (line, nounName(operandType(op)));
582 bailOut("printOp: unexpected operand type");
587 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
590 sprintf (line, "%s(%d)", op, ic->lineno);
592 strcat (line, " result=");
593 strcat (line, printOp (IC_RESULT(ic)));
596 strcat (line, " left=");
597 strcat (line, printOp (IC_LEFT(ic)));
600 strcat (line, " right=");
601 strcat (line, printOp (IC_RIGHT(ic)));
603 emitcode (";", line);
606 /*-----------------------------------------------------------------*/
607 /* toBoolean - return carry for operand!=0 */
608 /*-----------------------------------------------------------------*/
609 static char *toBoolean (operand * op) {
610 symbol *tlbl=newiTempLabel(NULL);
612 switch (AOP_SIZE(op))
616 emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
617 "This needs a second thought");
619 emitcode ("", "%05d$:", tlbl->key+100);
623 bailOut("toBoolean: unknown size");
627 /*-----------------------------------------------------------------*/
628 /* regsInCommon - two operands have some registers in common */
629 /*-----------------------------------------------------------------*/
630 static bool regsInCommon (operand * op1, operand * op2) {
634 /* if they have registers in common */
635 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
638 sym1 = OP_SYMBOL (op1);
639 sym2 = OP_SYMBOL (op2);
641 if (sym1->nRegs == 0 || sym2->nRegs == 0)
644 for (i = 0; i < sym1->nRegs; i++)
650 for (j = 0; j < sym2->nRegs; j++)
655 if (sym2->regs[j] == sym1->regs[i])
663 /*-----------------------------------------------------------------*/
664 /* resultRemat - result is rematerializable */
665 /*-----------------------------------------------------------------*/
666 static int resultRemat (iCode * ic) {
667 if (SKIP_IC (ic) || ic->op == IFX)
670 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
672 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
673 if (sym->remat && !POINTER_SET (ic))
680 /*-----------------------------------------------------------------*/
681 /* genNot - generate code for ! operation */
682 /*-----------------------------------------------------------------*/
683 static void genNot (iCode * ic) {
684 printIc("genNot:", ic, 1,1,0);
687 /*-----------------------------------------------------------------*/
688 /* genCpl - generate code for complement */
689 /*-----------------------------------------------------------------*/
690 static void genCpl (iCode * ic) {
691 printIc("genCpl", ic, 1,1,0);
694 /*-----------------------------------------------------------------*/
695 /* genUminus - unary minus code generation */
696 /*-----------------------------------------------------------------*/
697 static void genUminus (iCode * ic) {
698 printIc("genUminus", ic, 1,1,0);
701 /*-----------------------------------------------------------------*/
702 /* genIpush - generate code for pushing */
703 /*-----------------------------------------------------------------*/
704 static void genIpush (iCode * ic) {
705 operand *left=IC_LEFT(ic);
707 printIc ("genIpush", ic, 0,1,0);
708 aopOp(left,FALSE,FALSE);
711 if (AOP_TYPE(left)==AOP_LIT) {
712 switch (AOP_SIZE(left))
715 emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
716 emitcode ("push", "r1l");
720 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
721 emitcode ("push", "r1");
725 emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
726 emitcode ("push", "r1l");
727 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
728 emitcode ("push", "r1");
732 emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
733 emitcode ("push", "r1");
734 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
735 emitcode ("push", "r1");
740 if (AOP_SIZE(left)>2) {
741 emitcode ("push", "%s", AOP_NAME(left)[1]);
744 emitcode ("push", "%s", AOP_NAME(left)[0]);
749 /*-----------------------------------------------------------------*/
750 /* genIpop - recover the registers: can happen only for spilling */
751 /*-----------------------------------------------------------------*/
752 static void genIpop (iCode * ic) {
753 printIc ("genIpop", ic, 0,1,0);
756 /*-----------------------------------------------------------------*/
757 /* genCall - generates a call statement */
758 /*-----------------------------------------------------------------*/
759 static void genCall (iCode * ic) {
760 operand *result=IC_RESULT(ic);
762 emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
763 OP_SYMBOL(IC_LEFT(ic))->name,
764 printOp (IC_RESULT(ic)));
765 emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
767 /* readjust the stack if we have pushed some parms */
768 if (_G.parmsPushed) {
769 emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
773 /* if we need to assign a result value */
774 if (IS_ITEMP (IC_RESULT(ic)) &&
775 OP_SYMBOL (IC_RESULT (ic))->nRegs) {
776 aopOp(result,FALSE,FALSE);
777 switch (AOP_SIZE(result))
780 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
783 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
787 emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
788 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
791 emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
792 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
799 /*-----------------------------------------------------------------*/
800 /* genPcall - generates a call by pointer statement */
801 /*-----------------------------------------------------------------*/
803 genPcall (iCode * ic)
805 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
808 /*-----------------------------------------------------------------*/
809 /* genFunction - generated code for function entry */
810 /*-----------------------------------------------------------------*/
811 static void genFunction (iCode * ic) {
812 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
813 sym_link *type=sym->type;
815 emitcode (";", "genFunction %s", sym->rname);
817 /* print the allocation information */
818 printAllocInfo (currFunc, codeOutFile);
820 emitcode ("", "%s:", sym->rname);
822 if (IFFUNC_ISNAKED(type))
824 emitcode(";", "naked function: no prologue.");
828 /* adjust the stack for locals used in this function */
830 emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
834 /*-----------------------------------------------------------------*/
835 /* genEndFunction - generates epilogue for functions */
836 /*-----------------------------------------------------------------*/
838 genEndFunction (iCode * ic)
840 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
842 printIc ("genEndFunction", ic, 0,0,0);
844 if (IFFUNC_ISNAKED(sym->type)) {
845 emitcode(";", "naked function: no epilogue.");
849 /* readjust the stock for locals used in this function */
851 emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
854 if (IFFUNC_ISISR(sym->type)) {
855 emitcode ("reti", "");
857 emitcode ("ret", "");
861 /*-----------------------------------------------------------------*/
862 /* genRet - generate code for return statement */
863 /*-----------------------------------------------------------------*/
864 static void genRet (iCode * ic) {
866 printIc ("genRet", ic, 0,1,0);
868 aopOp(IC_LEFT(ic), TRUE, TRUE);
870 switch (AOP_SIZE(IC_LEFT(ic)))
873 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
874 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
877 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
880 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
883 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
888 emitcode ("jmp", "%05d$", returnLabel->key+100);
891 /*-----------------------------------------------------------------*/
892 /* genLabel - generates a label */
893 /*-----------------------------------------------------------------*/
894 static void genLabel (iCode * ic) {
895 /* special case never generate */
896 if (IC_LABEL (ic) == entryLabel)
899 emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
900 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
903 /*-----------------------------------------------------------------*/
904 /* genGoto - generates a jmp */
905 /*-----------------------------------------------------------------*/
906 static void genGoto (iCode * ic) {
907 emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
908 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
911 /*-----------------------------------------------------------------*/
912 /* genPlus - generates code for addition */
913 /*-----------------------------------------------------------------*/
914 static void genPlus (iCode * ic) {
915 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
919 printIc ("genPlus", ic, 1,1,1);
921 size=aopOp(result, TRUE, TRUE);
923 /* if left is a literal, then exchange them */
924 if (IS_LITERAL(operandType(left))) {
925 operand *tmp = right;
930 if (aopIsBit(result)) {
931 if (IS_LITERAL(operandType(right))) {
932 if (operandLitValue(right)) {
933 emitcode ("setb", AOP_NAME(result)[0]);
936 aopOp(left, TRUE, TRUE);
937 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
940 bailOut("genPlus: unfinished genPlus bit");
943 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
944 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
951 if (!aopEqual(result->aop, left->aop, 0)) {
952 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
954 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
956 if (!aopEqual(result->aop, left->aop, 1)) {
957 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
962 emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
968 /*-----------------------------------------------------------------*/
969 /* genMinus - generates code for subtraction */
970 /*-----------------------------------------------------------------*/
971 static void genMinus (iCode * ic) {
972 printIc ("genMinus", ic, 1,1,1);
976 /*-----------------------------------------------------------------*/
977 /* genMult - generates code for multiplication */
978 /*-----------------------------------------------------------------*/
979 static void genMult (iCode * ic) {
980 printIc ("genMult", ic, 1,1,1);
983 /*-----------------------------------------------------------------*/
984 /* genDiv - generates code for division */
985 /*-----------------------------------------------------------------*/
986 static void genDiv (iCode * ic) {
987 printIc ("genDiv", ic, 1,1,1);
990 /*-----------------------------------------------------------------*/
991 /* genMod - generates code for division */
992 /*-----------------------------------------------------------------*/
993 static void genMod (iCode * ic) {
994 printIc ("genMod", ic, 1,1,1);
997 /*-----------------------------------------------------------------*/
998 /* genCmpGt :- greater than comparison */
999 /*-----------------------------------------------------------------*/
1000 static void genCmpGt (iCode * ic) {
1001 printIc ("genCmpGt", ic, 1,1,1);
1003 /*-----------------------------------------------------------------*/
1004 /* genCmpGt :- greater than comparison */
1005 /*-----------------------------------------------------------------*/
1006 static void genCmpLe (iCode * ic) {
1007 printIc ("genCmpLe", ic, 1,1,1);
1009 /*-----------------------------------------------------------------*/
1010 /* genCmpGt :- greater than comparison */
1011 /*-----------------------------------------------------------------*/
1012 static void genCmpGe (iCode * ic) {
1013 printIc ("genCmpGe", ic, 1,1,1);
1015 /*-----------------------------------------------------------------*/
1016 /* genCmpGt :- greater than comparison */
1017 /*-----------------------------------------------------------------*/
1018 static void genCmpNe (iCode * ic) {
1019 printIc ("genCmpNe", ic, 1,1,1);
1021 /*-----------------------------------------------------------------*/
1022 /* genCmpLt - less than comparisons */
1023 /*-----------------------------------------------------------------*/
1024 static void genCmpLt (iCode * ic) {
1025 printIc ("genCmpLt", ic, 1,1,1);
1027 /*-----------------------------------------------------------------*/
1028 /* genCmpEq - generates code for equal to */
1029 /*-----------------------------------------------------------------*/
1030 static void genCmpEq (iCode * ic) {
1031 printIc ("genCmpEq", ic, 1,1,1);
1034 /*-----------------------------------------------------------------*/
1035 /* ifxForOp - returns the icode containing the ifx for operand */
1036 /*-----------------------------------------------------------------*/
1037 static iCode *ifxForOp (operand * op, iCode * ic) {
1038 /* if true symbol then needs to be assigned */
1039 if (IS_TRUE_SYMOP (op))
1042 /* if this has register type condition and
1043 the next instruction is ifx with the same operand
1044 and live to of the operand is upto the ifx only then */
1046 ic->next->op == IFX &&
1047 IC_COND (ic->next)->key == op->key &&
1048 OP_SYMBOL (op)->liveTo <= ic->next->seq)
1054 /*-----------------------------------------------------------------*/
1055 /* hasInc - operand is incremented before any other use */
1056 /*-----------------------------------------------------------------*/
1057 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1058 sym_link *type = operandType(op);
1059 sym_link *retype = getSpec (type);
1060 iCode *lic = ic->next;
1063 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1064 if (!IS_SYMOP(op)) return NULL;
1066 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1067 if (IS_AGGREGATE(type->next)) return NULL;
1068 if (osize != (isize = getSize(type->next))) return NULL;
1071 /* if operand of the form op = op + <sizeof *op> */
1072 if (lic->op == '+') {
1073 if (isOperandEqual(IC_LEFT(lic),op) &&
1074 //isOperandEqual(IC_RESULT(lic),op) &&
1075 isOperandLiteral(IC_RIGHT(lic)) &&
1076 operandLitValue(IC_RIGHT(lic)) == isize) {
1077 emitcode (";", "Found hasInc");
1081 /* if the operand used or deffed */
1082 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1085 /* if GOTO or IFX */
1086 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1092 /*-----------------------------------------------------------------*/
1093 /* genAndOp - for && operation */
1094 /*-----------------------------------------------------------------*/
1095 static void genAndOp (iCode * ic) {
1096 printIc ("genAndOp(&&)", ic, 1,1,1);
1099 /*-----------------------------------------------------------------*/
1100 /* genOrOp - for || operation */
1101 /*-----------------------------------------------------------------*/
1102 static void genOrOp (iCode * ic) {
1103 printIc ("genOrOp(||)", ic, 1,1,1);
1106 /*-----------------------------------------------------------------*/
1107 /* genAnd - code for and */
1108 /*-----------------------------------------------------------------*/
1109 static void genAnd (iCode * ic, iCode * ifx) {
1110 printIc ("genAnd", ic, 1,1,1);
1113 /*-----------------------------------------------------------------*/
1114 /* genOr - code for or */
1115 /*-----------------------------------------------------------------*/
1116 static void genOr (iCode * ic, iCode * ifx) {
1117 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1121 printIc ("genOr", ic, 1,1,1);
1123 size=aopOp(result, TRUE, TRUE);
1125 /* if left is a literal, then exchange them */
1126 if (IS_LITERAL(operandType(left))) {
1127 operand *tmp = right;
1132 if (aopIsBit(result)) {
1133 if (IS_LITERAL(operandType(right))) {
1134 if (operandLitValue(right)) {
1135 emitcode ("setb", AOP_NAME(result)[0]);
1138 aopOp(left, TRUE, TRUE);
1139 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1144 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1145 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1152 if (!aopEqual(result->aop, left->aop, 0)) {
1153 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1155 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1157 if (!aopEqual(result->aop, left->aop, 1)) {
1158 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1160 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1165 /*-----------------------------------------------------------------*/
1166 /* genXor - code for xclusive or */
1167 /*-----------------------------------------------------------------*/
1168 static void genXor (iCode * ic, iCode * ifx) {
1169 printIc ("genXor", ic, 1,1,1);
1172 /*-----------------------------------------------------------------*/
1173 /* genInline - write the inline code out */
1174 /*-----------------------------------------------------------------*/
1175 static void genInline (iCode * ic) {
1177 printIc ("genInline", ic, 0,0,0);
1179 emitcode ("", IC_INLINE(ic));
1182 /*-----------------------------------------------------------------*/
1183 /* genRRC - rotate right with carry */
1184 /*-----------------------------------------------------------------*/
1185 static void genRRC (iCode * ic) {
1186 printIc ("genRRC", ic, 1,1,0);
1189 /*-----------------------------------------------------------------*/
1190 /* genRLC - generate code for rotate left with carry */
1191 /*-----------------------------------------------------------------*/
1192 static void genRLC (iCode * ic) {
1193 printIc ("genRLC", ic, 1,1,0);
1196 /*-----------------------------------------------------------------*/
1197 /* genGetHbit - generates code get highest order bit */
1198 /*-----------------------------------------------------------------*/
1199 static void genGetHbit (iCode * ic) {
1200 printIc ("genGetHbit", ic, 1,1,0);
1203 /*-----------------------------------------------------------------*/
1204 /* genLeftShift - generates code for left shifting */
1205 /*-----------------------------------------------------------------*/
1206 static void genLeftShift (iCode * ic) {
1207 printIc ("genLeftShift", ic, 1,1,1);
1210 /*-----------------------------------------------------------------*/
1211 /* genRightShift - generate code for right shifting */
1212 /*-----------------------------------------------------------------*/
1213 static void genRightShift (iCode * ic) {
1214 printIc ("genRightShift", ic, 1,1,1);
1217 /*-----------------------------------------------------------------*/
1218 /* genPointerGet - generate code for pointer get */
1219 /*-----------------------------------------------------------------*/
1220 static void genPointerGet (iCode * ic, iCode *pi) {
1221 char *instr, *scratchReg;
1222 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1223 bool codePointer=IS_CODEPTR(operandType(left));
1226 printIc ("genPointerGet", ic, 1,1,0);
1228 if (!IS_PTR(operandType(left))) {
1229 bailOut ("genPointerGet: pointer required");
1232 aopOp(left,FALSE,FALSE);
1233 size=aopOp(result,TRUE,aopIsDir(left));
1235 if (IS_GENPTR(operandType(left))) {
1236 symbol *tlbl1=newiTempLabel(NULL);
1237 symbol *tlbl2=newiTempLabel(NULL);
1238 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1239 emitcode ("bne", "%05d$", tlbl1->key+100);
1242 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1245 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1249 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1251 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1254 emitcode ("br", "%05d$", tlbl2->key+100);
1255 emitcode ("", "%05d$:", tlbl1->key+100);
1258 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1261 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1262 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1266 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1268 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1271 emitcode ("", "%05d$:", tlbl2->key+100);
1275 switch (AOP_TYPE(left))
1293 if (AOP_TYPE(result)==AOP_STK) {
1294 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1295 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1298 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
1303 emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1304 emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1306 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
1320 if (AOP_TYPE(result)==AOP_STK) {
1321 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1322 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1325 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1329 emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1331 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1339 bailOut ("genPointerGet");
1342 /*-----------------------------------------------------------------*/
1343 /* genPointerSet - stores the value into a pointer location */
1344 /*-----------------------------------------------------------------*/
1345 static void genPointerSet (iCode * ic, iCode *pi) {
1347 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1350 printIc ("genPointerSet", ic, 1,0,1);
1352 if (!IS_PTR(operandType(result))) {
1353 bailOut ("genPointerSet: pointer required");
1356 aopOp(result,FALSE,FALSE);
1357 size=aopOp(right,FALSE, FALSE);
1359 if (IS_GENPTR(operandType(result))) {
1360 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1361 AOP_NAME(result)[0], AOP_NAME(result)[1],
1362 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1366 switch (AOP_TYPE(right))
1376 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1379 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1386 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1387 AOP_NAME(right)[1]);
1389 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1390 AOP_NAME(right)[1]);
1395 bailOut ("genPointerSet");
1398 /*-----------------------------------------------------------------*/
1399 /* genIfx - generate code for Ifx statement */
1400 /*-----------------------------------------------------------------*/
1401 static void genIfx (iCode * ic, iCode * popIc) {
1405 symbol *jlbl, *tlbl;
1406 operand *cond=IC_COND(ic);
1408 emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s",
1409 ic->lineno, printOp(cond),
1410 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1411 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1413 size=aopOp(cond,TRUE,TRUE);
1423 switch (AOP_TYPE(cond) )
1426 emitcode (trueOrFalse ? "jb" : "jnb", "%s,%05d$",
1427 AOP_NAME(cond)[0], jlbl->key+100);
1433 tlbl=newiTempLabel(NULL);
1439 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1440 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1443 // generic pointer, forget the generic part
1445 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1446 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1449 emitcode ("jmp", "%05d$", jlbl->key+100);
1450 emitcode ("", "%05d$:", tlbl->key+100);
1456 /*-----------------------------------------------------------------*/
1457 /* genAddrOf - generates code for address of */
1458 /*-----------------------------------------------------------------*/
1459 static void genAddrOf (iCode * ic) {
1461 operand *left=IC_LEFT(ic);
1463 printIc ("genAddrOf", ic, 1,1,0);
1465 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1467 if (isOperandOnStack(left)) {
1468 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1469 getStackOffset(OP_SYMBOL(left)->stack));
1471 // this must be a generic pointer
1472 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1477 if (isOperandInDirSpace(left) ||
1478 isOperandInFarSpace(left) ||
1479 isOperandInCodeSpace(left)) {
1480 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1481 OP_SYMBOL(left)->rname);
1483 // this must be a generic pointer
1484 int space=0; // dir space
1485 if (isOperandInFarSpace(left)) {
1487 } else if (isOperandInCodeSpace(left)) {
1490 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1495 bailOut("genAddrOf");
1498 /*-----------------------------------------------------------------*/
1499 /* genAssign - generate code for assignment */
1500 /*-----------------------------------------------------------------*/
1501 static void genAssign (iCode * ic) {
1502 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1506 printIc ("genAssign", ic, 1,0,1);
1508 if (!IS_SYMOP(result)) {
1509 bailOut("genAssign: result is not a symbol");
1512 aopOp(result, TRUE, TRUE);
1513 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1514 size=AOP_SIZE(result);
1516 /* if result is a bit */
1517 if (AOP_TYPE(result) == AOP_BIT) {
1518 /* if right is literal, we know what the value is */
1519 if (AOP_TYPE(right) == AOP_LIT) {
1520 if (operandLitValue(right)) {
1521 emitcode ("setb", AOP_NAME(result)[0]);
1523 emitcode ("clr", AOP_NAME(result)[0]);
1527 /* if right is also a bit */
1528 if (AOP_TYPE(right) == AOP_BIT) {
1529 emitcode ("mov", "c,%s", AOP_NAME(right));
1530 emitcode ("mov", "%s,c", AOP_NAME(result));
1534 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1544 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1551 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1556 /*-----------------------------------------------------------------*/
1557 /* genJumpTab - genrates code for jump table */
1558 /*-----------------------------------------------------------------*/
1559 static void genJumpTab (iCode * ic) {
1560 printIc ("genJumpTab", ic, 0,0,0);
1563 /*-----------------------------------------------------------------*/
1564 /* genCast - gen code for casting */
1565 /*-----------------------------------------------------------------*/
1566 static void genCast (iCode * ic) {
1567 printIc ("genCast", ic, 1,1,1);
1570 /*-----------------------------------------------------------------*/
1571 /* genDjnz - generate decrement & jump if not zero instrucion */
1572 /*-----------------------------------------------------------------*/
1573 static bool genDjnz (iCode * ic, iCode * ifx) {
1579 /* if the if condition has a false label
1580 then we cannot save */
1584 /* if the minus is not of the form
1586 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1587 !IS_OP_LITERAL (IC_RIGHT (ic)))
1590 if (operandLitValue (IC_RIGHT (ic)) != 1)
1593 /* if the size of this greater than two then no
1595 if (getSize (operandType (IC_RESULT (ic))) > 2)
1598 printIc ("genDjnz", ic, 1,1,1);
1600 /* otherwise we can save BIG */
1601 lbl = newiTempLabel (NULL);
1602 lbl1 = newiTempLabel (NULL);
1604 aopOp (IC_RESULT (ic), FALSE, TRUE);
1606 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1607 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1608 emitcode ("br", "%05d$", lbl1->key + 100);
1609 emitcode ("", "%05d$:", lbl->key + 100);
1610 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1611 emitcode ("", "%05d$:", lbl1->key + 100);
1615 bailOut("genDjnz: aop type");
1619 /*-----------------------------------------------------------------*/
1620 /* genReceive - generate code for a receive iCode */
1621 /*-----------------------------------------------------------------*/
1622 static void genReceive (iCode * ic) {
1623 printIc ("genReceive", ic, 1,0,0);
1626 /*-----------------------------------------------------------------*/
1627 /* gen51Code - generate code for 8051 based controllers */
1628 /*-----------------------------------------------------------------*/
1629 void genXA51Code (iCode * lic) {
1633 lineHead = lineCurr = NULL;
1635 /* if debug information required */
1636 if (options.debug && currFunc)
1638 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1640 if (IS_STATIC (currFunc->etype))
1641 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1643 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1647 for (ic = lic; ic; ic = ic->next) {
1648 if (ic->lineno && cln != ic->lineno) {
1649 if (options.debug) {
1651 emitcode ("", "C$%s$%d$%d$%d ==.",
1652 FileBaseName (ic->filename), ic->lineno,
1653 ic->level, ic->block);
1656 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1657 printCLine(ic->filename, ic->lineno));
1660 /* if the result is marked as
1661 spilt and rematerializable or code for
1662 this has already been generated then
1664 if (resultRemat (ic) || ic->generated)
1667 /* depending on the operation */
1687 /* IPOP happens only when trying to restore a
1688 spilt live range, if there is an ifx statement
1689 following this pop then the if statement might
1690 be using some of the registers being popped which
1691 would destory the contents of the register so
1692 we need to check for this condition and handle it */
1694 ic->next->op == IFX &&
1695 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1696 genIfx (ic->next, ic);
1714 genEndFunction (ic);
1734 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1783 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1787 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1791 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1818 case GET_VALUE_AT_ADDRESS:
1819 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
1823 if (POINTER_SET (ic))
1824 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1850 addSet (&_G.sendSet, ic);
1859 /* now we are ready to call the
1860 peep hole optimizer */
1861 if (!options.nopeep)
1862 peepHole (&lineHead);
1864 /* now do the actual printing */
1865 printLine (lineHead, codeOutFile);