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)", stack,
147 currFunc->stack, _G.nRegsSaved);
151 /*-----------------------------------------------------------------*/
152 /* newAsmop - creates a new asmOp */
153 /*-----------------------------------------------------------------*/
155 newAsmop (short type)
159 aop = Safe_calloc (1, sizeof (asmop));
164 char *aopTypeName(asmop *aop) {
167 case AOP_LIT: return "lit";
168 case AOP_REG: return "reg";
169 case AOP_DIR: return "dir";
170 case AOP_FAR: return "far";
171 case AOP_CODE: return "code";
172 case AOP_GPTR: return "gptr";
173 case AOP_STK: return "stack";
174 case AOP_IMMD: return "imm";
175 case AOP_BIT: return "bit";
180 /*-----------------------------------------------------------------*/
181 /* aopForSym - for a true symbol */
182 /*-----------------------------------------------------------------*/
183 static asmop *aopForSym(symbol *sym,
184 bool canUsePointer, bool canUseOffset) {
188 sym->aop = aop = newAsmop(0);
189 size=aop->size=getSize(sym->type);
191 // if the sym has registers
192 if (sym->nRegs && sym->regs[0]) {
194 sprintf (aop->name[0], sym->regs[0]->name);
196 sprintf (aop->name[1], sym->regs[1]->name);
203 if (!canUsePointer || !canUseOffset) {
208 emitcode ("mov.b", "r0l,[%s]", getStackOffset(sym->stack));
209 sprintf (aop->name[0], "r0l");
212 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
213 sprintf (aop->name[0], "r0");
216 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
217 sprintf (aop->name[0], "r0");
218 emitcode ("mov.b", "r1l,[%s]", getStackOffset(sym->stack+2));
219 sprintf (aop->name[1], "r1l");
222 emitcode ("mov.w", "r0,[%s]", getStackOffset(sym->stack));
223 sprintf (aop->name[0], "r0");
224 emitcode ("mov.w", "r1,[%s]", getStackOffset(sym->stack+2));
225 sprintf (aop->name[1], "r1");
230 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
232 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
237 // if it has a spillLoc
238 if (sym->usl.spillLoc) {
239 return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
243 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
245 sprintf (aop->name[0], sym->rname);
249 // if in direct space
250 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
252 sprintf (aop->name[0], sym->rname);
254 sprintf (aop->name[1], "%s+2", sym->rname);
260 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
261 if (!canUsePointer) {
266 emitcode (MOV, "r0,#%s", sym->rname);
267 emitcode (MOVC, "r0l,[r0]");
268 sprintf (aop->name[0], "r0l");
271 emitcode (MOV, "r0,#%s", sym->rname);
272 emitcode (MOVC, "r0,[r0]");
273 sprintf (aop->name[0], "r0");
276 emitcode (MOV, "r0,#%s", sym->rname);
277 emitcode (MOVC, "r1l,[r0+2]");
278 sprintf (aop->name[1], "r1l");
279 emitcode (MOV, "r0,[r0]");
280 sprintf (aop->name[0], "r0");
283 emitcode (MOV, "r0,#%s", sym->rname);
284 emitcode (MOVC, "r1,[r0+2]");
285 sprintf (aop->name[1], "r1");
286 emitcode (MOVC, "r0,[r0]");
287 sprintf (aop->name[0], "r0");
293 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
294 sprintf (aop->name[0], "[r0]");
296 sprintf (aop->name[1], "[r0+2]");
303 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
304 if (!canUsePointer) {
309 emitcode (MOV, "r0,#%s", sym->rname);
310 emitcode (MOV, "r0l,[r0]");
311 sprintf (aop->name[0], "r0l");
314 emitcode (MOV, "r0,#%s", sym->rname);
315 emitcode (MOV, "r0,[r0]");
316 sprintf (aop->name[0], "r0");
319 emitcode (MOV, "r0,#%s", sym->rname);
320 emitcode (MOV, "r1l,[r0+2]");
321 sprintf (aop->name[1], "r1l");
322 emitcode (MOV, "r0,[r0]");
323 sprintf (aop->name[0], "r0");
326 emitcode (MOV, "r0,#%s", sym->rname);
327 emitcode (MOV, "r1,[r0+2]");
328 sprintf (aop->name[1], "r1");
329 emitcode (MOV, "r0,[r0]");
330 sprintf (aop->name[0], "r0");
335 emitcode ("mov", "r0,#%s ; aopForSym:far", sym->rname);
336 sprintf (aop->name[0], "[r0]");
338 sprintf (aop->name[1], "[r0+2]");
344 bailOut("aopForSym");
348 /*-----------------------------------------------------------------*/
349 /* aopForVal - for a value */
350 /*-----------------------------------------------------------------*/
351 static asmop *aopForVal(operand *op) {
354 if (IS_OP_LITERAL(op)) {
355 op->aop = aop = newAsmop (AOP_LIT);
356 switch ((aop->size=getSize(operandType(op))))
359 sprintf (aop->name[0], "#0x%02x",
360 SPEC_CVAL(operandType(op)).v_int & 0xff);
361 sprintf (aop->name[1], "#0");
364 sprintf (aop->name[0], "#0x%04x",
365 SPEC_CVAL(operandType(op)).v_int & 0xffff);
366 sprintf (aop->name[1], "#0");
369 // must be a generic pointer, can only be zero
370 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
371 sprintf (aop->name[0], "#0x%04x",
372 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
373 sprintf (aop->name[1], "#0");
376 sprintf (aop->name[0], "#0x%04lx",
377 SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
378 sprintf (aop->name[1], "#0x%04lx",
379 SPEC_CVAL(operandType(op)).v_ulong >> 16);
382 bailOut("aopForVal");
389 op->aop = aop = newAsmop (AOP_IMMD);
390 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
394 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
396 case 3: // generic pointer
397 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
398 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
403 bailOut ("aopForVal: unknown type");
407 static int aopOp(operand *op,
408 bool canUsePointer, bool canUseOffset) {
411 op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
415 op->aop=aopForVal (op);
419 bailOut("aopOp: unexpected operand");
423 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
424 if (strcmp(aop1->name[offset], aop2->name[offset])) {
430 bool aopIsDir(operand *op) {
431 return AOP_TYPE(op)==AOP_DIR;
434 bool aopIsBit(operand *op) {
435 return AOP_TYPE(op)==AOP_BIT;
438 bool aopIsPtr(operand *op) {
439 if (AOP_TYPE(op)==AOP_STK ||
440 AOP_TYPE(op)==AOP_CODE ||
441 AOP_TYPE(op)==AOP_FAR) {
448 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
451 if (OP_SYMBOL(op)->onStack) {
452 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
455 if (IS_TRUE_SYMOP(op))
456 return OP_SYMBOL(op)->rname;
457 else if (OP_SYMBOL(op)->regs[offset])
458 return OP_SYMBOL(op)->regs[offset]->name;
460 bailOut("opRegName: unknown regs");
464 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
467 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
468 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
469 bailOut("opRegName: invalid bit value");
473 sprintf (opName, "#%s0x%02x", decorate?"(char)":"",
474 SPEC_CVAL(OP_VALUE(op)->type).v_int);
477 if (SPEC_LONG(OP_VALUE(op)->type)) {
478 sprintf (opName, "#%s0x%02lx", decorate?"(long)":"",
479 SPEC_CVAL(OP_VALUE(op)->type).v_long);
481 sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
482 SPEC_CVAL(OP_VALUE(op)->type).v_int);
486 sprintf (opName, "#%s%f", decorate?"(float)":"",
487 SPEC_CVAL(OP_VALUE(op)->type).v_float);
490 bailOut("opRegName: unexpected noun");
494 bailOut("opRegName: unexpected operand type");
498 char * printOp (operand *op) {
499 static char line[132];
500 sym_link *optype=operandType(op);
501 bool isPtr = IS_PTR(optype);
504 symbol *sym=OP_SYMBOL(op);
505 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
506 sym=SYM_SPIL_LOC(sym);
510 if (DCL_TYPE(optype)==FPOINTER)
511 strcat (line, "far * ");
512 else if (DCL_TYPE(optype)==CPOINTER)
513 strcat (line, "code * ");
514 else if (DCL_TYPE(optype)==GPOINTER)
515 strcat (line, "gen * ");
516 else if (DCL_TYPE(optype)==POINTER)
517 strcat (line, "near * ");
519 strcat (line, "unknown * ");
521 strcat (line, nounName(sym->etype));
523 strcat (line, sym->name);
526 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
529 strcat (line, sym->regs[0]->name);
532 strcat (line, sym->regs[1]->name);
537 sprintf (line+strlen(line), "stack%+d", sym->stack);
540 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
541 strcat (line, "code");
544 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
545 strcat (line, "far");
548 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
549 strcat (line, "bit");
552 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
553 strcat (line, "dir");
556 strcat (line, "unknown");
558 } else if (IS_VALOP(op)) {
559 opRegName(op, 0, line, 1);
560 } else if (IS_TYPOP(op)) {
563 if (DCL_TYPE(optype)==FPOINTER)
564 strcat (line, "far * ");
565 else if (DCL_TYPE(optype)==CPOINTER)
566 strcat (line, "code * ");
567 else if (DCL_TYPE(optype)==GPOINTER)
568 strcat (line, "gen * ");
569 else if (DCL_TYPE(optype)==POINTER)
570 strcat (line, "near * ");
572 strcat (line, "unknown * ");
574 // forget about static, volatile, ... for now
575 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
576 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
577 strcat (line, nounName(operandType(op)));
580 bailOut("printOp: unexpected operand type");
585 void printIc (char *op, iCode * ic, bool result, bool left, bool right) {
588 sprintf (line, "%s(%d)", op, ic->lineno);
590 strcat (line, " result=");
591 strcat (line, printOp (IC_RESULT(ic)));
594 strcat (line, " left=");
595 strcat (line, printOp (IC_LEFT(ic)));
598 strcat (line, " right=");
599 strcat (line, printOp (IC_RIGHT(ic)));
601 emitcode (";", line);
604 /*-----------------------------------------------------------------*/
605 /* toBoolean - return carry for operand!=0 */
606 /*-----------------------------------------------------------------*/
607 static char *toBoolean (operand * op) {
608 symbol *tlbl=newiTempLabel(NULL);
610 switch (AOP_SIZE(op))
614 emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
615 "This needs a second thought");
617 emitcode ("", "%05d$:", tlbl->key+100);
621 bailOut("toBoolean: unknown size");
625 /*-----------------------------------------------------------------*/
626 /* regsInCommon - two operands have some registers in common */
627 /*-----------------------------------------------------------------*/
628 static bool regsInCommon (operand * op1, operand * op2) {
632 /* if they have registers in common */
633 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
636 sym1 = OP_SYMBOL (op1);
637 sym2 = OP_SYMBOL (op2);
639 if (sym1->nRegs == 0 || sym2->nRegs == 0)
642 for (i = 0; i < sym1->nRegs; i++)
648 for (j = 0; j < sym2->nRegs; j++)
653 if (sym2->regs[j] == sym1->regs[i])
661 /*-----------------------------------------------------------------*/
662 /* resultRemat - result is rematerializable */
663 /*-----------------------------------------------------------------*/
664 static int resultRemat (iCode * ic) {
665 if (SKIP_IC (ic) || ic->op == IFX)
668 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
670 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
671 if (sym->remat && !POINTER_SET (ic))
678 /*-----------------------------------------------------------------*/
679 /* genNot - generate code for ! operation */
680 /*-----------------------------------------------------------------*/
681 static void genNot (iCode * ic) {
682 printIc("genNot:", ic, 1,1,0);
685 /*-----------------------------------------------------------------*/
686 /* genCpl - generate code for complement */
687 /*-----------------------------------------------------------------*/
688 static void genCpl (iCode * ic) {
689 printIc("genCpl", ic, 1,1,0);
692 /*-----------------------------------------------------------------*/
693 /* genUminus - unary minus code generation */
694 /*-----------------------------------------------------------------*/
695 static void genUminus (iCode * ic) {
696 printIc("genUminus", ic, 1,1,0);
699 /*-----------------------------------------------------------------*/
700 /* genIpush - generate code for pushing */
701 /*-----------------------------------------------------------------*/
702 static void genIpush (iCode * ic) {
703 operand *left=IC_LEFT(ic);
705 printIc ("genIpush", ic, 0,1,0);
706 aopOp(left,FALSE,FALSE);
709 if (AOP_TYPE(left)==AOP_LIT) {
710 switch (AOP_SIZE(left))
713 emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
714 emitcode ("push", "r1l");
718 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
719 emitcode ("push", "r1");
723 emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
724 emitcode ("push", "r1l");
725 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
726 emitcode ("push", "r1");
730 emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
731 emitcode ("push", "r1");
732 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
733 emitcode ("push", "r1");
738 if (AOP_SIZE(left)>2) {
739 emitcode ("push", "%s", AOP_NAME(left)[1]);
742 emitcode ("push", "%s", AOP_NAME(left)[0]);
747 /*-----------------------------------------------------------------*/
748 /* genIpop - recover the registers: can happen only for spilling */
749 /*-----------------------------------------------------------------*/
750 static void genIpop (iCode * ic) {
751 printIc ("genIpop", ic, 0,1,0);
754 /*-----------------------------------------------------------------*/
755 /* genCall - generates a call statement */
756 /*-----------------------------------------------------------------*/
757 static void genCall (iCode * ic) {
758 operand *result=IC_RESULT(ic);
760 emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
761 OP_SYMBOL(IC_LEFT(ic))->name,
762 printOp (IC_RESULT(ic)));
763 emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
765 /* readjust the stack if we have pushed some parms */
766 if (_G.parmsPushed) {
767 emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
771 /* if we need to assign a result value */
772 if (IS_ITEMP (IC_RESULT(ic)) &&
773 OP_SYMBOL (IC_RESULT (ic))->nRegs) {
774 aopOp(result,FALSE,FALSE);
775 switch (AOP_SIZE(result))
778 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
781 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
785 emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
786 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
789 emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
790 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
797 /*-----------------------------------------------------------------*/
798 /* genPcall - generates a call by pointer statement */
799 /*-----------------------------------------------------------------*/
801 genPcall (iCode * ic)
803 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
806 /*-----------------------------------------------------------------*/
807 /* genFunction - generated code for function entry */
808 /*-----------------------------------------------------------------*/
809 static void genFunction (iCode * ic) {
810 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
811 sym_link *type=sym->type;
813 emitcode (";", "genFunction %s", sym->rname);
815 /* print the allocation information */
816 printAllocInfo (currFunc, codeOutFile);
818 emitcode ("", "%s:", sym->rname);
820 if (IFFUNC_ISNAKED(type))
822 emitcode(";", "naked function: no prologue.");
826 /* adjust the stack for locals used in this function */
828 emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
832 /*-----------------------------------------------------------------*/
833 /* genEndFunction - generates epilogue for functions */
834 /*-----------------------------------------------------------------*/
836 genEndFunction (iCode * ic)
838 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
840 printIc ("genEndFunction", ic, 0,0,0);
842 if (IFFUNC_ISNAKED(sym->type)) {
843 emitcode(";", "naked function: no epilogue.");
847 /* readjust the stock for locals used in this function */
849 emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
852 if (IFFUNC_ISISR(sym->type)) {
853 emitcode ("reti", "");
855 emitcode ("ret", "");
859 /*-----------------------------------------------------------------*/
860 /* genRet - generate code for return statement */
861 /*-----------------------------------------------------------------*/
862 static void genRet (iCode * ic) {
864 printIc ("genRet", ic, 0,1,0);
866 aopOp(IC_LEFT(ic), TRUE, TRUE);
868 switch (AOP_SIZE(IC_LEFT(ic)))
871 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
872 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
875 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
878 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
881 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
886 emitcode ("jmp", "%05d$", returnLabel->key+100);
889 /*-----------------------------------------------------------------*/
890 /* genLabel - generates a label */
891 /*-----------------------------------------------------------------*/
892 static void genLabel (iCode * ic) {
893 /* special case never generate */
894 if (IC_LABEL (ic) == entryLabel)
897 emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
898 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
901 /*-----------------------------------------------------------------*/
902 /* genGoto - generates a jmp */
903 /*-----------------------------------------------------------------*/
904 static void genGoto (iCode * ic) {
905 emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
906 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
909 /*-----------------------------------------------------------------*/
910 /* genPlus - generates code for addition */
911 /*-----------------------------------------------------------------*/
912 static void genPlus (iCode * ic) {
913 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
917 printIc ("genPlus", ic, 1,1,1);
919 size=aopOp(result, TRUE, TRUE);
921 /* if left is a literal, then exchange them */
922 if (IS_LITERAL(operandType(left))) {
923 operand *tmp = right;
928 if (aopIsBit(result)) {
929 if (IS_LITERAL(operandType(right))) {
930 if (operandLitValue(right)) {
931 emitcode ("setb", AOP_NAME(result)[0]);
934 aopOp(left, TRUE, TRUE);
935 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
938 bailOut("genPlus: unfinished genPlus bit");
941 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
942 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
949 if (!aopEqual(result->aop, left->aop, 0)) {
950 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
952 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
954 if (!aopEqual(result->aop, left->aop, 1)) {
955 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
960 emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
966 /*-----------------------------------------------------------------*/
967 /* genMinus - generates code for subtraction */
968 /*-----------------------------------------------------------------*/
969 static void genMinus (iCode * ic) {
970 printIc ("genMinus", ic, 1,1,1);
974 /*-----------------------------------------------------------------*/
975 /* genMult - generates code for multiplication */
976 /*-----------------------------------------------------------------*/
977 static void genMult (iCode * ic) {
978 printIc ("genMult", ic, 1,1,1);
981 /*-----------------------------------------------------------------*/
982 /* genDiv - generates code for division */
983 /*-----------------------------------------------------------------*/
984 static void genDiv (iCode * ic) {
985 printIc ("genDiv", ic, 1,1,1);
988 /*-----------------------------------------------------------------*/
989 /* genMod - generates code for division */
990 /*-----------------------------------------------------------------*/
991 static void genMod (iCode * ic) {
992 printIc ("genMod", ic, 1,1,1);
995 /*-----------------------------------------------------------------*/
996 /* genCmpGt :- greater than comparison */
997 /*-----------------------------------------------------------------*/
998 static void genCmpGt (iCode * ic) {
999 printIc ("genCmpGt", ic, 1,1,1);
1001 /*-----------------------------------------------------------------*/
1002 /* genCmpGt :- greater than comparison */
1003 /*-----------------------------------------------------------------*/
1004 static void genCmpLe (iCode * ic) {
1005 printIc ("genCmpLe", ic, 1,1,1);
1007 /*-----------------------------------------------------------------*/
1008 /* genCmpGt :- greater than comparison */
1009 /*-----------------------------------------------------------------*/
1010 static void genCmpGe (iCode * ic) {
1011 printIc ("genCmpGe", ic, 1,1,1);
1013 /*-----------------------------------------------------------------*/
1014 /* genCmpGt :- greater than comparison */
1015 /*-----------------------------------------------------------------*/
1016 static void genCmpNe (iCode * ic) {
1017 printIc ("genCmpNe", ic, 1,1,1);
1019 /*-----------------------------------------------------------------*/
1020 /* genCmpLt - less than comparisons */
1021 /*-----------------------------------------------------------------*/
1022 static void genCmpLt (iCode * ic) {
1023 printIc ("genCmpLt", ic, 1,1,1);
1025 /*-----------------------------------------------------------------*/
1026 /* genCmpEq - generates code for equal to */
1027 /*-----------------------------------------------------------------*/
1028 static void genCmpEq (iCode * ic) {
1029 printIc ("genCmpEq", ic, 1,1,1);
1032 /*-----------------------------------------------------------------*/
1033 /* ifxForOp - returns the icode containing the ifx for operand */
1034 /*-----------------------------------------------------------------*/
1035 static iCode *ifxForOp (operand * op, iCode * ic) {
1036 /* if true symbol then needs to be assigned */
1037 if (IS_TRUE_SYMOP (op))
1040 /* if this has register type condition and
1041 the next instruction is ifx with the same operand
1042 and live to of the operand is upto the ifx only then */
1044 ic->next->op == IFX &&
1045 IC_COND (ic->next)->key == op->key &&
1046 OP_SYMBOL (op)->liveTo <= ic->next->seq)
1052 /*-----------------------------------------------------------------*/
1053 /* hasInc - operand is incremented before any other use */
1054 /*-----------------------------------------------------------------*/
1055 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1056 sym_link *type = operandType(op);
1057 sym_link *retype = getSpec (type);
1058 iCode *lic = ic->next;
1061 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1062 if (!IS_SYMOP(op)) return NULL;
1064 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1065 if (IS_AGGREGATE(type->next)) return NULL;
1066 if (osize != (isize = getSize(type->next))) return NULL;
1069 /* if operand of the form op = op + <sizeof *op> */
1070 if (lic->op == '+') {
1071 if (isOperandEqual(IC_LEFT(lic),op) &&
1072 //isOperandEqual(IC_RESULT(lic),op) &&
1073 isOperandLiteral(IC_RIGHT(lic)) &&
1074 operandLitValue(IC_RIGHT(lic)) == isize) {
1075 emitcode (";", "Found hasInc");
1079 /* if the operand used or deffed */
1080 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1083 /* if GOTO or IFX */
1084 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1090 /*-----------------------------------------------------------------*/
1091 /* genAndOp - for && operation */
1092 /*-----------------------------------------------------------------*/
1093 static void genAndOp (iCode * ic) {
1094 printIc ("genAndOp(&&)", ic, 1,1,1);
1097 /*-----------------------------------------------------------------*/
1098 /* genOrOp - for || operation */
1099 /*-----------------------------------------------------------------*/
1100 static void genOrOp (iCode * ic) {
1101 printIc ("genOrOp(||)", ic, 1,1,1);
1104 /*-----------------------------------------------------------------*/
1105 /* genAnd - code for and */
1106 /*-----------------------------------------------------------------*/
1107 static void genAnd (iCode * ic, iCode * ifx) {
1108 printIc ("genAnd", ic, 1,1,1);
1111 /*-----------------------------------------------------------------*/
1112 /* genOr - code for or */
1113 /*-----------------------------------------------------------------*/
1114 static void genOr (iCode * ic, iCode * ifx) {
1115 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1119 printIc ("genOr", ic, 1,1,1);
1121 size=aopOp(result, TRUE, TRUE);
1123 /* if left is a literal, then exchange them */
1124 if (IS_LITERAL(operandType(left))) {
1125 operand *tmp = right;
1130 if (aopIsBit(result)) {
1131 if (IS_LITERAL(operandType(right))) {
1132 if (operandLitValue(right)) {
1133 emitcode ("setb", AOP_NAME(result)[0]);
1136 aopOp(left, TRUE, TRUE);
1137 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1142 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1143 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1150 if (!aopEqual(result->aop, left->aop, 0)) {
1151 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1153 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1155 if (!aopEqual(result->aop, left->aop, 1)) {
1156 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1158 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1163 /*-----------------------------------------------------------------*/
1164 /* genXor - code for xclusive or */
1165 /*-----------------------------------------------------------------*/
1166 static void genXor (iCode * ic, iCode * ifx) {
1167 printIc ("genXor", ic, 1,1,1);
1170 /*-----------------------------------------------------------------*/
1171 /* genInline - write the inline code out */
1172 /*-----------------------------------------------------------------*/
1173 static void genInline (iCode * ic) {
1175 printIc ("genInline", ic, 0,0,0);
1177 emitcode ("", IC_INLINE(ic));
1180 /*-----------------------------------------------------------------*/
1181 /* genRRC - rotate right with carry */
1182 /*-----------------------------------------------------------------*/
1183 static void genRRC (iCode * ic) {
1184 printIc ("genRRC", ic, 1,1,0);
1187 /*-----------------------------------------------------------------*/
1188 /* genRLC - generate code for rotate left with carry */
1189 /*-----------------------------------------------------------------*/
1190 static void genRLC (iCode * ic) {
1191 printIc ("genRLC", ic, 1,1,0);
1194 /*-----------------------------------------------------------------*/
1195 /* genGetHbit - generates code get highest order bit */
1196 /*-----------------------------------------------------------------*/
1197 static void genGetHbit (iCode * ic) {
1198 printIc ("genGetHbit", ic, 1,1,0);
1201 /*-----------------------------------------------------------------*/
1202 /* genLeftShift - generates code for left shifting */
1203 /*-----------------------------------------------------------------*/
1204 static void genLeftShift (iCode * ic) {
1205 printIc ("genLeftShift", ic, 1,1,1);
1208 /*-----------------------------------------------------------------*/
1209 /* genRightShift - generate code for right shifting */
1210 /*-----------------------------------------------------------------*/
1211 static void genRightShift (iCode * ic) {
1212 printIc ("genRightShift", ic, 1,1,1);
1215 /*-----------------------------------------------------------------*/
1216 /* genPointerGet - generate code for pointer get */
1217 /*-----------------------------------------------------------------*/
1218 static void genPointerGet (iCode * ic, iCode *pi) {
1219 char *instr, *scratchReg;
1220 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1221 bool codePointer=IS_CODEPTR(operandType(left));
1224 printIc ("genPointerGet", ic, 1,1,0);
1226 if (!IS_PTR(operandType(left))) {
1227 bailOut ("genPointerGet: pointer required");
1230 aopOp(left,FALSE,FALSE);
1231 size=aopOp(result,TRUE,aopIsDir(left));
1233 if (IS_GENPTR(operandType(left))) {
1234 symbol *tlbl1=newiTempLabel(NULL);
1235 symbol *tlbl2=newiTempLabel(NULL);
1236 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1237 emitcode ("beq", "%05d$", tlbl1->key+100);
1240 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1243 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1247 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1249 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1252 emitcode ("br", "%05d$", tlbl2->key+100);
1253 emitcode ("", "%05d$:", tlbl1->key+100);
1256 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1259 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1260 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1264 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1266 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1269 emitcode ("", "%05d$:", tlbl2->key+100);
1273 switch (AOP_TYPE(left))
1291 if (AOP_TYPE(result)==AOP_STK) {
1292 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1293 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1296 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
1301 emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1302 emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1304 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
1318 if (AOP_TYPE(result)==AOP_STK) {
1319 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1320 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1323 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1327 emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1329 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1337 bailOut ("genPointerGet");
1340 /*-----------------------------------------------------------------*/
1341 /* genPointerSet - stores the value into a pointer location */
1342 /*-----------------------------------------------------------------*/
1343 static void genPointerSet (iCode * ic, iCode *pi) {
1345 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1348 printIc ("genPointerSet", ic, 1,0,1);
1350 if (!IS_PTR(operandType(result))) {
1351 bailOut ("genPointerSet: pointer required");
1354 aopOp(result,FALSE,FALSE);
1355 size=aopOp(right,FALSE, FALSE);
1357 if (IS_GENPTR(operandType(result))) {
1358 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1359 AOP_NAME(result)[0], AOP_NAME(result)[1],
1360 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1364 switch (AOP_TYPE(right))
1374 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1377 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1384 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1385 AOP_NAME(right)[1]);
1387 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1388 AOP_NAME(right)[1]);
1393 bailOut ("genPointerSet");
1396 /*-----------------------------------------------------------------*/
1397 /* genIfx - generate code for Ifx statement */
1398 /*-----------------------------------------------------------------*/
1399 static void genIfx (iCode * ic, iCode * popIc) {
1403 symbol *jlbl, *tlbl;
1404 operand *cond=IC_COND(ic);
1406 emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s",
1407 ic->lineno, printOp(cond),
1408 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1409 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1411 size=aopOp(cond,TRUE,TRUE);
1421 switch (AOP_TYPE(cond) )
1424 emitcode (trueOrFalse ? "jb" : "jnb", "%s,%05d$",
1425 AOP_NAME(cond)[0], jlbl->key+100);
1431 tlbl=newiTempLabel(NULL);
1437 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1438 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1441 // generic pointer, forget the generic part
1443 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1444 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1447 emitcode ("jmp", "%05d$", jlbl->key+100);
1448 emitcode ("", "%05d$:", tlbl->key+100);
1454 /*-----------------------------------------------------------------*/
1455 /* genAddrOf - generates code for address of */
1456 /*-----------------------------------------------------------------*/
1457 static void genAddrOf (iCode * ic) {
1459 operand *left=IC_LEFT(ic);
1461 printIc ("genAddrOf", ic, 1,1,0);
1463 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1465 if (isOperandOnStack(left)) {
1466 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1467 getStackOffset(OP_SYMBOL(left)->stack));
1469 // this must be a generic pointer
1470 emitcode ("mov", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1475 if (isOperandInDirSpace(left) ||
1476 isOperandInFarSpace(left) ||
1477 isOperandInCodeSpace(left)) {
1478 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1479 OP_SYMBOL(left)->rname);
1481 // this must be a generic pointer
1482 int space=0; // dir space
1483 if (isOperandInFarSpace(left)) {
1485 } else if (isOperandInCodeSpace(left)) {
1488 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1493 bailOut("genAddrOf");
1496 /*-----------------------------------------------------------------*/
1497 /* genAssign - generate code for assignment */
1498 /*-----------------------------------------------------------------*/
1499 static void genAssign (iCode * ic) {
1500 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1504 printIc ("genAssign", ic, 1,0,1);
1506 if (!IS_SYMOP(result)) {
1507 bailOut("genAssign: result is not a symbol");
1510 aopOp(result, TRUE, TRUE);
1511 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1512 size=AOP_SIZE(result);
1514 /* if result is a bit */
1515 if (AOP_TYPE(result) == AOP_BIT) {
1516 /* if right is literal, we know what the value is */
1517 if (AOP_TYPE(right) == AOP_LIT) {
1518 if (operandLitValue(right)) {
1519 emitcode ("setb", AOP_NAME(result)[0]);
1521 emitcode ("clr", AOP_NAME(result)[0]);
1525 /* if right is also a bit */
1526 if (AOP_TYPE(right) == AOP_BIT) {
1527 emitcode ("mov", "c,%s", AOP_NAME(right));
1528 emitcode ("mov", "%s,c", AOP_NAME(result));
1532 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1542 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1549 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1554 /*-----------------------------------------------------------------*/
1555 /* genJumpTab - genrates code for jump table */
1556 /*-----------------------------------------------------------------*/
1557 static void genJumpTab (iCode * ic) {
1558 printIc ("genJumpTab", ic, 0,0,0);
1561 /*-----------------------------------------------------------------*/
1562 /* genCast - gen code for casting */
1563 /*-----------------------------------------------------------------*/
1564 static void genCast (iCode * ic) {
1566 operand *result=IC_RESULT(ic);
1567 operand *right=IC_RIGHT(ic);
1568 sym_link *ctype=operandType(IC_LEFT(ic));
1569 sym_link *rtype=operandType(IC_RIGHT(ic));
1570 sym_link *etype=getSpec(rtype);
1571 short ptrType, signedness;
1573 printIc ("genCast", ic, 1,1,1);
1575 aopOp(result, TRUE, TRUE);
1576 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1577 size=AOP_SIZE(result);
1579 /* if result is a bit */
1580 if (AOP_TYPE(result) == AOP_BIT) {
1581 /* if right is literal, we know what the value is */
1582 if (AOP_TYPE(right) == AOP_LIT) {
1583 if (operandLitValue(right)) {
1584 emitcode ("setb", AOP_NAME(result)[0]);
1586 emitcode ("clr", AOP_NAME(result)[0]);
1590 /* if right is also a bit */
1591 if (AOP_TYPE(right) == AOP_BIT) {
1592 emitcode ("mov", "c,%s", AOP_NAME(right));
1593 emitcode ("mov", "%s,c", AOP_NAME(result));
1597 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1601 /* if right is a bit */
1602 if (AOP_TYPE(right)==AOP_BIT) {
1603 emitcode ("mov", "c,%s", AOP_NAME(right));
1604 emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1605 emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1607 emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1612 /* if the result is of type pointer */
1613 if (IS_PTR (ctype)) {
1615 if (AOP_SIZE(right)>1) {
1616 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1618 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1619 emitcode ("sext", "r1h");
1620 emitcode ("mov", "%s,r1", AOP_NAME(result)[0]);
1623 /* if pointer to generic pointer */
1624 if (IS_GENPTR (ctype)) {
1626 if (IS_GENPTR (rtype)) {
1627 bailOut("genCast: gptr -> gptr");
1630 if (IS_PTR (rtype)) {
1631 ptrType = DCL_TYPE (rtype);
1633 /* we have to go by the storage class */
1634 if (!SPEC_OCLS(etype)) {
1635 bailOut("genCast: unknown storage class");
1637 ptrType = PTR_TYPE (SPEC_OCLS (etype));
1641 /* the generic part depends on the type */
1645 emitcode ("mov", "%s,#0x00", AOP_NAME(result)[1]);
1648 emitcode ("mov", "%s,#0x01", AOP_NAME(result)[1]);
1651 emitcode ("mov", "%s,#0x02", AOP_NAME(result)[1]);
1654 bailOut("genCast: got unknown storage class");
1660 /* do we have to sign extend? */
1661 signedness = SPEC_USIGN(rtype);
1663 /* now depending on the size */
1664 switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1668 emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1673 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1677 emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1679 emitcode("sext", "r1h");
1681 emitcode("mov", "rlh,#0");
1683 emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1686 // fall through: case 0x41
1687 emitcode("sext", AOP_NAME(result)[1]);
1691 emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1692 emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1695 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1698 bailOut("genCast: unknown size");
1702 /*-----------------------------------------------------------------*/
1703 /* genDjnz - generate decrement & jump if not zero instrucion */
1704 /*-----------------------------------------------------------------*/
1705 static bool genDjnz (iCode * ic, iCode * ifx) {
1711 /* if the if condition has a false label
1712 then we cannot save */
1716 /* if the minus is not of the form
1718 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1719 !IS_OP_LITERAL (IC_RIGHT (ic)))
1722 if (operandLitValue (IC_RIGHT (ic)) != 1)
1725 /* if the size of this greater than two then no
1727 if (getSize (operandType (IC_RESULT (ic))) > 2)
1730 printIc ("genDjnz", ic, 1,1,1);
1732 /* otherwise we can save BIG */
1733 lbl = newiTempLabel (NULL);
1734 lbl1 = newiTempLabel (NULL);
1736 aopOp (IC_RESULT (ic), FALSE, TRUE);
1738 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1739 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1740 emitcode ("br", "%05d$", lbl1->key + 100);
1741 emitcode ("", "%05d$:", lbl->key + 100);
1742 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1743 emitcode ("", "%05d$:", lbl1->key + 100);
1747 bailOut("genDjnz: aop type");
1751 /*-----------------------------------------------------------------*/
1752 /* genReceive - generate code for a receive iCode */
1753 /*-----------------------------------------------------------------*/
1754 static void genReceive (iCode * ic) {
1755 printIc ("genReceive", ic, 1,0,0);
1758 /*-----------------------------------------------------------------*/
1759 /* gen51Code - generate code for 8051 based controllers */
1760 /*-----------------------------------------------------------------*/
1761 void genXA51Code (iCode * lic) {
1765 lineHead = lineCurr = NULL;
1767 /* if debug information required */
1768 if (options.debug && currFunc)
1770 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1772 if (IS_STATIC (currFunc->etype))
1773 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1775 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1779 for (ic = lic; ic; ic = ic->next) {
1780 if (ic->lineno && cln != ic->lineno) {
1781 if (options.debug) {
1783 emitcode ("", "C$%s$%d$%d$%d ==.",
1784 FileBaseName (ic->filename), ic->lineno,
1785 ic->level, ic->block);
1788 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1789 printCLine(ic->filename, ic->lineno));
1792 /* if the result is marked as
1793 spilt and rematerializable or code for
1794 this has already been generated then
1796 if (resultRemat (ic) || ic->generated)
1799 /* depending on the operation */
1819 /* IPOP happens only when trying to restore a
1820 spilt live range, if there is an ifx statement
1821 following this pop then the if statement might
1822 be using some of the registers being popped which
1823 would destory the contents of the register so
1824 we need to check for this condition and handle it */
1826 ic->next->op == IFX &&
1827 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1828 genIfx (ic->next, ic);
1846 genEndFunction (ic);
1866 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
1915 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
1919 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
1923 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
1950 case GET_VALUE_AT_ADDRESS:
1951 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
1955 if (POINTER_SET (ic))
1956 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
1982 addSet (&_G.sendSet, ic);
1991 /* now we are ready to call the
1992 peep hole optimizer */
1993 if (!options.nopeep)
1994 peepHole (&lineHead);
1996 /* now do the actual printing */
1997 printLine (lineHead, codeOutFile);