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!
27 000123 mlh Moved aopLiteral to SDCCglue.c to help the split
28 Made everything static
29 -------------------------------------------------------------------------*/
38 #include "SDCCglobl.h"
41 #ifdef HAVE_SYS_ISA_DEFS_H
42 #include <sys/isa_defs.h>
44 #ifdef HAVE_MACHINE_ENDIAN_H
45 #include <machine/endian.h>
50 #if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__) && !defined(__CYGWIN__)
51 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
52 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
59 #include "SDCCpeeph.h"
63 char *aopLiteral (value * val, int offset);
66 /* this is the down and dirty file with all kinds of
67 kludgy & hacky stuff. This is what it is all about
68 CODE GENERATION for a specific MCU . some of the
69 routines may be reusable, will have to see */
71 static char *zero = "#0x00";
72 static char *one = "#0x01";
76 {"dpl", "dph", "b", "a"};
77 unsigned fReturnSizeMCS51 = 4; /* shared with ralloc.c */
78 char **fReturn = fReturn8051;
79 static char *accUse[] =
82 static short rbank = -1;
96 extern int mcs51_ptrRegReq;
97 extern int mcs51_nRegs;
98 extern FILE *codeOutFile;
99 static void saveRBank (int, iCode *, bool);
100 #define RESULTONSTACK(x) \
101 (IC_RESULT(x) && IC_RESULT(x)->aop && \
102 IC_RESULT(x)->aop->type == AOP_STK )
104 #define MOVA(x) if (strcmp(x,"a") && strcmp(x,"acc")) emitcode("mov","a,%s",x);
105 #define CLRC emitcode("clr","c")
106 #define SETC emitcode("setb","c")
108 static lineNode *lineHead = NULL;
109 static lineNode *lineCurr = NULL;
111 static unsigned char SLMask[] =
112 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
113 0xE0, 0xC0, 0x80, 0x00};
114 static unsigned char SRMask[] =
115 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
123 /*-----------------------------------------------------------------*/
124 /* emitcode - writes the code into a file : for now it is simple */
125 /*-----------------------------------------------------------------*/
127 emitcode (char *inst, char *fmt,...)
130 char lb[INITIAL_INLINEASM];
138 sprintf (lb, "%s\t", inst);
140 sprintf (lb, "%s", inst);
141 vsprintf (lb + (strlen (lb)), fmt, ap);
144 vsprintf (lb, fmt, ap);
146 while (isspace (*lbp))
150 lineCurr = (lineCurr ?
151 connectLine (lineCurr, newLineNode (lb)) :
152 (lineHead = newLineNode (lb)));
153 lineCurr->isInline = _G.inLine;
154 lineCurr->isDebug = _G.debugLine;
158 /*-----------------------------------------------------------------*/
159 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
160 /*-----------------------------------------------------------------*/
162 getFreePtr (iCode * ic, asmop ** aopp, bool result)
164 bool r0iu = FALSE, r1iu = FALSE;
165 bool r0ou = FALSE, r1ou = FALSE;
167 /* the logic: if r0 & r1 used in the instruction
168 then we are in trouble otherwise */
170 /* first check if r0 & r1 are used by this
171 instruction, in which case we are in trouble */
172 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
173 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
178 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
179 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
181 /* if no usage of r0 then return it */
184 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
185 (*aopp)->type = AOP_R0;
187 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
190 /* if no usage of r1 then return it */
193 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
194 (*aopp)->type = AOP_R1;
196 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R1_IDX);
199 /* now we know they both have usage */
200 /* if r0 not used in this instruction */
203 /* push it if not already pushed */
206 emitcode ("push", "%s",
207 mcs51_regWithIdx (R0_IDX)->dname);
211 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
212 (*aopp)->type = AOP_R0;
214 return (*aopp)->aopu.aop_ptr = mcs51_regWithIdx (R0_IDX);
217 /* if r1 not used then */
221 /* push it if not already pushed */
224 emitcode ("push", "%s",
225 mcs51_regWithIdx (R1_IDX)->dname);
229 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
230 (*aopp)->type = AOP_R1;
231 return mcs51_regWithIdx (R1_IDX);
235 /* I said end of world but not quite end of world yet */
236 /* if this is a result then we can push it on the stack */
239 (*aopp)->type = AOP_STK;
243 /* other wise this is true end of the world */
244 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
245 "getFreePtr should never reach here");
249 /*-----------------------------------------------------------------*/
250 /* newAsmop - creates a new asmOp */
251 /*-----------------------------------------------------------------*/
253 newAsmop (short type)
257 aop = Safe_calloc (1, sizeof (asmop));
262 /*-----------------------------------------------------------------*/
263 /* pointerCode - returns the code for a pointer type */
264 /*-----------------------------------------------------------------*/
266 pointerCode (sym_link * etype)
269 return PTR_TYPE (SPEC_OCLS (etype));
273 /*-----------------------------------------------------------------*/
274 /* aopForSym - for a true symbol */
275 /*-----------------------------------------------------------------*/
277 aopForSym (iCode * ic, symbol * sym, bool result)
282 wassertl (ic != NULL, "Got a null iCode");
283 wassertl (sym != NULL, "Got a null symbol");
285 space = SPEC_OCLS (sym->etype);
287 /* if already has one */
291 /* assign depending on the storage class */
292 /* if it is on the stack or indirectly addressable */
293 /* space we need to assign either r0 or r1 to it */
294 if (sym->onStack || sym->iaccess)
296 sym->aop = aop = newAsmop (0);
297 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
298 aop->size = getSize (sym->type);
300 /* now assign the address of the variable to
301 the pointer register */
302 if (aop->type != AOP_STK)
308 emitcode ("push", "acc");
310 emitcode ("mov", "a,_bp");
311 emitcode ("add", "a,#0x%02x",
313 ((char) (sym->stack - _G.nRegsSaved)) :
314 ((char) sym->stack)) & 0xff);
315 emitcode ("mov", "%s,a",
316 aop->aopu.aop_ptr->name);
319 emitcode ("pop", "acc");
322 emitcode ("mov", "%s,#%s",
323 aop->aopu.aop_ptr->name,
325 aop->paged = space->paged;
328 aop->aopu.aop_stk = sym->stack;
332 /* if in bit space */
333 if (IN_BITSPACE (space))
335 sym->aop = aop = newAsmop (AOP_CRY);
336 aop->aopu.aop_dir = sym->rname;
337 aop->size = getSize (sym->type);
340 /* if it is in direct space */
341 if (IN_DIRSPACE (space))
343 sym->aop = aop = newAsmop (AOP_DIR);
344 aop->aopu.aop_dir = sym->rname;
345 aop->size = getSize (sym->type);
349 /* special case for a function */
350 if (IS_FUNC (sym->type))
352 sym->aop = aop = newAsmop (AOP_IMMD);
353 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
354 strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
355 aop->size = FPTRSIZE;
359 /* only remaining is far space */
360 /* in which case DPTR gets the address */
361 sym->aop = aop = newAsmop (AOP_DPTR);
362 emitcode ("mov", "dptr,#%s", sym->rname);
363 aop->size = getSize (sym->type);
365 /* if it is in code space */
366 if (IN_CODESPACE (space))
372 /*-----------------------------------------------------------------*/
373 /* aopForRemat - rematerialzes an object */
374 /*-----------------------------------------------------------------*/
376 aopForRemat (symbol * sym)
378 iCode *ic = sym->rematiCode;
379 asmop *aop = newAsmop (AOP_IMMD);
386 val += (int) operandLitValue (IC_RIGHT (ic));
387 else if (ic->op == '-')
388 val -= (int) operandLitValue (IC_RIGHT (ic));
389 else if (IS_CAST_ICODE(ic)) {
390 sym_link *from_type = operandType(IC_RIGHT(ic));
391 aop->aopu.aop_immd.from_cast_remat = 1;
392 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
393 ptr_type = DCL_TYPE(from_type);
397 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
401 sprintf (buffer, "(%s %c 0x%04x)",
402 OP_SYMBOL (IC_LEFT (ic))->rname,
403 val >= 0 ? '+' : '-',
406 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
408 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
409 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
410 /* set immd2 field if required */
411 if (aop->aopu.aop_immd.from_cast_remat) {
412 sprintf(buffer,"#0x%02x",ptr_type);
413 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
414 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
420 /*-----------------------------------------------------------------*/
421 /* regsInCommon - two operands have some registers in common */
422 /*-----------------------------------------------------------------*/
424 regsInCommon (operand * op1, operand * op2)
429 /* if they have registers in common */
430 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
433 sym1 = OP_SYMBOL (op1);
434 sym2 = OP_SYMBOL (op2);
436 if (sym1->nRegs == 0 || sym2->nRegs == 0)
439 for (i = 0; i < sym1->nRegs; i++)
445 for (j = 0; j < sym2->nRegs; j++)
450 if (sym2->regs[j] == sym1->regs[i])
458 /*-----------------------------------------------------------------*/
459 /* operandsEqu - equivalent */
460 /*-----------------------------------------------------------------*/
462 operandsEqu (operand * op1, operand * op2)
466 /* if they not symbols */
467 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
470 sym1 = OP_SYMBOL (op1);
471 sym2 = OP_SYMBOL (op2);
473 /* if both are itemps & one is spilt
474 and the other is not then false */
475 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
476 sym1->isspilt != sym2->isspilt)
479 /* if they are the same */
483 if (strcmp (sym1->rname, sym2->rname) == 0)
487 /* if left is a tmp & right is not */
488 if (IS_ITEMP (op1) &&
491 (sym1->usl.spillLoc == sym2))
494 if (IS_ITEMP (op2) &&
498 (sym2->usl.spillLoc == sym1))
504 /*-----------------------------------------------------------------*/
505 /* sameRegs - two asmops have the same registers */
506 /*-----------------------------------------------------------------*/
508 sameRegs (asmop * aop1, asmop * aop2)
515 if (aop1->type != AOP_REG ||
516 aop2->type != AOP_REG)
519 if (aop1->size != aop2->size)
522 for (i = 0; i < aop1->size; i++)
523 if (aop1->aopu.aop_reg[i] !=
524 aop2->aopu.aop_reg[i])
530 /*-----------------------------------------------------------------*/
531 /* aopOp - allocates an asmop for an operand : */
532 /*-----------------------------------------------------------------*/
534 aopOp (operand * op, iCode * ic, bool result)
543 /* if this a literal */
544 if (IS_OP_LITERAL (op))
546 op->aop = aop = newAsmop (AOP_LIT);
547 aop->aopu.aop_lit = op->operand.valOperand;
548 aop->size = getSize (operandType (op));
552 /* if already has a asmop then continue */
556 /* if the underlying symbol has a aop */
557 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
559 op->aop = OP_SYMBOL (op)->aop;
563 /* if this is a true symbol */
564 if (IS_TRUE_SYMOP (op))
566 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
570 /* this is a temporary : this has
576 e) can be a return use only */
578 sym = OP_SYMBOL (op);
580 /* if the type is a conditional */
581 if (sym->regType == REG_CND)
583 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
588 /* if it is spilt then two situations
590 b) has a spill location */
591 if (sym->isspilt || sym->nRegs == 0)
594 /* rematerialize it NOW */
597 sym->aop = op->aop = aop =
599 aop->size = getSize (sym->type);
606 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
607 aop->size = getSize (sym->type);
608 for (i = 0; i < 2; i++)
609 aop->aopu.aop_str[i] = accUse[i];
617 aop = op->aop = sym->aop = newAsmop (AOP_STR);
618 aop->size = getSize (sym->type);
619 for (i = 0; i < fReturnSizeMCS51; i++)
620 aop->aopu.aop_str[i] = fReturn[i];
624 /* else spill location */
625 sym->aop = op->aop = aop =
626 aopForSym (ic, sym->usl.spillLoc, result);
627 aop->size = getSize (sym->type);
631 /* must be in a register */
632 sym->aop = op->aop = aop = newAsmop (AOP_REG);
633 aop->size = sym->nRegs;
634 for (i = 0; i < sym->nRegs; i++)
635 aop->aopu.aop_reg[i] = sym->regs[i];
638 /*-----------------------------------------------------------------*/
639 /* freeAsmop - free up the asmop given to an operand */
640 /*----------------------------------------------------------------*/
642 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
659 /* depending on the asmop type only three cases need work AOP_RO
660 , AOP_R1 && AOP_STK */
668 emitcode ("pop", "ar0");
672 bitVectUnSetBit (ic->rUsed, R0_IDX);
680 emitcode ("pop", "ar1");
684 bitVectUnSetBit (ic->rUsed, R1_IDX);
690 int stk = aop->aopu.aop_stk + aop->size;
691 bitVectUnSetBit (ic->rUsed, R0_IDX);
692 bitVectUnSetBit (ic->rUsed, R1_IDX);
694 getFreePtr (ic, &aop, FALSE);
698 emitcode ("mov", "a,_bp");
699 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
700 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
704 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
709 emitcode ("pop", "acc");
710 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
713 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
716 freeAsmop (op, NULL, ic, TRUE);
719 emitcode ("pop", "ar0");
725 emitcode ("pop", "ar1");
732 /* all other cases just dealloc */
738 OP_SYMBOL (op)->aop = NULL;
739 /* if the symbol has a spill */
741 SPIL_LOC (op)->aop = NULL;
746 /*-----------------------------------------------------------------*/
747 /* aopGet - for fetching value of the aop */
748 /*-----------------------------------------------------------------*/
750 aopGet (asmop * aop, int offset, bool bit16, bool dname)
755 /* offset is greater than
757 if (offset > (aop->size - 1) &&
758 aop->type != AOP_LIT)
761 /* depending on type */
767 /* if we need to increment it */
768 while (offset > aop->coff)
770 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
774 while (offset < aop->coff)
776 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
783 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
784 return (dname ? "acc" : "a");
786 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
787 rs = Safe_calloc (1, strlen (s) + 1);
792 while (offset > aop->coff)
794 emitcode ("inc", "dptr");
798 while (offset < aop->coff)
800 emitcode ("lcall", "__decdptr");
807 emitcode ("clr", "a");
808 emitcode ("movc", "a,@a+dptr");
812 emitcode ("movx", "a,@dptr");
814 return (dname ? "acc" : "a");
818 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
819 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
821 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
823 sprintf (s, "#(%s >> %d)",
824 aop->aopu.aop_immd.aop_immd1,
828 aop->aopu.aop_immd.aop_immd1);
829 rs = Safe_calloc (1, strlen (s) + 1);
835 sprintf (s, "(%s + %d)",
839 sprintf (s, "%s", aop->aopu.aop_dir);
840 rs = Safe_calloc (1, strlen (s) + 1);
846 return aop->aopu.aop_reg[offset]->dname;
848 return aop->aopu.aop_reg[offset]->name;
851 emitcode ("clr", "a");
852 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
853 emitcode ("rlc", "a");
854 return (dname ? "acc" : "a");
857 if (!offset && dname)
859 return aop->aopu.aop_str[offset];
862 return aopLiteral (aop->aopu.aop_lit, offset);
866 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
870 return aop->aopu.aop_str[offset];
874 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
875 "aopget got unsupported aop->type");
878 /*-----------------------------------------------------------------*/
879 /* aopPut - puts a string for a aop */
880 /*-----------------------------------------------------------------*/
882 aopPut (asmop * aop, char *s, int offset)
886 if (aop->size && offset > (aop->size - 1))
888 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
889 "aopPut got offset > aop->size");
893 /* will assign value to value */
894 /* depending on where it is ofcourse */
899 sprintf (d, "(%s + %d)",
900 aop->aopu.aop_dir, offset);
902 sprintf (d, "%s", aop->aopu.aop_dir);
905 emitcode ("mov", "%s,%s", d, s);
910 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
911 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
914 strcmp (s, "r0") == 0 ||
915 strcmp (s, "r1") == 0 ||
916 strcmp (s, "r2") == 0 ||
917 strcmp (s, "r3") == 0 ||
918 strcmp (s, "r4") == 0 ||
919 strcmp (s, "r5") == 0 ||
920 strcmp (s, "r6") == 0 ||
921 strcmp (s, "r7") == 0)
922 emitcode ("mov", "%s,%s",
923 aop->aopu.aop_reg[offset]->dname, s);
925 emitcode ("mov", "%s,%s",
926 aop->aopu.aop_reg[offset]->name, s);
933 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
934 "aopPut writting to code space");
938 while (offset > aop->coff)
941 emitcode ("inc", "dptr");
944 while (offset < aop->coff)
947 emitcode ("lcall", "__decdptr");
952 /* if not in accumulater */
955 emitcode ("movx", "@dptr,a");
960 while (offset > aop->coff)
963 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
965 while (offset < aop->coff)
968 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
975 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
981 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
983 else if (strcmp (s, "r0") == 0 ||
984 strcmp (s, "r1") == 0 ||
985 strcmp (s, "r2") == 0 ||
986 strcmp (s, "r3") == 0 ||
987 strcmp (s, "r4") == 0 ||
988 strcmp (s, "r5") == 0 ||
989 strcmp (s, "r6") == 0 ||
990 strcmp (s, "r7") == 0)
993 sprintf (buffer, "a%s", s);
994 emitcode ("mov", "@%s,%s",
995 aop->aopu.aop_ptr->name, buffer);
998 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1003 if (strcmp (s, "a") == 0)
1004 emitcode ("push", "acc");
1006 emitcode ("push", "%s", s);
1011 /* if bit variable */
1012 if (!aop->aopu.aop_dir)
1014 emitcode ("clr", "a");
1015 emitcode ("rlc", "a");
1020 emitcode ("clr", "%s", aop->aopu.aop_dir);
1022 emitcode ("setb", "%s", aop->aopu.aop_dir);
1023 else if (!strcmp (s, "c"))
1024 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1027 if (strcmp (s, "a"))
1032 symbol *lbl = newiTempLabel (NULL);
1033 emitcode ("clr", "c");
1034 emitcode ("jz", "%05d$", lbl->key + 100);
1035 emitcode ("cpl", "c");
1036 emitcode ("", "%05d$:", lbl->key + 100);
1037 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1045 if (strcmp (aop->aopu.aop_str[offset], s))
1046 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1051 if (!offset && (strcmp (s, "acc") == 0))
1054 if (strcmp (aop->aopu.aop_str[offset], s))
1055 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1059 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1060 "aopPut got unsupported aop->type");
1068 /*-----------------------------------------------------------------*/
1069 /* pointToEnd :- points to the last byte of the operand */
1070 /*-----------------------------------------------------------------*/
1072 pointToEnd (asmop * aop)
1078 aop->coff = count = (aop->size - 1);
1084 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1088 emitcode ("inc", "dptr");
1095 /*-----------------------------------------------------------------*/
1096 /* reAdjustPreg - points a register back to where it should */
1097 /*-----------------------------------------------------------------*/
1099 reAdjustPreg (asmop * aop)
1101 if ((aop->coff==0) || aop->size <= 1)
1109 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1114 emitcode ("lcall", "__decdptr");
1121 #define AOP(op) op->aop
1122 #define AOP_TYPE(op) AOP(op)->type
1123 #define AOP_SIZE(op) AOP(op)->size
1124 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1125 AOP_TYPE(x) == AOP_R0))
1127 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1128 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1130 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1131 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1132 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1134 /*-----------------------------------------------------------------*/
1135 /* genNotFloat - generates not for float operations */
1136 /*-----------------------------------------------------------------*/
1138 genNotFloat (operand * op, operand * res)
1144 D(emitcode (";", "genNotFloat"));
1146 /* we will put 127 in the first byte of
1148 aopPut (AOP (res), "#127", 0);
1149 size = AOP_SIZE (op) - 1;
1152 l = aopGet (op->aop, offset++, FALSE, FALSE);
1157 emitcode ("orl", "a,%s",
1159 offset++, FALSE, FALSE));
1162 tlbl = newiTempLabel (NULL);
1163 aopPut (res->aop, one, 1);
1164 emitcode ("jz", "%05d$", (tlbl->key + 100));
1165 aopPut (res->aop, zero, 1);
1166 emitcode ("", "%05d$:", (tlbl->key + 100));
1168 size = res->aop->size - 2;
1170 /* put zeros in the rest */
1172 aopPut (res->aop, zero, offset++);
1175 /*-----------------------------------------------------------------*/
1176 /* opIsGptr: returns non-zero if the passed operand is */
1177 /* a generic pointer type. */
1178 /*-----------------------------------------------------------------*/
1180 opIsGptr (operand * op)
1182 sym_link *type = operandType (op);
1184 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1191 /*-----------------------------------------------------------------*/
1192 /* getDataSize - get the operand data size */
1193 /*-----------------------------------------------------------------*/
1195 getDataSize (operand * op)
1198 size = AOP_SIZE (op);
1199 if (size == GPTRSIZE)
1201 sym_link *type = operandType (op);
1202 if (IS_GENPTR (type))
1204 /* generic pointer; arithmetic operations
1205 * should ignore the high byte (pointer type).
1213 /*-----------------------------------------------------------------*/
1214 /* outAcc - output Acc */
1215 /*-----------------------------------------------------------------*/
1217 outAcc (operand * result)
1220 size = getDataSize (result);
1223 aopPut (AOP (result), "a", 0);
1226 /* unsigned or positive */
1229 aopPut (AOP (result), zero, offset++);
1234 /*-----------------------------------------------------------------*/
1235 /* outBitC - output a bit C */
1236 /*-----------------------------------------------------------------*/
1238 outBitC (operand * result)
1240 /* if the result is bit */
1241 if (AOP_TYPE (result) == AOP_CRY)
1242 aopPut (AOP (result), "c", 0);
1245 emitcode ("clr", "a");
1246 emitcode ("rlc", "a");
1251 /*-----------------------------------------------------------------*/
1252 /* toBoolean - emit code for orl a,operator(sizeop) */
1253 /*-----------------------------------------------------------------*/
1255 toBoolean (operand * oper)
1257 int size = AOP_SIZE (oper) - 1;
1259 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1261 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1265 /*-----------------------------------------------------------------*/
1266 /* genNot - generate code for ! operation */
1267 /*-----------------------------------------------------------------*/
1272 sym_link *optype = operandType (IC_LEFT (ic));
1274 D(emitcode (";", "genNot"));
1276 /* assign asmOps to operand & result */
1277 aopOp (IC_LEFT (ic), ic, FALSE);
1278 aopOp (IC_RESULT (ic), ic, TRUE);
1280 /* if in bit space then a special case */
1281 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1283 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1284 emitcode ("cpl", "c");
1285 outBitC (IC_RESULT (ic));
1289 /* if type float then do float */
1290 if (IS_FLOAT (optype))
1292 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1296 toBoolean (IC_LEFT (ic));
1298 tlbl = newiTempLabel (NULL);
1299 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1300 emitcode ("", "%05d$:", tlbl->key + 100);
1301 outBitC (IC_RESULT (ic));
1304 /* release the aops */
1305 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1306 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1310 /*-----------------------------------------------------------------*/
1311 /* genCpl - generate code for complement */
1312 /*-----------------------------------------------------------------*/
1320 D(emitcode (";", "genCpl"));
1322 /* assign asmOps to operand & result */
1323 aopOp (IC_LEFT (ic), ic, FALSE);
1324 aopOp (IC_RESULT (ic), ic, TRUE);
1326 /* if both are in bit space then
1328 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1329 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1332 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1333 emitcode ("cpl", "c");
1334 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1338 size = AOP_SIZE (IC_RESULT (ic));
1341 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1343 emitcode ("cpl", "a");
1344 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1349 /* release the aops */
1350 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1351 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1354 /*-----------------------------------------------------------------*/
1355 /* genUminusFloat - unary minus for floating points */
1356 /*-----------------------------------------------------------------*/
1358 genUminusFloat (operand * op, operand * result)
1360 int size, offset = 0;
1363 D(emitcode (";", "genUminusFloat"));
1365 /* for this we just need to flip the
1366 first it then copy the rest in place */
1367 size = AOP_SIZE (op) - 1;
1368 l = aopGet (AOP (op), 3, FALSE, FALSE);
1372 emitcode ("cpl", "acc.7");
1373 aopPut (AOP (result), "a", 3);
1377 aopPut (AOP (result),
1378 aopGet (AOP (op), offset, FALSE, FALSE),
1384 /*-----------------------------------------------------------------*/
1385 /* genUminus - unary minus code generation */
1386 /*-----------------------------------------------------------------*/
1388 genUminus (iCode * ic)
1391 sym_link *optype, *rtype;
1394 D(emitcode (";", "genUminus"));
1397 aopOp (IC_LEFT (ic), ic, FALSE);
1398 aopOp (IC_RESULT (ic), ic, TRUE);
1400 /* if both in bit space then special
1402 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1403 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1406 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1407 emitcode ("cpl", "c");
1408 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1412 optype = operandType (IC_LEFT (ic));
1413 rtype = operandType (IC_RESULT (ic));
1415 /* if float then do float stuff */
1416 if (IS_FLOAT (optype))
1418 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1422 /* otherwise subtract from zero */
1423 size = AOP_SIZE (IC_LEFT (ic));
1428 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1429 if (!strcmp (l, "a"))
1433 emitcode ("cpl", "a");
1434 emitcode ("addc", "a,#0");
1440 emitcode ("clr", "a");
1441 emitcode ("subb", "a,%s", l);
1443 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1446 /* if any remaining bytes in the result */
1447 /* we just need to propagate the sign */
1448 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1450 emitcode ("rlc", "a");
1451 emitcode ("subb", "a,acc");
1453 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1457 /* release the aops */
1458 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1459 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1462 /*-----------------------------------------------------------------*/
1463 /* saveRegisters - will look for a call and save the registers */
1464 /*-----------------------------------------------------------------*/
1466 saveRegisters (iCode * lic)
1473 for (ic = lic; ic; ic = ic->next)
1474 if (ic->op == CALL || ic->op == PCALL)
1479 fprintf (stderr, "found parameter push with no function call\n");
1483 /* if the registers have been saved already or don't need to be then
1485 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1486 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1489 /* safe the registers in use at this time but skip the
1490 ones for the result */
1491 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1492 mcs51_rUmaskForOp (IC_RESULT(ic)));
1495 if (options.useXstack)
1497 if (bitVectBitValue (rsave, R0_IDX))
1498 emitcode ("mov", "b,r0");
1499 emitcode ("mov", "r0,%s", spname);
1500 for (i = 0; i < mcs51_nRegs; i++)
1502 if (bitVectBitValue (rsave, i))
1505 emitcode ("mov", "a,b");
1507 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1508 emitcode ("movx", "@r0,a");
1509 emitcode ("inc", "r0");
1512 emitcode ("mov", "%s,r0", spname);
1513 if (bitVectBitValue (rsave, R0_IDX))
1514 emitcode ("mov", "r0,b");
1517 for (i = 0; i < mcs51_nRegs; i++)
1519 if (bitVectBitValue (rsave, i))
1520 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1524 /*-----------------------------------------------------------------*/
1525 /* unsaveRegisters - pop the pushed registers */
1526 /*-----------------------------------------------------------------*/
1528 unsaveRegisters (iCode * ic)
1533 /* restore the registers in use at this time but skip the
1534 ones for the result */
1535 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1536 mcs51_rUmaskForOp (IC_RESULT(ic)));
1538 if (options.useXstack)
1540 emitcode ("mov", "r0,%s", spname);
1541 for (i = mcs51_nRegs; i >= 0; i--)
1543 if (bitVectBitValue (rsave, i))
1545 emitcode ("dec", "r0");
1546 emitcode ("movx", "a,@r0");
1548 emitcode ("mov", "b,a");
1550 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1554 emitcode ("mov", "%s,r0", spname);
1555 if (bitVectBitValue (rsave, R0_IDX))
1556 emitcode ("mov", "r0,b");
1559 for (i = mcs51_nRegs; i >= 0; i--)
1561 if (bitVectBitValue (rsave, i))
1562 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1568 /*-----------------------------------------------------------------*/
1570 /*-----------------------------------------------------------------*/
1572 pushSide (operand * oper, int size)
1577 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1578 if (AOP_TYPE (oper) != AOP_REG &&
1579 AOP_TYPE (oper) != AOP_DIR &&
1582 emitcode ("mov", "a,%s", l);
1583 emitcode ("push", "acc");
1586 emitcode ("push", "%s", l);
1590 /*-----------------------------------------------------------------*/
1591 /* assignResultValue - */
1592 /*-----------------------------------------------------------------*/
1594 assignResultValue (operand * oper)
1597 int size = AOP_SIZE (oper);
1600 aopPut (AOP (oper), fReturn[offset], offset);
1606 /*-----------------------------------------------------------------*/
1607 /* genXpush - pushes onto the external stack */
1608 /*-----------------------------------------------------------------*/
1610 genXpush (iCode * ic)
1612 asmop *aop = newAsmop (0);
1614 int size, offset = 0;
1616 D(emitcode (";", "genXpush"));
1618 aopOp (IC_LEFT (ic), ic, FALSE);
1619 r = getFreePtr (ic, &aop, FALSE);
1622 emitcode ("mov", "%s,_spx", r->name);
1624 size = AOP_SIZE (IC_LEFT (ic));
1628 char *l = aopGet (AOP (IC_LEFT (ic)),
1629 offset++, FALSE, FALSE);
1631 emitcode ("movx", "@%s,a", r->name);
1632 emitcode ("inc", "%s", r->name);
1637 emitcode ("mov", "_spx,%s", r->name);
1639 freeAsmop (NULL, aop, ic, TRUE);
1640 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1643 /*-----------------------------------------------------------------*/
1644 /* genIpush - genrate code for pushing this gets a little complex */
1645 /*-----------------------------------------------------------------*/
1647 genIpush (iCode * ic)
1649 int size, offset = 0;
1652 D(emitcode (";", "genIpush"));
1654 /* if this is not a parm push : ie. it is spill push
1655 and spill push is always done on the local stack */
1659 /* and the item is spilt then do nothing */
1660 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1663 aopOp (IC_LEFT (ic), ic, FALSE);
1664 size = AOP_SIZE (IC_LEFT (ic));
1665 /* push it on the stack */
1668 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1674 emitcode ("push", "%s", l);
1679 /* this is a paramter push: in this case we call
1680 the routine to find the call and save those
1681 registers that need to be saved */
1684 /* if use external stack then call the external
1685 stack pushing routine */
1686 if (options.useXstack)
1692 /* then do the push */
1693 aopOp (IC_LEFT (ic), ic, FALSE);
1696 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1697 size = AOP_SIZE (IC_LEFT (ic));
1701 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1702 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1703 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1706 emitcode ("mov", "a,%s", l);
1707 emitcode ("push", "acc");
1710 emitcode ("push", "%s", l);
1713 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1716 /*-----------------------------------------------------------------*/
1717 /* genIpop - recover the registers: can happen only for spilling */
1718 /*-----------------------------------------------------------------*/
1720 genIpop (iCode * ic)
1724 D(emitcode (";", "genIpop"));
1726 /* if the temp was not pushed then */
1727 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1730 aopOp (IC_LEFT (ic), ic, FALSE);
1731 size = AOP_SIZE (IC_LEFT (ic));
1732 offset = (size - 1);
1734 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1737 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1740 /*-----------------------------------------------------------------*/
1741 /* unsaveRBank - restores the resgister bank from stack */
1742 /*-----------------------------------------------------------------*/
1744 unsaveRBank (int bank, iCode * ic, bool popPsw)
1750 if (options.useXstack)
1754 /* Assume r0 is available for use. */
1755 r = mcs51_regWithIdx (R0_IDX);;
1760 r = getFreePtr (ic, &aop, FALSE);
1762 emitcode ("mov", "%s,_spx", r->name);
1767 if (options.useXstack)
1769 emitcode ("movx", "a,@%s", r->name);
1770 emitcode ("mov", "psw,a");
1771 emitcode ("dec", "%s", r->name);
1775 emitcode ("pop", "psw");
1779 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1781 if (options.useXstack)
1783 emitcode ("movx", "a,@%s", r->name);
1784 emitcode ("mov", "(%s+%d),a",
1785 regs8051[i].base, 8 * bank + regs8051[i].offset);
1786 emitcode ("dec", "%s", r->name);
1790 emitcode ("pop", "(%s+%d)",
1791 regs8051[i].base, 8 * bank + regs8051[i].offset);
1794 if (options.useXstack)
1796 emitcode ("mov", "_spx,%s", r->name);
1801 freeAsmop (NULL, aop, ic, TRUE);
1805 /*-----------------------------------------------------------------*/
1806 /* saveRBank - saves an entire register bank on the stack */
1807 /*-----------------------------------------------------------------*/
1809 saveRBank (int bank, iCode * ic, bool pushPsw)
1815 if (options.useXstack)
1819 /* Assume r0 is available for use. */
1820 r = mcs51_regWithIdx (R0_IDX);;
1825 r = getFreePtr (ic, &aop, FALSE);
1827 emitcode ("mov", "%s,_spx", r->name);
1830 for (i = 0; i < mcs51_nRegs; i++)
1832 if (options.useXstack)
1834 emitcode ("inc", "%s", r->name);
1835 emitcode ("mov", "a,(%s+%d)",
1836 regs8051[i].base, 8 * bank + regs8051[i].offset);
1837 emitcode ("movx", "@%s,a", r->name);
1840 emitcode ("push", "(%s+%d)",
1841 regs8051[i].base, 8 * bank + regs8051[i].offset);
1846 if (options.useXstack)
1848 emitcode ("mov", "a,psw");
1849 emitcode ("movx", "@%s,a", r->name);
1850 emitcode ("inc", "%s", r->name);
1851 emitcode ("mov", "_spx,%s", r->name);
1856 emitcode ("push", "psw");
1859 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1864 freeAsmop (NULL, aop, ic, TRUE);
1873 /*-----------------------------------------------------------------*/
1874 /* genCall - generates a call statement */
1875 /*-----------------------------------------------------------------*/
1877 genCall (iCode * ic)
1880 bool restoreBank = FALSE;
1881 bool swapBanks = FALSE;
1883 D(emitcode(";", "genCall"));
1885 /* if send set is not empty the assign */
1890 for (sic = setFirstItem (_G.sendSet); sic;
1891 sic = setNextItem (_G.sendSet))
1893 int size, offset = 0;
1894 aopOp (IC_LEFT (sic), sic, FALSE);
1895 size = AOP_SIZE (IC_LEFT (sic));
1898 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1900 if (strcmp (l, fReturn[offset]))
1901 emitcode ("mov", "%s,%s",
1906 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1911 /* if we are calling a not _naked function that is not using
1912 the same register bank then we need to save the
1913 destination registers on the stack */
1914 dtype = operandType (IC_LEFT (ic));
1915 if (dtype && !IFFUNC_ISNAKED(dtype) &&
1916 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1917 IFFUNC_ISISR (currFunc->type))
1921 /* This is unexpected; the bank should have been saved in
1924 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1930 /* if caller saves & we have not saved then */
1936 emitcode ("mov", "psw,#0x%02x",
1937 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1941 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1942 OP_SYMBOL (IC_LEFT (ic))->rname :
1943 OP_SYMBOL (IC_LEFT (ic))->name));
1947 emitcode ("mov", "psw,#0x%02x",
1948 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1951 /* if we need assign a result value */
1952 if ((IS_ITEMP (IC_RESULT (ic)) &&
1953 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1954 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1955 IS_TRUE_SYMOP (IC_RESULT (ic)))
1959 aopOp (IC_RESULT (ic), ic, FALSE);
1962 assignResultValue (IC_RESULT (ic));
1964 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1967 /* adjust the stack for parameters if
1972 if (ic->parmBytes > 3)
1974 emitcode ("mov", "a,%s", spname);
1975 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1976 emitcode ("mov", "%s,a", spname);
1979 for (i = 0; i < ic->parmBytes; i++)
1980 emitcode ("dec", "%s", spname);
1983 /* if we hade saved some registers then unsave them */
1984 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
1985 unsaveRegisters (ic);
1987 /* if register bank was saved then pop them */
1989 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1992 /*-----------------------------------------------------------------*/
1993 /* genPcall - generates a call by pointer statement */
1994 /*-----------------------------------------------------------------*/
1996 genPcall (iCode * ic)
1999 symbol *rlbl = newiTempLabel (NULL);
2000 bool restoreBank=FALSE;
2002 D(emitcode(";", "genPCall"));
2004 /* if caller saves & we have not saved then */
2008 /* if we are calling a function that is not using
2009 the same register bank then we need to save the
2010 destination registers on the stack */
2011 dtype = operandType (IC_LEFT (ic));
2012 if (dtype && !FUNC_ISNAKED(dtype) &&
2013 IFFUNC_ISISR (currFunc->type) &&
2014 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2015 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2019 /* push the return address on to the stack */
2020 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2021 emitcode ("push", "acc");
2022 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2023 emitcode ("push", "acc");
2025 /* now push the calling address */
2026 aopOp (IC_LEFT (ic), ic, FALSE);
2028 pushSide (IC_LEFT (ic), FPTRSIZE);
2030 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2032 /* if send set is not empty the assign */
2037 for (sic = setFirstItem (_G.sendSet); sic;
2038 sic = setNextItem (_G.sendSet))
2040 int size, offset = 0;
2041 aopOp (IC_LEFT (sic), sic, FALSE);
2042 size = AOP_SIZE (IC_LEFT (sic));
2045 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2047 if (strcmp (l, fReturn[offset]))
2048 emitcode ("mov", "%s,%s",
2053 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2058 emitcode ("ret", "");
2059 emitcode ("", "%05d$:", (rlbl->key + 100));
2062 /* if we need assign a result value */
2063 if ((IS_ITEMP (IC_RESULT (ic)) &&
2064 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2065 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2066 IS_TRUE_SYMOP (IC_RESULT (ic)))
2070 aopOp (IC_RESULT (ic), ic, FALSE);
2073 assignResultValue (IC_RESULT (ic));
2075 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2078 /* adjust the stack for parameters if
2083 if (ic->parmBytes > 3)
2085 emitcode ("mov", "a,%s", spname);
2086 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2087 emitcode ("mov", "%s,a", spname);
2090 for (i = 0; i < ic->parmBytes; i++)
2091 emitcode ("dec", "%s", spname);
2095 /* if register bank was saved then unsave them */
2097 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2099 /* if we hade saved some registers then
2101 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2102 unsaveRegisters (ic);
2105 /*-----------------------------------------------------------------*/
2106 /* resultRemat - result is rematerializable */
2107 /*-----------------------------------------------------------------*/
2109 resultRemat (iCode * ic)
2111 if (SKIP_IC (ic) || ic->op == IFX)
2114 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2116 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2117 if (sym->remat && !POINTER_SET (ic))
2124 #if defined(__BORLANDC__) || defined(_MSC_VER)
2125 #define STRCASECMP stricmp
2127 #define STRCASECMP strcasecmp
2130 /*-----------------------------------------------------------------*/
2131 /* inExcludeList - return 1 if the string is in exclude Reg list */
2132 /*-----------------------------------------------------------------*/
2134 inExcludeList (char *s)
2138 if (options.excludeRegs[i] &&
2139 STRCASECMP (options.excludeRegs[i], "none") == 0)
2142 for (i = 0; options.excludeRegs[i]; i++)
2144 if (options.excludeRegs[i] &&
2145 STRCASECMP (s, options.excludeRegs[i]) == 0)
2151 /*-----------------------------------------------------------------*/
2152 /* genFunction - generated code for function entry */
2153 /*-----------------------------------------------------------------*/
2155 genFunction (iCode * ic)
2159 bool switchedPSW = FALSE;
2162 /* create the function header */
2163 emitcode (";", "-----------------------------------------");
2164 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2165 emitcode (";", "-----------------------------------------");
2167 emitcode ("", "%s:", sym->rname);
2168 ftype = operandType (IC_LEFT (ic));
2170 if (IFFUNC_ISNAKED(ftype))
2172 emitcode(";", "naked function: no prologue.");
2176 /* if critical function then turn interrupts off */
2177 if (IFFUNC_ISCRITICAL (ftype))
2178 emitcode ("clr", "ea");
2180 /* here we need to generate the equates for the
2181 register bank if required */
2182 if (FUNC_REGBANK (ftype) != rbank)
2186 rbank = FUNC_REGBANK (ftype);
2187 for (i = 0; i < mcs51_nRegs; i++)
2189 if (strcmp (regs8051[i].base, "0") == 0)
2190 emitcode ("", "%s = 0x%02x",
2192 8 * rbank + regs8051[i].offset);
2194 emitcode ("", "%s = %s + 0x%02x",
2197 8 * rbank + regs8051[i].offset);
2201 /* if this is an interrupt service routine then
2202 save acc, b, dpl, dph */
2203 if (IFFUNC_ISISR (sym->type))
2206 if (!inExcludeList ("acc"))
2207 emitcode ("push", "acc");
2208 if (!inExcludeList ("b"))
2209 emitcode ("push", "b");
2210 if (!inExcludeList ("dpl"))
2211 emitcode ("push", "dpl");
2212 if (!inExcludeList ("dph"))
2213 emitcode ("push", "dph");
2214 /* if this isr has no bank i.e. is going to
2215 run with bank 0 , then we need to save more
2217 if (!FUNC_REGBANK (sym->type))
2220 /* if this function does not call any other
2221 function then we can be economical and
2222 save only those registers that are used */
2223 if (!IFFUNC_HASFCALL(sym->type))
2227 /* if any registers used */
2230 /* save the registers used */
2231 for (i = 0; i < sym->regsUsed->size; i++)
2233 if (bitVectBitValue (sym->regsUsed, i) ||
2234 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2235 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2242 /* this function has a function call cannot
2243 determines register usage so we will have to push the
2245 saveRBank (0, ic, FALSE);
2250 /* This ISR uses a non-zero bank.
2252 * We assume that the bank is available for our
2255 * However, if this ISR calls a function which uses some
2256 * other bank, we must save that bank entirely.
2258 unsigned long banksToSave = 0;
2260 if (IFFUNC_HASFCALL(sym->type))
2263 #define MAX_REGISTER_BANKS 4
2268 for (i = ic; i; i = i->next)
2270 if (i->op == ENDFUNCTION)
2272 /* we got to the end OK. */
2280 dtype = operandType (IC_LEFT(i));
2282 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2284 /* Mark this bank for saving. */
2285 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2287 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2291 banksToSave |= (1 << FUNC_REGBANK(dtype));
2294 /* And note that we don't need to do it in
2302 /* This is a mess; we have no idea what
2303 * register bank the called function might
2306 * The only thing I can think of to do is
2307 * throw a warning and hope.
2309 werror(W_FUNCPTR_IN_USING_ISR);
2313 if (banksToSave && options.useXstack)
2315 /* Since we aren't passing it an ic,
2316 * saveRBank will assume r0 is available to abuse.
2318 * So switch to our (trashable) bank now, so
2319 * the caller's R0 isn't trashed.
2321 emitcode ("push", "psw");
2322 emitcode ("mov", "psw,#0x%02x",
2323 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2327 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2329 if (banksToSave & (1 << ix))
2331 saveRBank(ix, NULL, FALSE);
2335 // jwk: this needs a closer look
2336 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2341 /* if callee-save to be used for this function
2342 then save the registers being used in this function */
2343 if (IFFUNC_CALLEESAVES(sym->type))
2347 /* if any registers used */
2350 /* save the registers used */
2351 for (i = 0; i < sym->regsUsed->size; i++)
2353 if (bitVectBitValue (sym->regsUsed, i) ||
2354 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2356 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2364 /* set the register bank to the desired value */
2365 if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2368 emitcode ("push", "psw");
2369 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2372 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2375 if (options.useXstack)
2377 emitcode ("mov", "r0,%s", spname);
2378 emitcode ("mov", "a,_bp");
2379 emitcode ("movx", "@r0,a");
2380 emitcode ("inc", "%s", spname);
2384 /* set up the stack */
2385 emitcode ("push", "_bp"); /* save the callers stack */
2387 emitcode ("mov", "_bp,%s", spname);
2390 /* adjust the stack for the function */
2396 werror (W_STACK_OVERFLOW, sym->name);
2398 if (i > 3 && sym->recvSize < 4)
2401 emitcode ("mov", "a,sp");
2402 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2403 emitcode ("mov", "sp,a");
2408 emitcode ("inc", "sp");
2414 emitcode ("mov", "a,_spx");
2415 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2416 emitcode ("mov", "_spx,a");
2421 /*-----------------------------------------------------------------*/
2422 /* genEndFunction - generates epilogue for functions */
2423 /*-----------------------------------------------------------------*/
2425 genEndFunction (iCode * ic)
2427 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2429 if (IFFUNC_ISNAKED(sym->type))
2431 emitcode(";", "naked function: no epilogue.");
2435 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2437 emitcode ("mov", "%s,_bp", spname);
2440 /* if use external stack but some variables were
2441 added to the local stack then decrement the
2443 if (options.useXstack && sym->stack)
2445 emitcode ("mov", "a,sp");
2446 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2447 emitcode ("mov", "sp,a");
2451 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2453 if (options.useXstack)
2455 emitcode ("mov", "r0,%s", spname);
2456 emitcode ("movx", "a,@r0");
2457 emitcode ("mov", "_bp,a");
2458 emitcode ("dec", "%s", spname);
2462 emitcode ("pop", "_bp");
2466 /* restore the register bank */
2467 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2469 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2470 || !options.useXstack)
2472 /* Special case of ISR using non-zero bank with useXstack
2475 emitcode ("pop", "psw");
2479 if (IFFUNC_ISISR (sym->type))
2482 /* now we need to restore the registers */
2483 /* if this isr has no bank i.e. is going to
2484 run with bank 0 , then we need to save more
2486 if (!FUNC_REGBANK (sym->type))
2488 /* if this function does not call any other
2489 function then we can be economical and
2490 save only those registers that are used */
2491 if (!IFFUNC_HASFCALL(sym->type))
2495 /* if any registers used */
2498 /* save the registers used */
2499 for (i = sym->regsUsed->size; i >= 0; i--)
2501 if (bitVectBitValue (sym->regsUsed, i) ||
2502 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2503 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2510 /* this function has a function call cannot
2511 determines register usage so we will have to pop the
2513 unsaveRBank (0, ic, FALSE);
2518 /* This ISR uses a non-zero bank.
2520 * Restore any register banks saved by genFunction
2523 // jwk: this needs a closer look
2524 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2527 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2529 if (savedBanks & (1 << ix))
2531 unsaveRBank(ix, NULL, FALSE);
2535 if (options.useXstack)
2537 /* Restore bank AFTER calling unsaveRBank,
2538 * since it can trash r0.
2540 emitcode ("pop", "psw");
2544 if (!inExcludeList ("dph"))
2545 emitcode ("pop", "dph");
2546 if (!inExcludeList ("dpl"))
2547 emitcode ("pop", "dpl");
2548 if (!inExcludeList ("b"))
2549 emitcode ("pop", "b");
2550 if (!inExcludeList ("acc"))
2551 emitcode ("pop", "acc");
2553 if (IFFUNC_ISCRITICAL (sym->type))
2554 emitcode ("setb", "ea");
2556 /* if debug then send end of function */
2557 /* if (options.debug && currFunc) */
2558 if (options.debug && currFunc)
2561 emitcode ("", "C$%s$%d$%d$%d ==.",
2562 FileBaseName (ic->filename), currFunc->lastLine,
2563 ic->level, ic->block);
2564 if (IS_STATIC (currFunc->etype))
2565 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2567 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2571 emitcode ("reti", "");
2575 if (IFFUNC_ISCRITICAL (sym->type))
2576 emitcode ("setb", "ea");
2578 if (IFFUNC_CALLEESAVES(sym->type))
2582 /* if any registers used */
2585 /* save the registers used */
2586 for (i = sym->regsUsed->size; i >= 0; i--)
2588 if (bitVectBitValue (sym->regsUsed, i) ||
2589 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2590 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2596 /* if debug then send end of function */
2597 if (options.debug && currFunc)
2600 emitcode ("", "C$%s$%d$%d$%d ==.",
2601 FileBaseName (ic->filename), currFunc->lastLine,
2602 ic->level, ic->block);
2603 if (IS_STATIC (currFunc->etype))
2604 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2606 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2610 emitcode ("ret", "");
2615 /*-----------------------------------------------------------------*/
2616 /* genRet - generate code for return statement */
2617 /*-----------------------------------------------------------------*/
2621 int size, offset = 0, pushed = 0;
2623 /* if we have no return value then
2624 just generate the "ret" */
2628 /* we have something to return then
2629 move the return value into place */
2630 aopOp (IC_LEFT (ic), ic, FALSE);
2631 size = AOP_SIZE (IC_LEFT (ic));
2636 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2639 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2641 emitcode ("push", "%s", l);
2646 l = aopGet (AOP (IC_LEFT (ic)), offset,
2648 if (strcmp (fReturn[offset], l))
2649 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2658 if (strcmp (fReturn[pushed], "a"))
2659 emitcode ("pop", fReturn[pushed]);
2661 emitcode ("pop", "acc");
2664 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2667 /* generate a jump to the return label
2668 if the next is not the return statement */
2669 if (!(ic->next && ic->next->op == LABEL &&
2670 IC_LABEL (ic->next) == returnLabel))
2672 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2676 /*-----------------------------------------------------------------*/
2677 /* genLabel - generates a label */
2678 /*-----------------------------------------------------------------*/
2680 genLabel (iCode * ic)
2682 /* special case never generate */
2683 if (IC_LABEL (ic) == entryLabel)
2686 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2689 /*-----------------------------------------------------------------*/
2690 /* genGoto - generates a ljmp */
2691 /*-----------------------------------------------------------------*/
2693 genGoto (iCode * ic)
2695 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2698 /*-----------------------------------------------------------------*/
2699 /* findLabelBackwards: walks back through the iCode chain looking */
2700 /* for the given label. Returns number of iCode instructions */
2701 /* between that label and given ic. */
2702 /* Returns zero if label not found. */
2703 /*-----------------------------------------------------------------*/
2705 findLabelBackwards (iCode * ic, int key)
2714 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2716 /* printf("findLabelBackwards = %d\n", count); */
2724 /*-----------------------------------------------------------------*/
2725 /* genPlusIncr :- does addition with increment if possible */
2726 /*-----------------------------------------------------------------*/
2728 genPlusIncr (iCode * ic)
2730 unsigned int icount;
2731 unsigned int size = getDataSize (IC_RESULT (ic));
2733 D(emitcode (";", "genPlusIncr"));
2735 /* will try to generate an increment */
2736 /* if the right side is not a literal
2738 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2741 /* if the literal value of the right hand side
2742 is greater than 4 then it is not worth it */
2743 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2746 /* if increment 16 bits in register */
2747 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2755 /* If the next instruction is a goto and the goto target
2756 * is < 10 instructions previous to this, we can generate
2757 * jumps straight to that target.
2759 if (ic->next && ic->next->op == GOTO
2760 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2761 && labelRange <= 10)
2763 emitcode (";", "tail increment optimized");
2764 tlbl = IC_LABEL (ic->next);
2769 tlbl = newiTempLabel (NULL);
2772 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2773 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2774 IS_AOP_PREG (IC_RESULT (ic)))
2775 emitcode ("cjne", "%s,#0x00,%05d$"
2776 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2780 emitcode ("clr", "a");
2781 emitcode ("cjne", "a,%s,%05d$"
2782 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2786 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2789 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2790 IS_AOP_PREG (IC_RESULT (ic)))
2791 emitcode ("cjne", "%s,#0x00,%05d$"
2792 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2795 emitcode ("cjne", "a,%s,%05d$"
2796 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2799 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2803 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2804 IS_AOP_PREG (IC_RESULT (ic)))
2805 emitcode ("cjne", "%s,#0x00,%05d$"
2806 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2810 emitcode ("cjne", "a,%s,%05d$"
2811 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2814 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2819 emitcode ("", "%05d$:", tlbl->key + 100);
2824 /* if the sizes are greater than 1 then we cannot */
2825 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2826 AOP_SIZE (IC_LEFT (ic)) > 1)
2829 /* we can if the aops of the left & result match or
2830 if they are in registers and the registers are the
2832 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2837 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2838 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2839 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2845 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2854 /*-----------------------------------------------------------------*/
2855 /* outBitAcc - output a bit in acc */
2856 /*-----------------------------------------------------------------*/
2858 outBitAcc (operand * result)
2860 symbol *tlbl = newiTempLabel (NULL);
2861 /* if the result is a bit */
2862 if (AOP_TYPE (result) == AOP_CRY)
2864 aopPut (AOP (result), "a", 0);
2868 emitcode ("jz", "%05d$", tlbl->key + 100);
2869 emitcode ("mov", "a,%s", one);
2870 emitcode ("", "%05d$:", tlbl->key + 100);
2875 /*-----------------------------------------------------------------*/
2876 /* genPlusBits - generates code for addition of two bits */
2877 /*-----------------------------------------------------------------*/
2879 genPlusBits (iCode * ic)
2881 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2883 symbol *lbl = newiTempLabel (NULL);
2884 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2885 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2886 emitcode ("cpl", "c");
2887 emitcode ("", "%05d$:", (lbl->key + 100));
2888 outBitC (IC_RESULT (ic));
2892 emitcode ("clr", "a");
2893 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2894 emitcode ("rlc", "a");
2895 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2896 emitcode ("addc", "a,#0x00");
2897 outAcc (IC_RESULT (ic));
2902 /* This is the original version of this code.
2904 * This is being kept around for reference,
2905 * because I am not entirely sure I got it right...
2908 adjustArithmeticResult (iCode * ic)
2910 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2911 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2912 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2913 aopPut (AOP (IC_RESULT (ic)),
2914 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2917 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2918 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2919 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2920 aopPut (AOP (IC_RESULT (ic)),
2921 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2924 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2925 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2926 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2927 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2928 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2931 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2932 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2936 /* This is the pure and virtuous version of this code.
2937 * I'm pretty certain it's right, but not enough to toss the old
2941 adjustArithmeticResult (iCode * ic)
2943 if (opIsGptr (IC_RESULT (ic)) &&
2944 opIsGptr (IC_LEFT (ic)) &&
2945 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2947 aopPut (AOP (IC_RESULT (ic)),
2948 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2952 if (opIsGptr (IC_RESULT (ic)) &&
2953 opIsGptr (IC_RIGHT (ic)) &&
2954 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2956 aopPut (AOP (IC_RESULT (ic)),
2957 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2961 if (opIsGptr (IC_RESULT (ic)) &&
2962 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2963 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2964 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2965 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2968 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2969 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2974 /*-----------------------------------------------------------------*/
2975 /* genPlus - generates code for addition */
2976 /*-----------------------------------------------------------------*/
2978 genPlus (iCode * ic)
2980 int size, offset = 0;
2982 /* special cases :- */
2984 D(emitcode (";", "genPlus"));
2986 aopOp (IC_LEFT (ic), ic, FALSE);
2987 aopOp (IC_RIGHT (ic), ic, FALSE);
2988 aopOp (IC_RESULT (ic), ic, TRUE);
2990 /* if literal, literal on the right or
2991 if left requires ACC or right is already
2993 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
2994 (AOP_NEEDSACC (IC_LEFT (ic))) ||
2995 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
2997 operand *t = IC_RIGHT (ic);
2998 IC_RIGHT (ic) = IC_LEFT (ic);
3002 /* if both left & right are in bit
3004 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3005 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3011 /* if left in bit space & right literal */
3012 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3013 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3015 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3016 /* if result in bit space */
3017 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3019 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3020 emitcode ("cpl", "c");
3021 outBitC (IC_RESULT (ic));
3025 size = getDataSize (IC_RESULT (ic));
3028 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3029 emitcode ("addc", "a,#00");
3030 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3036 /* if I can do an increment instead
3037 of add then GOOD for ME */
3038 if (genPlusIncr (ic) == TRUE)
3041 size = getDataSize (IC_RESULT (ic));
3045 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3047 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3049 emitcode ("add", "a,%s",
3050 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3052 emitcode ("addc", "a,%s",
3053 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3057 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3059 emitcode ("add", "a,%s",
3060 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3062 emitcode ("addc", "a,%s",
3063 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3065 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3068 adjustArithmeticResult (ic);
3071 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3072 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3073 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3076 /*-----------------------------------------------------------------*/
3077 /* genMinusDec :- does subtraction with deccrement if possible */
3078 /*-----------------------------------------------------------------*/
3080 genMinusDec (iCode * ic)
3082 unsigned int icount;
3083 unsigned int size = getDataSize (IC_RESULT (ic));
3085 D(emitcode (";", "genMinusDec"));
3087 /* will try to generate an increment */
3088 /* if the right side is not a literal
3090 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3093 /* if the literal value of the right hand side
3094 is greater than 4 then it is not worth it */
3095 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3098 /* if decrement 16 bits in register */
3099 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3107 /* If the next instruction is a goto and the goto target
3108 * is <= 10 instructions previous to this, we can generate
3109 * jumps straight to that target.
3111 if (ic->next && ic->next->op == GOTO
3112 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3113 && labelRange <= 10)
3115 emitcode (";", "tail decrement optimized");
3116 tlbl = IC_LABEL (ic->next);
3121 tlbl = newiTempLabel (NULL);
3125 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3126 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3127 IS_AOP_PREG (IC_RESULT (ic)))
3128 emitcode ("cjne", "%s,#0xff,%05d$"
3129 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3133 emitcode ("mov", "a,#0xff");
3134 emitcode ("cjne", "a,%s,%05d$"
3135 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3138 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3141 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3142 IS_AOP_PREG (IC_RESULT (ic)))
3143 emitcode ("cjne", "%s,#0xff,%05d$"
3144 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3148 emitcode ("cjne", "a,%s,%05d$"
3149 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3152 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3156 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3157 IS_AOP_PREG (IC_RESULT (ic)))
3158 emitcode ("cjne", "%s,#0xff,%05d$"
3159 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3163 emitcode ("cjne", "a,%s,%05d$"
3164 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3167 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3171 emitcode ("", "%05d$:", tlbl->key + 100);
3176 /* if the sizes are greater than 1 then we cannot */
3177 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3178 AOP_SIZE (IC_LEFT (ic)) > 1)
3181 /* we can if the aops of the left & result match or
3182 if they are in registers and the registers are the
3184 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3188 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3196 /*-----------------------------------------------------------------*/
3197 /* addSign - complete with sign */
3198 /*-----------------------------------------------------------------*/
3200 addSign (operand * result, int offset, int sign)
3202 int size = (getDataSize (result) - offset);
3207 emitcode ("rlc", "a");
3208 emitcode ("subb", "a,acc");
3210 aopPut (AOP (result), "a", offset++);
3214 aopPut (AOP (result), zero, offset++);
3218 /*-----------------------------------------------------------------*/
3219 /* genMinusBits - generates code for subtraction of two bits */
3220 /*-----------------------------------------------------------------*/
3222 genMinusBits (iCode * ic)
3224 symbol *lbl = newiTempLabel (NULL);
3225 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3227 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3228 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3229 emitcode ("cpl", "c");
3230 emitcode ("", "%05d$:", (lbl->key + 100));
3231 outBitC (IC_RESULT (ic));
3235 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3236 emitcode ("subb", "a,acc");
3237 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3238 emitcode ("inc", "a");
3239 emitcode ("", "%05d$:", (lbl->key + 100));
3240 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3241 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3245 /*-----------------------------------------------------------------*/
3246 /* genMinus - generates code for subtraction */
3247 /*-----------------------------------------------------------------*/
3249 genMinus (iCode * ic)
3251 int size, offset = 0;
3252 unsigned long lit = 0L;
3254 aopOp (IC_LEFT (ic), ic, FALSE);
3255 aopOp (IC_RIGHT (ic), ic, FALSE);
3256 aopOp (IC_RESULT (ic), ic, TRUE);
3258 /* special cases :- */
3259 /* if both left & right are in bit space */
3260 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3261 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3267 /* if I can do an decrement instead
3268 of subtract then GOOD for ME */
3269 if (genMinusDec (ic) == TRUE)
3272 size = getDataSize (IC_RESULT (ic));
3274 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3280 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3284 /* if literal, add a,#-lit, else normal subb */
3287 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3288 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3289 emitcode ("subb", "a,%s",
3290 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3293 /* first add without previous c */
3295 if (!size && lit==-1) {
3296 emitcode ("dec", "a");
3298 emitcode ("add", "a,#0x%02x",
3299 (unsigned int) (lit & 0x0FFL));
3302 emitcode ("addc", "a,#0x%02x",
3303 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3306 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3309 adjustArithmeticResult (ic);
3312 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3313 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3314 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3318 /*-----------------------------------------------------------------*/
3319 /* genMultbits :- multiplication of bits */
3320 /*-----------------------------------------------------------------*/
3322 genMultbits (operand * left,
3326 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3327 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3332 /*-----------------------------------------------------------------*/
3333 /* genMultOneByte : 8*8=8/16 bit multiplication */
3334 /*-----------------------------------------------------------------*/
3336 genMultOneByte (operand * left,
3340 sym_link *opetype = operandType (result);
3342 int size=AOP_SIZE(result);
3344 if (size<1 || size>2) {
3345 // this should never happen
3346 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3347 AOP_SIZE(result), __FILE__, lineno);
3351 /* (if two literals: the value is computed before) */
3352 /* if one literal, literal on the right */
3353 if (AOP_TYPE (left) == AOP_LIT)
3358 //emitcode (";", "swapped left and right");
3361 if (SPEC_USIGN(opetype)
3362 // ignore the sign of left and right, what else can we do?
3363 || (SPEC_USIGN(operandType(left)) &&
3364 SPEC_USIGN(operandType(right)))) {
3365 // just an unsigned 8*8=8/16 multiply
3366 //emitcode (";","unsigned");
3367 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3368 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3369 emitcode ("mul", "ab");
3370 aopPut (AOP (result), "a", 0);
3372 aopPut (AOP (result), "b", 1);
3377 // we have to do a signed multiply
3379 //emitcode (";", "signed");
3380 emitcode ("clr", "F0"); // reset sign flag
3381 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3383 lbl=newiTempLabel(NULL);
3384 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3385 // left side is negative, 8-bit two's complement, this fails for -128
3386 emitcode ("setb", "F0"); // set sign flag
3387 emitcode ("cpl", "a");
3388 emitcode ("inc", "a");
3390 emitcode ("", "%05d$:", lbl->key+100);
3393 if (AOP_TYPE(right)==AOP_LIT) {
3394 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3395 /* AND literal negative */
3397 emitcode ("cpl", "F0"); // complement sign flag
3398 emitcode ("mov", "b,#0x%02x", -val);
3400 emitcode ("mov", "b,#0x%02x", val);
3403 lbl=newiTempLabel(NULL);
3404 emitcode ("mov", "b,a");
3405 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3406 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3407 // right side is negative, 8-bit two's complement
3408 emitcode ("cpl", "F0"); // complement sign flag
3409 emitcode ("cpl", "a");
3410 emitcode ("inc", "a");
3411 emitcode ("", "%05d$:", lbl->key+100);
3413 emitcode ("mul", "ab");
3415 lbl=newiTempLabel(NULL);
3416 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3417 // only ONE op was negative, we have to do a 8/16-bit two's complement
3418 emitcode ("cpl", "a"); // lsb
3420 emitcode ("inc", "a");
3422 emitcode ("add", "a,#1");
3423 emitcode ("xch", "a,b");
3424 emitcode ("cpl", "a"); // msb
3425 emitcode ("addc", "a,#0");
3426 emitcode ("xch", "a,b");
3429 emitcode ("", "%05d$:", lbl->key+100);
3430 aopPut (AOP (result), "a", 0);
3432 aopPut (AOP (result), "b", 1);
3436 /*-----------------------------------------------------------------*/
3437 /* genMult - generates code for multiplication */
3438 /*-----------------------------------------------------------------*/
3440 genMult (iCode * ic)
3442 operand *left = IC_LEFT (ic);
3443 operand *right = IC_RIGHT (ic);
3444 operand *result = IC_RESULT (ic);
3446 /* assign the amsops */
3447 aopOp (left, ic, FALSE);
3448 aopOp (right, ic, FALSE);
3449 aopOp (result, ic, TRUE);
3451 /* special cases first */
3453 if (AOP_TYPE (left) == AOP_CRY &&
3454 AOP_TYPE (right) == AOP_CRY)
3456 genMultbits (left, right, result);
3460 /* if both are of size == 1 */
3461 #if 0 // one of them can be a sloc shared with the result
3462 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3464 if (getSize(operandType(left)) == 1 &&
3465 getSize(operandType(right)) == 1)
3468 genMultOneByte (left, right, result);
3472 /* should have been converted to function call */
3473 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3474 getSize(OP_SYMBOL(right)->type));
3478 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3479 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3480 freeAsmop (result, NULL, ic, TRUE);
3483 /*-----------------------------------------------------------------*/
3484 /* genDivbits :- division of bits */
3485 /*-----------------------------------------------------------------*/
3487 genDivbits (operand * left,
3494 /* the result must be bit */
3495 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3496 l = aopGet (AOP (left), 0, FALSE, FALSE);
3500 emitcode ("div", "ab");
3501 emitcode ("rrc", "a");
3502 aopPut (AOP (result), "c", 0);
3505 /*-----------------------------------------------------------------*/
3506 /* genDivOneByte : 8 bit division */
3507 /*-----------------------------------------------------------------*/
3509 genDivOneByte (operand * left,
3513 sym_link *opetype = operandType (result);
3518 size = AOP_SIZE (result) - 1;
3520 /* signed or unsigned */
3521 if (SPEC_USIGN (opetype))
3523 /* unsigned is easy */
3524 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3525 l = aopGet (AOP (left), 0, FALSE, FALSE);
3527 emitcode ("div", "ab");
3528 aopPut (AOP (result), "a", 0);
3530 aopPut (AOP (result), zero, offset++);
3534 /* signed is a little bit more difficult */
3536 /* save the signs of the operands */
3537 l = aopGet (AOP (left), 0, FALSE, FALSE);
3539 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3540 emitcode ("push", "acc"); /* save it on the stack */
3542 /* now sign adjust for both left & right */
3543 l = aopGet (AOP (right), 0, FALSE, FALSE);
3545 lbl = newiTempLabel (NULL);
3546 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3547 emitcode ("cpl", "a");
3548 emitcode ("inc", "a");
3549 emitcode ("", "%05d$:", (lbl->key + 100));
3550 emitcode ("mov", "b,a");
3552 /* sign adjust left side */
3553 l = aopGet (AOP (left), 0, FALSE, FALSE);
3556 lbl = newiTempLabel (NULL);
3557 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3558 emitcode ("cpl", "a");
3559 emitcode ("inc", "a");
3560 emitcode ("", "%05d$:", (lbl->key + 100));
3562 /* now the division */
3563 emitcode ("div", "ab");
3564 /* we are interested in the lower order
3566 emitcode ("mov", "b,a");
3567 lbl = newiTempLabel (NULL);
3568 emitcode ("pop", "acc");
3569 /* if there was an over flow we don't
3570 adjust the sign of the result */
3571 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3572 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3574 emitcode ("clr", "a");
3575 emitcode ("subb", "a,b");
3576 emitcode ("mov", "b,a");
3577 emitcode ("", "%05d$:", (lbl->key + 100));
3579 /* now we are done */
3580 aopPut (AOP (result), "b", 0);
3583 emitcode ("mov", "c,b.7");
3584 emitcode ("subb", "a,acc");
3587 aopPut (AOP (result), "a", offset++);
3591 /*-----------------------------------------------------------------*/
3592 /* genDiv - generates code for division */
3593 /*-----------------------------------------------------------------*/
3597 operand *left = IC_LEFT (ic);
3598 operand *right = IC_RIGHT (ic);
3599 operand *result = IC_RESULT (ic);
3601 /* assign the amsops */
3602 aopOp (left, ic, FALSE);
3603 aopOp (right, ic, FALSE);
3604 aopOp (result, ic, TRUE);
3606 /* special cases first */
3608 if (AOP_TYPE (left) == AOP_CRY &&
3609 AOP_TYPE (right) == AOP_CRY)
3611 genDivbits (left, right, result);
3615 /* if both are of size == 1 */
3616 if (AOP_SIZE (left) == 1 &&
3617 AOP_SIZE (right) == 1)
3619 genDivOneByte (left, right, result);
3623 /* should have been converted to function call */
3626 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3627 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3628 freeAsmop (result, NULL, ic, TRUE);
3631 /*-----------------------------------------------------------------*/
3632 /* genModbits :- modulus of bits */
3633 /*-----------------------------------------------------------------*/
3635 genModbits (operand * left,
3642 /* the result must be bit */
3643 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3644 l = aopGet (AOP (left), 0, FALSE, FALSE);
3648 emitcode ("div", "ab");
3649 emitcode ("mov", "a,b");
3650 emitcode ("rrc", "a");
3651 aopPut (AOP (result), "c", 0);
3654 /*-----------------------------------------------------------------*/
3655 /* genModOneByte : 8 bit modulus */
3656 /*-----------------------------------------------------------------*/
3658 genModOneByte (operand * left,
3662 sym_link *opetype = operandType (result);
3666 /* signed or unsigned */
3667 if (SPEC_USIGN (opetype))
3669 /* unsigned is easy */
3670 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3671 l = aopGet (AOP (left), 0, FALSE, FALSE);
3673 emitcode ("div", "ab");
3674 aopPut (AOP (result), "b", 0);
3678 /* signed is a little bit more difficult */
3680 /* save the signs of the operands */
3681 l = aopGet (AOP (left), 0, FALSE, FALSE);
3684 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3685 emitcode ("push", "acc"); /* save it on the stack */
3687 /* now sign adjust for both left & right */
3688 l = aopGet (AOP (right), 0, FALSE, FALSE);
3691 lbl = newiTempLabel (NULL);
3692 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3693 emitcode ("cpl", "a");
3694 emitcode ("inc", "a");
3695 emitcode ("", "%05d$:", (lbl->key + 100));
3696 emitcode ("mov", "b,a");
3698 /* sign adjust left side */
3699 l = aopGet (AOP (left), 0, FALSE, FALSE);
3702 lbl = newiTempLabel (NULL);
3703 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3704 emitcode ("cpl", "a");
3705 emitcode ("inc", "a");
3706 emitcode ("", "%05d$:", (lbl->key + 100));
3708 /* now the multiplication */
3709 emitcode ("div", "ab");
3710 /* we are interested in the lower order
3712 lbl = newiTempLabel (NULL);
3713 emitcode ("pop", "acc");
3714 /* if there was an over flow we don't
3715 adjust the sign of the result */
3716 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3717 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3719 emitcode ("clr", "a");
3720 emitcode ("subb", "a,b");
3721 emitcode ("mov", "b,a");
3722 emitcode ("", "%05d$:", (lbl->key + 100));
3724 /* now we are done */
3725 aopPut (AOP (result), "b", 0);
3729 /*-----------------------------------------------------------------*/
3730 /* genMod - generates code for division */
3731 /*-----------------------------------------------------------------*/
3735 operand *left = IC_LEFT (ic);
3736 operand *right = IC_RIGHT (ic);
3737 operand *result = IC_RESULT (ic);
3739 /* assign the amsops */
3740 aopOp (left, ic, FALSE);
3741 aopOp (right, ic, FALSE);
3742 aopOp (result, ic, TRUE);
3744 /* special cases first */
3746 if (AOP_TYPE (left) == AOP_CRY &&
3747 AOP_TYPE (right) == AOP_CRY)
3749 genModbits (left, right, result);
3753 /* if both are of size == 1 */
3754 if (AOP_SIZE (left) == 1 &&
3755 AOP_SIZE (right) == 1)
3757 genModOneByte (left, right, result);
3761 /* should have been converted to function call */
3765 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3766 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3767 freeAsmop (result, NULL, ic, TRUE);
3770 /*-----------------------------------------------------------------*/
3771 /* genIfxJump :- will create a jump depending on the ifx */
3772 /*-----------------------------------------------------------------*/
3774 genIfxJump (iCode * ic, char *jval)
3777 symbol *tlbl = newiTempLabel (NULL);
3780 /* if true label then we jump if condition
3784 jlbl = IC_TRUE (ic);
3785 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3786 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3790 /* false label is present */
3791 jlbl = IC_FALSE (ic);
3792 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3793 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3795 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3796 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3798 emitcode (inst, "%05d$", tlbl->key + 100);
3799 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3800 emitcode ("", "%05d$:", tlbl->key + 100);
3802 /* mark the icode as generated */
3806 /*-----------------------------------------------------------------*/
3807 /* genCmp :- greater or less than comparison */
3808 /*-----------------------------------------------------------------*/
3810 genCmp (operand * left, operand * right,
3811 operand * result, iCode * ifx, int sign, iCode *ic)
3813 int size, offset = 0;
3814 unsigned long lit = 0L;
3816 /* if left & right are bit variables */
3817 if (AOP_TYPE (left) == AOP_CRY &&
3818 AOP_TYPE (right) == AOP_CRY)
3820 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3821 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3825 /* subtract right from left if at the
3826 end the carry flag is set then we know that
3827 left is greater than right */
3828 size = max (AOP_SIZE (left), AOP_SIZE (right));
3830 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3831 if ((size == 1) && !sign &&
3832 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3834 symbol *lbl = newiTempLabel (NULL);
3835 emitcode ("cjne", "%s,%s,%05d$",
3836 aopGet (AOP (left), offset, FALSE, FALSE),
3837 aopGet (AOP (right), offset, FALSE, FALSE),
3839 emitcode ("", "%05d$:", lbl->key + 100);
3843 if (AOP_TYPE (right) == AOP_LIT)
3845 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3846 /* optimize if(x < 0) or if(x >= 0) */
3855 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3856 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3858 genIfxJump (ifx, "acc.7");
3862 emitcode ("rlc", "a");
3870 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3871 if (sign && size == 0)
3873 emitcode ("xrl", "a,#0x80");
3874 if (AOP_TYPE (right) == AOP_LIT)
3876 unsigned long lit = (unsigned long)
3877 floatFromVal (AOP (right)->aopu.aop_lit);
3878 emitcode ("subb", "a,#0x%02x",
3879 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3883 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3884 emitcode ("xrl", "b,#0x80");
3885 emitcode ("subb", "a,b");
3889 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3895 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3896 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3897 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3903 /* if the result is used in the next
3904 ifx conditional branch then generate
3905 code a little differently */
3907 genIfxJump (ifx, "c");
3910 /* leave the result in acc */
3914 /*-----------------------------------------------------------------*/
3915 /* genCmpGt :- greater than comparison */
3916 /*-----------------------------------------------------------------*/
3918 genCmpGt (iCode * ic, iCode * ifx)
3920 operand *left, *right, *result;
3921 sym_link *letype, *retype;
3924 left = IC_LEFT (ic);
3925 right = IC_RIGHT (ic);
3926 result = IC_RESULT (ic);
3928 letype = getSpec (operandType (left));
3929 retype = getSpec (operandType (right));
3930 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3931 /* assign the amsops */
3932 aopOp (left, ic, FALSE);
3933 aopOp (right, ic, FALSE);
3934 aopOp (result, ic, TRUE);
3936 genCmp (right, left, result, ifx, sign,ic);
3938 freeAsmop (result, NULL, ic, TRUE);
3941 /*-----------------------------------------------------------------*/
3942 /* genCmpLt - less than comparisons */
3943 /*-----------------------------------------------------------------*/
3945 genCmpLt (iCode * ic, iCode * ifx)
3947 operand *left, *right, *result;
3948 sym_link *letype, *retype;
3951 left = IC_LEFT (ic);
3952 right = IC_RIGHT (ic);
3953 result = IC_RESULT (ic);
3955 letype = getSpec (operandType (left));
3956 retype = getSpec (operandType (right));
3957 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3959 /* assign the amsops */
3960 aopOp (left, ic, FALSE);
3961 aopOp (right, ic, FALSE);
3962 aopOp (result, ic, TRUE);
3964 genCmp (left, right, result, ifx, sign,ic);
3966 freeAsmop (result, NULL, ic, TRUE);
3969 /*-----------------------------------------------------------------*/
3970 /* gencjneshort - compare and jump if not equal */
3971 /*-----------------------------------------------------------------*/
3973 gencjneshort (operand * left, operand * right, symbol * lbl)
3975 int size = max (AOP_SIZE (left), AOP_SIZE (right));
3977 unsigned long lit = 0L;
3979 /* if the left side is a literal or
3980 if the right is in a pointer register and left
3982 if ((AOP_TYPE (left) == AOP_LIT) ||
3983 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
3989 if (AOP_TYPE (right) == AOP_LIT)
3990 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3992 /* if the right side is a literal then anything goes */
3993 if (AOP_TYPE (right) == AOP_LIT &&
3994 AOP_TYPE (left) != AOP_DIR)
3998 emitcode ("cjne", "%s,%s,%05d$",
3999 aopGet (AOP (left), offset, FALSE, FALSE),
4000 aopGet (AOP (right), offset, FALSE, FALSE),
4006 /* if the right side is in a register or in direct space or
4007 if the left is a pointer register & right is not */
4008 else if (AOP_TYPE (right) == AOP_REG ||
4009 AOP_TYPE (right) == AOP_DIR ||
4010 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4011 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4015 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4016 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4017 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4018 emitcode ("jnz", "%05d$", lbl->key + 100);
4020 emitcode ("cjne", "a,%s,%05d$",
4021 aopGet (AOP (right), offset, FALSE, TRUE),
4028 /* right is a pointer reg need both a & b */
4031 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4032 if (strcmp (l, "b"))
4033 emitcode ("mov", "b,%s", l);
4034 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4035 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4041 /*-----------------------------------------------------------------*/
4042 /* gencjne - compare and jump if not equal */
4043 /*-----------------------------------------------------------------*/
4045 gencjne (operand * left, operand * right, symbol * lbl)
4047 symbol *tlbl = newiTempLabel (NULL);
4049 gencjneshort (left, right, lbl);
4051 emitcode ("mov", "a,%s", one);
4052 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4053 emitcode ("", "%05d$:", lbl->key + 100);
4054 emitcode ("clr", "a");
4055 emitcode ("", "%05d$:", tlbl->key + 100);
4058 /*-----------------------------------------------------------------*/
4059 /* genCmpEq - generates code for equal to */
4060 /*-----------------------------------------------------------------*/
4062 genCmpEq (iCode * ic, iCode * ifx)
4064 operand *left, *right, *result;
4066 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4067 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4068 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4070 /* if literal, literal on the right or
4071 if the right is in a pointer register and left
4073 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4074 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4076 operand *t = IC_RIGHT (ic);
4077 IC_RIGHT (ic) = IC_LEFT (ic);
4081 if (ifx && !AOP_SIZE (result))
4084 /* if they are both bit variables */
4085 if (AOP_TYPE (left) == AOP_CRY &&
4086 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4088 if (AOP_TYPE (right) == AOP_LIT)
4090 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4093 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4094 emitcode ("cpl", "c");
4098 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4102 emitcode ("clr", "c");
4104 /* AOP_TYPE(right) == AOP_CRY */
4108 symbol *lbl = newiTempLabel (NULL);
4109 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4110 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4111 emitcode ("cpl", "c");
4112 emitcode ("", "%05d$:", (lbl->key + 100));
4114 /* if true label then we jump if condition
4116 tlbl = newiTempLabel (NULL);
4119 emitcode ("jnc", "%05d$", tlbl->key + 100);
4120 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4124 emitcode ("jc", "%05d$", tlbl->key + 100);
4125 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4127 emitcode ("", "%05d$:", tlbl->key + 100);
4131 tlbl = newiTempLabel (NULL);
4132 gencjneshort (left, right, tlbl);
4135 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4136 emitcode ("", "%05d$:", tlbl->key + 100);
4140 symbol *lbl = newiTempLabel (NULL);
4141 emitcode ("sjmp", "%05d$", lbl->key + 100);
4142 emitcode ("", "%05d$:", tlbl->key + 100);
4143 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4144 emitcode ("", "%05d$:", lbl->key + 100);
4147 /* mark the icode as generated */
4152 /* if they are both bit variables */
4153 if (AOP_TYPE (left) == AOP_CRY &&
4154 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4156 if (AOP_TYPE (right) == AOP_LIT)
4158 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4161 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4162 emitcode ("cpl", "c");
4166 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4170 emitcode ("clr", "c");
4172 /* AOP_TYPE(right) == AOP_CRY */
4176 symbol *lbl = newiTempLabel (NULL);
4177 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4178 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4179 emitcode ("cpl", "c");
4180 emitcode ("", "%05d$:", (lbl->key + 100));
4183 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4190 genIfxJump (ifx, "c");
4193 /* if the result is used in an arithmetic operation
4194 then put the result in place */
4199 gencjne (left, right, newiTempLabel (NULL));
4200 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4202 aopPut (AOP (result), "a", 0);
4207 genIfxJump (ifx, "a");
4210 /* if the result is used in an arithmetic operation
4211 then put the result in place */
4212 if (AOP_TYPE (result) != AOP_CRY)
4214 /* leave the result in acc */
4218 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4219 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4220 freeAsmop (result, NULL, ic, TRUE);
4223 /*-----------------------------------------------------------------*/
4224 /* ifxForOp - returns the icode containing the ifx for operand */
4225 /*-----------------------------------------------------------------*/
4227 ifxForOp (operand * op, iCode * ic)
4229 /* if true symbol then needs to be assigned */
4230 if (IS_TRUE_SYMOP (op))
4233 /* if this has register type condition and
4234 the next instruction is ifx with the same operand
4235 and live to of the operand is upto the ifx only then */
4237 ic->next->op == IFX &&
4238 IC_COND (ic->next)->key == op->key &&
4239 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4245 /*-----------------------------------------------------------------*/
4246 /* hasInc - operand is incremented before any other use */
4247 /*-----------------------------------------------------------------*/
4249 hasInc (operand *op, iCode *ic)
4251 sym_link *type = operandType(op);
4252 sym_link *retype = getSpec (type);
4253 iCode *lic = ic->next;
4256 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4257 if (!IS_SYMOP(op)) return NULL;
4259 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4260 isize = getSize(type->next);
4262 /* if operand of the form op = op + <sizeof *op> */
4263 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4264 isOperandEqual(IC_RESULT(lic),op) &&
4265 isOperandLiteral(IC_RIGHT(lic)) &&
4266 operandLitValue(IC_RIGHT(lic)) == isize) {
4269 /* if the operand used or deffed */
4270 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4278 /*-----------------------------------------------------------------*/
4279 /* genAndOp - for && operation */
4280 /*-----------------------------------------------------------------*/
4282 genAndOp (iCode * ic)
4284 operand *left, *right, *result;
4287 /* note here that && operations that are in an
4288 if statement are taken away by backPatchLabels
4289 only those used in arthmetic operations remain */
4290 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4291 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4292 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4294 /* if both are bit variables */
4295 if (AOP_TYPE (left) == AOP_CRY &&
4296 AOP_TYPE (right) == AOP_CRY)
4298 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4299 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4304 tlbl = newiTempLabel (NULL);
4306 emitcode ("jz", "%05d$", tlbl->key + 100);
4308 emitcode ("", "%05d$:", tlbl->key + 100);
4312 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4313 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4314 freeAsmop (result, NULL, ic, TRUE);
4318 /*-----------------------------------------------------------------*/
4319 /* genOrOp - for || operation */
4320 /*-----------------------------------------------------------------*/
4322 genOrOp (iCode * ic)
4324 operand *left, *right, *result;
4327 /* note here that || operations that are in an
4328 if statement are taken away by backPatchLabels
4329 only those used in arthmetic operations remain */
4330 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4331 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4332 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4334 /* if both are bit variables */
4335 if (AOP_TYPE (left) == AOP_CRY &&
4336 AOP_TYPE (right) == AOP_CRY)
4338 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4339 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4344 tlbl = newiTempLabel (NULL);
4346 emitcode ("jnz", "%05d$", tlbl->key + 100);
4348 emitcode ("", "%05d$:", tlbl->key + 100);
4352 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4353 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4354 freeAsmop (result, NULL, ic, TRUE);
4357 /*-----------------------------------------------------------------*/
4358 /* isLiteralBit - test if lit == 2^n */
4359 /*-----------------------------------------------------------------*/
4361 isLiteralBit (unsigned long lit)
4363 unsigned long pw[32] =
4364 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4365 0x100L, 0x200L, 0x400L, 0x800L,
4366 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4367 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4368 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4369 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4370 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4373 for (idx = 0; idx < 32; idx++)
4379 /*-----------------------------------------------------------------*/
4380 /* continueIfTrue - */
4381 /*-----------------------------------------------------------------*/
4383 continueIfTrue (iCode * ic)
4386 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4390 /*-----------------------------------------------------------------*/
4392 /*-----------------------------------------------------------------*/
4394 jumpIfTrue (iCode * ic)
4397 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4401 /*-----------------------------------------------------------------*/
4402 /* jmpTrueOrFalse - */
4403 /*-----------------------------------------------------------------*/
4405 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4407 // ugly but optimized by peephole
4410 symbol *nlbl = newiTempLabel (NULL);
4411 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4412 emitcode ("", "%05d$:", tlbl->key + 100);
4413 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4414 emitcode ("", "%05d$:", nlbl->key + 100);
4418 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4419 emitcode ("", "%05d$:", tlbl->key + 100);
4424 /*-----------------------------------------------------------------*/
4425 /* genAnd - code for and */
4426 /*-----------------------------------------------------------------*/
4428 genAnd (iCode * ic, iCode * ifx)
4430 operand *left, *right, *result;
4431 int size, offset = 0;
4432 unsigned long lit = 0L;
4436 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4437 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4438 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4441 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4443 AOP_TYPE (left), AOP_TYPE (right));
4444 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4446 AOP_SIZE (left), AOP_SIZE (right));
4449 /* if left is a literal & right is not then exchange them */
4450 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4451 AOP_NEEDSACC (left))
4453 operand *tmp = right;
4458 /* if result = right then exchange them */
4459 if (sameRegs (AOP (result), AOP (right)))
4461 operand *tmp = right;
4466 /* if right is bit then exchange them */
4467 if (AOP_TYPE (right) == AOP_CRY &&
4468 AOP_TYPE (left) != AOP_CRY)
4470 operand *tmp = right;
4474 if (AOP_TYPE (right) == AOP_LIT)
4475 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4477 size = AOP_SIZE (result);
4480 // result = bit & yy;
4481 if (AOP_TYPE (left) == AOP_CRY)
4483 // c = bit & literal;
4484 if (AOP_TYPE (right) == AOP_LIT)
4488 if (size && sameRegs (AOP (result), AOP (left)))
4491 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4496 if (size && (AOP_TYPE (result) == AOP_CRY))
4498 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4501 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4506 emitcode ("clr", "c");
4511 if (AOP_TYPE (right) == AOP_CRY)
4514 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4515 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4520 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4522 emitcode ("rrc", "a");
4523 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4531 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4532 genIfxJump (ifx, "c");
4536 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4537 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4538 if ((AOP_TYPE (right) == AOP_LIT) &&
4539 (AOP_TYPE (result) == AOP_CRY) &&
4540 (AOP_TYPE (left) != AOP_CRY))
4542 int posbit = isLiteralBit (lit);
4547 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4550 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4556 sprintf (buffer, "acc.%d", posbit & 0x07);
4557 genIfxJump (ifx, buffer);
4564 symbol *tlbl = newiTempLabel (NULL);
4565 int sizel = AOP_SIZE (left);
4567 emitcode ("setb", "c");
4570 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4572 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4574 if ((posbit = isLiteralBit (bytelit)) != 0)
4575 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4578 if (bytelit != 0x0FFL)
4579 emitcode ("anl", "a,%s",
4580 aopGet (AOP (right), offset, FALSE, TRUE));
4581 emitcode ("jnz", "%05d$", tlbl->key + 100);
4586 // bit = left & literal
4589 emitcode ("clr", "c");
4590 emitcode ("", "%05d$:", tlbl->key + 100);
4592 // if(left & literal)
4596 jmpTrueOrFalse (ifx, tlbl);
4604 /* if left is same as result */
4605 if (sameRegs (AOP (result), AOP (left)))
4607 for (; size--; offset++)
4609 if (AOP_TYPE (right) == AOP_LIT)
4611 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4613 else if (bytelit == 0)
4614 aopPut (AOP (result), zero, offset);
4615 else if (IS_AOP_PREG (result))
4617 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4618 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4619 aopPut (AOP (result), "a", offset);
4622 emitcode ("anl", "%s,%s",
4623 aopGet (AOP (left), offset, FALSE, TRUE),
4624 aopGet (AOP (right), offset, FALSE, FALSE));
4628 if (AOP_TYPE (left) == AOP_ACC)
4629 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4632 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4633 if (IS_AOP_PREG (result))
4635 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4636 aopPut (AOP (result), "a", offset);
4640 emitcode ("anl", "%s,a",
4641 aopGet (AOP (left), offset, FALSE, TRUE));
4648 // left & result in different registers
4649 if (AOP_TYPE (result) == AOP_CRY)
4652 // if(size), result in bit
4653 // if(!size && ifx), conditional oper: if(left & right)
4654 symbol *tlbl = newiTempLabel (NULL);
4655 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4657 emitcode ("setb", "c");
4660 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4661 emitcode ("anl", "a,%s",
4662 aopGet (AOP (right), offset, FALSE, FALSE));
4664 if (AOP_TYPE(left)==AOP_ACC) {
4665 emitcode("mov", "b,a");
4666 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4667 emitcode("anl", "a,b");
4669 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4670 emitcode ("anl", "a,%s",
4671 aopGet (AOP (left), offset, FALSE, FALSE));
4674 emitcode ("jnz", "%05d$", tlbl->key + 100);
4680 emitcode ("", "%05d$:", tlbl->key + 100);
4684 jmpTrueOrFalse (ifx, tlbl);
4688 for (; (size--); offset++)
4691 // result = left & right
4692 if (AOP_TYPE (right) == AOP_LIT)
4694 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4696 aopPut (AOP (result),
4697 aopGet (AOP (left), offset, FALSE, FALSE),
4701 else if (bytelit == 0)
4703 aopPut (AOP (result), zero, offset);
4707 // faster than result <- left, anl result,right
4708 // and better if result is SFR
4709 if (AOP_TYPE (left) == AOP_ACC)
4710 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4713 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4714 emitcode ("anl", "a,%s",
4715 aopGet (AOP (left), offset, FALSE, FALSE));
4717 aopPut (AOP (result), "a", offset);
4723 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4724 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4725 freeAsmop (result, NULL, ic, TRUE);
4728 /*-----------------------------------------------------------------*/
4729 /* genOr - code for or */
4730 /*-----------------------------------------------------------------*/
4732 genOr (iCode * ic, iCode * ifx)
4734 operand *left, *right, *result;
4735 int size, offset = 0;
4736 unsigned long lit = 0L;
4738 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4739 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4740 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4743 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4745 AOP_TYPE (left), AOP_TYPE (right));
4746 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4748 AOP_SIZE (left), AOP_SIZE (right));
4751 /* if left is a literal & right is not then exchange them */
4752 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4753 AOP_NEEDSACC (left))
4755 operand *tmp = right;
4760 /* if result = right then exchange them */
4761 if (sameRegs (AOP (result), AOP (right)))
4763 operand *tmp = right;
4768 /* if right is bit then exchange them */
4769 if (AOP_TYPE (right) == AOP_CRY &&
4770 AOP_TYPE (left) != AOP_CRY)
4772 operand *tmp = right;
4776 if (AOP_TYPE (right) == AOP_LIT)
4777 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4779 size = AOP_SIZE (result);
4783 if (AOP_TYPE (left) == AOP_CRY)
4785 if (AOP_TYPE (right) == AOP_LIT)
4787 // c = bit & literal;
4790 // lit != 0 => result = 1
4791 if (AOP_TYPE (result) == AOP_CRY)
4794 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4796 continueIfTrue (ifx);
4799 emitcode ("setb", "c");
4803 // lit == 0 => result = left
4804 if (size && sameRegs (AOP (result), AOP (left)))
4806 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4811 if (AOP_TYPE (right) == AOP_CRY)
4814 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4815 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4820 symbol *tlbl = newiTempLabel (NULL);
4821 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4822 emitcode ("setb", "c");
4823 emitcode ("jb", "%s,%05d$",
4824 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4826 emitcode ("jnz", "%05d$", tlbl->key + 100);
4827 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4829 jmpTrueOrFalse (ifx, tlbl);
4835 emitcode ("", "%05d$:", tlbl->key + 100);
4844 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4845 genIfxJump (ifx, "c");
4849 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4850 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4851 if ((AOP_TYPE (right) == AOP_LIT) &&
4852 (AOP_TYPE (result) == AOP_CRY) &&
4853 (AOP_TYPE (left) != AOP_CRY))
4859 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4861 continueIfTrue (ifx);
4866 // lit = 0, result = boolean(left)
4868 emitcode ("setb", "c");
4872 symbol *tlbl = newiTempLabel (NULL);
4873 emitcode ("jnz", "%05d$", tlbl->key + 100);
4875 emitcode ("", "%05d$:", tlbl->key + 100);
4879 genIfxJump (ifx, "a");
4887 /* if left is same as result */
4888 if (sameRegs (AOP (result), AOP (left)))
4890 for (; size--; offset++)
4892 if (AOP_TYPE (right) == AOP_LIT)
4894 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4896 else if (IS_AOP_PREG (left))
4898 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4899 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4900 aopPut (AOP (result), "a", offset);
4903 emitcode ("orl", "%s,%s",
4904 aopGet (AOP (left), offset, FALSE, TRUE),
4905 aopGet (AOP (right), offset, FALSE, FALSE));
4909 if (AOP_TYPE (left) == AOP_ACC)
4910 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4913 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4914 if (IS_AOP_PREG (left))
4916 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4917 aopPut (AOP (result), "a", offset);
4920 emitcode ("orl", "%s,a",
4921 aopGet (AOP (left), offset, FALSE, TRUE));
4928 // left & result in different registers
4929 if (AOP_TYPE (result) == AOP_CRY)
4932 // if(size), result in bit
4933 // if(!size && ifx), conditional oper: if(left | right)
4934 symbol *tlbl = newiTempLabel (NULL);
4935 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4937 emitcode ("setb", "c");
4940 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4941 emitcode ("orl", "a,%s",
4942 aopGet (AOP (right), offset, FALSE, FALSE));
4944 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4945 emitcode ("orl", "a,%s",
4946 aopGet (AOP (left), offset, FALSE, FALSE));
4948 emitcode ("jnz", "%05d$", tlbl->key + 100);
4954 emitcode ("", "%05d$:", tlbl->key + 100);
4958 jmpTrueOrFalse (ifx, tlbl);
4961 for (; (size--); offset++)
4964 // result = left & right
4965 if (AOP_TYPE (right) == AOP_LIT)
4967 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4969 aopPut (AOP (result),
4970 aopGet (AOP (left), offset, FALSE, FALSE),
4975 // faster than result <- left, anl result,right
4976 // and better if result is SFR
4977 if (AOP_TYPE (left) == AOP_ACC)
4978 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4981 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4982 emitcode ("orl", "a,%s",
4983 aopGet (AOP (left), offset, FALSE, FALSE));
4985 aopPut (AOP (result), "a", offset);
4990 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4991 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4992 freeAsmop (result, NULL, ic, TRUE);
4995 /*-----------------------------------------------------------------*/
4996 /* genXor - code for xclusive or */
4997 /*-----------------------------------------------------------------*/
4999 genXor (iCode * ic, iCode * ifx)
5001 operand *left, *right, *result;
5002 int size, offset = 0;
5003 unsigned long lit = 0L;
5005 D(emitcode (";", "genXor"));
5007 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5008 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5009 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5012 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5014 AOP_TYPE (left), AOP_TYPE (right));
5015 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5017 AOP_SIZE (left), AOP_SIZE (right));
5020 /* if left is a literal & right is not ||
5021 if left needs acc & right does not */
5022 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5023 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5025 operand *tmp = right;
5030 /* if result = right then exchange them */
5031 if (sameRegs (AOP (result), AOP (right)))
5033 operand *tmp = right;
5038 /* if right is bit then exchange them */
5039 if (AOP_TYPE (right) == AOP_CRY &&
5040 AOP_TYPE (left) != AOP_CRY)
5042 operand *tmp = right;
5046 if (AOP_TYPE (right) == AOP_LIT)
5047 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5049 size = AOP_SIZE (result);
5053 if (AOP_TYPE (left) == AOP_CRY)
5055 if (AOP_TYPE (right) == AOP_LIT)
5057 // c = bit & literal;
5060 // lit>>1 != 0 => result = 1
5061 if (AOP_TYPE (result) == AOP_CRY)
5064 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5066 continueIfTrue (ifx);
5069 emitcode ("setb", "c");
5076 // lit == 0, result = left
5077 if (size && sameRegs (AOP (result), AOP (left)))
5079 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5083 // lit == 1, result = not(left)
5084 if (size && sameRegs (AOP (result), AOP (left)))
5086 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5091 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5092 emitcode ("cpl", "c");
5101 symbol *tlbl = newiTempLabel (NULL);
5102 if (AOP_TYPE (right) == AOP_CRY)
5105 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5109 int sizer = AOP_SIZE (right);
5111 // if val>>1 != 0, result = 1
5112 emitcode ("setb", "c");
5115 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5117 // test the msb of the lsb
5118 emitcode ("anl", "a,#0xfe");
5119 emitcode ("jnz", "%05d$", tlbl->key + 100);
5123 emitcode ("rrc", "a");
5125 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5126 emitcode ("cpl", "c");
5127 emitcode ("", "%05d$:", (tlbl->key + 100));
5134 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5135 genIfxJump (ifx, "c");
5139 if (sameRegs (AOP (result), AOP (left)))
5141 /* if left is same as result */
5142 for (; size--; offset++)
5144 if (AOP_TYPE (right) == AOP_LIT)
5146 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5148 else if (IS_AOP_PREG (left))
5150 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5151 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5152 aopPut (AOP (result), "a", offset);
5155 emitcode ("xrl", "%s,%s",
5156 aopGet (AOP (left), offset, FALSE, TRUE),
5157 aopGet (AOP (right), offset, FALSE, FALSE));
5161 if (AOP_TYPE (left) == AOP_ACC)
5162 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5165 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5166 if (IS_AOP_PREG (left))
5168 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5169 aopPut (AOP (result), "a", offset);
5172 emitcode ("xrl", "%s,a",
5173 aopGet (AOP (left), offset, FALSE, TRUE));
5180 // left & result in different registers
5181 if (AOP_TYPE (result) == AOP_CRY)
5184 // if(size), result in bit
5185 // if(!size && ifx), conditional oper: if(left ^ right)
5186 symbol *tlbl = newiTempLabel (NULL);
5187 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5189 emitcode ("setb", "c");
5192 if ((AOP_TYPE (right) == AOP_LIT) &&
5193 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5195 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5199 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5200 emitcode ("xrl", "a,%s",
5201 aopGet (AOP (right), offset, FALSE, FALSE));
5203 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5204 emitcode ("xrl", "a,%s",
5205 aopGet (AOP (left), offset, FALSE, FALSE));
5208 emitcode ("jnz", "%05d$", tlbl->key + 100);
5214 emitcode ("", "%05d$:", tlbl->key + 100);
5218 jmpTrueOrFalse (ifx, tlbl);
5221 for (; (size--); offset++)
5224 // result = left & right
5225 if (AOP_TYPE (right) == AOP_LIT)
5227 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5229 aopPut (AOP (result),
5230 aopGet (AOP (left), offset, FALSE, FALSE),
5235 // faster than result <- left, anl result,right
5236 // and better if result is SFR
5237 if (AOP_TYPE (left) == AOP_ACC)
5238 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5241 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5242 emitcode ("xrl", "a,%s",
5243 aopGet (AOP (left), offset, FALSE, TRUE));
5245 aopPut (AOP (result), "a", offset);
5250 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5251 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5252 freeAsmop (result, NULL, ic, TRUE);
5255 /*-----------------------------------------------------------------*/
5256 /* genInline - write the inline code out */
5257 /*-----------------------------------------------------------------*/
5259 genInline (iCode * ic)
5261 char *buffer, *bp, *bp1;
5263 D(emitcode (";", "genInline"));
5265 _G.inLine += (!options.asmpeep);
5267 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5268 strcpy (buffer, IC_INLINE (ic));
5270 /* emit each line as a code */
5295 /* emitcode("",buffer); */
5296 _G.inLine -= (!options.asmpeep);
5299 /*-----------------------------------------------------------------*/
5300 /* genRRC - rotate right with carry */
5301 /*-----------------------------------------------------------------*/
5305 operand *left, *result;
5306 int size, offset = 0;
5309 D(emitcode (";", "genRRC"));
5311 /* rotate right with carry */
5312 left = IC_LEFT (ic);
5313 result = IC_RESULT (ic);
5314 aopOp (left, ic, FALSE);
5315 aopOp (result, ic, FALSE);
5317 /* move it to the result */
5318 size = AOP_SIZE (result);
5320 if (size == 1) { /* special case for 1 byte */
5321 l = aopGet (AOP (left), offset, FALSE, FALSE);
5323 emitcode ("rr", "a");
5329 l = aopGet (AOP (left), offset, FALSE, FALSE);
5331 emitcode ("rrc", "a");
5332 if (AOP_SIZE (result) > 1)
5333 aopPut (AOP (result), "a", offset--);
5335 /* now we need to put the carry into the
5336 highest order byte of the result */
5337 if (AOP_SIZE (result) > 1)
5339 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5342 emitcode ("mov", "acc.7,c");
5344 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5345 freeAsmop (left, NULL, ic, TRUE);
5346 freeAsmop (result, NULL, ic, TRUE);
5349 /*-----------------------------------------------------------------*/
5350 /* genRLC - generate code for rotate left with carry */
5351 /*-----------------------------------------------------------------*/
5355 operand *left, *result;
5356 int size, offset = 0;
5359 D(emitcode (";", "genRLC"));
5361 /* rotate right with carry */
5362 left = IC_LEFT (ic);
5363 result = IC_RESULT (ic);
5364 aopOp (left, ic, FALSE);
5365 aopOp (result, ic, FALSE);
5367 /* move it to the result */
5368 size = AOP_SIZE (result);
5372 l = aopGet (AOP (left), offset, FALSE, FALSE);
5374 if (size == 0) { /* special case for 1 byte */
5378 emitcode ("add", "a,acc");
5379 if (AOP_SIZE (result) > 1)
5380 aopPut (AOP (result), "a", offset++);
5383 l = aopGet (AOP (left), offset, FALSE, FALSE);
5385 emitcode ("rlc", "a");
5386 if (AOP_SIZE (result) > 1)
5387 aopPut (AOP (result), "a", offset++);
5390 /* now we need to put the carry into the
5391 highest order byte of the result */
5392 if (AOP_SIZE (result) > 1)
5394 l = aopGet (AOP (result), 0, FALSE, FALSE);
5397 emitcode ("mov", "acc.0,c");
5399 aopPut (AOP (result), "a", 0);
5400 freeAsmop (left, NULL, ic, TRUE);
5401 freeAsmop (result, NULL, ic, TRUE);
5404 /*-----------------------------------------------------------------*/
5405 /* genGetHbit - generates code get highest order bit */
5406 /*-----------------------------------------------------------------*/
5408 genGetHbit (iCode * ic)
5410 operand *left, *result;
5412 D(emitcode (";", "genGetHbit"));
5414 left = IC_LEFT (ic);
5415 result = IC_RESULT (ic);
5416 aopOp (left, ic, FALSE);
5417 aopOp (result, ic, FALSE);
5419 /* get the highest order byte into a */
5420 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5421 if (AOP_TYPE (result) == AOP_CRY)
5423 emitcode ("rlc", "a");
5428 emitcode ("rl", "a");
5429 emitcode ("anl", "a,#0x01");
5434 freeAsmop (left, NULL, ic, TRUE);
5435 freeAsmop (result, NULL, ic, TRUE);
5438 /*-----------------------------------------------------------------*/
5439 /* AccRol - rotate left accumulator by known count */
5440 /*-----------------------------------------------------------------*/
5442 AccRol (int shCount)
5444 shCount &= 0x0007; // shCount : 0..7
5451 emitcode ("rl", "a");
5454 emitcode ("rl", "a");
5455 emitcode ("rl", "a");
5458 emitcode ("swap", "a");
5459 emitcode ("rr", "a");
5462 emitcode ("swap", "a");
5465 emitcode ("swap", "a");
5466 emitcode ("rl", "a");
5469 emitcode ("rr", "a");
5470 emitcode ("rr", "a");
5473 emitcode ("rr", "a");
5478 /*-----------------------------------------------------------------*/
5479 /* AccLsh - left shift accumulator by known count */
5480 /*-----------------------------------------------------------------*/
5482 AccLsh (int shCount)
5487 emitcode ("add", "a,acc");
5488 else if (shCount == 2)
5490 emitcode ("add", "a,acc");
5491 emitcode ("add", "a,acc");
5495 /* rotate left accumulator */
5497 /* and kill the lower order bits */
5498 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5503 /*-----------------------------------------------------------------*/
5504 /* AccRsh - right shift accumulator by known count */
5505 /*-----------------------------------------------------------------*/
5507 AccRsh (int shCount)
5514 emitcode ("rrc", "a");
5518 /* rotate right accumulator */
5519 AccRol (8 - shCount);
5520 /* and kill the higher order bits */
5521 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5526 /*-----------------------------------------------------------------*/
5527 /* AccSRsh - signed right shift accumulator by known count */
5528 /*-----------------------------------------------------------------*/
5530 AccSRsh (int shCount)
5537 emitcode ("mov", "c,acc.7");
5538 emitcode ("rrc", "a");
5540 else if (shCount == 2)
5542 emitcode ("mov", "c,acc.7");
5543 emitcode ("rrc", "a");
5544 emitcode ("mov", "c,acc.7");
5545 emitcode ("rrc", "a");
5549 tlbl = newiTempLabel (NULL);
5550 /* rotate right accumulator */
5551 AccRol (8 - shCount);
5552 /* and kill the higher order bits */
5553 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5554 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5555 emitcode ("orl", "a,#0x%02x",
5556 (unsigned char) ~SRMask[shCount]);
5557 emitcode ("", "%05d$:", tlbl->key + 100);
5562 /*-----------------------------------------------------------------*/
5563 /* shiftR1Left2Result - shift right one byte from left to result */
5564 /*-----------------------------------------------------------------*/
5566 shiftR1Left2Result (operand * left, int offl,
5567 operand * result, int offr,
5568 int shCount, int sign)
5570 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5571 /* shift right accumulator */
5576 aopPut (AOP (result), "a", offr);
5579 /*-----------------------------------------------------------------*/
5580 /* shiftL1Left2Result - shift left one byte from left to result */
5581 /*-----------------------------------------------------------------*/
5583 shiftL1Left2Result (operand * left, int offl,
5584 operand * result, int offr, int shCount)
5587 l = aopGet (AOP (left), offl, FALSE, FALSE);
5589 /* shift left accumulator */
5591 aopPut (AOP (result), "a", offr);
5594 /*-----------------------------------------------------------------*/
5595 /* movLeft2Result - move byte from left to result */
5596 /*-----------------------------------------------------------------*/
5598 movLeft2Result (operand * left, int offl,
5599 operand * result, int offr, int sign)
5602 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5604 l = aopGet (AOP (left), offl, FALSE, FALSE);
5606 if (*l == '@' && (IS_AOP_PREG (result)))
5608 emitcode ("mov", "a,%s", l);
5609 aopPut (AOP (result), "a", offr);
5614 aopPut (AOP (result), l, offr);
5617 /* MSB sign in acc.7 ! */
5618 if (getDataSize (left) == offl + 1)
5620 emitcode ("mov", "a,%s", l);
5621 aopPut (AOP (result), "a", offr);
5628 /*-----------------------------------------------------------------*/
5629 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5630 /*-----------------------------------------------------------------*/
5634 emitcode ("rrc", "a");
5635 emitcode ("xch", "a,%s", x);
5636 emitcode ("rrc", "a");
5637 emitcode ("xch", "a,%s", x);
5640 /*-----------------------------------------------------------------*/
5641 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5642 /*-----------------------------------------------------------------*/
5646 emitcode ("xch", "a,%s", x);
5647 emitcode ("rlc", "a");
5648 emitcode ("xch", "a,%s", x);
5649 emitcode ("rlc", "a");
5652 /*-----------------------------------------------------------------*/
5653 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5654 /*-----------------------------------------------------------------*/
5658 emitcode ("xch", "a,%s", x);
5659 emitcode ("add", "a,acc");
5660 emitcode ("xch", "a,%s", x);
5661 emitcode ("rlc", "a");
5664 /*-----------------------------------------------------------------*/
5665 /* AccAXLsh - left shift a:x by known count (0..7) */
5666 /*-----------------------------------------------------------------*/
5668 AccAXLsh (char *x, int shCount)
5683 case 5: // AAAAABBB:CCCCCDDD
5685 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5687 emitcode ("anl", "a,#0x%02x",
5688 SLMask[shCount]); // BBB00000:CCCCCDDD
5690 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5692 AccRol (shCount); // DDDCCCCC:BBB00000
5694 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5696 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5698 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5700 emitcode ("anl", "a,#0x%02x",
5701 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5703 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5705 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5708 case 6: // AAAAAABB:CCCCCCDD
5709 emitcode ("anl", "a,#0x%02x",
5710 SRMask[shCount]); // 000000BB:CCCCCCDD
5711 emitcode ("mov", "c,acc.0"); // c = B
5712 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5714 AccAXRrl1 (x); // BCCCCCCD:D000000B
5715 AccAXRrl1 (x); // BBCCCCCC:DD000000
5717 emitcode("rrc","a");
5718 emitcode("xch","a,%s", x);
5719 emitcode("rrc","a");
5720 emitcode("mov","c,acc.0"); //<< get correct bit
5721 emitcode("xch","a,%s", x);
5723 emitcode("rrc","a");
5724 emitcode("xch","a,%s", x);
5725 emitcode("rrc","a");
5726 emitcode("xch","a,%s", x);
5729 case 7: // a:x <<= 7
5731 emitcode ("anl", "a,#0x%02x",
5732 SRMask[shCount]); // 0000000B:CCCCCCCD
5734 emitcode ("mov", "c,acc.0"); // c = B
5736 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5738 AccAXRrl1 (x); // BCCCCCCC:D0000000
5746 /*-----------------------------------------------------------------*/
5747 /* AccAXRsh - right shift a:x known count (0..7) */
5748 /*-----------------------------------------------------------------*/
5750 AccAXRsh (char *x, int shCount)
5758 AccAXRrl1 (x); // 0->a:x
5763 AccAXRrl1 (x); // 0->a:x
5766 AccAXRrl1 (x); // 0->a:x
5771 case 5: // AAAAABBB:CCCCCDDD = a:x
5773 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5775 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5777 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5779 emitcode ("anl", "a,#0x%02x",
5780 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5782 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5784 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5786 emitcode ("anl", "a,#0x%02x",
5787 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5789 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5791 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5793 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5796 case 6: // AABBBBBB:CCDDDDDD
5798 emitcode ("mov", "c,acc.7");
5799 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5801 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5803 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5805 emitcode ("anl", "a,#0x%02x",
5806 SRMask[shCount]); // 000000AA:BBBBBBCC
5809 case 7: // ABBBBBBB:CDDDDDDD
5811 emitcode ("mov", "c,acc.7"); // c = A
5813 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5815 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5817 emitcode ("anl", "a,#0x%02x",
5818 SRMask[shCount]); // 0000000A:BBBBBBBC
5826 /*-----------------------------------------------------------------*/
5827 /* AccAXRshS - right shift signed a:x known count (0..7) */
5828 /*-----------------------------------------------------------------*/
5830 AccAXRshS (char *x, int shCount)
5838 emitcode ("mov", "c,acc.7");
5839 AccAXRrl1 (x); // s->a:x
5843 emitcode ("mov", "c,acc.7");
5844 AccAXRrl1 (x); // s->a:x
5846 emitcode ("mov", "c,acc.7");
5847 AccAXRrl1 (x); // s->a:x
5852 case 5: // AAAAABBB:CCCCCDDD = a:x
5854 tlbl = newiTempLabel (NULL);
5855 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5857 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5859 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5861 emitcode ("anl", "a,#0x%02x",
5862 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5864 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5866 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5868 emitcode ("anl", "a,#0x%02x",
5869 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5871 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5873 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5875 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5877 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5878 emitcode ("orl", "a,#0x%02x",
5879 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5881 emitcode ("", "%05d$:", tlbl->key + 100);
5882 break; // SSSSAAAA:BBBCCCCC
5884 case 6: // AABBBBBB:CCDDDDDD
5886 tlbl = newiTempLabel (NULL);
5887 emitcode ("mov", "c,acc.7");
5888 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5890 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5892 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5894 emitcode ("anl", "a,#0x%02x",
5895 SRMask[shCount]); // 000000AA:BBBBBBCC
5897 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5898 emitcode ("orl", "a,#0x%02x",
5899 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5901 emitcode ("", "%05d$:", tlbl->key + 100);
5903 case 7: // ABBBBBBB:CDDDDDDD
5905 tlbl = newiTempLabel (NULL);
5906 emitcode ("mov", "c,acc.7"); // c = A
5908 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5910 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5912 emitcode ("anl", "a,#0x%02x",
5913 SRMask[shCount]); // 0000000A:BBBBBBBC
5915 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5916 emitcode ("orl", "a,#0x%02x",
5917 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5919 emitcode ("", "%05d$:", tlbl->key + 100);
5926 /*-----------------------------------------------------------------*/
5927 /* shiftL2Left2Result - shift left two bytes from left to result */
5928 /*-----------------------------------------------------------------*/
5930 shiftL2Left2Result (operand * left, int offl,
5931 operand * result, int offr, int shCount)
5933 if (sameRegs (AOP (result), AOP (left)) &&
5934 ((offl + MSB16) == offr))
5936 /* don't crash result[offr] */
5937 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5938 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5942 movLeft2Result (left, offl, result, offr, 0);
5943 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5945 /* ax << shCount (x = lsb(result)) */
5946 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5947 aopPut (AOP (result), "a", offr + MSB16);
5951 /*-----------------------------------------------------------------*/
5952 /* shiftR2Left2Result - shift right two bytes from left to result */
5953 /*-----------------------------------------------------------------*/
5955 shiftR2Left2Result (operand * left, int offl,
5956 operand * result, int offr,
5957 int shCount, int sign)
5959 if (sameRegs (AOP (result), AOP (left)) &&
5960 ((offl + MSB16) == offr))
5962 /* don't crash result[offr] */
5963 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5964 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5968 movLeft2Result (left, offl, result, offr, 0);
5969 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5971 /* a:x >> shCount (x = lsb(result)) */
5973 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5975 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
5976 if (getDataSize (result) > 1)
5977 aopPut (AOP (result), "a", offr + MSB16);
5980 /*-----------------------------------------------------------------*/
5981 /* shiftLLeftOrResult - shift left one byte from left, or to result */
5982 /*-----------------------------------------------------------------*/
5984 shiftLLeftOrResult (operand * left, int offl,
5985 operand * result, int offr, int shCount)
5987 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5988 /* shift left accumulator */
5990 /* or with result */
5991 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
5992 /* back to result */
5993 aopPut (AOP (result), "a", offr);
5996 /*-----------------------------------------------------------------*/
5997 /* shiftRLeftOrResult - shift right one byte from left,or to result */
5998 /*-----------------------------------------------------------------*/
6000 shiftRLeftOrResult (operand * left, int offl,
6001 operand * result, int offr, int shCount)
6003 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6004 /* shift right accumulator */
6006 /* or with result */
6007 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6008 /* back to result */
6009 aopPut (AOP (result), "a", offr);
6012 /*-----------------------------------------------------------------*/
6013 /* genlshOne - left shift a one byte quantity by known count */
6014 /*-----------------------------------------------------------------*/
6016 genlshOne (operand * result, operand * left, int shCount)
6018 D(emitcode (";", "genlshOne"));
6020 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6023 /*-----------------------------------------------------------------*/
6024 /* genlshTwo - left shift two bytes by known amount != 0 */
6025 /*-----------------------------------------------------------------*/
6027 genlshTwo (operand * result, operand * left, int shCount)
6031 D(emitcode (";", "genlshTwo"));
6033 size = getDataSize (result);
6035 /* if shCount >= 8 */
6043 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6045 movLeft2Result (left, LSB, result, MSB16, 0);
6047 aopPut (AOP (result), zero, LSB);
6050 /* 1 <= shCount <= 7 */
6054 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6056 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6060 /*-----------------------------------------------------------------*/
6061 /* shiftLLong - shift left one long from left to result */
6062 /* offl = LSB or MSB16 */
6063 /*-----------------------------------------------------------------*/
6065 shiftLLong (operand * left, operand * result, int offr)
6068 int size = AOP_SIZE (result);
6070 if (size >= LSB + offr)
6072 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6074 emitcode ("add", "a,acc");
6075 if (sameRegs (AOP (left), AOP (result)) &&
6076 size >= MSB16 + offr && offr != LSB)
6077 emitcode ("xch", "a,%s",
6078 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6080 aopPut (AOP (result), "a", LSB + offr);
6083 if (size >= MSB16 + offr)
6085 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6087 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6090 emitcode ("rlc", "a");
6091 if (sameRegs (AOP (left), AOP (result)) &&
6092 size >= MSB24 + offr && offr != LSB)
6093 emitcode ("xch", "a,%s",
6094 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6096 aopPut (AOP (result), "a", MSB16 + offr);
6099 if (size >= MSB24 + offr)
6101 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6103 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6106 emitcode ("rlc", "a");
6107 if (sameRegs (AOP (left), AOP (result)) &&
6108 size >= MSB32 + offr && offr != LSB)
6109 emitcode ("xch", "a,%s",
6110 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6112 aopPut (AOP (result), "a", MSB24 + offr);
6115 if (size > MSB32 + offr)
6117 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6119 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6122 emitcode ("rlc", "a");
6123 aopPut (AOP (result), "a", MSB32 + offr);
6126 aopPut (AOP (result), zero, LSB);
6129 /*-----------------------------------------------------------------*/
6130 /* genlshFour - shift four byte by a known amount != 0 */
6131 /*-----------------------------------------------------------------*/
6133 genlshFour (operand * result, operand * left, int shCount)
6137 D(emitcode (";", "genlshFour"));
6139 size = AOP_SIZE (result);
6141 /* if shifting more that 3 bytes */
6146 /* lowest order of left goes to the highest
6147 order of the destination */
6148 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6150 movLeft2Result (left, LSB, result, MSB32, 0);
6151 aopPut (AOP (result), zero, LSB);
6152 aopPut (AOP (result), zero, MSB16);
6153 aopPut (AOP (result), zero, MSB24);
6157 /* more than two bytes */
6158 else if (shCount >= 16)
6160 /* lower order two bytes goes to higher order two bytes */
6162 /* if some more remaining */
6164 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6167 movLeft2Result (left, MSB16, result, MSB32, 0);
6168 movLeft2Result (left, LSB, result, MSB24, 0);
6170 aopPut (AOP (result), zero, MSB16);
6171 aopPut (AOP (result), zero, LSB);
6175 /* if more than 1 byte */
6176 else if (shCount >= 8)
6178 /* lower order three bytes goes to higher order three bytes */
6183 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6185 movLeft2Result (left, LSB, result, MSB16, 0);
6191 movLeft2Result (left, MSB24, result, MSB32, 0);
6192 movLeft2Result (left, MSB16, result, MSB24, 0);
6193 movLeft2Result (left, LSB, result, MSB16, 0);
6194 aopPut (AOP (result), zero, LSB);
6196 else if (shCount == 1)
6197 shiftLLong (left, result, MSB16);
6200 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6201 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6202 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6203 aopPut (AOP (result), zero, LSB);
6208 /* 1 <= shCount <= 7 */
6209 else if (shCount <= 2)
6211 shiftLLong (left, result, LSB);
6213 shiftLLong (result, result, LSB);
6215 /* 3 <= shCount <= 7, optimize */
6218 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6219 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6220 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6224 /*-----------------------------------------------------------------*/
6225 /* genLeftShiftLiteral - left shifting by known count */
6226 /*-----------------------------------------------------------------*/
6228 genLeftShiftLiteral (operand * left,
6233 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6236 D(emitcode (";", "genLeftShiftLiteral"));
6238 freeAsmop (right, NULL, ic, TRUE);
6240 aopOp (left, ic, FALSE);
6241 aopOp (result, ic, FALSE);
6243 size = getSize (operandType (result));
6246 emitcode ("; shift left ", "result %d, left %d", size,
6250 /* I suppose that the left size >= result size */
6255 movLeft2Result (left, size, result, size, 0);
6259 else if (shCount >= (size * 8))
6261 aopPut (AOP (result), zero, size);
6267 genlshOne (result, left, shCount);
6271 genlshTwo (result, left, shCount);
6275 genlshFour (result, left, shCount);
6278 fprintf(stderr, "*** ack! mystery literal shift!\n");
6282 freeAsmop (left, NULL, ic, TRUE);
6283 freeAsmop (result, NULL, ic, TRUE);
6286 /*-----------------------------------------------------------------*/
6287 /* genLeftShift - generates code for left shifting */
6288 /*-----------------------------------------------------------------*/
6290 genLeftShift (iCode * ic)
6292 operand *left, *right, *result;
6295 symbol *tlbl, *tlbl1;
6297 D(emitcode (";", "genLeftShift"));
6299 right = IC_RIGHT (ic);
6300 left = IC_LEFT (ic);
6301 result = IC_RESULT (ic);
6303 aopOp (right, ic, FALSE);
6305 /* if the shift count is known then do it
6306 as efficiently as possible */
6307 if (AOP_TYPE (right) == AOP_LIT)
6309 genLeftShiftLiteral (left, right, result, ic);
6313 /* shift count is unknown then we have to form
6314 a loop get the loop count in B : Note: we take
6315 only the lower order byte since shifting
6316 more that 32 bits make no sense anyway, ( the
6317 largest size of an object can be only 32 bits ) */
6319 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6320 emitcode ("inc", "b");
6321 freeAsmop (right, NULL, ic, TRUE);
6322 aopOp (left, ic, FALSE);
6323 aopOp (result, ic, FALSE);
6325 /* now move the left to the result if they are not the
6327 if (!sameRegs (AOP (left), AOP (result)) &&
6328 AOP_SIZE (result) > 1)
6331 size = AOP_SIZE (result);
6335 l = aopGet (AOP (left), offset, FALSE, TRUE);
6336 if (*l == '@' && (IS_AOP_PREG (result)))
6339 emitcode ("mov", "a,%s", l);
6340 aopPut (AOP (result), "a", offset);
6343 aopPut (AOP (result), l, offset);
6348 tlbl = newiTempLabel (NULL);
6349 size = AOP_SIZE (result);
6351 tlbl1 = newiTempLabel (NULL);
6353 /* if it is only one byte then */
6356 symbol *tlbl1 = newiTempLabel (NULL);
6358 l = aopGet (AOP (left), 0, FALSE, FALSE);
6360 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6361 emitcode ("", "%05d$:", tlbl->key + 100);
6362 emitcode ("add", "a,acc");
6363 emitcode ("", "%05d$:", tlbl1->key + 100);
6364 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6365 aopPut (AOP (result), "a", 0);
6369 reAdjustPreg (AOP (result));
6371 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6372 emitcode ("", "%05d$:", tlbl->key + 100);
6373 l = aopGet (AOP (result), offset, FALSE, FALSE);
6375 emitcode ("add", "a,acc");
6376 aopPut (AOP (result), "a", offset++);
6379 l = aopGet (AOP (result), offset, FALSE, FALSE);
6381 emitcode ("rlc", "a");
6382 aopPut (AOP (result), "a", offset++);
6384 reAdjustPreg (AOP (result));
6386 emitcode ("", "%05d$:", tlbl1->key + 100);
6387 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6389 freeAsmop (left, NULL, ic, TRUE);
6390 freeAsmop (result, NULL, ic, TRUE);
6393 /*-----------------------------------------------------------------*/
6394 /* genrshOne - right shift a one byte quantity by known count */
6395 /*-----------------------------------------------------------------*/
6397 genrshOne (operand * result, operand * left,
6398 int shCount, int sign)
6400 D(emitcode (";", "genrshOne"));
6402 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6405 /*-----------------------------------------------------------------*/
6406 /* genrshTwo - right shift two bytes by known amount != 0 */
6407 /*-----------------------------------------------------------------*/
6409 genrshTwo (operand * result, operand * left,
6410 int shCount, int sign)
6412 D(emitcode (";", "genrshTwo"));
6414 /* if shCount >= 8 */
6419 shiftR1Left2Result (left, MSB16, result, LSB,
6422 movLeft2Result (left, MSB16, result, LSB, sign);
6423 addSign (result, MSB16, sign);
6426 /* 1 <= shCount <= 7 */
6428 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6431 /*-----------------------------------------------------------------*/
6432 /* shiftRLong - shift right one long from left to result */
6433 /* offl = LSB or MSB16 */
6434 /*-----------------------------------------------------------------*/
6436 shiftRLong (operand * left, int offl,
6437 operand * result, int sign)
6439 int isSameRegs=sameRegs(AOP(left),AOP(result));
6441 if (isSameRegs && offl>1) {
6442 // we are in big trouble, but this shouldn't happen
6443 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6446 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6451 emitcode ("rlc", "a");
6452 emitcode ("subb", "a,acc");
6453 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6455 aopPut (AOP(result), zero, MSB32);
6460 emitcode ("clr", "c");
6462 emitcode ("mov", "c,acc.7");
6465 emitcode ("rrc", "a");
6467 if (isSameRegs && offl==MSB16) {
6468 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6470 aopPut (AOP (result), "a", MSB32);
6471 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6474 emitcode ("rrc", "a");
6475 if (isSameRegs && offl==1) {
6476 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6478 aopPut (AOP (result), "a", MSB24);
6479 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6481 emitcode ("rrc", "a");
6482 aopPut (AOP (result), "a", MSB16 - offl);
6486 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6487 emitcode ("rrc", "a");
6488 aopPut (AOP (result), "a", LSB);
6492 /*-----------------------------------------------------------------*/
6493 /* genrshFour - shift four byte by a known amount != 0 */
6494 /*-----------------------------------------------------------------*/
6496 genrshFour (operand * result, operand * left,
6497 int shCount, int sign)
6499 D(emitcode (";", "genrshFour"));
6501 /* if shifting more that 3 bytes */
6506 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6508 movLeft2Result (left, MSB32, result, LSB, sign);
6509 addSign (result, MSB16, sign);
6511 else if (shCount >= 16)
6515 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6518 movLeft2Result (left, MSB24, result, LSB, 0);
6519 movLeft2Result (left, MSB32, result, MSB16, sign);
6521 addSign (result, MSB24, sign);
6523 else if (shCount >= 8)
6527 shiftRLong (left, MSB16, result, sign);
6528 else if (shCount == 0)
6530 movLeft2Result (left, MSB16, result, LSB, 0);
6531 movLeft2Result (left, MSB24, result, MSB16, 0);
6532 movLeft2Result (left, MSB32, result, MSB24, sign);
6533 addSign (result, MSB32, sign);
6537 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6538 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6539 /* the last shift is signed */
6540 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6541 addSign (result, MSB32, sign);
6545 { /* 1 <= shCount <= 7 */
6548 shiftRLong (left, LSB, result, sign);
6550 shiftRLong (result, LSB, result, sign);
6554 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6555 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6556 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6561 /*-----------------------------------------------------------------*/
6562 /* genRightShiftLiteral - right shifting by known count */
6563 /*-----------------------------------------------------------------*/
6565 genRightShiftLiteral (operand * left,
6571 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6574 D(emitcode (";", "genRightShiftLiteral"));
6576 freeAsmop (right, NULL, ic, TRUE);
6578 aopOp (left, ic, FALSE);
6579 aopOp (result, ic, FALSE);
6582 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6586 size = getDataSize (left);
6587 /* test the LEFT size !!! */
6589 /* I suppose that the left size >= result size */
6592 size = getDataSize (result);
6594 movLeft2Result (left, size, result, size, 0);
6597 else if (shCount >= (size * 8))
6600 /* get sign in acc.7 */
6601 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6602 addSign (result, LSB, sign);
6609 genrshOne (result, left, shCount, sign);
6613 genrshTwo (result, left, shCount, sign);
6617 genrshFour (result, left, shCount, sign);
6623 freeAsmop (left, NULL, ic, TRUE);
6624 freeAsmop (result, NULL, ic, TRUE);
6628 /*-----------------------------------------------------------------*/
6629 /* genSignedRightShift - right shift of signed number */
6630 /*-----------------------------------------------------------------*/
6632 genSignedRightShift (iCode * ic)
6634 operand *right, *left, *result;
6637 symbol *tlbl, *tlbl1;
6639 D(emitcode (";", "genSignedRightShift"));
6641 /* we do it the hard way put the shift count in b
6642 and loop thru preserving the sign */
6644 right = IC_RIGHT (ic);
6645 left = IC_LEFT (ic);
6646 result = IC_RESULT (ic);
6648 aopOp (right, ic, FALSE);
6651 if (AOP_TYPE (right) == AOP_LIT)
6653 genRightShiftLiteral (left, right, result, ic, 1);
6656 /* shift count is unknown then we have to form
6657 a loop get the loop count in B : Note: we take
6658 only the lower order byte since shifting
6659 more that 32 bits make no sense anyway, ( the
6660 largest size of an object can be only 32 bits ) */
6662 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6663 emitcode ("inc", "b");
6664 freeAsmop (right, NULL, ic, TRUE);
6665 aopOp (left, ic, FALSE);
6666 aopOp (result, ic, FALSE);
6668 /* now move the left to the result if they are not the
6670 if (!sameRegs (AOP (left), AOP (result)) &&
6671 AOP_SIZE (result) > 1)
6674 size = AOP_SIZE (result);
6678 l = aopGet (AOP (left), offset, FALSE, TRUE);
6679 if (*l == '@' && IS_AOP_PREG (result))
6682 emitcode ("mov", "a,%s", l);
6683 aopPut (AOP (result), "a", offset);
6686 aopPut (AOP (result), l, offset);
6691 /* mov the highest order bit to OVR */
6692 tlbl = newiTempLabel (NULL);
6693 tlbl1 = newiTempLabel (NULL);
6695 size = AOP_SIZE (result);
6697 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6698 emitcode ("rlc", "a");
6699 emitcode ("mov", "ov,c");
6700 /* if it is only one byte then */
6703 l = aopGet (AOP (left), 0, FALSE, FALSE);
6705 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6706 emitcode ("", "%05d$:", tlbl->key + 100);
6707 emitcode ("mov", "c,ov");
6708 emitcode ("rrc", "a");
6709 emitcode ("", "%05d$:", tlbl1->key + 100);
6710 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6711 aopPut (AOP (result), "a", 0);
6715 reAdjustPreg (AOP (result));
6716 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6717 emitcode ("", "%05d$:", tlbl->key + 100);
6718 emitcode ("mov", "c,ov");
6721 l = aopGet (AOP (result), offset, FALSE, FALSE);
6723 emitcode ("rrc", "a");
6724 aopPut (AOP (result), "a", offset--);
6726 reAdjustPreg (AOP (result));
6727 emitcode ("", "%05d$:", tlbl1->key + 100);
6728 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6731 freeAsmop (left, NULL, ic, TRUE);
6732 freeAsmop (result, NULL, ic, TRUE);
6735 /*-----------------------------------------------------------------*/
6736 /* genRightShift - generate code for right shifting */
6737 /*-----------------------------------------------------------------*/
6739 genRightShift (iCode * ic)
6741 operand *right, *left, *result;
6745 symbol *tlbl, *tlbl1;
6747 D(emitcode (";", "genRightShift"));
6749 /* if signed then we do it the hard way preserve the
6750 sign bit moving it inwards */
6751 retype = getSpec (operandType (IC_RESULT (ic)));
6753 if (!SPEC_USIGN (retype))
6755 genSignedRightShift (ic);
6759 /* signed & unsigned types are treated the same : i.e. the
6760 signed is NOT propagated inwards : quoting from the
6761 ANSI - standard : "for E1 >> E2, is equivalent to division
6762 by 2**E2 if unsigned or if it has a non-negative value,
6763 otherwise the result is implementation defined ", MY definition
6764 is that the sign does not get propagated */
6766 right = IC_RIGHT (ic);
6767 left = IC_LEFT (ic);
6768 result = IC_RESULT (ic);
6770 aopOp (right, ic, FALSE);
6772 /* if the shift count is known then do it
6773 as efficiently as possible */
6774 if (AOP_TYPE (right) == AOP_LIT)
6776 genRightShiftLiteral (left, right, result, ic, 0);
6780 /* shift count is unknown then we have to form
6781 a loop get the loop count in B : Note: we take
6782 only the lower order byte since shifting
6783 more that 32 bits make no sense anyway, ( the
6784 largest size of an object can be only 32 bits ) */
6786 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6787 emitcode ("inc", "b");
6788 freeAsmop (right, NULL, ic, TRUE);
6789 aopOp (left, ic, FALSE);
6790 aopOp (result, ic, FALSE);
6792 /* now move the left to the result if they are not the
6794 if (!sameRegs (AOP (left), AOP (result)) &&
6795 AOP_SIZE (result) > 1)
6798 size = AOP_SIZE (result);
6802 l = aopGet (AOP (left), offset, FALSE, TRUE);
6803 if (*l == '@' && IS_AOP_PREG (result))
6806 emitcode ("mov", "a,%s", l);
6807 aopPut (AOP (result), "a", offset);
6810 aopPut (AOP (result), l, offset);
6815 tlbl = newiTempLabel (NULL);
6816 tlbl1 = newiTempLabel (NULL);
6817 size = AOP_SIZE (result);
6820 /* if it is only one byte then */
6823 l = aopGet (AOP (left), 0, FALSE, FALSE);
6825 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6826 emitcode ("", "%05d$:", tlbl->key + 100);
6828 emitcode ("rrc", "a");
6829 emitcode ("", "%05d$:", tlbl1->key + 100);
6830 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6831 aopPut (AOP (result), "a", 0);
6835 reAdjustPreg (AOP (result));
6836 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6837 emitcode ("", "%05d$:", tlbl->key + 100);
6841 l = aopGet (AOP (result), offset, FALSE, FALSE);
6843 emitcode ("rrc", "a");
6844 aopPut (AOP (result), "a", offset--);
6846 reAdjustPreg (AOP (result));
6848 emitcode ("", "%05d$:", tlbl1->key + 100);
6849 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6852 freeAsmop (left, NULL, ic, TRUE);
6853 freeAsmop (result, NULL, ic, TRUE);
6856 /*-----------------------------------------------------------------*/
6857 /* genUnpackBits - generates code for unpacking bits */
6858 /*-----------------------------------------------------------------*/
6860 genUnpackBits (operand * result, char *rname, int ptype)
6868 D(emitcode (";", "genUnpackBits"));
6870 etype = getSpec (operandType (result));
6871 rsize = getSize (operandType (result));
6872 /* read the first byte */
6878 emitcode ("mov", "a,@%s", rname);
6882 emitcode ("movx", "a,@%s", rname);
6886 emitcode ("movx", "a,@dptr");
6890 emitcode ("clr", "a");
6891 emitcode ("movc", "a,@a+dptr");
6895 emitcode ("lcall", "__gptrget");
6899 rlen = SPEC_BLEN (etype);
6901 /* if we have bitdisplacement then it fits */
6902 /* into this byte completely or if length is */
6903 /* less than a byte */
6904 if ((shCnt = SPEC_BSTR (etype)) ||
6905 (SPEC_BLEN (etype) <= 8))
6908 /* shift right acc */
6911 emitcode ("anl", "a,#0x%02x",
6912 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6913 aopPut (AOP (result), "a", offset++);
6917 /* bit field did not fit in a byte */
6918 aopPut (AOP (result), "a", offset++);
6927 emitcode ("inc", "%s", rname);
6928 emitcode ("mov", "a,@%s", rname);
6932 emitcode ("inc", "%s", rname);
6933 emitcode ("movx", "a,@%s", rname);
6937 emitcode ("inc", "dptr");
6938 emitcode ("movx", "a,@dptr");
6942 emitcode ("clr", "a");
6943 emitcode ("inc", "dptr");
6944 emitcode ("movc", "a,@a+dptr");
6948 emitcode ("inc", "dptr");
6949 emitcode ("lcall", "__gptrget");
6954 /* if we are done */
6958 aopPut (AOP (result), "a", offset++);
6964 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
6966 aopPut (AOP (result), "a", offset++);
6974 aopPut (AOP (result), zero, offset++);
6980 /*-----------------------------------------------------------------*/
6981 /* genDataPointerGet - generates code when ptr offset is known */
6982 /*-----------------------------------------------------------------*/
6984 genDataPointerGet (operand * left,
6990 int size, offset = 0;
6992 D(emitcode (";", "genDataPointerGet"));
6994 aopOp (result, ic, TRUE);
6996 /* get the string representation of the name */
6997 l = aopGet (AOP (left), 0, FALSE, TRUE);
6998 size = AOP_SIZE (result);
7002 sprintf (buffer, "(%s + %d)", l + 1, offset);
7004 sprintf (buffer, "%s", l + 1);
7005 aopPut (AOP (result), buffer, offset++);
7008 freeAsmop (left, NULL, ic, TRUE);
7009 freeAsmop (result, NULL, ic, TRUE);
7012 /*-----------------------------------------------------------------*/
7013 /* genNearPointerGet - emitcode for near pointer fetch */
7014 /*-----------------------------------------------------------------*/
7016 genNearPointerGet (operand * left,
7024 sym_link *rtype, *retype;
7025 sym_link *ltype = operandType (left);
7028 D(emitcode (";", "genNearPointerGet"));
7030 rtype = operandType (result);
7031 retype = getSpec (rtype);
7033 aopOp (left, ic, FALSE);
7035 /* if left is rematerialisable and
7036 result is not bit variable type and
7037 the left is pointer to data space i.e
7038 lower 128 bytes of space */
7039 if (AOP_TYPE (left) == AOP_IMMD &&
7040 !IS_BITVAR (retype) &&
7041 DCL_TYPE (ltype) == POINTER)
7043 genDataPointerGet (left, result, ic);
7047 /* if the value is already in a pointer register
7048 then don't need anything more */
7049 if (!AOP_INPREG (AOP (left)))
7051 /* otherwise get a free pointer register */
7053 preg = getFreePtr (ic, &aop, FALSE);
7054 emitcode ("mov", "%s,%s",
7056 aopGet (AOP (left), 0, FALSE, TRUE));
7060 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7062 //aopOp (result, ic, FALSE);
7063 aopOp (result, ic, result?TRUE:FALSE);
7065 /* if bitfield then unpack the bits */
7066 if (IS_BITVAR (retype))
7067 genUnpackBits (result, rname, POINTER);
7070 /* we have can just get the values */
7071 int size = AOP_SIZE (result);
7076 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7079 emitcode ("mov", "a,@%s", rname);
7080 aopPut (AOP (result), "a", offset);
7084 sprintf (buffer, "@%s", rname);
7085 aopPut (AOP (result), buffer, offset);
7089 emitcode ("inc", "%s", rname);
7093 /* now some housekeeping stuff */
7094 if (aop) /* we had to allocate for this iCode */
7096 if (pi) { /* post increment present */
7097 aopPut(AOP ( left ),rname,0);
7099 freeAsmop (NULL, aop, ic, TRUE);
7103 /* we did not allocate which means left
7104 already in a pointer register, then
7105 if size > 0 && this could be used again
7106 we have to point it back to where it
7108 if ((AOP_SIZE (result) > 1 &&
7109 !OP_SYMBOL (left)->remat &&
7110 (OP_SYMBOL (left)->liveTo > ic->seq ||
7114 int size = AOP_SIZE (result) - 1;
7116 emitcode ("dec", "%s", rname);
7121 freeAsmop (left, NULL, ic, TRUE);
7122 freeAsmop (result, NULL, ic, TRUE);
7123 if (pi) pi->generated = 1;
7126 /*-----------------------------------------------------------------*/
7127 /* genPagedPointerGet - emitcode for paged pointer fetch */
7128 /*-----------------------------------------------------------------*/
7130 genPagedPointerGet (operand * left,
7138 sym_link *rtype, *retype;
7140 D(emitcode (";", "genPagedPointerGet"));
7142 rtype = operandType (result);
7143 retype = getSpec (rtype);
7145 aopOp (left, ic, FALSE);
7147 /* if the value is already in a pointer register
7148 then don't need anything more */
7149 if (!AOP_INPREG (AOP (left)))
7151 /* otherwise get a free pointer register */
7153 preg = getFreePtr (ic, &aop, FALSE);
7154 emitcode ("mov", "%s,%s",
7156 aopGet (AOP (left), 0, FALSE, TRUE));
7160 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7162 aopOp (result, ic, FALSE);
7164 /* if bitfield then unpack the bits */
7165 if (IS_BITVAR (retype))
7166 genUnpackBits (result, rname, PPOINTER);
7169 /* we have can just get the values */
7170 int size = AOP_SIZE (result);
7176 emitcode ("movx", "a,@%s", rname);
7177 aopPut (AOP (result), "a", offset);
7182 emitcode ("inc", "%s", rname);
7186 /* now some housekeeping stuff */
7187 if (aop) /* we had to allocate for this iCode */
7189 if (pi) aopPut ( AOP (left), rname, 0);
7190 freeAsmop (NULL, aop, ic, TRUE);
7194 /* we did not allocate which means left
7195 already in a pointer register, then
7196 if size > 0 && this could be used again
7197 we have to point it back to where it
7199 if ((AOP_SIZE (result) > 1 &&
7200 !OP_SYMBOL (left)->remat &&
7201 (OP_SYMBOL (left)->liveTo > ic->seq ||
7205 int size = AOP_SIZE (result) - 1;
7207 emitcode ("dec", "%s", rname);
7212 freeAsmop (left, NULL, ic, TRUE);
7213 freeAsmop (result, NULL, ic, TRUE);
7214 if (pi) pi->generated = 1;
7218 /*-----------------------------------------------------------------*/
7219 /* genFarPointerGet - gget value from far space */
7220 /*-----------------------------------------------------------------*/
7222 genFarPointerGet (operand * left,
7223 operand * result, iCode * ic, iCode * pi)
7226 sym_link *retype = getSpec (operandType (result));
7228 D(emitcode (";", "genFarPointerGet"));
7230 aopOp (left, ic, FALSE);
7232 /* if the operand is already in dptr
7233 then we do nothing else we move the value to dptr */
7234 if (AOP_TYPE (left) != AOP_STR)
7236 /* if this is remateriazable */
7237 if (AOP_TYPE (left) == AOP_IMMD)
7238 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7240 { /* we need to get it byte by byte */
7241 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7242 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7245 /* so dptr know contains the address */
7246 aopOp (result, ic, FALSE);
7248 /* if bit then unpack */
7249 if (IS_BITVAR (retype))
7250 genUnpackBits (result, "dptr", FPOINTER);
7253 size = AOP_SIZE (result);
7258 emitcode ("movx", "a,@dptr");
7259 aopPut (AOP (result), "a", offset++);
7261 emitcode ("inc", "dptr");
7265 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7266 aopPut ( AOP (left), "dpl", 0);
7267 aopPut ( AOP (left), "dph", 1);
7270 freeAsmop (left, NULL, ic, TRUE);
7271 freeAsmop (result, NULL, ic, TRUE);
7274 /*-----------------------------------------------------------------*/
7275 /* genCodePointerGet - gget value from code space */
7276 /*-----------------------------------------------------------------*/
7278 genCodePointerGet (operand * left,
7279 operand * result, iCode * ic, iCode *pi)
7282 sym_link *retype = getSpec (operandType (result));
7284 D(emitcode (";", "genCodePointerGet"));
7286 aopOp (left, ic, FALSE);
7288 /* if the operand is already in dptr
7289 then we do nothing else we move the value to dptr */
7290 if (AOP_TYPE (left) != AOP_STR)
7292 /* if this is remateriazable */
7293 if (AOP_TYPE (left) == AOP_IMMD)
7294 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7296 { /* we need to get it byte by byte */
7297 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7298 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7301 /* so dptr know contains the address */
7302 aopOp (result, ic, FALSE);
7304 /* if bit then unpack */
7305 if (IS_BITVAR (retype))
7306 genUnpackBits (result, "dptr", CPOINTER);
7309 size = AOP_SIZE (result);
7314 emitcode ("clr", "a");
7315 emitcode ("movc", "a,@a+dptr");
7316 aopPut (AOP (result), "a", offset++);
7318 emitcode ("inc", "dptr");
7322 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7323 aopPut ( AOP (left), "dpl", 0);
7324 aopPut ( AOP (left), "dph", 1);
7327 freeAsmop (left, NULL, ic, TRUE);
7328 freeAsmop (result, NULL, ic, TRUE);
7331 /*-----------------------------------------------------------------*/
7332 /* genGenPointerGet - gget value from generic pointer space */
7333 /*-----------------------------------------------------------------*/
7335 genGenPointerGet (operand * left,
7336 operand * result, iCode * ic, iCode *pi)
7339 sym_link *retype = getSpec (operandType (result));
7341 D(emitcode (";", "genGenPointerGet"));
7343 aopOp (left, ic, FALSE);
7345 /* if the operand is already in dptr
7346 then we do nothing else we move the value to dptr */
7347 if (AOP_TYPE (left) != AOP_STR)
7349 /* if this is remateriazable */
7350 if (AOP_TYPE (left) == AOP_IMMD)
7352 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7353 emitcode ("mov", "b,#%d", pointerCode (retype));
7356 { /* we need to get it byte by byte */
7357 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7358 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7359 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7362 /* so dptr know contains the address */
7363 aopOp (result, ic, FALSE);
7365 /* if bit then unpack */
7366 if (IS_BITVAR (retype))
7367 genUnpackBits (result, "dptr", GPOINTER);
7370 size = AOP_SIZE (result);
7375 emitcode ("lcall", "__gptrget");
7376 aopPut (AOP (result), "a", offset++);
7378 emitcode ("inc", "dptr");
7382 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7383 aopPut ( AOP (left), "dpl", 0);
7384 aopPut ( AOP (left), "dph", 1);
7387 freeAsmop (left, NULL, ic, TRUE);
7388 freeAsmop (result, NULL, ic, TRUE);
7391 /*-----------------------------------------------------------------*/
7392 /* genPointerGet - generate code for pointer get */
7393 /*-----------------------------------------------------------------*/
7395 genPointerGet (iCode * ic, iCode *pi)
7397 operand *left, *result;
7398 sym_link *type, *etype;
7401 D(emitcode (";", "genPointerGet"));
7403 left = IC_LEFT (ic);
7404 result = IC_RESULT (ic);
7406 /* depending on the type of pointer we need to
7407 move it to the correct pointer register */
7408 type = operandType (left);
7409 etype = getSpec (type);
7410 /* if left is of type of pointer then it is simple */
7411 if (IS_PTR (type) && !IS_FUNC (type->next))
7412 p_type = DCL_TYPE (type);
7415 /* we have to go by the storage class */
7416 p_type = PTR_TYPE (SPEC_OCLS (etype));
7419 /* now that we have the pointer type we assign
7420 the pointer values */
7426 genNearPointerGet (left, result, ic, pi);
7430 genPagedPointerGet (left, result, ic, pi);
7434 genFarPointerGet (left, result, ic, pi);
7438 genCodePointerGet (left, result, ic, pi);
7442 genGenPointerGet (left, result, ic, pi);
7448 /*-----------------------------------------------------------------*/
7449 /* genPackBits - generates code for packed bit storage */
7450 /*-----------------------------------------------------------------*/
7452 genPackBits (sym_link * etype,
7454 char *rname, int p_type)
7462 D(emitcode (";", "genPackBits"));
7464 blen = SPEC_BLEN (etype);
7465 bstr = SPEC_BSTR (etype);
7467 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7470 /* if the bit lenth is less than or */
7471 /* it exactly fits a byte then */
7472 if (SPEC_BLEN (etype) <= 8)
7474 shCount = SPEC_BSTR (etype);
7476 /* shift left acc */
7479 if (SPEC_BLEN (etype) < 8)
7480 { /* if smaller than a byte */
7486 emitcode ("mov", "b,a");
7487 emitcode ("mov", "a,@%s", rname);
7491 emitcode ("mov", "b,a");
7492 emitcode ("movx", "a,@dptr");
7496 emitcode ("push", "b");
7497 emitcode ("push", "acc");
7498 emitcode ("lcall", "__gptrget");
7499 emitcode ("pop", "b");
7503 emitcode ("anl", "a,#0x%02x", (unsigned char)
7504 ((unsigned char) (0xFF << (blen + bstr)) |
7505 (unsigned char) (0xFF >> (8 - bstr))));
7506 emitcode ("orl", "a,b");
7507 if (p_type == GPOINTER)
7508 emitcode ("pop", "b");
7515 emitcode ("mov", "@%s,a", rname);
7519 emitcode ("movx", "@dptr,a");
7523 emitcode ("lcall", "__gptrput");
7528 if (SPEC_BLEN (etype) <= 8)
7531 emitcode ("inc", "%s", rname);
7532 rLen = SPEC_BLEN (etype);
7534 /* now generate for lengths greater than one byte */
7538 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7550 emitcode ("mov", "@%s,a", rname);
7553 emitcode ("mov", "@%s,%s", rname, l);
7558 emitcode ("movx", "@dptr,a");
7563 emitcode ("lcall", "__gptrput");
7566 emitcode ("inc", "%s", rname);
7571 /* last last was not complete */
7574 /* save the byte & read byte */
7578 emitcode ("mov", "b,a");
7579 emitcode ("mov", "a,@%s", rname);
7583 emitcode ("mov", "b,a");
7584 emitcode ("movx", "a,@dptr");
7588 emitcode ("push", "b");
7589 emitcode ("push", "acc");
7590 emitcode ("lcall", "__gptrget");
7591 emitcode ("pop", "b");
7595 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7596 emitcode ("orl", "a,b");
7599 if (p_type == GPOINTER)
7600 emitcode ("pop", "b");
7606 emitcode ("mov", "@%s,a", rname);
7610 emitcode ("movx", "@dptr,a");
7614 emitcode ("lcall", "__gptrput");
7618 /*-----------------------------------------------------------------*/
7619 /* genDataPointerSet - remat pointer to data space */
7620 /*-----------------------------------------------------------------*/
7622 genDataPointerSet (operand * right,
7626 int size, offset = 0;
7627 char *l, buffer[256];
7629 D(emitcode (";", "genDataPointerSet"));
7631 aopOp (right, ic, FALSE);
7633 l = aopGet (AOP (result), 0, FALSE, TRUE);
7634 size = AOP_SIZE (right);
7638 sprintf (buffer, "(%s + %d)", l + 1, offset);
7640 sprintf (buffer, "%s", l + 1);
7641 emitcode ("mov", "%s,%s", buffer,
7642 aopGet (AOP (right), offset++, FALSE, FALSE));
7645 freeAsmop (right, NULL, ic, TRUE);
7646 freeAsmop (result, NULL, ic, TRUE);
7649 /*-----------------------------------------------------------------*/
7650 /* genNearPointerSet - emitcode for near pointer put */
7651 /*-----------------------------------------------------------------*/
7653 genNearPointerSet (operand * right,
7661 sym_link *retype, *letype;
7662 sym_link *ptype = operandType (result);
7664 D(emitcode (";", "genNearPointerSet"));
7666 retype = getSpec (operandType (right));
7667 letype = getSpec (ptype);
7668 aopOp (result, ic, FALSE);
7670 /* if the result is rematerializable &
7671 in data space & not a bit variable */
7672 if (AOP_TYPE (result) == AOP_IMMD &&
7673 DCL_TYPE (ptype) == POINTER &&
7674 !IS_BITVAR (retype) &&
7675 !IS_BITVAR (letype))
7677 genDataPointerSet (right, result, ic);
7681 /* if the value is already in a pointer register
7682 then don't need anything more */
7683 if (!AOP_INPREG (AOP (result)))
7686 //AOP_TYPE (result) == AOP_STK
7690 // Aha, it is a pointer, just in disguise.
7691 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7694 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7695 __FILE__, __LINE__);
7700 rname++; // skip the '@'.
7705 /* otherwise get a free pointer register */
7707 preg = getFreePtr (ic, &aop, FALSE);
7708 emitcode ("mov", "%s,%s",
7710 aopGet (AOP (result), 0, FALSE, TRUE));
7716 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7719 aopOp (right, ic, FALSE);
7721 /* if bitfield then unpack the bits */
7722 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7723 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7726 /* we have can just get the values */
7727 int size = AOP_SIZE (right);
7732 l = aopGet (AOP (right), offset, FALSE, TRUE);
7736 emitcode ("mov", "@%s,a", rname);
7739 emitcode ("mov", "@%s,%s", rname, l);
7741 emitcode ("inc", "%s", rname);
7746 /* now some housekeeping stuff */
7747 if (aop) /* we had to allocate for this iCode */
7749 if (pi) aopPut (AOP (result),rname,0);
7750 freeAsmop (NULL, aop, ic, TRUE);
7754 /* we did not allocate which means left
7755 already in a pointer register, then
7756 if size > 0 && this could be used again
7757 we have to point it back to where it
7759 if ((AOP_SIZE (right) > 1 &&
7760 !OP_SYMBOL (result)->remat &&
7761 (OP_SYMBOL (result)->liveTo > ic->seq ||
7765 int size = AOP_SIZE (right) - 1;
7767 emitcode ("dec", "%s", rname);
7772 if (pi) pi->generated = 1;
7773 freeAsmop (result, NULL, ic, TRUE);
7774 freeAsmop (right, NULL, ic, TRUE);
7777 /*-----------------------------------------------------------------*/
7778 /* genPagedPointerSet - emitcode for Paged pointer put */
7779 /*-----------------------------------------------------------------*/
7781 genPagedPointerSet (operand * right,
7789 sym_link *retype, *letype;
7791 D(emitcode (";", "genPagedPointerSet"));
7793 retype = getSpec (operandType (right));
7794 letype = getSpec (operandType (result));
7796 aopOp (result, ic, FALSE);
7798 /* if the value is already in a pointer register
7799 then don't need anything more */
7800 if (!AOP_INPREG (AOP (result)))
7802 /* otherwise get a free pointer register */
7804 preg = getFreePtr (ic, &aop, FALSE);
7805 emitcode ("mov", "%s,%s",
7807 aopGet (AOP (result), 0, FALSE, TRUE));
7811 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7813 aopOp (right, ic, FALSE);
7815 /* if bitfield then unpack the bits */
7816 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7817 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7820 /* we have can just get the values */
7821 int size = AOP_SIZE (right);
7826 l = aopGet (AOP (right), offset, FALSE, TRUE);
7829 emitcode ("movx", "@%s,a", rname);
7832 emitcode ("inc", "%s", rname);
7838 /* now some housekeeping stuff */
7839 if (aop) /* we had to allocate for this iCode */
7841 if (pi) aopPut (AOP (result),rname,0);
7842 freeAsmop (NULL, aop, ic, TRUE);
7846 /* we did not allocate which means left
7847 already in a pointer register, then
7848 if size > 0 && this could be used again
7849 we have to point it back to where it
7851 if (AOP_SIZE (right) > 1 &&
7852 !OP_SYMBOL (result)->remat &&
7853 (OP_SYMBOL (result)->liveTo > ic->seq ||
7856 int size = AOP_SIZE (right) - 1;
7858 emitcode ("dec", "%s", rname);
7863 if (pi) pi->generated = 1;
7864 freeAsmop (result, NULL, ic, TRUE);
7865 freeAsmop (right, NULL, ic, TRUE);
7870 /*-----------------------------------------------------------------*/
7871 /* genFarPointerSet - set value from far space */
7872 /*-----------------------------------------------------------------*/
7874 genFarPointerSet (operand * right,
7875 operand * result, iCode * ic, iCode * pi)
7878 sym_link *retype = getSpec (operandType (right));
7879 sym_link *letype = getSpec (operandType (result));
7881 D(emitcode (";", "genFarPointerSet"));
7883 aopOp (result, ic, FALSE);
7885 /* if the operand is already in dptr
7886 then we do nothing else we move the value to dptr */
7887 if (AOP_TYPE (result) != AOP_STR)
7889 /* if this is remateriazable */
7890 if (AOP_TYPE (result) == AOP_IMMD)
7891 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7893 { /* we need to get it byte by byte */
7894 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7895 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7898 /* so dptr know contains the address */
7899 aopOp (right, ic, FALSE);
7901 /* if bit then unpack */
7902 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7903 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7906 size = AOP_SIZE (right);
7911 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7913 emitcode ("movx", "@dptr,a");
7915 emitcode ("inc", "dptr");
7918 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7919 aopPut (AOP(result),"dpl",0);
7920 aopPut (AOP(result),"dph",1);
7923 freeAsmop (result, NULL, ic, TRUE);
7924 freeAsmop (right, NULL, ic, TRUE);
7927 /*-----------------------------------------------------------------*/
7928 /* genGenPointerSet - set value from generic pointer space */
7929 /*-----------------------------------------------------------------*/
7931 genGenPointerSet (operand * right,
7932 operand * result, iCode * ic, iCode * pi)
7935 sym_link *retype = getSpec (operandType (right));
7936 sym_link *letype = getSpec (operandType (result));
7938 D(emitcode (";", "genGenPointerSet"));
7940 aopOp (result, ic, FALSE);
7942 /* if the operand is already in dptr
7943 then we do nothing else we move the value to dptr */
7944 if (AOP_TYPE (result) != AOP_STR)
7946 /* if this is remateriazable */
7947 if (AOP_TYPE (result) == AOP_IMMD)
7949 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7950 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
7953 { /* we need to get it byte by byte */
7954 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7955 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7956 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
7959 /* so dptr know contains the address */
7960 aopOp (right, ic, FALSE);
7962 /* if bit then unpack */
7963 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7964 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
7967 size = AOP_SIZE (right);
7972 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7974 emitcode ("lcall", "__gptrput");
7976 emitcode ("inc", "dptr");
7980 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7981 aopPut (AOP(result),"dpl",0);
7982 aopPut (AOP(result),"dph",1);
7985 freeAsmop (result, NULL, ic, TRUE);
7986 freeAsmop (right, NULL, ic, TRUE);
7989 /*-----------------------------------------------------------------*/
7990 /* genPointerSet - stores the value into a pointer location */
7991 /*-----------------------------------------------------------------*/
7993 genPointerSet (iCode * ic, iCode *pi)
7995 operand *right, *result;
7996 sym_link *type, *etype;
7999 D(emitcode (";", "genPointerSet"));
8001 right = IC_RIGHT (ic);
8002 result = IC_RESULT (ic);
8004 /* depending on the type of pointer we need to
8005 move it to the correct pointer register */
8006 type = operandType (result);
8007 etype = getSpec (type);
8008 /* if left is of type of pointer then it is simple */
8009 if (IS_PTR (type) && !IS_FUNC (type->next))
8011 p_type = DCL_TYPE (type);
8015 /* we have to go by the storage class */
8016 p_type = PTR_TYPE (SPEC_OCLS (etype));
8019 /* now that we have the pointer type we assign
8020 the pointer values */
8026 genNearPointerSet (right, result, ic, pi);
8030 genPagedPointerSet (right, result, ic, pi);
8034 genFarPointerSet (right, result, ic, pi);
8038 genGenPointerSet (right, result, ic, pi);
8044 /*-----------------------------------------------------------------*/
8045 /* genIfx - generate code for Ifx statement */
8046 /*-----------------------------------------------------------------*/
8048 genIfx (iCode * ic, iCode * popIc)
8050 operand *cond = IC_COND (ic);
8053 D(emitcode (";", "genIfx"));
8055 aopOp (cond, ic, FALSE);
8057 /* get the value into acc */
8058 if (AOP_TYPE (cond) != AOP_CRY)
8062 /* the result is now in the accumulator */
8063 freeAsmop (cond, NULL, ic, TRUE);
8065 /* if there was something to be popped then do it */
8069 /* if the condition is a bit variable */
8070 if (isbit && IS_ITEMP (cond) &&
8072 genIfxJump (ic, SPIL_LOC (cond)->rname);
8073 else if (isbit && !IS_ITEMP (cond))
8074 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8076 genIfxJump (ic, "a");
8081 /*-----------------------------------------------------------------*/
8082 /* genAddrOf - generates code for address of */
8083 /*-----------------------------------------------------------------*/
8085 genAddrOf (iCode * ic)
8087 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8090 D(emitcode (";", "genAddrOf"));
8092 aopOp (IC_RESULT (ic), ic, FALSE);
8094 /* if the operand is on the stack then we
8095 need to get the stack offset of this
8099 /* if it has an offset then we need to compute
8103 emitcode ("mov", "a,_bp");
8104 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
8105 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8109 /* we can just move _bp */
8110 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8112 /* fill the result with zero */
8113 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8118 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8124 /* object not on stack then we need the name */
8125 size = AOP_SIZE (IC_RESULT (ic));
8130 char s[SDCC_NAME_MAX];
8132 sprintf (s, "#(%s >> %d)",
8136 sprintf (s, "#%s", sym->rname);
8137 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8141 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8145 /*-----------------------------------------------------------------*/
8146 /* genFarFarAssign - assignment when both are in far space */
8147 /*-----------------------------------------------------------------*/
8149 genFarFarAssign (operand * result, operand * right, iCode * ic)
8151 int size = AOP_SIZE (right);
8155 D(emitcode (";", "genFarFarAssign"));
8157 /* first push the right side on to the stack */
8160 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8162 emitcode ("push", "acc");
8165 freeAsmop (right, NULL, ic, FALSE);
8166 /* now assign DPTR to result */
8167 aopOp (result, ic, FALSE);
8168 size = AOP_SIZE (result);
8171 emitcode ("pop", "acc");
8172 aopPut (AOP (result), "a", --offset);
8174 freeAsmop (result, NULL, ic, FALSE);
8178 /*-----------------------------------------------------------------*/
8179 /* genAssign - generate code for assignment */
8180 /*-----------------------------------------------------------------*/
8182 genAssign (iCode * ic)
8184 operand *result, *right;
8186 unsigned long lit = 0L;
8188 D(emitcode(";","genAssign"));
8190 result = IC_RESULT (ic);
8191 right = IC_RIGHT (ic);
8193 /* if they are the same */
8194 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8197 aopOp (right, ic, FALSE);
8199 /* special case both in far space */
8200 if (AOP_TYPE (right) == AOP_DPTR &&
8201 IS_TRUE_SYMOP (result) &&
8202 isOperandInFarSpace (result))
8205 genFarFarAssign (result, right, ic);
8209 aopOp (result, ic, TRUE);
8211 /* if they are the same registers */
8212 if (sameRegs (AOP (right), AOP (result)))
8215 /* if the result is a bit */
8216 if (AOP_TYPE (result) == AOP_CRY)
8219 /* if the right size is a literal then
8220 we know what the value is */
8221 if (AOP_TYPE (right) == AOP_LIT)
8223 if (((int) operandLitValue (right)))
8224 aopPut (AOP (result), one, 0);
8226 aopPut (AOP (result), zero, 0);
8230 /* the right is also a bit variable */
8231 if (AOP_TYPE (right) == AOP_CRY)
8233 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8234 aopPut (AOP (result), "c", 0);
8240 aopPut (AOP (result), "a", 0);
8244 /* bit variables done */
8246 size = AOP_SIZE (result);
8248 if (AOP_TYPE (right) == AOP_LIT)
8249 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8251 (AOP_TYPE (result) != AOP_REG) &&
8252 (AOP_TYPE (right) == AOP_LIT) &&
8253 !IS_FLOAT (operandType (right)) &&
8256 emitcode ("clr", "a");
8259 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8260 aopPut (AOP (result), "a", size);
8262 aopPut (AOP (result),
8263 aopGet (AOP (right), size, FALSE, FALSE),
8271 aopPut (AOP (result),
8272 aopGet (AOP (right), offset, FALSE, FALSE),
8279 freeAsmop (right, NULL, ic, TRUE);
8280 freeAsmop (result, NULL, ic, TRUE);
8283 /*-----------------------------------------------------------------*/
8284 /* genJumpTab - genrates code for jump table */
8285 /*-----------------------------------------------------------------*/
8287 genJumpTab (iCode * ic)
8292 D(emitcode (";", "genJumpTab"));
8294 aopOp (IC_JTCOND (ic), ic, FALSE);
8295 /* get the condition into accumulator */
8296 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8298 /* multiply by three */
8299 emitcode ("add", "a,acc");
8300 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8301 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8303 jtab = newiTempLabel (NULL);
8304 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8305 emitcode ("jmp", "@a+dptr");
8306 emitcode ("", "%05d$:", jtab->key + 100);
8307 /* now generate the jump labels */
8308 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8309 jtab = setNextItem (IC_JTLABELS (ic)))
8310 emitcode ("ljmp", "%05d$", jtab->key + 100);
8314 /*-----------------------------------------------------------------*/
8315 /* genCast - gen code for casting */
8316 /*-----------------------------------------------------------------*/
8318 genCast (iCode * ic)
8320 operand *result = IC_RESULT (ic);
8321 sym_link *ctype = operandType (IC_LEFT (ic));
8322 sym_link *rtype = operandType (IC_RIGHT (ic));
8323 operand *right = IC_RIGHT (ic);
8326 D(emitcode(";", "genCast"));
8328 /* if they are equivalent then do nothing */
8329 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8332 aopOp (right, ic, FALSE);
8333 aopOp (result, ic, FALSE);
8335 /* if the result is a bit */
8336 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8337 if (IS_BITVAR(OP_SYMBOL(result)->type))
8339 /* if the right size is a literal then
8340 we know what the value is */
8341 if (AOP_TYPE (right) == AOP_LIT)
8343 if (((int) operandLitValue (right)))
8344 aopPut (AOP (result), one, 0);
8346 aopPut (AOP (result), zero, 0);
8351 /* the right is also a bit variable */
8352 if (AOP_TYPE (right) == AOP_CRY)
8354 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8355 aopPut (AOP (result), "c", 0);
8361 aopPut (AOP (result), "a", 0);
8365 /* if they are the same size : or less */
8366 if (AOP_SIZE (result) <= AOP_SIZE (right))
8369 /* if they are in the same place */
8370 if (sameRegs (AOP (right), AOP (result)))
8373 /* if they in different places then copy */
8374 size = AOP_SIZE (result);
8378 aopPut (AOP (result),
8379 aopGet (AOP (right), offset, FALSE, FALSE),
8387 /* if the result is of type pointer */
8392 sym_link *type = operandType (right);
8393 sym_link *etype = getSpec (type);
8395 /* pointer to generic pointer */
8396 if (IS_GENPTR (ctype))
8401 p_type = DCL_TYPE (type);
8404 if (SPEC_SCLS(etype)==S_REGISTER) {
8405 // let's assume it is a generic pointer
8408 /* we have to go by the storage class */
8409 p_type = PTR_TYPE (SPEC_OCLS (etype));
8413 /* the first two bytes are known */
8414 size = GPTRSIZE - 1;
8418 aopPut (AOP (result),
8419 aopGet (AOP (right), offset, FALSE, FALSE),
8423 /* the last byte depending on type */
8439 case PPOINTER: // what the fck is this?
8444 /* this should never happen */
8445 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8446 "got unknown pointer type");
8449 aopPut (AOP (result), l, GPTRSIZE - 1);
8453 /* just copy the pointers */
8454 size = AOP_SIZE (result);
8458 aopPut (AOP (result),
8459 aopGet (AOP (right), offset, FALSE, FALSE),
8466 /* so we now know that the size of destination is greater
8467 than the size of the source */
8468 /* we move to result for the size of source */
8469 size = AOP_SIZE (right);
8473 aopPut (AOP (result),
8474 aopGet (AOP (right), offset, FALSE, FALSE),
8479 /* now depending on the sign of the source && destination */
8480 size = AOP_SIZE (result) - AOP_SIZE (right);
8481 /* if unsigned or not an integral type */
8482 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8485 aopPut (AOP (result), zero, offset++);
8489 /* we need to extend the sign :{ */
8490 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8493 emitcode ("rlc", "a");
8494 emitcode ("subb", "a,acc");
8496 aopPut (AOP (result), "a", offset++);
8499 /* we are done hurray !!!! */
8502 freeAsmop (right, NULL, ic, TRUE);
8503 freeAsmop (result, NULL, ic, TRUE);
8507 /*-----------------------------------------------------------------*/
8508 /* genDjnz - generate decrement & jump if not zero instrucion */
8509 /*-----------------------------------------------------------------*/
8511 genDjnz (iCode * ic, iCode * ifx)
8517 D(emitcode (";", "genDjnz"));
8519 /* if the if condition has a false label
8520 then we cannot save */
8524 /* if the minus is not of the form
8526 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8527 !IS_OP_LITERAL (IC_RIGHT (ic)))
8530 if (operandLitValue (IC_RIGHT (ic)) != 1)
8533 /* if the size of this greater than one then no
8535 if (getSize (operandType (IC_RESULT (ic))) > 1)
8538 /* otherwise we can save BIG */
8539 lbl = newiTempLabel (NULL);
8540 lbl1 = newiTempLabel (NULL);
8542 aopOp (IC_RESULT (ic), ic, FALSE);
8544 if (AOP_NEEDSACC(IC_RESULT(ic)))
8546 /* If the result is accessed indirectly via
8547 * the accumulator, we must explicitly write
8548 * it back after the decrement.
8550 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8552 if (strcmp(rByte, "a"))
8554 /* Something is hopelessly wrong */
8555 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8556 __FILE__, __LINE__);
8557 /* We can just give up; the generated code will be inefficient,
8560 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8563 emitcode ("dec", "%s", rByte);
8564 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8565 emitcode ("jnz", "%05d$", lbl->key + 100);
8567 else if (IS_AOP_PREG (IC_RESULT (ic)))
8569 emitcode ("dec", "%s",
8570 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8571 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8572 emitcode ("jnz", "%05d$", lbl->key + 100);
8576 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8579 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8580 emitcode ("", "%05d$:", lbl->key + 100);
8581 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8582 emitcode ("", "%05d$:", lbl1->key + 100);
8584 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8589 /*-----------------------------------------------------------------*/
8590 /* genReceive - generate code for a receive iCode */
8591 /*-----------------------------------------------------------------*/
8593 genReceive (iCode * ic)
8595 D(emitcode (";", "genReceive"));
8597 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8598 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8599 IS_TRUE_SYMOP (IC_RESULT (ic))))
8602 int size = getSize (operandType (IC_RESULT (ic)));
8603 int offset = fReturnSizeMCS51 - size;
8606 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8607 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8610 aopOp (IC_RESULT (ic), ic, FALSE);
8611 size = AOP_SIZE (IC_RESULT (ic));
8615 emitcode ("pop", "acc");
8616 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8623 aopOp (IC_RESULT (ic), ic, FALSE);
8625 assignResultValue (IC_RESULT (ic));
8628 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8631 /*-----------------------------------------------------------------*/
8632 /* gen51AggregateAssign - copy complete array's or structures */
8633 /*-----------------------------------------------------------------*/
8634 void gen51AggregateAssign(iCode *ic) {
8635 operand *left=IC_LEFT(ic);
8636 operand *right=IC_RIGHT(ic);
8637 char *fromName=OP_SYMBOL(right)->rname;
8638 char *toName=OP_SYMBOL(left)->rname;
8639 int fromSize=getSize(OP_SYMBOL(right)->type);
8640 int toSize=getSize(OP_SYMBOL(left)->type);
8643 D(emitcode (";", "gen51AggregateAssign"));
8645 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8646 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8647 // well, this code isn't used yet from anywhere else as for initialising
8648 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8652 if (fromSize!=toSize) {
8653 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8654 ic->filename, ic->lineno);
8659 // use the generic memcpy() for now
8660 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8661 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8662 emitcode ("mov", "a,#%s", fromName);
8663 emitcode ("movx", "@dptr,a");
8664 emitcode ("inc", "dptr");
8665 emitcode ("mov", "a,#(%s>>8)", fromName);
8666 emitcode ("movx", "@dptr,a");
8667 emitcode ("inc", "dptr");
8668 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8669 emitcode ("movx", "@dptr,a");
8670 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8671 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8672 emitcode ("movx", "@dptr,a");
8673 emitcode ("inc", "dptr");
8674 emitcode ("mov", "a,#(%d>>8)", count);
8675 emitcode ("movx", "@dptr,a");
8676 emitcode ("mov", "dptr,#%s", toName);
8677 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8678 emitcode ("lcall", "_memcpy");
8680 // more efficient, but will require the native_memcpy_cs2xs
8681 emitcode ("mov", "r0,#%s", fromName);
8682 emitcode ("mov", "r1,#(%s>>8)", fromName);
8683 emitcode ("mov", "r2,#%s", toName);
8684 emitcode ("mov", "r3,#(%s>>8)", toName);
8685 emitcode ("mov", "r4,#%d", count);
8686 emitcode ("mov", "r5,#(%d>>8)", count);
8687 emitcode ("lcall", "_native_memcpy_cs2xs");
8691 /*-----------------------------------------------------------------*/
8692 /* gen51Code - generate code for 8051 based controllers */
8693 /*-----------------------------------------------------------------*/
8695 gen51Code (iCode * lic)
8700 lineHead = lineCurr = NULL;
8702 /* print the allocation information */
8704 printAllocInfo (currFunc, codeOutFile);
8705 /* if debug information required */
8706 /* if (options.debug && currFunc) { */
8707 if (options.debug && currFunc)
8709 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8711 if (IS_STATIC (currFunc->etype))
8712 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8714 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8717 /* stack pointer name */
8718 if (options.useXstack)
8724 for (ic = lic; ic; ic = ic->next)
8727 if (cln != ic->lineno)
8732 emitcode ("", "C$%s$%d$%d$%d ==.",
8733 FileBaseName (ic->filename), ic->lineno,
8734 ic->level, ic->block);
8737 emitcode (";", "%s %d", ic->filename, ic->lineno);
8740 /* if the result is marked as
8741 spilt and rematerializable or code for
8742 this has already been generated then
8744 if (resultRemat (ic) || ic->generated)
8747 /* depending on the operation */
8767 /* IPOP happens only when trying to restore a
8768 spilt live range, if there is an ifx statement
8769 following this pop then the if statement might
8770 be using some of the registers being popped which
8771 would destory the contents of the register so
8772 we need to check for this condition and handle it */
8774 ic->next->op == IFX &&
8775 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8776 genIfx (ic->next, ic);
8794 genEndFunction (ic);
8814 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8831 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8835 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8842 /* note these two are xlated by algebraic equivalence
8843 during parsing SDCC.y */
8844 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8845 "got '>=' or '<=' shouldn't have come here");
8849 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8861 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8865 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8869 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8896 case GET_VALUE_AT_ADDRESS:
8897 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8901 if (POINTER_SET (ic))
8902 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
8928 addSet (&_G.sendSet, ic);
8932 gen51AggregateAssign(ic);
8941 /* now we are ready to call the
8942 peep hole optimizer */
8943 if (!options.nopeep)
8944 peepHole (&lineHead);
8946 /* now do the actual printing */
8947 printLine (lineHead, codeOutFile);