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"
39 #include "SDCCpeeph.h"
43 #if defined(__BORLANDC__) || defined(_MSC_VER)
44 #define STRCASECMP stricmp
46 #define STRCASECMP strcasecmp
51 /* this is the down and dirty file with all kinds of
52 kludgy & hacky stuff. This is what it is all about
53 CODE GENERATION for a specific MCU . some of the
54 routines may be reusable, will have to see */
67 extern int xa51_ptrRegReq;
68 extern int xa51_nRegs;
69 extern FILE *codeOutFile;
71 static lineNode *lineHead = NULL;
72 static lineNode *lineCurr = NULL;
79 static char *MOV="mov";
80 static char *MOVB="mov.b";
81 static char *MOVW="mov.w";
82 static char *MOVC="movc";
83 static char *MOVCB="movc.b";
84 static char *MOVCW="movc.w";
86 static char *R1L="r1l";
89 void bailOut (char *mesg) {
90 fprintf (stderr, "%s: bailing out\n", mesg);
94 /*-----------------------------------------------------------------*/
95 /* emitcode - writes the code into a file : for now it is simple */
96 /*-----------------------------------------------------------------*/
97 static void emitcode (char *inst, char *fmt,...) {
99 char lb[INITIAL_INLINEASM];
100 unsigned char *lbp = lb;
107 sprintf (lb, "%s\t", inst);
109 sprintf (lb, "%s", inst);
110 vsprintf (lb + (strlen (lb)), fmt, ap);
113 vsprintf (lb, fmt, ap);
115 while (isspace (*lbp))
119 lineCurr = (lineCurr ?
120 connectLine (lineCurr, newLineNode (lb)) :
121 (lineHead = newLineNode (lb)));
122 lineCurr->isInline = _G.inLine;
123 lineCurr->isDebug = _G.debugLine;
127 /*-----------------------------------------------------------------*/
128 /* xa51_emitDebuggerSymbol - associate the current code location */
129 /* with a debugger symbol */
130 /*-----------------------------------------------------------------*/
132 xa51_emitDebuggerSymbol (char * debugSym)
135 emitcode ("", "%s ==.", debugSym);
140 char *getStackOffset(int stack) {
141 static char gsoBuf[1024];
142 sprintf (gsoBuf, "r7+(%d%+d%+d)", stack,
143 currFunc->stack, _G.nRegsSaved);
147 /*-----------------------------------------------------------------*/
148 /* newAsmop - creates a new asmOp */
149 /*-----------------------------------------------------------------*/
151 newAsmop (short type)
155 aop = Safe_calloc (1, sizeof (asmop));
160 char *aopTypeName(asmop *aop) {
163 case AOP_LIT: return "lit";
164 case AOP_REG: return "reg";
165 case AOP_DIR: return "dir";
166 case AOP_FAR: return "far";
167 case AOP_CODE: return "code";
168 case AOP_GPTR: return "gptr";
169 case AOP_STK: return "stack";
170 case AOP_IMMD: return "imm";
171 case AOP_BIT: return "bit";
176 /*-----------------------------------------------------------------*/
177 /* aopForSym - for a true symbol */
178 /*-----------------------------------------------------------------*/
179 static asmop *aopForSym(symbol *sym,
180 bool canUsePointer, bool canUseOffset) {
184 sym->aop = aop = newAsmop(0);
185 size=aop->size=getSize(sym->type);
187 // if the sym has registers
188 if (sym->nRegs && sym->regs[0]) {
190 sprintf (aop->name[0], sym->regs[0]->name);
192 sprintf (aop->name[1], sym->regs[1]->name);
199 if (!canUsePointer || !canUseOffset) {
204 emitcode ("mov.b", "r0l,[%s] ;aopForSym:stack:1", getStackOffset(sym->stack));
205 sprintf (aop->name[0], "r0l");
208 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:2", getStackOffset(sym->stack));
209 sprintf (aop->name[0], "r0");
212 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:3.w", getStackOffset(sym->stack));
213 sprintf (aop->name[0], "r0");
214 emitcode ("mov.b", "r1l,[%s] ;aopForSym:stack:3.b", getStackOffset(sym->stack+2));
215 sprintf (aop->name[1], "r1l");
218 emitcode ("mov.w", "r0,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack));
219 sprintf (aop->name[0], "r0");
220 emitcode ("mov.w", "r1,[%s] ;aopForSym:stack:4", getStackOffset(sym->stack+2));
221 sprintf (aop->name[1], "r1");
226 sprintf (aop->name[0], "[%s]", getStackOffset(sym->stack));
228 sprintf (aop->name[1], "[%s]", getStackOffset(sym->stack+2));
233 // if it has a spillLoc
234 if (sym->usl.spillLoc) {
235 return aopForSym (sym->usl.spillLoc, canUsePointer, canUseOffset);
239 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
241 sprintf (aop->name[0], sym->rname);
245 // if in direct space
246 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
248 sprintf (aop->name[0], sym->rname);
250 sprintf (aop->name[1], "%s+2", sym->rname);
256 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
257 if (!canUsePointer) {
262 emitcode (MOV, "r0,#%s", sym->rname);
263 emitcode (MOVC, "r0l,[r0+]");
264 sprintf (aop->name[0], "r0l");
267 emitcode (MOV, "r0,#%s", sym->rname);
268 emitcode (MOVC, "r0,[r0+]");
269 sprintf (aop->name[0], "r0");
272 emitcode (MOV, "r0,#%s", sym->rname);
273 emitcode (MOVC, "r0,[r0+]");
274 sprintf (aop->name[1], "r0");
275 emitcode (MOV, "r1l,[r0+]");
276 sprintf (aop->name[0], "r1l");
279 emitcode (MOV, "r0,#%s", sym->rname);
280 emitcode (MOVC, "r1,[r0+]");
281 emitcode (MOVC, "r0,[r0+]");
282 emitcode ("xch", "r0,r1");
283 sprintf (aop->name[0], "r0");
284 sprintf (aop->name[1], "r1");
290 emitcode ("mov", "r0,#%s ; aopForSym:code", sym->rname);
291 sprintf (aop->name[0], "[r0]");
293 sprintf (aop->name[1], "[r0+2]");
300 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
301 if (!canUsePointer) {
306 emitcode (MOV, "r0,#%s", sym->rname);
307 emitcode (MOV, "r0l,[r0]");
308 sprintf (aop->name[0], "r0l");
311 emitcode (MOV, "r0,#%s", sym->rname);
312 emitcode (MOV, "r0,[r0]");
313 sprintf (aop->name[0], "r0");
316 emitcode (MOV, "r0,#%s", sym->rname);
317 emitcode (MOV, "r1l,[r0+2]");
318 sprintf (aop->name[1], "r1l");
319 emitcode (MOV, "r0,[r0]");
320 sprintf (aop->name[0], "r0");
323 emitcode (MOV, "r0,#%s", sym->rname);
324 emitcode (MOV, "r1,[r0+2]");
325 sprintf (aop->name[1], "r1");
326 emitcode (MOV, "r0,[r0]");
327 sprintf (aop->name[0], "r0");
332 emitcode ("mov.w", "r0,#%s ; aopForSym:far", sym->rname);
333 sprintf (aop->name[0], "[r0]");
335 sprintf (aop->name[1], "[r0+2]");
341 bailOut("aopForSym");
345 /*-----------------------------------------------------------------*/
346 /* aopForVal - for a value */
347 /*-----------------------------------------------------------------*/
348 static asmop *aopForVal(operand *op) {
351 if (IS_OP_LITERAL(op)) {
352 op->aop = aop = newAsmop (AOP_LIT);
353 switch ((aop->size=getSize(operandType(op))))
356 sprintf (aop->name[0], "#0x%02x",
357 SPEC_CVAL(operandType(op)).v_int & 0xff);
358 sprintf (aop->name[1], "#0");
361 sprintf (aop->name[0], "#0x%04x",
362 SPEC_CVAL(operandType(op)).v_int & 0xffff);
363 sprintf (aop->name[1], "#0");
366 // must be a generic pointer, can only be zero
367 // ?? if (v!=0) fprintf (stderr, "invalid val op for gptr\n"); exit(1);
368 sprintf (aop->name[0], "#0x%04x",
369 SPEC_CVAL(operandType(op)).v_uint & 0xffff);
370 sprintf (aop->name[1], "#0");
373 sprintf (aop->name[0], "#0x%04x",
374 SPEC_CVAL(operandType(op)).v_ulong & 0xffff);
375 sprintf (aop->name[1], "#0x%04x",
376 SPEC_CVAL(operandType(op)).v_ulong >> 16);
379 bailOut("aopForVal");
386 op->aop = aop = newAsmop (AOP_IMMD);
387 switch ((aop->size=getSize(OP_SYMBOL(op)->type)))
391 sprintf (aop->name[0], "#%s", OP_SYMBOL(op)->rname);
393 case 3: // generic pointer
394 sprintf (aop->name[0], "#0x%02x", DCL_TYPE(operandType(op)));
395 sprintf (aop->name[1], "#%s", OP_SYMBOL(op)->rname);
400 bailOut ("aopForVal: unknown type");
404 static int aopOp(operand *op,
405 bool canUsePointer, bool canUseOffset) {
408 op->aop=aopForSym (OP_SYMBOL(op), canUsePointer, canUseOffset);
412 op->aop=aopForVal (op);
416 bailOut("aopOp: unexpected operand");
420 bool aopEqual(asmop *aop1, asmop *aop2, int offset) {
421 if (strcmp(aop1->name[offset], aop2->name[offset])) {
427 bool aopIsDir(operand *op) {
428 return AOP_TYPE(op)==AOP_DIR;
431 bool aopIsBit(operand *op) {
432 return AOP_TYPE(op)==AOP_BIT;
435 bool aopIsPtr(operand *op) {
436 if (AOP_TYPE(op)==AOP_STK ||
437 AOP_TYPE(op)==AOP_CODE ||
438 AOP_TYPE(op)==AOP_FAR) {
445 char *opRegName(operand *op, int offset, char *opName, bool decorate) {
448 if (OP_SYMBOL(op)->onStack) {
449 sprintf (opName, "[%s]", getStackOffset(OP_SYMBOL(op)->stack));
452 if (IS_TRUE_SYMOP(op))
453 return OP_SYMBOL(op)->rname;
454 else if (OP_SYMBOL(op)->regs[offset])
455 return OP_SYMBOL(op)->regs[offset]->name;
457 bailOut("opRegName: unknown regs");
461 switch (SPEC_NOUN(OP_VALUE(op)->type)) {
464 if (SPEC_CVAL(OP_VALUE(op)->type).v_int &&
465 SPEC_CVAL(OP_VALUE(op)->type).v_int != 1) {
466 bailOut("opRegName: invalid bit value");
470 sprintf (opName, "#%s0x%02x", decorate?"(char)":"",
471 SPEC_CVAL(OP_VALUE(op)->type).v_int);
474 if (SPEC_LONG(OP_VALUE(op)->type)) {
475 sprintf (opName, "#%s0x%02x", decorate?"(long)":"",
476 SPEC_CVAL(OP_VALUE(op)->type).v_long);
478 sprintf (opName, "#%s0x%02x", decorate?"(int)":"",
479 SPEC_CVAL(OP_VALUE(op)->type).v_int);
483 sprintf (opName, "#%s%f", decorate?"(float)":"",
484 SPEC_CVAL(OP_VALUE(op)->type).v_float);
487 bailOut("opRegName: unexpected noun");
491 bailOut("opRegName: unexpected operand type");
495 char * printOp (operand *op) {
496 static char line[132];
497 sym_link *optype=operandType(op);
498 bool isPtr = IS_PTR(optype);
501 symbol *sym=OP_SYMBOL(op);
502 if (!sym->regs[0] && SYM_SPIL_LOC(sym)) {
503 sym=SYM_SPIL_LOC(sym);
507 if (DCL_TYPE(optype)==FPOINTER)
508 strcat (line, "far * ");
509 else if (DCL_TYPE(optype)==CPOINTER)
510 strcat (line, "code * ");
511 else if (DCL_TYPE(optype)==GPOINTER)
512 strcat (line, "gen * ");
513 else if (DCL_TYPE(optype)==POINTER)
514 strcat (line, "near * ");
516 strcat (line, "unknown * ");
518 strcat (line, nounName(sym->etype));
520 strcat (line, sym->name);
523 sprintf (line, "(%s)%s:", nounName(sym->etype), sym->name);
526 strcat (line, sym->regs[0]->name);
529 strcat (line, sym->regs[1]->name);
534 sprintf (line+strlen(line), "stack%+d", sym->stack);
537 if (IN_CODESPACE(SPEC_OCLS(sym->etype))) {
538 strcat (line, "code");
541 if (IN_FARSPACE(SPEC_OCLS(sym->etype))) {
542 strcat (line, "far");
545 if (IN_BITSPACE(SPEC_OCLS(sym->etype))) {
546 strcat (line, "bit");
549 if (IN_DIRSPACE(SPEC_OCLS(sym->etype))) {
550 strcat (line, "dir");
553 strcat (line, "unknown");
555 } else if (IS_VALOP(op)) {
556 opRegName(op, 0, line, 1);
557 } else if (IS_TYPOP(op)) {
560 if (DCL_TYPE(optype)==FPOINTER)
561 strcat (line, "far * ");
562 else if (DCL_TYPE(optype)==CPOINTER)
563 strcat (line, "code * ");
564 else if (DCL_TYPE(optype)==GPOINTER)
565 strcat (line, "gen * ");
566 else if (DCL_TYPE(optype)==POINTER)
567 strcat (line, "near * ");
569 strcat (line, "unknown * ");
571 // forget about static, volatile, ... for now
572 if (SPEC_USIGN(operandType(op))) strcat (line, "unsigned ");
573 if (SPEC_LONG(operandType(op))) strcat (line, "long ");
574 strcat (line, nounName(operandType(op)));
577 bailOut("printOp: unexpected operand type");
582 void printIc (bool printToStderr,
583 char *op, iCode * ic, bool result, bool left, bool right) {
586 sprintf (line, "%s(%d)", op, ic->lineno);
588 strcat (line, " result=");
589 strcat (line, printOp (IC_RESULT(ic)));
592 strcat (line, " left=");
593 strcat (line, printOp (IC_LEFT(ic)));
596 strcat (line, " right=");
597 strcat (line, printOp (IC_RIGHT(ic)));
599 emitcode (";", line);
601 fprintf (stderr, "%s\n", line);
605 /*-----------------------------------------------------------------*/
606 /* toBoolean - return carry for operand!=0 */
607 /*-----------------------------------------------------------------*/
608 static char *toBoolean (operand * op) {
609 symbol *tlbl=newiTempLabel(NULL);
611 switch (AOP_SIZE(op))
615 emitcode ("cjne", "%s,#1,%05d$; %s", AOP_NAME(op), tlbl->key+100,
616 "This needs a second thought");
618 emitcode ("", "%05d$:", tlbl->key+100);
622 bailOut("toBoolean: unknown size");
626 /*-----------------------------------------------------------------*/
627 /* regsInCommon - two operands have some registers in common */
628 /*-----------------------------------------------------------------*/
629 static bool regsInCommon (operand * op1, operand * op2) {
633 /* if they have registers in common */
634 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
637 sym1 = OP_SYMBOL (op1);
638 sym2 = OP_SYMBOL (op2);
640 if (sym1->nRegs == 0 || sym2->nRegs == 0)
643 for (i = 0; i < sym1->nRegs; i++)
649 for (j = 0; j < sym2->nRegs; j++)
654 if (sym2->regs[j] == sym1->regs[i])
662 /*-----------------------------------------------------------------*/
663 /* resultRemat - result is rematerializable */
664 /*-----------------------------------------------------------------*/
665 static int resultRemat (iCode * ic) {
666 if (SKIP_IC (ic) || ic->op == IFX)
669 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
671 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
672 if (sym->remat && !POINTER_SET (ic))
679 /*-----------------------------------------------------------------*/
680 /* genNot - generate code for ! operation */
681 /*-----------------------------------------------------------------*/
682 static void genNot (iCode * ic) {
683 printIc (0, "genNot:", ic, 1,1,0);
686 /*-----------------------------------------------------------------*/
687 /* genCpl - generate code for complement */
688 /*-----------------------------------------------------------------*/
689 static void genCpl (iCode * ic) {
690 printIc (0, "genCpl", ic, 1,1,0);
693 /*-----------------------------------------------------------------*/
694 /* genUminus - unary minus code generation */
695 /*-----------------------------------------------------------------*/
696 static void genUminus (iCode * ic) {
697 printIc (0, "genUminus", ic, 1,1,0);
700 /*-----------------------------------------------------------------*/
701 /* genIpush - generate code for pushing */
702 /*-----------------------------------------------------------------*/
703 static void genIpush (iCode * ic) {
704 operand *left=IC_LEFT(ic);
706 printIc (0, "genIpush", ic, 0,1,0);
707 aopOp(left,FALSE,FALSE);
710 if (AOP_TYPE(left)==AOP_LIT) {
711 switch (AOP_SIZE(left))
714 emitcode ("mov", "r1l,%s", AOP_NAME(left)[0]);
715 emitcode ("push", "r1l");
719 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
720 emitcode ("push", "r1");
724 emitcode ("mov", "r1l,%s", AOP_NAME(left)[1]);
725 emitcode ("push", "r1l");
726 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
727 emitcode ("push", "r1");
731 emitcode ("mov", "r1,%s", AOP_NAME(left)[1]);
732 emitcode ("push", "r1");
733 emitcode ("mov", "r1,%s", AOP_NAME(left)[0]);
734 emitcode ("push", "r1");
739 if (AOP_SIZE(left)>2) {
740 emitcode ("push", "%s", AOP_NAME(left)[1]);
743 emitcode ("push", "%s", AOP_NAME(left)[0]);
748 /*-----------------------------------------------------------------*/
749 /* genIpop - recover the registers: can happen only for spilling */
750 /*-----------------------------------------------------------------*/
751 static void genIpop (iCode * ic) {
752 printIc (0, "genIpop", ic, 0,1,0);
755 /*-----------------------------------------------------------------*/
756 /* genCall - generates a call statement */
757 /*-----------------------------------------------------------------*/
758 static void genCall (iCode * ic) {
759 operand *result=IC_RESULT(ic);
761 emitcode (";", "genCall(%d) %s result=%s", ic->lineno,
762 OP_SYMBOL(IC_LEFT(ic))->name,
763 printOp (IC_RESULT(ic)));
764 emitcode ("call", "%s", OP_SYMBOL(IC_LEFT(ic))->rname);
766 /* readjust the stack if we have pushed some parms */
767 if (_G.parmsPushed) {
768 emitcode ("add", "r7,#0x%02x", _G.parmsPushed*2);
772 /* if we need to assign a result value */
773 if (IS_ITEMP (IC_RESULT(ic)) &&
774 OP_SYMBOL (IC_RESULT (ic))->nRegs) {
775 aopOp(result,FALSE,FALSE);
776 switch (AOP_SIZE(result))
779 emitcode ("mov", "%s,r0l", AOP_NAME(result)[0]);
782 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
786 emitcode ("mov", "%s,r1l", AOP_NAME(result)[1]);
787 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
790 emitcode ("mov", "%s,r1", AOP_NAME(result)[1]);
791 emitcode ("mov", "%s,r0", AOP_NAME(result)[0]);
798 /*-----------------------------------------------------------------*/
799 /* genPcall - generates a call by pointer statement */
800 /*-----------------------------------------------------------------*/
802 genPcall (iCode * ic)
804 emitcode (";", "genPcall %s\n", OP_SYMBOL(IC_LEFT(ic))->name);
807 /*-----------------------------------------------------------------*/
808 /* genFunction - generated code for function entry */
809 /*-----------------------------------------------------------------*/
810 static void genFunction (iCode * ic) {
811 symbol *sym=OP_SYMBOL(IC_LEFT(ic));
812 sym_link *type=sym->type;
814 emitcode (";", "genFunction %s", sym->rname);
816 /* print the allocation information */
817 printAllocInfo (currFunc, codeOutFile);
819 emitcode ("", "%s:", sym->rname);
821 if (IFFUNC_ISNAKED(type))
823 emitcode(";", "naked function: no prologue.");
827 /* adjust the stack for locals used in this function */
829 emitcode ("sub", "r7,#%d\t; create stack space for locals", sym->stack);
833 /*-----------------------------------------------------------------*/
834 /* genEndFunction - generates epilogue for functions */
835 /*-----------------------------------------------------------------*/
837 genEndFunction (iCode * ic)
839 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
841 printIc (0, "genEndFunction", ic, 0,0,0);
843 if (IFFUNC_ISNAKED(sym->type)) {
844 emitcode(";", "naked function: no epilogue.");
845 if (options.debug && currFunc)
846 debugFile->writeEndFunction (currFunc, ic, 0);
850 /* readjust the stock for locals used in this function */
852 emitcode ("add", "r7,#%d\t; release stack space for locals", sym->stack);
855 if (options.debug && currFunc) {
856 debugFile->writeEndFunction (currFunc, ic, 1);
859 if (IFFUNC_ISISR(sym->type)) {
860 emitcode ("reti", "");
862 emitcode ("ret", "");
866 /*-----------------------------------------------------------------*/
867 /* genRet - generate code for return statement */
868 /*-----------------------------------------------------------------*/
869 static void genRet (iCode * ic) {
872 printIc (0, "genRet", ic, 0, 0, 0);
874 printIc (0, "genRet", ic, 0, 1, 0);
875 aopOp(IC_LEFT(ic), TRUE, TRUE);
876 switch (AOP_SIZE(IC_LEFT(ic)))
879 emitcode ("mov", "r1,%s", AOP_NAME(IC_LEFT(ic))[1]);
880 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
883 emitcode ("mov", "r1l,%s", AOP_NAME(IC_LEFT(ic))[1]);
886 emitcode ("mov", "r0,%s", AOP_NAME(IC_LEFT(ic))[0]);
889 emitcode ("mov", "r0l,%s", AOP_NAME(IC_LEFT(ic))[0]);
896 emitcode ("jmp", "%05d$", returnLabel->key+100);
899 /*-----------------------------------------------------------------*/
900 /* genLabel - generates a label */
901 /*-----------------------------------------------------------------*/
902 static void genLabel (iCode * ic) {
903 /* special case never generate */
904 if (IC_LABEL (ic) == entryLabel)
907 emitcode (";", "genLabel(%d) %s", ic->lineno, IC_LABEL(ic)->name);
908 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
911 /*-----------------------------------------------------------------*/
912 /* genGoto - generates a jmp */
913 /*-----------------------------------------------------------------*/
914 static void genGoto (iCode * ic) {
915 emitcode (";", "genGoto(%d) %s", ic->lineno, IC_LABEL(ic)->name);
916 emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
919 /*-----------------------------------------------------------------*/
920 /* genPlus - generates code for addition */
921 /*-----------------------------------------------------------------*/
922 static void genPlus (iCode * ic) {
923 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
927 printIc (0, "genPlus", ic, 1,1,1);
929 size=aopOp(result, TRUE, TRUE);
931 /* if left is a literal, then exchange them */
932 if (IS_LITERAL(operandType(left))) {
933 operand *tmp = right;
938 if (aopIsBit(result)) {
939 if (IS_LITERAL(operandType(right))) {
940 if (operandLitValue(right)) {
941 emitcode ("setb", AOP_NAME(result)[0]);
944 aopOp(left, TRUE, TRUE);
945 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
948 bailOut("genPlus: unfinished genPlus bit");
951 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
952 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
954 // special case for "* = * + char", needs a closer look
955 // heck, this shouldn't have come here but bug-223113 does
956 if (size==3 && AOP_SIZE(right)==1) {
957 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
958 emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
959 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
960 emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
961 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
965 // special case for "xdata * = xdata * + char", needs a closer look
966 // heck, this shouldn't have come here but bug-441448 does
967 if (size==2 && AOP_SIZE(right)==1) {
968 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
969 emitcode ("mov", "r1h,#0"); // ptr arith unsigned????????????
970 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
971 emitcode ("add.w", "%s,r1", AOP_NAME(result)[0]);
980 if (!aopEqual(result->aop, left->aop, 0)) {
981 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
983 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
985 if (!aopEqual(result->aop, left->aop, 1)) {
986 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
991 emitcode ("addc.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
997 /*-----------------------------------------------------------------*/
998 /* genMinus - generates code for subtraction */
999 /*-----------------------------------------------------------------*/
1000 static void genMinus (iCode * ic) {
1001 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1005 printIc (0, "genMinus", ic, 1,1,1);
1007 size=aopOp(result, TRUE, TRUE);
1009 /* if left is a literal, then exchange them */
1010 if (IS_LITERAL(operandType(left))) {
1011 operand *tmp = right;
1016 if (aopIsBit(result)) {
1017 if (IS_LITERAL(operandType(right))) {
1018 if (operandLitValue(right)) {
1019 emitcode ("clr", AOP_NAME(result)[0]);
1022 aopOp(left, TRUE, TRUE);
1023 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1026 bailOut("genPlus: unfinished genPlus bit");
1029 if (isOperandEqual(result,left)) {
1030 left->aop=result->aop;
1032 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1034 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1041 if (!aopEqual(result->aop, left->aop, 0)) {
1042 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1044 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1046 if (!aopEqual(result->aop, left->aop, 1)) {
1047 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1052 emitcode ("subb.w", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1058 /*-----------------------------------------------------------------*/
1059 /* genMult - generates code for multiplication */
1060 /*-----------------------------------------------------------------*/
1061 static void genMult (iCode * ic) {
1062 printIc (0, "genMult", ic, 1,1,1);
1065 /*-----------------------------------------------------------------*/
1066 /* genDiv - generates code for division */
1067 /*-----------------------------------------------------------------*/
1068 static void genDiv (iCode * ic) {
1069 printIc (0, "genDiv", ic, 1,1,1);
1072 /*-----------------------------------------------------------------*/
1073 /* genMod - generates code for division */
1074 /*-----------------------------------------------------------------*/
1075 static void genMod (iCode * ic) {
1076 printIc (0, "genMod", ic, 1,1,1);
1079 /*-----------------------------------------------------------------*/
1080 /* ifxForOp - returns the icode containing the ifx for operand */
1081 /*-----------------------------------------------------------------*/
1082 static iCode *ifxForOp (operand * op, iCode * ic) {
1083 /* if true symbol then needs to be assigned */
1084 if (IS_TRUE_SYMOP (op))
1087 /* if this has register type condition and
1088 the next instruction is ifx with the same operand
1089 and live to of the operand is upto the ifx only then */
1091 ic->next->op == IFX &&
1092 IC_COND (ic->next)->key == op->key &&
1093 OP_SYMBOL (op)->liveTo <= ic->next->seq)
1099 /*-----------------------------------------------------------------*/
1100 /* genCmp - compares whatever */
1101 /*-----------------------------------------------------------------*/
1102 static void genCmp (iCode * ic, char *trueInstr, char *falseInstr) {
1103 iCode *ifx=ifxForOp(IC_RESULT(ic),ic);
1104 operand *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1111 size=aopOp(left, TRUE, TRUE);
1112 aopOp(right, !aopIsPtr(left), TRUE);
1122 jlbl=IC_TRUE(ifx)->key+100;
1125 jlbl=IC_FALSE(ifx)->key+100;
1129 aopOp(IC_RESULT(ic), !aopIsPtr(left), TRUE);
1130 jlbl=newiTempLabel(NULL)->key+100;
1131 emitcode("mov", "%s,#-1", AOP_NAME(IC_RESULT(ic))[0]);
1132 emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1133 emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1134 emitcode("cpl", "%s", AOP_NAME(IC_RESULT(ic))[0]);
1135 emitcode("", "%05d$:", jlbl);
1137 emitcode(instr, "%s,%s", AOP_NAME(left)[0], AOP_NAME(right)[0]);
1138 emitcode(isTrue ? trueInstr : falseInstr, "%05d$", jlbl);
1143 bailOut("genCmp: size > 2");
1148 /*-----------------------------------------------------------------*/
1149 /* genCmpEq :- generates code for equal to */
1150 /*-----------------------------------------------------------------*/
1151 static void genCmpEq (iCode * ic) {
1152 printIc (0, "genCmpEq", ic, 0,1,1);
1153 genCmp(ic, "beq", "bne"); // no sign
1156 /*-----------------------------------------------------------------*/
1157 /* genCmpGt :- greater than comparison */
1158 /*-----------------------------------------------------------------*/
1159 static void genCmpGt (iCode * ic) {
1160 printIc (0, "genCmpGt", ic, 0,1,1);
1161 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1162 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1163 genCmp(ic, "bg", "bl"); // unsigned
1165 genCmp(ic, "bgt", "ble"); // signed
1169 /*-----------------------------------------------------------------*/
1170 /* genCmpLt - less than comparisons */
1171 /*-----------------------------------------------------------------*/
1172 static void genCmpLt (iCode * ic) {
1173 printIc (0, "genCmpLt", ic, 0,1,1);
1174 if (SPEC_USIGN(operandType(IC_LEFT(ic))) ||
1175 SPEC_USIGN(operandType(IC_RIGHT(ic)))) {
1176 genCmp(ic, "bcs", "bcc"); // unsigned
1178 genCmp(ic, "blt", "bge"); // signed
1182 /*-----------------------------------------------------------------*/
1183 /* hasInc - operand is incremented before any other use */
1184 /*-----------------------------------------------------------------*/
1185 static iCode *hasInc (operand *op, iCode *ic, int osize) {
1186 sym_link *type = operandType(op);
1187 sym_link *retype = getSpec (type);
1188 iCode *lic = ic->next;
1191 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
1192 if (!IS_SYMOP(op)) return NULL;
1194 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
1195 if (IS_AGGREGATE(type->next)) return NULL;
1196 if (osize != (isize = getSize(type->next))) return NULL;
1199 /* if operand of the form op = op + <sizeof *op> */
1200 if (lic->op == '+') {
1201 if (isOperandEqual(IC_LEFT(lic),op) &&
1202 //isOperandEqual(IC_RESULT(lic),op) &&
1203 isOperandLiteral(IC_RIGHT(lic)) &&
1204 operandLitValue(IC_RIGHT(lic)) == isize) {
1205 emitcode (";", "Found hasInc");
1209 /* if the operand used or deffed */
1210 if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
1213 /* if GOTO or IFX */
1214 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
1220 /*-----------------------------------------------------------------*/
1221 /* genAndOp - for && operation */
1222 /*-----------------------------------------------------------------*/
1223 static void genAndOp (iCode * ic) {
1224 printIc (0, "genAndOp(&&)", ic, 1,1,1);
1227 /*-----------------------------------------------------------------*/
1228 /* genOrOp - for || operation */
1229 /*-----------------------------------------------------------------*/
1230 static void genOrOp (iCode * ic) {
1231 printIc (0, "genOrOp(||)", ic, 1,1,1);
1234 /*-----------------------------------------------------------------*/
1235 /* genAnd - code for and */
1236 /*-----------------------------------------------------------------*/
1237 static void genAnd (iCode * ic, iCode * ifx) {
1238 printIc (0, "genAnd", ic, 1,1,1);
1241 /*-----------------------------------------------------------------*/
1242 /* genOr - code for or */
1243 /*-----------------------------------------------------------------*/
1244 static void genOr (iCode * ic, iCode * ifx) {
1245 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic), *right=IC_RIGHT(ic);
1249 printIc (0, "genOr", ic, 1,1,1);
1251 size=aopOp(result, TRUE, TRUE);
1253 /* if left is a literal, then exchange them */
1254 if (IS_LITERAL(operandType(left))) {
1255 operand *tmp = right;
1260 if (aopIsBit(result)) {
1261 if (IS_LITERAL(operandType(right))) {
1262 if (operandLitValue(right)) {
1263 emitcode ("setb", AOP_NAME(result)[0]);
1266 aopOp(left, TRUE, TRUE);
1267 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], toBoolean(left));
1272 aopOp(left, !aopIsPtr(result), !aopIsDir(result));
1273 aopOp(right, !aopIsPtr(result), !aopIsDir(result));
1280 if (!aopEqual(result->aop, left->aop, 0)) {
1281 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1283 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1285 if (!aopEqual(result->aop, left->aop, 1)) {
1286 emitcode ("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(left)[1]);
1288 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1293 /*-----------------------------------------------------------------*/
1294 /* genXor - code for xclusive or */
1295 /*-----------------------------------------------------------------*/
1296 static void genXor (iCode * ic, iCode * ifx) {
1297 printIc (0, "genXor", ic, 1,1,1);
1300 /*-----------------------------------------------------------------*/
1301 /* genInline - write the inline code out */
1302 /*-----------------------------------------------------------------*/
1303 static void genInline (iCode * ic) {
1305 printIc (0, "genInline", ic, 0,0,0);
1307 emitcode ("", IC_INLINE(ic));
1310 /*-----------------------------------------------------------------*/
1311 /* genRRC - rotate right with carry */
1312 /*-----------------------------------------------------------------*/
1313 static void genRRC (iCode * ic) {
1314 printIc (0, "genRRC", ic, 1,1,0);
1317 /*-----------------------------------------------------------------*/
1318 /* genRLC - generate code for rotate left with carry */
1319 /*-----------------------------------------------------------------*/
1320 static void genRLC (iCode * ic) {
1321 printIc (0, "genRLC", ic, 1,1,0);
1324 /*-----------------------------------------------------------------*/
1325 /* genGetHbit - generates code get highest order bit */
1326 /*-----------------------------------------------------------------*/
1327 static void genGetHbit (iCode * ic) {
1328 printIc (0, "genGetHbit", ic, 1,1,0);
1331 /*-----------------------------------------------------------------*/
1332 /* genLeftShift - generates code for left shifting */
1333 /*-----------------------------------------------------------------*/
1334 static void genLeftShift (iCode * ic) {
1335 printIc (0, "genLeftShift", ic, 1,1,1);
1338 /*-----------------------------------------------------------------*/
1339 /* genRightShift - generate code for right shifting */
1340 /*-----------------------------------------------------------------*/
1341 static void genRightShift (iCode * ic) {
1342 printIc (0, "genRightShift", ic, 1,1,1);
1345 /*-----------------------------------------------------------------*/
1346 /* genPointerGet - generate code for pointer get */
1347 /*-----------------------------------------------------------------*/
1348 static void genPointerGet (iCode * ic, iCode *pi) {
1349 char *instr, *scratchReg;
1350 operand *result=IC_RESULT(ic), *left=IC_LEFT(ic);
1351 bool codePointer=IS_CODEPTR(operandType(left));
1355 printIc (0, "genPointerGet pi", ic, 1,1,0);
1357 printIc (0, "genPointerGet", ic, 1,1,0);
1360 if (!IS_PTR(operandType(left))) {
1361 bailOut ("genPointerGet: pointer required");
1364 aopOp(left,FALSE,FALSE);
1365 size=aopOp(result,TRUE,aopIsDir(left));
1367 if (IS_GENPTR(operandType(left))) {
1368 symbol *tlbl1=newiTempLabel(NULL);
1369 symbol *tlbl2=newiTempLabel(NULL);
1370 emitcode ("cmp", "%s,#0x%02x", AOP_NAME(left)[1], CPOINTER);
1371 emitcode ("beq", "%05d$", tlbl1->key+100);
1374 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1377 emitcode ("mov", "%s,[%s]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1381 emitcode ("mov", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1383 emitcode ("mov", "%s,[%s+2]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1386 emitcode ("br", "%05d$", tlbl2->key+100);
1387 emitcode ("", "%05d$:", tlbl1->key+100);
1390 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[0], AOP_NAME(left)[0]);
1393 emitcode ("mov", "r0,%s", AOP_NAME(left)[0]);
1394 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[0]);
1398 emitcode ("movc", "%s,[%s+]", AOP_NAME(result)[1], AOP_NAME(left)[0]);
1400 emitcode ("movc", "%s,[r0+]", AOP_NAME(result)[1]);
1403 emitcode ("", "%05d$:", tlbl2->key+100);
1407 switch (AOP_TYPE(left))
1410 emitcode("mov","r1,%s", AOP_NAME(left)[0]);
1411 sprintf (AOP_NAME(left)[0], "r1");
1429 if (AOP_TYPE(result)==AOP_STK) {
1430 emitcode (MOV, "%s,[%s]", scratchReg, AOP_NAME(left)[0]);
1431 emitcode (MOV, "%s,%s", AOP_NAME(result)[0], scratchReg);
1434 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[0],
1439 emitcode (MOV, "r1,%s", AOP_NAME(left)[0]);
1440 emitcode (instr, "%s,[r1+]", AOP_NAME(result)[0]);
1442 emitcode (instr, "%s,[%s]", AOP_NAME(result)[0],
1456 if (AOP_TYPE(result)==AOP_STK) {
1457 emitcode (MOV, "%s,[%s+2]", scratchReg, AOP_NAME(left)[0]);
1458 emitcode (MOV, "%s,%s", AOP_NAME(result)[1], scratchReg);
1461 emitcode (instr, "%s,[%s+]", AOP_NAME(result)[1],
1465 emitcode (instr, "%s,[r1]", AOP_NAME(result)[1]);
1467 emitcode (instr, "%s,[%s+2]", AOP_NAME(result)[1],
1475 bailOut ("genPointerGet");
1478 /*-----------------------------------------------------------------*/
1479 /* genPointerSet - stores the value into a pointer location */
1480 /*-----------------------------------------------------------------*/
1481 static void genPointerSet (iCode * ic, iCode *pi) {
1483 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1486 printIc (0, "genPointerSet", ic, 1,0,1);
1488 if (!IS_PTR(operandType(result))) {
1489 bailOut ("genPointerSet: pointer required");
1492 aopOp(result,FALSE,FALSE);
1493 size=aopOp(right,FALSE, FALSE);
1495 if (IS_GENPTR(operandType(result))) {
1496 emitcode (";", "INLINE\t_gptrset ; [%s %s] = %s %s",
1497 AOP_NAME(result)[0], AOP_NAME(result)[1],
1498 AOP_NAME(right)[0], AOP_NAME(right)[1]);
1502 switch (AOP_TYPE(right))
1512 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1515 emitcode (instr, "[%s],%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1522 emitcode (instr, "[%s+],%s", AOP_NAME(result)[0],
1523 AOP_NAME(right)[1]);
1525 emitcode (instr, "[%s+2],%s", AOP_NAME(result)[0],
1526 AOP_NAME(right)[1]);
1531 bailOut ("genPointerSet");
1534 /*-----------------------------------------------------------------*/
1535 /* genIfx - generate code for Ifx statement */
1536 /*-----------------------------------------------------------------*/
1537 static void genIfx (iCode * ic, iCode * popIc) {
1541 symbol *jlbl, *tlbl=newiTempLabel(NULL);
1542 operand *cond=IC_COND(ic);
1544 emitcode (";", "genIfx(%d) cond=%s trueLabel:%s falseLabel:%s",
1545 ic->lineno, printOp(cond),
1546 IC_TRUE(ic) ? IC_TRUE(ic)->name : "NULL",
1547 IC_FALSE(ic) ? IC_FALSE(ic)->name : "NULL");
1549 size=aopOp(cond,TRUE,TRUE);
1559 switch (AOP_TYPE(cond) )
1562 emitcode (trueOrFalse ? "jnb" : "jb", "%s,%05d$",
1563 AOP_NAME(cond)[0], tlbl->key+100);
1564 emitcode ("jmp", "%05d$", jlbl->key+100);
1565 emitcode ("", "%05d$:", tlbl->key+100);
1576 emitcode (instr, "%s,#0", AOP_NAME(cond)[0]);
1577 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1580 // generic pointer, forget the generic part
1582 emitcode (instr, "%s,#0", AOP_NAME(cond)[1]);
1583 emitcode (trueOrFalse ? "beq" : "bne", "%05d$", tlbl->key+100);
1586 emitcode ("jmp", "%05d$", jlbl->key+100);
1587 emitcode ("", "%05d$:", tlbl->key+100);
1593 /*-----------------------------------------------------------------*/
1594 /* genAddrOf - generates code for address of */
1595 /*-----------------------------------------------------------------*/
1596 static void genAddrOf (iCode * ic) {
1598 operand *left=IC_LEFT(ic);
1600 printIc (0, "genAddrOf", ic, 1,1,0);
1602 size=aopOp (IC_RESULT(ic), FALSE, TRUE);
1604 if (isOperandOnStack(left)) {
1605 emitcode ("lea", "%s,%s", AOP_NAME(IC_RESULT(ic))[0],
1606 getStackOffset(OP_SYMBOL(left)->stack));
1608 // this must be a generic pointer
1609 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], FPOINTER);
1614 if (isOperandInDirSpace(left) ||
1615 isOperandInFarSpace(left) ||
1616 isOperandInCodeSpace(left)) {
1617 emitcode ("mov.w", "%s,#%s", AOP_NAME(IC_RESULT(ic))[0],
1618 OP_SYMBOL(left)->rname);
1620 // this must be a generic pointer
1621 int space=0; // dir space
1622 if (isOperandInFarSpace(left)) {
1624 } else if (isOperandInCodeSpace(left)) {
1627 emitcode ("mov.b", "%s,#0x%02x", AOP_NAME(IC_RESULT(ic))[1], space);
1632 bailOut("genAddrOf");
1635 /*-----------------------------------------------------------------*/
1636 /* genAssign - generate code for assignment */
1637 /*-----------------------------------------------------------------*/
1638 static void genAssign (iCode * ic) {
1639 operand *result=IC_RESULT(ic), *right=IC_RIGHT(ic);
1643 printIc (0, "genAssign", ic, 1,0,1);
1645 if (!IS_SYMOP(result)) {
1646 bailOut("genAssign: result is not a symbol");
1649 aopOp(result, TRUE, TRUE);
1650 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1651 size=AOP_SIZE(result);
1653 /* if result is a bit */
1654 if (AOP_TYPE(result) == AOP_BIT) {
1655 /* if right is literal, we know what the value is */
1656 if (AOP_TYPE(right) == AOP_LIT) {
1657 if (operandLitValue(right)) {
1658 emitcode ("setb", AOP_NAME(result)[0]);
1660 emitcode ("clr", AOP_NAME(result)[0]);
1664 /* if right is also a bit */
1665 if (AOP_TYPE(right) == AOP_BIT) {
1666 emitcode ("mov", "c,%s", AOP_NAME(right));
1667 emitcode ("mov", "%s,c", AOP_NAME(result));
1671 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1675 // TODO: if (-8 >= right==lit <= 7) instr=MOVS
1682 emitcode (instr, "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1689 emitcode (instr, "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1694 /*-----------------------------------------------------------------*/
1695 /* genJumpTab - genrates code for jump table */
1696 /*-----------------------------------------------------------------*/
1697 static void genJumpTab (iCode * ic) {
1698 printIc (0, "genJumpTab", ic, 0,0,0);
1701 /*-----------------------------------------------------------------*/
1702 /* genCast - gen code for casting */
1703 /*-----------------------------------------------------------------*/
1704 static void genCast (iCode * ic) {
1706 operand *result=IC_RESULT(ic);
1707 operand *right=IC_RIGHT(ic);
1708 sym_link *ctype=operandType(IC_LEFT(ic));
1709 sym_link *rtype=operandType(IC_RIGHT(ic));
1710 sym_link *etype=getSpec(rtype);
1711 short ptrType, signedness;
1713 printIc (0, "genCast", ic, 1,1,1);
1715 aopOp(result, TRUE, TRUE);
1716 aopOp(right, !aopIsPtr(result), AOP_TYPE(result)!=AOP_DIR);
1717 size=AOP_SIZE(result);
1719 /* if result is a bit */
1720 if (AOP_TYPE(result) == AOP_BIT) {
1721 /* if right is literal, we know what the value is */
1722 if (AOP_TYPE(right) == AOP_LIT) {
1723 if (operandLitValue(right)) {
1724 emitcode ("setb", AOP_NAME(result)[0]);
1726 emitcode ("clr", AOP_NAME(result)[0]);
1730 /* if right is also a bit */
1731 if (AOP_TYPE(right) == AOP_BIT) {
1732 emitcode ("mov", "c,%s", AOP_NAME(right));
1733 emitcode ("mov", "%s,c", AOP_NAME(result));
1737 emitcode ("mov", "%s,%s; toBoolean", AOP_NAME(result), toBoolean(right));
1741 /* if right is a bit */
1742 if (AOP_TYPE(right)==AOP_BIT) {
1743 emitcode ("mov", "c,%s", AOP_NAME(right));
1744 emitcode ("mov", "%s,#0", AOP_NAME(result)[0]);
1745 emitcode ("rlc", "%s,#1", AOP_NAME(result)[0]);
1747 emitcode ("mov", "%s,#0", AOP_NAME(result)[1]);
1752 /* if the result is of type pointer */
1753 if (IS_PTR (ctype)) {
1755 if (AOP_SIZE(right)>1) {
1756 emitcode ("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1758 emitcode ("mov", "r1l,%s", AOP_NAME(right)[0]);
1759 emitcode ("sext", "r1h");
1760 emitcode ("mov", "%s,r1", AOP_NAME(result)[0]);
1763 /* if pointer to generic pointer */
1764 if (IS_GENPTR (ctype)) {
1766 if (IS_GENPTR (rtype)) {
1767 bailOut("genCast: gptr -> gptr");
1770 if (IS_PTR (rtype)) {
1771 ptrType = DCL_TYPE (rtype);
1773 /* we have to go by the storage class */
1774 if (!SPEC_OCLS(etype)) {
1775 ptrType=0; // hush the compiler
1776 bailOut("genCast: unknown storage class");
1778 ptrType = PTR_TYPE (SPEC_OCLS (etype));
1782 /* the generic part depends on the type */
1786 emitcode ("mov.b", "%s,#0x00", AOP_NAME(result)[1]);
1789 emitcode ("mov.b", "%s,#0x01", AOP_NAME(result)[1]);
1792 emitcode ("mov.b", "%s,#0x02", AOP_NAME(result)[1]);
1795 bailOut("genCast: got unknown storage class");
1801 /* do we have to sign extend? */
1802 signedness = SPEC_USIGN(rtype);
1804 /* now depending on the size */
1805 switch ((AOP_SIZE(result)<<4) + AOP_SIZE(right))
1809 emitcode("mov", "%s,%s", AOP_NAME(result)[1], AOP_NAME(right)[1]);
1814 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1817 emitcode("mov", "%s,%s", AOP_NAME(result)[0], AOP_NAME(right)[0]);
1819 emitcode("sext", "%s", AOP_NAME(result)[1]);
1821 emitcode("mov", "%s,#0", AOP_NAME(result)[1]);
1826 emitcode("mov", "r1l,%s", AOP_NAME(right)[0]);
1828 emitcode("sext", "r1h");
1830 emitcode("mov", "r1h,#0");
1832 emitcode("mov", "%s,r1", AOP_NAME(result)[0]);
1835 // fall through: case 0x41
1837 emitcode("sext", "r1");
1839 emitcode("mov", "r1,#0");
1841 emitcode("mov", "%s,r1", AOP_NAME(result)[1]);
1845 emitcode("mov", "r1,%s", AOP_NAME(right)[0]);
1846 emitcode("mov", "%s,r1l", AOP_NAME(result)[0]);
1849 fprintf(stderr, "genCast: unknown size: %d:%d\n",
1850 AOP_SIZE(result), AOP_SIZE(right));
1851 bailOut("genCast: unknown size");
1855 /*-----------------------------------------------------------------*/
1856 /* genDjnz - generate decrement & jump if not zero instrucion */
1857 /*-----------------------------------------------------------------*/
1858 static bool genDjnz (iCode * ic, iCode * ifx) {
1864 /* if the if condition has a false label
1865 then we cannot save */
1869 /* if the minus is not of the form
1871 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
1872 !IS_OP_LITERAL (IC_RIGHT (ic)))
1875 if (operandLitValue (IC_RIGHT (ic)) != 1)
1878 /* if the size of this greater than two then no
1880 if (getSize (operandType (IC_RESULT (ic))) > 2)
1883 printIc (0, "genDjnz", ic, 1,1,1);
1885 /* otherwise we can save BIG */
1886 lbl = newiTempLabel (NULL);
1887 lbl1 = newiTempLabel (NULL);
1889 aopOp (IC_RESULT (ic), FALSE, TRUE);
1891 if (AOP_TYPE(IC_RESULT(ic))==AOP_REG || AOP_TYPE(IC_RESULT(ic))==AOP_DIR) {
1892 emitcode ("djnz", "%s,%05d$", AOP_NAME(IC_RESULT(ic)), lbl->key+100);
1893 emitcode ("br", "%05d$", lbl1->key + 100);
1894 emitcode ("", "%05d$:", lbl->key + 100);
1895 emitcode ("jmp", "%05d$", IC_TRUE (ifx)->key + 100);
1896 emitcode ("", "%05d$:", lbl1->key + 100);
1900 bailOut("genDjnz: aop type");
1904 /*-----------------------------------------------------------------*/
1905 /* genReceive - generate code for a receive iCode */
1906 /*-----------------------------------------------------------------*/
1907 static void genReceive (iCode * ic) {
1908 printIc (0, "genReceive", ic, 1,0,0);
1911 /*-----------------------------------------------------------------*/
1912 /* genDummyRead - generate code for dummy read of volatiles */
1913 /*-----------------------------------------------------------------*/
1915 genDummyRead (iCode * ic)
1917 emitcode ("; genDummyRead","");
1922 /*-----------------------------------------------------------------*/
1923 /* gen51Code - generate code for 8051 based controllers */
1924 /*-----------------------------------------------------------------*/
1925 void genXA51Code (iCode * lic) {
1929 lineHead = lineCurr = NULL;
1931 /* if debug information required */
1932 if (options.debug && currFunc)
1934 debugFile->writeFunction (currFunc, lic);
1937 for (ic = lic; ic; ic = ic->next) {
1938 if (ic->lineno && cln != ic->lineno) {
1939 if (options.debug) {
1940 debugFile->writeCLine (ic);
1942 if (!options.noCcodeInAsm) {
1943 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
1944 printCLine(ic->filename, ic->lineno));
1948 if (options.iCodeInAsm) {
1949 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
1952 /* if the result is marked as
1953 spilt and rematerializable or code for
1954 this has already been generated then
1956 if (resultRemat (ic) || ic->generated)
1959 /* depending on the operation */
1979 /* IPOP happens only when trying to restore a
1980 spilt live range, if there is an ifx statement
1981 following this pop then the if statement might
1982 be using some of the registers being popped which
1983 would destory the contents of the register so
1984 we need to check for this condition and handle it */
1986 ic->next->op == IFX &&
1987 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
1988 genIfx (ic->next, ic);
2006 genEndFunction (ic);
2026 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
2054 /* note these two are xlated by algebraic equivalence
2055 during parsing SDCC.y */
2056 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
2057 "got '>=' or '<=' shouldn't have come here");
2073 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
2077 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
2081 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
2108 case GET_VALUE_AT_ADDRESS:
2109 genPointerGet (ic, hasInc(IC_LEFT(ic), ic, getSize(operandType(IC_RESULT(ic)))));
2113 if (POINTER_SET (ic))
2114 genPointerSet (ic, hasInc(IC_RESULT(ic), ic, getSize(operandType(IC_RIGHT(ic)))));
2140 addSet (&_G.sendSet, ic);
2143 case DUMMY_READ_VOLATILE:
2153 /* now we are ready to call the
2154 peep hole optimizer */
2155 if (!options.nopeep)
2156 peepHole (&lineHead);
2158 /* now do the actual printing */
2159 printLine (lineHead, codeOutFile);