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] ;aopForSym:stack:1", getStackOffset(sym->stack));
209 sprintf (aop->name[0], "r0l");
212 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:2", getStackOffset(sym->stack));
213 sprintf (aop->name[0], "r0");
216 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:3", getStackOffset(sym->stack));
217 sprintf (aop->name[0], "r0");
218 emitcode ("mov.b", "r1l,[%s] ;aopForSym:stack:3", getStackOffset(sym->stack+2));
219 sprintf (aop->name[1], "r1l");
222 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack));
223 sprintf (aop->name[0], "r0");
224 emitcode ("mov.w", "r1,[%s] ;aopForSym:stack:4", 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, "r0,[r0+]");
278 sprintf (aop->name[1], "r0");
279 emitcode (MOV, "r1l,[r0+]");
280 sprintf (aop->name[0], "r1l");
283 emitcode (MOV, "r0,#%s", sym->rname);
284 emitcode (MOVC, "r1,[r0+]");
285 emitcode (MOVC, "r0,[r0+]");
286 emitcode ("xch", "r0,r1");
287 sprintf (aop->name[0], "r0");
288 sprintf (aop->name[1], "r1");
294 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
295 sprintf (aop->name[0], "[r0]");
297 sprintf (aop->name[1], "[r0+2]");
304 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
305 if (!canUsePointer) {
310 emitcode (MOV, "r0,#%s", sym->rname);
311 emitcode (MOV, "r0l,[r0]");
312 sprintf (aop->name[0], "r0l");
315 emitcode (MOV, "r0,#%s", sym->rname);
316 emitcode (MOV, "r0,[r0]");
317 sprintf (aop->name[0], "r0");
320 emitcode (MOV, "r0,#%s", sym->rname);
321 emitcode (MOV, "r1l,[r0+2]");
322 sprintf (aop->name[1], "r1l");
323 emitcode (MOV, "r0,[r0]");
324 sprintf (aop->name[0], "r0");
327 emitcode (MOV, "r0,#%s", sym->rname);
328 emitcode (MOV, "r1,[r0+2]");
329 sprintf (aop->name[1], "r1");
330 emitcode (MOV, "r0,[r0]");
331 sprintf (aop->name[0], "r0");
336 emitcode ("mov.w", "r0,#%s ; aopForSym:far", sym->rname);
337 sprintf (aop->name[0], "[r0]");
339 sprintf (aop->name[1], "[r0+2]");
345 bailOut("aopForSym");
349 /*-----------------------------------------------------------------*/
350 /* aopForVal - for a value */
351 /*-----------------------------------------------------------------*/
352 static asmop *aopForVal(operand *op) {
355 if (IS_OP_LITERAL(op)) {
356 op->aop = aop = newAsmop (AOP_LIT);
357 switch ((aop->size=getSize(operandType(op))))
360 sprintf (aop->name[0], "#0x%02x",
361 SPEC_CVAL(operandType(op)).v_int & 0xff);
362 sprintf (aop->name[1], "#0");
365 sprintf (aop->name[0], "#0x%04x",
366 SPEC_CVAL(operandType(op)).v_int & 0xffff);
367 sprintf (aop->name[1], "#0");
370 // must be a generic pointer, can only be zero
371 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
372 sprintf (aop->name[0], "#0x%04x",
373 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
374 sprintf (aop->name[1], "#0");
377 sprintf (aop->name[0], "#0x%04lx",
378 SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
379 sprintf (aop->name[1], "#0x%04lx",
380 SPEC_CVAL(operandType(op)).v_ulong >> 16);
383 bailOut("aopForVal");
390 op->aop = aop = newAsmop (AOP_IMMD);
391 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
395 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
397 case 3: // generic pointer
398 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
399 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
404 bailOut ("aopForVal: unknown type");
408 static int aopOp(operand *op,
409 bool canUsePointer, bool canUseOffset) {
412 op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
416 op->aop=aopForVal (op);
420 bailOut("aopOp: unexpected operand");
424 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
425 if (strcmp(aop1->name[offset], aop2->name[offset])) {
431 bool aopIsDir(operand *op) {
432 return AOP_TYPE(op)==AOP_DIR;
435 bool aopIsBit(operand *op) {
436 return AOP_TYPE(op)==AOP_BIT;
439 bool aopIsPtr(operand *op) {
440 if (AOP_TYPE(op)==AOP_STK ||
441 AOP_TYPE(op)==AOP_CODE ||
442 AOP_TYPE(op)==AOP_FAR) {
449 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
452 if (OP_SYMBOL(op)->onStack) {
453 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
456 if (IS_TRUE_SYMOP(op))
457 return OP_SYMBOL(op)->rname;
458 else if (OP_SYMBOL(op)->regs[offset])
459 return OP_SYMBOL(op)->regs[offset]->name;
461 bailOut("opRegName: unknown regs");
465 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
468 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
469 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
470 bailOut("opRegName: invalid bit value");
474 sprintf (opName, "#%s0x%02x", decorate?"(char)":"",
475 SPEC_CVAL(OP_VALUE(op)->type).v_int);
478 if (SPEC_LONG(OP_VALUE(op)->type)) {
479 sprintf (opName, "#%s0x%02lx", decorate?"(long)":"",
480 SPEC_CVAL(OP_VALUE(op)->type).v_long);
482 sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
483 SPEC_CVAL(OP_VALUE(op)->type).v_int);
487 sprintf (opName, "#%s%f", decorate?"(float)":"",
488 SPEC_CVAL(OP_VALUE(op)->type).v_float);
491 bailOut("opRegName: unexpected noun");
495 bailOut("opRegName: unexpected operand type");
499 char * printOp (operand *op) {
500 static char line[132];
501 sym_link *optype=operandType(op);
502 bool isPtr = IS_PTR(optype);
505 symbol *sym=OP_SYMBOL(op);
506 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
507 sym=SYM_SPIL_LOC(sym);
511 if (DCL_TYPE(optype)==FPOINTER)
512 strcat (line, "far * ");
513 else if (DCL_TYPE(optype)==CPOINTER)
514 strcat (line, "code * ");
515 else if (DCL_TYPE(optype)==GPOINTER)
516 strcat (line, "gen * ");
517 else if (DCL_TYPE(optype)==POINTER)
518 strcat (line, "near * ");
520 strcat (line, "unknown * ");
522 strcat (line, nounName(sym->etype));
524 strcat (line, sym->name);
527 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
530 strcat (line, sym->regs[0]->name);
533 strcat (line, sym->regs[1]->name);
538 sprintf (line+strlen(line), "stack%+d", sym->stack);
541 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
542 strcat (line, "code");
545 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
546 strcat (line, "far");
549 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
550 strcat (line, "bit");
553 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
554 strcat (line, "dir");
557 strcat (line, "unknown");
559 } else if (IS_VALOP(op)) {
560 opRegName(op, 0, line, 1);
561 } else if (IS_TYPOP(op)) {
564 if (DCL_TYPE(optype)==FPOINTER)
565 strcat (line, "far * ");
566 else if (DCL_TYPE(optype)==CPOINTER)
567 strcat (line, "code * ");
568 else if (DCL_TYPE(optype)==GPOINTER)
569 strcat (line, "gen * ");
570 else if (DCL_TYPE(optype)==POINTER)
571 strcat (line, "near * ");
573 strcat (line, "unknown * ");
575 // forget about static, volatile, ... for now
576 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
577 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
578 strcat (line, nounName(operandType(op)));
581 bailOut("printOp: unexpected operand type");
586 void printIc (bool printToStderr,
587 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);
605 fprintf (stderr, "%s\n", line);
609 /*-----------------------------------------------------------------*/
610 /* toBoolean - return carry for operand!=0 */
611 /*-----------------------------------------------------------------*/
612 static char *toBoolean (operand * op) {
613 symbol *tlbl=newiTempLabel(NULL);
615 switch (AOP_SIZE(op))
619 emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
620 "This needs a second thought");
622 emitcode ("", "%05d$:", tlbl->key+100);
626 bailOut("toBoolean: unknown size");
630 /*-----------------------------------------------------------------*/
631 /* regsInCommon - two operands have some registers in common */
632 /*-----------------------------------------------------------------*/
633 static bool regsInCommon (operand * op1, operand * op2) {
637 /* if they have registers in common */
638 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
641 sym1 = OP_SYMBOL (op1);
642 sym2 = OP_SYMBOL (op2);
644 if (sym1->nRegs == 0 || sym2->nRegs == 0)
647 for (i = 0; i < sym1->nRegs; i++)
653 for (j = 0; j < sym2->nRegs; j++)
658 if (sym2->regs[j] == sym1->regs[i])
666 /*-----------------------------------------------------------------*/
667 /* resultRemat - result is rematerializable */
668 /*-----------------------------------------------------------------*/
669 static int resultRemat (iCode * ic) {
670 if (SKIP_IC (ic) || ic->op == IFX)
673 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
675 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
676 if (sym->remat && !POINTER_SET (ic))
683 /*-----------------------------------------------------------------*/
684 /* genNot - generate code for ! operation */
685 /*-----------------------------------------------------------------*/
686 static void genNot (iCode * ic) {
687 printIc (0, "genNot:", ic, 1,1,0);
690 /*-----------------------------------------------------------------*/
691 /* genCpl - generate code for complement */
692 /*-----------------------------------------------------------------*/
693 static void genCpl (iCode * ic) {
694 printIc (0, "genCpl", ic, 1,1,0);
697 /*-----------------------------------------------------------------*/
698 /* genUminus - unary minus code generation */
699 /*-----------------------------------------------------------------*/
700 static void genUminus (iCode * ic) {
701 printIc (0, "genUminus", ic, 1,1,0);
704 /*-----------------------------------------------------------------*/
705 /* genIpush - generate code for pushing */
706 /*-----------------------------------------------------------------*/
707 static void genIpush (iCode * ic) {
708 operand *left=IC_LEFT(ic);
710 printIc (0, "genIpush", ic, 0,1,0);
711 aopOp(left,FALSE,FALSE);
714 if (AOP_TYPE(left)==AOP_LIT) {
715 switch (AOP_SIZE(left))
718 emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
719 emitcode ("push", "r1l");
723 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
724 emitcode ("push", "r1");
728 emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
729 emitcode ("push", "r1l");
730 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
731 emitcode ("push", "r1");
735 emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
736 emitcode ("push", "r1");
737 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
738 emitcode ("push", "r1");
743 if (AOP_SIZE(left)>2) {
744 emitcode ("push", "%s", AOP_NAME(left)[1]);
747 emitcode ("push", "%s", AOP_NAME(left)[0]);
752 /*-----------------------------------------------------------------*/
753 /* genIpop - recover the registers: can happen only for spilling */
754 /*-----------------------------------------------------------------*/
755 static void genIpop (iCode * ic) {
756 printIc (0, "genIpop", ic, 0,1,0);
759 /*-----------------------------------------------------------------*/
760 /* genCall - generates a call statement */
761 /*-----------------------------------------------------------------*/
762 static void genCall (iCode * ic) {
763 operand *result=IC_RESULT(ic);
765 emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
766 OP_SYMBOL(IC_LEFT(ic))->name,
767 printOp (IC_RESULT(ic)));
768 emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
770 /* readjust the stack if we have pushed some parms */
771 if (_G.parmsPushed) {
772 emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
776 /* if we need to assign a result value */
777 if (IS_ITEMP (IC_RESULT(ic)) &&
778 OP_SYMBOL (IC_RESULT (ic))->nRegs) {
779 aopOp(result,FALSE,FALSE);
780 switch (AOP_SIZE(result))
783 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
786 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
790 emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
791 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
794 emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
795 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
802 /*-----------------------------------------------------------------*/
803 /* genPcall - generates a call by pointer statement */
804 /*-----------------------------------------------------------------*/
806 genPcall (iCode * ic)
808 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
811 /*-----------------------------------------------------------------*/
812 /* genFunction - generated code for function entry */
813 /*-----------------------------------------------------------------*/
814 static void genFunction (iCode * ic) {
815 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
816 sym_link *type=sym->type;
818 emitcode (";", "genFunction %s", sym->rname);
820 /* print the allocation information */
821 printAllocInfo (currFunc, codeOutFile);
823 emitcode ("", "%s:", sym->rname);
825 if (IFFUNC_ISNAKED(type))
827 emitcode(";", "naked function: no prologue.");
831 /* adjust the stack for locals used in this function */
833 emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
837 /*-----------------------------------------------------------------*/
838 /* genEndFunction - generates epilogue for functions */
839 /*-----------------------------------------------------------------*/
841 genEndFunction (iCode * ic)
843 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
845 printIc (0, "genEndFunction", ic, 0,0,0);
847 if (IFFUNC_ISNAKED(sym->type)) {
848 emitcode(";", "naked function: no epilogue.");
852 /* readjust the stock for locals used in this function */
854 emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
857 if (IFFUNC_ISISR(sym->type)) {
858 emitcode ("reti", "");
860 emitcode ("ret", "");
864 /*-----------------------------------------------------------------*/
865 /* genRet - generate code for return statement */
866 /*-----------------------------------------------------------------*/
867 static void genRet (iCode * ic) {
870 printIc (0, "genRet", ic, 0, 0, 0);
872 printIc (0, "genRet", ic, 0, 1, 0);
873 aopOp(IC_LEFT(ic), TRUE, TRUE);
874 switch (AOP_SIZE(IC_LEFT(ic)))
877 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
878 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
881 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
884 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
887 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
894 emitcode ("jmp", "%05d$", returnLabel->key+100);
897 /*-----------------------------------------------------------------*/
898 /* genLabel - generates a label */
899 /*-----------------------------------------------------------------*/
900 static void genLabel (iCode * ic) {
901 /* special case never generate */
902 if (IC_LABEL (ic) == entryLabel)
905 emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
906 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
909 /*-----------------------------------------------------------------*/
910 /* genGoto - generates a jmp */
911 /*-----------------------------------------------------------------*/
912 static void genGoto (iCode * ic) {
913 emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
914 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
917 /*-----------------------------------------------------------------*/
918 /* genPlus - generates code for addition */
919 /*-----------------------------------------------------------------*/
920 static void genPlus (iCode * ic) {
921 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
925 printIc (0, "genPlus", ic, 1,1,1);
927 size=aopOp(result, TRUE, TRUE);
929 /* if left is a literal, then exchange them */
930 if (IS_LITERAL(operandType(left))) {
931 operand *tmp = right;
936 if (aopIsBit(result)) {
937 if (IS_LITERAL(operandType(right))) {
938 if (operandLitValue(right)) {
939 emitcode ("setb", AOP_NAME(result)[0]);
942 aopOp(left, TRUE, TRUE);
943 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
946 bailOut("genPlus: unfinished genPlus bit");
949 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
950 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
952 // special case for "* = * + char", needs a closer look
953 // heck, this shouldn't have come here but bug-223113 does
954 if (size==3 && AOP_SIZE(right)==1) {
955 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
956 emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
957 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
958 emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
959 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
963 // special case for "xdata * = xdata * + char", needs a closer look
964 // heck, this shouldn't have come here but bug-441448 does
965 if (size==2 && AOP_SIZE(right)==1) {
966 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
967 emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
968 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
969 emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
978 if (!aopEqual(result->aop, left->aop, 0)) {
979 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
981 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
983 if (!aopEqual(result->aop, left->aop, 1)) {
984 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
989 emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
995 /*-----------------------------------------------------------------*/
996 /* genMinus - generates code for subtraction */
997 /*-----------------------------------------------------------------*/
998 static void genMinus (iCode * ic) {
999 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1003 printIc (0, "genMinus", ic, 1,1,1);
1005 size=aopOp(result, TRUE, TRUE);
1007 /* if left is a literal, then exchange them */
1008 if (IS_LITERAL(operandType(left))) {
1009 operand *tmp = right;
1014 if (aopIsBit(result)) {
1015 if (IS_LITERAL(operandType(right))) {
1016 if (operandLitValue(right)) {
1017 emitcode ("clr", AOP_NAME(result)[0]);
1020 aopOp(left, TRUE, TRUE);
1021 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1024 bailOut("genPlus: unfinished genPlus bit");
1027 if (isOperandEqual(result,left)) {
1028 left->aop=result->aop;
1030 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1032 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1039 if (!aopEqual(result->aop, left->aop, 0)) {
1040 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1042 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1044 if (!aopEqual(result->aop, left->aop, 1)) {
1045 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1050 emitcode ("subb.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1056 /*-----------------------------------------------------------------*/
1057 /* genMult - generates code for multiplication */
1058 /*-----------------------------------------------------------------*/
1059 static void genMult (iCode * ic) {
1060 printIc (0, "genMult", ic, 1,1,1);
1063 /*-----------------------------------------------------------------*/
1064 /* genDiv - generates code for division */
1065 /*-----------------------------------------------------------------*/
1066 static void genDiv (iCode * ic) {
1067 printIc (0, "genDiv", ic, 1,1,1);
1070 /*-----------------------------------------------------------------*/
1071 /* genMod - generates code for division */
1072 /*-----------------------------------------------------------------*/
1073 static void genMod (iCode * ic) {
1074 printIc (0, "genMod", ic, 1,1,1);
1077 /*-----------------------------------------------------------------*/
1078 /* ifxForOp - returns the icode containing the ifx for operand */
1079 /*-----------------------------------------------------------------*/
1080 static iCode *ifxForOp (operand * op, iCode * ic) {
1081 /* if true symbol then needs to be assigned */
1082 if (IS_TRUE_SYMOP (op))
1085 /* if this has register type condition and
1086 the next instruction is ifx with the same operand
1087 and live to of the operand is upto the ifx only then */
1089 ic->next->op == IFX &&
1090 IC_COND (ic->next)->key == op->key &&
1091 OP_SYMBOL (op)->liveTo <= ic->next->seq)
1097 /*-----------------------------------------------------------------*/
1098 /* genCmp - compares whatever */
1099 /*-----------------------------------------------------------------*/
1100 static void genCmp (iCode * ic, char *trueInstr, char *falseInstr) {
1101 iCode *ifx=ifxForOp(IC_RESULT(ic),ic);
1102 operand *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1109 bailOut("genCmp: no ifx");
1114 size=aopOp(left, TRUE, TRUE);
1115 aopOp(right, !aopIsPtr(left), TRUE);
1119 jlbl=IC_TRUE(ifx)->key+100;
1122 jlbl=IC_FALSE(ifx)->key+100;
1130 emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1131 emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1133 bailOut("genCmp: size > 2");
1137 /*-----------------------------------------------------------------*/
1138 /* genCmpEq :- generates code for equal to */
1139 /*-----------------------------------------------------------------*/
1140 static void genCmpEq (iCode * ic) {
1141 printIc (0, "genCmpEq", ic, 0,1,1);
1142 genCmp(ic, "beq", "bne"); // no sign
1145 /*-----------------------------------------------------------------*/
1146 /* genCmpGt :- greater than comparison */
1147 /*-----------------------------------------------------------------*/
1148 static void genCmpGt (iCode * ic) {
1149 printIc (0, "genCmpGt", ic, 0,1,1);
1150 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1151 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1152 genCmp(ic, "bg", "bl"); // unsigned
1154 genCmp(ic, "bgt", "ble"); // signed
1158 /*-----------------------------------------------------------------*/
1159 /* genCmpLt - less than comparisons */
1160 /*-----------------------------------------------------------------*/
1161 static void genCmpLt (iCode * ic) {
1162 printIc (0, "genCmpLt", ic, 0,1,1);
1163 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1164 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1165 genCmp(ic, "bcs", "bcc"); // unsigned
1167 genCmp(ic, "blt", "bge"); // signed
1171 /*-----------------------------------------------------------------*/
1172 /* hasInc - operand is incremented before any other use */
1173 /*-----------------------------------------------------------------*/
1174 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1175 sym_link *type = operandType(op);
1176 sym_link *retype = getSpec (type);
1177 iCode *lic = ic->next;
1180 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1181 if (!IS_SYMOP(op)) return NULL;
1183 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1184 if (IS_AGGREGATE(type->next)) return NULL;
1185 if (osize != (isize = getSize(type->next))) return NULL;
1188 /* if operand of the form op = op + <sizeof *op> */
1189 if (lic->op == '+') {
1190 if (isOperandEqual(IC_LEFT(lic),op) &&
1191 //isOperandEqual(IC_RESULT(lic),op) &&
1192 isOperandLiteral(IC_RIGHT(lic)) &&
1193 operandLitValue(IC_RIGHT(lic)) == isize) {
1194 emitcode (";", "Found hasInc");
1198 /* if the operand used or deffed */
1199 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
1202 /* if GOTO or IFX */
1203 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1209 /*-----------------------------------------------------------------*/
1210 /* genAndOp - for && operation */
1211 /*-----------------------------------------------------------------*/
1212 static void genAndOp (iCode * ic) {
1213 printIc (0, "genAndOp(&&)", ic, 1,1,1);
1216 /*-----------------------------------------------------------------*/
1217 /* genOrOp - for || operation */
1218 /*-----------------------------------------------------------------*/
1219 static void genOrOp (iCode * ic) {
1220 printIc (0, "genOrOp(||)", ic, 1,1,1);
1223 /*-----------------------------------------------------------------*/
1224 /* genAnd - code for and */
1225 /*-----------------------------------------------------------------*/
1226 static void genAnd (iCode * ic, iCode * ifx) {
1227 printIc (0, "genAnd", ic, 1,1,1);
1230 /*-----------------------------------------------------------------*/
1231 /* genOr - code for or */
1232 /*-----------------------------------------------------------------*/
1233 static void genOr (iCode * ic, iCode * ifx) {
1234 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1238 printIc (0, "genOr", ic, 1,1,1);
1240 size=aopOp(result, TRUE, TRUE);
1242 /* if left is a literal, then exchange them */
1243 if (IS_LITERAL(operandType(left))) {
1244 operand *tmp = right;
1249 if (aopIsBit(result)) {
1250 if (IS_LITERAL(operandType(right))) {
1251 if (operandLitValue(right)) {
1252 emitcode ("setb", AOP_NAME(result)[0]);
1255 aopOp(left, TRUE, TRUE);
1256 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1261 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1262 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1269 if (!aopEqual(result->aop, left->aop, 0)) {
1270 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1272 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1274 if (!aopEqual(result->aop, left->aop, 1)) {
1275 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1277 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1282 /*-----------------------------------------------------------------*/
1283 /* genXor - code for xclusive or */
1284 /*-----------------------------------------------------------------*/
1285 static void genXor (iCode * ic, iCode * ifx) {
1286 printIc (0, "genXor", ic, 1,1,1);
1289 /*-----------------------------------------------------------------*/
1290 /* genInline - write the inline code out */
1291 /*-----------------------------------------------------------------*/
1292 static void genInline (iCode * ic) {
1294 printIc (0, "genInline", ic, 0,0,0);
1296 emitcode ("", IC_INLINE(ic));
1299 /*-----------------------------------------------------------------*/
1300 /* genRRC - rotate right with carry */
1301 /*-----------------------------------------------------------------*/
1302 static void genRRC (iCode * ic) {
1303 printIc (0, "genRRC", ic, 1,1,0);
1306 /*-----------------------------------------------------------------*/
1307 /* genRLC - generate code for rotate left with carry */
1308 /*-----------------------------------------------------------------*/
1309 static void genRLC (iCode * ic) {
1310 printIc (0, "genRLC", ic, 1,1,0);
1313 /*-----------------------------------------------------------------*/
1314 /* genGetHbit - generates code get highest order bit */
1315 /*-----------------------------------------------------------------*/
1316 static void genGetHbit (iCode * ic) {
1317 printIc (0, "genGetHbit", ic, 1,1,0);
1320 /*-----------------------------------------------------------------*/
1321 /* genLeftShift - generates code for left shifting */
1322 /*-----------------------------------------------------------------*/
1323 static void genLeftShift (iCode * ic) {
1324 printIc (0, "genLeftShift", ic, 1,1,1);
1327 /*-----------------------------------------------------------------*/
1328 /* genRightShift - generate code for right shifting */
1329 /*-----------------------------------------------------------------*/
1330 static void genRightShift (iCode * ic) {
1331 printIc (0, "genRightShift", ic, 1,1,1);
1334 /*-----------------------------------------------------------------*/
1335 /* genPointerGet - generate code for pointer get */
1336 /*-----------------------------------------------------------------*/
1337 static void genPointerGet (iCode * ic, iCode *pi) {
1338 char *instr, *scratchReg;
1339 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1340 bool codePointer=IS_CODEPTR(operandType(left));
1344 printIc (0, "genPointerGet pi", ic, 1,1,0);
1346 printIc (0, "genPointerGet", ic, 1,1,0);
1349 if (!IS_PTR(operandType(left))) {
1350 bailOut ("genPointerGet: pointer required");
1353 aopOp(left,FALSE,FALSE);
1354 size=aopOp(result,TRUE,aopIsDir(left));
1356 if (IS_GENPTR(operandType(left))) {
1357 symbol *tlbl1=newiTempLabel(NULL);
1358 symbol *tlbl2=newiTempLabel(NULL);
1359 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1360 emitcode ("beq", "%05d$", tlbl1->key+100);
1363 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1366 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1370 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1372 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1375 emitcode ("br", "%05d$", tlbl2->key+100);
1376 emitcode ("", "%05d$:", tlbl1->key+100);
1379 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1382 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1383 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1387 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1389 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1392 emitcode ("", "%05d$:", tlbl2->key+100);
1396 switch (AOP_TYPE(left))
1399 emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1400 sprintf (AOP_NAME(left)[0], "r1");
1418 if (AOP_TYPE(result)==AOP_STK) {
1419 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1420 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1423 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
1428 emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1429 emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1431 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
1445 if (AOP_TYPE(result)==AOP_STK) {
1446 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1447 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1450 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1454 emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1456 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1464 bailOut ("genPointerGet");
1467 /*-----------------------------------------------------------------*/
1468 /* genPointerSet - stores the value into a pointer location */
1469 /*-----------------------------------------------------------------*/
1470 static void genPointerSet (iCode * ic, iCode *pi) {
1472 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1475 printIc (0, "genPointerSet", ic, 1,0,1);
1477 if (!IS_PTR(operandType(result))) {
1478 bailOut ("genPointerSet: pointer required");
1481 aopOp(result,FALSE,FALSE);
1482 size=aopOp(right,FALSE, FALSE);
1484 if (IS_GENPTR(operandType(result))) {
1485 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1486 AOP_NAME(result)[0], AOP_NAME(result)[1],
1487 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1491 switch (AOP_TYPE(right))
1501 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1504 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1511 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1512 AOP_NAME(right)[1]);
1514 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1515 AOP_NAME(right)[1]);
1520 bailOut ("genPointerSet");
1523 /*-----------------------------------------------------------------*/
1524 /* genIfx - generate code for Ifx statement */
1525 /*-----------------------------------------------------------------*/
1526 static void genIfx (iCode * ic, iCode * popIc) {
1530 symbol *jlbl, *tlbl=newiTempLabel(NULL);
1531 operand *cond=IC_COND(ic);
1533 emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s",
1534 ic->lineno, printOp(cond),
1535 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1536 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1538 size=aopOp(cond,TRUE,TRUE);
1548 switch (AOP_TYPE(cond) )
1551 emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$",
1552 AOP_NAME(cond)[0], tlbl->key+100);
1553 emitcode ("jmp", "%05d$", jlbl->key+100);
1554 emitcode ("", "%05d$:", tlbl->key+100);
1565 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1566 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1569 // generic pointer, forget the generic part
1571 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1572 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1575 emitcode ("jmp", "%05d$", jlbl->key+100);
1576 emitcode ("", "%05d$:", tlbl->key+100);
1582 /*-----------------------------------------------------------------*/
1583 /* genAddrOf - generates code for address of */
1584 /*-----------------------------------------------------------------*/
1585 static void genAddrOf (iCode * ic) {
1587 operand *left=IC_LEFT(ic);
1589 printIc (0, "genAddrOf", ic, 1,1,0);
1591 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1593 if (isOperandOnStack(left)) {
1594 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1595 getStackOffset(OP_SYMBOL(left)->stack));
1597 // this must be a generic pointer
1598 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1603 if (isOperandInDirSpace(left) ||
1604 isOperandInFarSpace(left) ||
1605 isOperandInCodeSpace(left)) {
1606 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1607 OP_SYMBOL(left)->rname);
1609 // this must be a generic pointer
1610 int space=0; // dir space
1611 if (isOperandInFarSpace(left)) {
1613 } else if (isOperandInCodeSpace(left)) {
1616 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1621 bailOut("genAddrOf");
1624 /*-----------------------------------------------------------------*/
1625 /* genAssign - generate code for assignment */
1626 /*-----------------------------------------------------------------*/
1627 static void genAssign (iCode * ic) {
1628 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1632 printIc (0, "genAssign", ic, 1,0,1);
1634 if (!IS_SYMOP(result)) {
1635 bailOut("genAssign: result is not a symbol");
1638 aopOp(result, TRUE, TRUE);
1639 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1640 size=AOP_SIZE(result);
1642 /* if result is a bit */
1643 if (AOP_TYPE(result) == AOP_BIT) {
1644 /* if right is literal, we know what the value is */
1645 if (AOP_TYPE(right) == AOP_LIT) {
1646 if (operandLitValue(right)) {
1647 emitcode ("setb", AOP_NAME(result)[0]);
1649 emitcode ("clr", AOP_NAME(result)[0]);
1653 /* if right is also a bit */
1654 if (AOP_TYPE(right) == AOP_BIT) {
1655 emitcode ("mov", "c,%s", AOP_NAME(right));
1656 emitcode ("mov", "%s,c", AOP_NAME(result));
1660 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1664 // TODO: if (-8 >= right==lit <= 7) instr=MOVS
1671 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1678 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1683 /*-----------------------------------------------------------------*/
1684 /* genJumpTab - genrates code for jump table */
1685 /*-----------------------------------------------------------------*/
1686 static void genJumpTab (iCode * ic) {
1687 printIc (0, "genJumpTab", ic, 0,0,0);
1690 /*-----------------------------------------------------------------*/
1691 /* genCast - gen code for casting */
1692 /*-----------------------------------------------------------------*/
1693 static void genCast (iCode * ic) {
1695 operand *result=IC_RESULT(ic);
1696 operand *right=IC_RIGHT(ic);
1697 sym_link *ctype=operandType(IC_LEFT(ic));
1698 sym_link *rtype=operandType(IC_RIGHT(ic));
1699 sym_link *etype=getSpec(rtype);
1700 short ptrType, signedness;
1702 printIc (0, "genCast", ic, 1,1,1);
1704 aopOp(result, TRUE, TRUE);
1705 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1706 size=AOP_SIZE(result);
1708 /* if result is a bit */
1709 if (AOP_TYPE(result) == AOP_BIT) {
1710 /* if right is literal, we know what the value is */
1711 if (AOP_TYPE(right) == AOP_LIT) {
1712 if (operandLitValue(right)) {
1713 emitcode ("setb", AOP_NAME(result)[0]);
1715 emitcode ("clr", AOP_NAME(result)[0]);
1719 /* if right is also a bit */
1720 if (AOP_TYPE(right) == AOP_BIT) {
1721 emitcode ("mov", "c,%s", AOP_NAME(right));
1722 emitcode ("mov", "%s,c", AOP_NAME(result));
1726 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1730 /* if right is a bit */
1731 if (AOP_TYPE(right)==AOP_BIT) {
1732 emitcode ("mov", "c,%s", AOP_NAME(right));
1733 emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1734 emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1736 emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1741 /* if the result is of type pointer */
1742 if (IS_PTR (ctype)) {
1744 if (AOP_SIZE(right)>1) {
1745 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1747 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1748 emitcode ("sext", "r1h");
1749 emitcode ("mov", "%s,r1", AOP_NAME(result)[0]);
1752 /* if pointer to generic pointer */
1753 if (IS_GENPTR (ctype)) {
1755 if (IS_GENPTR (rtype)) {
1756 bailOut("genCast: gptr -> gptr");
1759 if (IS_PTR (rtype)) {
1760 ptrType = DCL_TYPE (rtype);
1762 /* we have to go by the storage class */
1763 if (!SPEC_OCLS(etype)) {
1764 ptrType=0; // hush the compiler
1765 bailOut("genCast: unknown storage class");
1767 ptrType = PTR_TYPE (SPEC_OCLS (etype));
1771 /* the generic part depends on the type */
1775 emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1778 emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1781 emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1784 bailOut("genCast: got unknown storage class");
1790 /* do we have to sign extend? */
1791 signedness = SPEC_USIGN(rtype);
1793 /* now depending on the size */
1794 switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1798 emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1803 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1806 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1808 emitcode("sext", "%s", AOP_NAME(result)[1]);
1810 emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1815 emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1817 emitcode("sext", "r1h");
1819 emitcode("mov", "r1h,#0");
1821 emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1824 // fall through: case 0x41
1826 emitcode("sext", "r1");
1828 emitcode("mov", "r1,#0");
1830 emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1834 emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1835 emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1838 fprintf(stderr, "genCast: unknown size: %d:%d\n",
1839 AOP_SIZE(result), AOP_SIZE(right));
1840 bailOut("genCast: unknown size");
1844 /*-----------------------------------------------------------------*/
1845 /* genDjnz - generate decrement & jump if not zero instrucion */
1846 /*-----------------------------------------------------------------*/
1847 static bool genDjnz (iCode * ic, iCode * ifx) {
1853 /* if the if condition has a false label
1854 then we cannot save */
1858 /* if the minus is not of the form
1860 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1861 !IS_OP_LITERAL (IC_RIGHT (ic)))
1864 if (operandLitValue (IC_RIGHT (ic)) != 1)
1867 /* if the size of this greater than two then no
1869 if (getSize (operandType (IC_RESULT (ic))) > 2)
1872 printIc (0, "genDjnz", ic, 1,1,1);
1874 /* otherwise we can save BIG */
1875 lbl = newiTempLabel (NULL);
1876 lbl1 = newiTempLabel (NULL);
1878 aopOp (IC_RESULT (ic), FALSE, TRUE);
1880 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1881 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1882 emitcode ("br", "%05d$", lbl1->key + 100);
1883 emitcode ("", "%05d$:", lbl->key + 100);
1884 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1885 emitcode ("", "%05d$:", lbl1->key + 100);
1889 bailOut("genDjnz: aop type");
1893 /*-----------------------------------------------------------------*/
1894 /* genReceive - generate code for a receive iCode */
1895 /*-----------------------------------------------------------------*/
1896 static void genReceive (iCode * ic) {
1897 printIc (0, "genReceive", ic, 1,0,0);
1900 /*-----------------------------------------------------------------*/
1901 /* gen51Code - generate code for 8051 based controllers */
1902 /*-----------------------------------------------------------------*/
1903 void genXA51Code (iCode * lic) {
1907 lineHead = lineCurr = NULL;
1909 /* if debug information required */
1910 if (options.debug && currFunc)
1912 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
1914 if (IS_STATIC (currFunc->etype))
1915 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
1917 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
1921 for (ic = lic; ic; ic = ic->next) {
1922 if (ic->lineno && cln != ic->lineno) {
1923 if (options.debug) {
1925 emitcode ("", "C$%s$%d$%d$%d ==.",
1926 FileBaseName (ic->filename), ic->lineno,
1927 ic->level, ic->block);
1930 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1931 printCLine(ic->filename, ic->lineno));
1934 /* if the result is marked as
1935 spilt and rematerializable or code for
1936 this has already been generated then
1938 if (resultRemat (ic) || ic->generated)
1941 /* depending on the operation */
1961 /* IPOP happens only when trying to restore a
1962 spilt live range, if there is an ifx statement
1963 following this pop then the if statement might
1964 be using some of the registers being popped which
1965 would destory the contents of the register so
1966 we need to check for this condition and handle it */
1968 ic->next->op == IFX &&
1969 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1970 genIfx (ic->next, ic);
1988 genEndFunction (ic);
2008 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
2036 /* note these two are xlated by algebraic equivalence
2037 during parsing SDCC.y */
2038 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2039 "got '>=' or '<=' shouldn't have come here");
2055 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
2059 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
2063 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
2090 case GET_VALUE_AT_ADDRESS:
2091 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
2095 if (POINTER_SET (ic))
2096 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2122 addSet (&_G.sendSet, ic);
2131 /* now we are ready to call the
2132 peep hole optimizer */
2133 if (!options.nopeep)
2134 peepHole (&lineHead);
2136 /* now do the actual printing */
2137 printLine (lineHead, codeOutFile);