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);
394 if (ptr_type == IPOINTER) {
401 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
405 sprintf (buffer, "(%s %c 0x%04x)",
406 OP_SYMBOL (IC_LEFT (ic))->rname,
407 val >= 0 ? '+' : '-',
410 strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
412 aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
413 strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
414 /* set immd2 field if required */
415 if (aop->aopu.aop_immd.from_cast_remat) {
416 sprintf(buffer,"#0x%02x",ptr_type);
417 aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
418 strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
424 /*-----------------------------------------------------------------*/
425 /* regsInCommon - two operands have some registers in common */
426 /*-----------------------------------------------------------------*/
428 regsInCommon (operand * op1, operand * op2)
433 /* if they have registers in common */
434 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
437 sym1 = OP_SYMBOL (op1);
438 sym2 = OP_SYMBOL (op2);
440 if (sym1->nRegs == 0 || sym2->nRegs == 0)
443 for (i = 0; i < sym1->nRegs; i++)
449 for (j = 0; j < sym2->nRegs; j++)
454 if (sym2->regs[j] == sym1->regs[i])
462 /*-----------------------------------------------------------------*/
463 /* operandsEqu - equivalent */
464 /*-----------------------------------------------------------------*/
466 operandsEqu (operand * op1, operand * op2)
470 /* if they not symbols */
471 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
474 sym1 = OP_SYMBOL (op1);
475 sym2 = OP_SYMBOL (op2);
477 /* if both are itemps & one is spilt
478 and the other is not then false */
479 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
480 sym1->isspilt != sym2->isspilt)
483 /* if they are the same */
487 if (strcmp (sym1->rname, sym2->rname) == 0)
491 /* if left is a tmp & right is not */
492 if (IS_ITEMP (op1) &&
495 (sym1->usl.spillLoc == sym2))
498 if (IS_ITEMP (op2) &&
502 (sym2->usl.spillLoc == sym1))
508 /*-----------------------------------------------------------------*/
509 /* sameRegs - two asmops have the same registers */
510 /*-----------------------------------------------------------------*/
512 sameRegs (asmop * aop1, asmop * aop2)
519 if (aop1->type != AOP_REG ||
520 aop2->type != AOP_REG)
523 if (aop1->size != aop2->size)
526 for (i = 0; i < aop1->size; i++)
527 if (aop1->aopu.aop_reg[i] !=
528 aop2->aopu.aop_reg[i])
534 /*-----------------------------------------------------------------*/
535 /* aopOp - allocates an asmop for an operand : */
536 /*-----------------------------------------------------------------*/
538 aopOp (operand * op, iCode * ic, bool result)
547 /* if this a literal */
548 if (IS_OP_LITERAL (op))
550 op->aop = aop = newAsmop (AOP_LIT);
551 aop->aopu.aop_lit = op->operand.valOperand;
552 aop->size = getSize (operandType (op));
556 /* if already has a asmop then continue */
560 /* if the underlying symbol has a aop */
561 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
563 op->aop = OP_SYMBOL (op)->aop;
567 /* if this is a true symbol */
568 if (IS_TRUE_SYMOP (op))
570 op->aop = aopForSym (ic, OP_SYMBOL (op), result);
574 /* this is a temporary : this has
580 e) can be a return use only */
582 sym = OP_SYMBOL (op);
584 /* if the type is a conditional */
585 if (sym->regType == REG_CND)
587 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
592 /* if it is spilt then two situations
594 b) has a spill location */
595 if (sym->isspilt || sym->nRegs == 0)
598 /* rematerialize it NOW */
601 sym->aop = op->aop = aop =
603 aop->size = getSize (sym->type);
610 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
611 aop->size = getSize (sym->type);
612 for (i = 0; i < 2; i++)
613 aop->aopu.aop_str[i] = accUse[i];
621 aop = op->aop = sym->aop = newAsmop (AOP_STR);
622 aop->size = getSize (sym->type);
623 for (i = 0; i < fReturnSizeMCS51; i++)
624 aop->aopu.aop_str[i] = fReturn[i];
628 /* else spill location */
629 sym->aop = op->aop = aop =
630 aopForSym (ic, sym->usl.spillLoc, result);
631 aop->size = getSize (sym->type);
635 /* must be in a register */
636 sym->aop = op->aop = aop = newAsmop (AOP_REG);
637 aop->size = sym->nRegs;
638 for (i = 0; i < sym->nRegs; i++)
639 aop->aopu.aop_reg[i] = sym->regs[i];
642 /*-----------------------------------------------------------------*/
643 /* freeAsmop - free up the asmop given to an operand */
644 /*----------------------------------------------------------------*/
646 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
663 /* depending on the asmop type only three cases need work AOP_RO
664 , AOP_R1 && AOP_STK */
672 emitcode ("pop", "ar0");
676 bitVectUnSetBit (ic->rUsed, R0_IDX);
684 emitcode ("pop", "ar1");
688 bitVectUnSetBit (ic->rUsed, R1_IDX);
694 int stk = aop->aopu.aop_stk + aop->size;
695 bitVectUnSetBit (ic->rUsed, R0_IDX);
696 bitVectUnSetBit (ic->rUsed, R1_IDX);
698 getFreePtr (ic, &aop, FALSE);
702 emitcode ("mov", "a,_bp");
703 emitcode ("add", "a,#0x%02x", ((char) stk) & 0xff);
704 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
708 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
713 emitcode ("pop", "acc");
714 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
717 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
720 freeAsmop (op, NULL, ic, TRUE);
723 emitcode ("pop", "ar0");
729 emitcode ("pop", "ar1");
736 /* all other cases just dealloc */
742 OP_SYMBOL (op)->aop = NULL;
743 /* if the symbol has a spill */
745 SPIL_LOC (op)->aop = NULL;
750 /*-----------------------------------------------------------------*/
751 /* aopGet - for fetching value of the aop */
752 /*-----------------------------------------------------------------*/
754 aopGet (asmop * aop, int offset, bool bit16, bool dname)
759 /* offset is greater than
761 if (offset > (aop->size - 1) &&
762 aop->type != AOP_LIT)
765 /* depending on type */
771 /* if we need to increment it */
772 while (offset > aop->coff)
774 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
778 while (offset < aop->coff)
780 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
787 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
788 return (dname ? "acc" : "a");
790 sprintf (s, "@%s", aop->aopu.aop_ptr->name);
791 rs = Safe_calloc (1, strlen (s) + 1);
796 while (offset > aop->coff)
798 emitcode ("inc", "dptr");
802 while (offset < aop->coff)
804 emitcode ("lcall", "__decdptr");
811 emitcode ("clr", "a");
812 emitcode ("movc", "a,@a+dptr");
816 emitcode ("movx", "a,@dptr");
818 return (dname ? "acc" : "a");
822 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1))) {
823 sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
825 sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
827 sprintf (s, "#(%s >> %d)",
828 aop->aopu.aop_immd.aop_immd1,
832 aop->aopu.aop_immd.aop_immd1);
833 rs = Safe_calloc (1, strlen (s) + 1);
839 sprintf (s, "(%s + %d)",
843 sprintf (s, "%s", aop->aopu.aop_dir);
844 rs = Safe_calloc (1, strlen (s) + 1);
850 return aop->aopu.aop_reg[offset]->dname;
852 return aop->aopu.aop_reg[offset]->name;
855 emitcode ("clr", "a");
856 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
857 emitcode ("rlc", "a");
858 return (dname ? "acc" : "a");
861 if (!offset && dname)
863 return aop->aopu.aop_str[offset];
866 return aopLiteral (aop->aopu.aop_lit, offset);
870 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
874 return aop->aopu.aop_str[offset];
878 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
879 "aopget got unsupported aop->type");
882 /*-----------------------------------------------------------------*/
883 /* aopPut - puts a string for a aop */
884 /*-----------------------------------------------------------------*/
886 aopPut (asmop * aop, char *s, int offset)
890 if (aop->size && offset > (aop->size - 1))
892 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
893 "aopPut got offset > aop->size");
897 /* will assign value to value */
898 /* depending on where it is ofcourse */
903 sprintf (d, "(%s + %d)",
904 aop->aopu.aop_dir, offset);
906 sprintf (d, "%s", aop->aopu.aop_dir);
909 emitcode ("mov", "%s,%s", d, s);
914 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
915 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
918 strcmp (s, "r0") == 0 ||
919 strcmp (s, "r1") == 0 ||
920 strcmp (s, "r2") == 0 ||
921 strcmp (s, "r3") == 0 ||
922 strcmp (s, "r4") == 0 ||
923 strcmp (s, "r5") == 0 ||
924 strcmp (s, "r6") == 0 ||
925 strcmp (s, "r7") == 0)
926 emitcode ("mov", "%s,%s",
927 aop->aopu.aop_reg[offset]->dname, s);
929 emitcode ("mov", "%s,%s",
930 aop->aopu.aop_reg[offset]->name, s);
937 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
938 "aopPut writting to code space");
942 while (offset > aop->coff)
945 emitcode ("inc", "dptr");
948 while (offset < aop->coff)
951 emitcode ("lcall", "__decdptr");
956 /* if not in accumulater */
959 emitcode ("movx", "@dptr,a");
964 while (offset > aop->coff)
967 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
969 while (offset < aop->coff)
972 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
979 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
985 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
987 else if (strcmp (s, "r0") == 0 ||
988 strcmp (s, "r1") == 0 ||
989 strcmp (s, "r2") == 0 ||
990 strcmp (s, "r3") == 0 ||
991 strcmp (s, "r4") == 0 ||
992 strcmp (s, "r5") == 0 ||
993 strcmp (s, "r6") == 0 ||
994 strcmp (s, "r7") == 0)
997 sprintf (buffer, "a%s", s);
998 emitcode ("mov", "@%s,%s",
999 aop->aopu.aop_ptr->name, buffer);
1002 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1007 if (strcmp (s, "a") == 0)
1008 emitcode ("push", "acc");
1012 emitcode ("push", "acc");
1014 emitcode ("push", s);
1020 /* if bit variable */
1021 if (!aop->aopu.aop_dir)
1023 emitcode ("clr", "a");
1024 emitcode ("rlc", "a");
1029 emitcode ("clr", "%s", aop->aopu.aop_dir);
1031 emitcode ("setb", "%s", aop->aopu.aop_dir);
1032 else if (!strcmp (s, "c"))
1033 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1036 if (strcmp (s, "a"))
1041 symbol *lbl = newiTempLabel (NULL);
1042 emitcode ("clr", "c");
1043 emitcode ("jz", "%05d$", lbl->key + 100);
1044 emitcode ("cpl", "c");
1045 emitcode ("", "%05d$:", lbl->key + 100);
1046 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1054 if (strcmp (aop->aopu.aop_str[offset], s))
1055 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1060 if (!offset && (strcmp (s, "acc") == 0))
1063 if (strcmp (aop->aopu.aop_str[offset], s))
1064 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1068 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1069 "aopPut got unsupported aop->type");
1077 /*-----------------------------------------------------------------*/
1078 /* pointToEnd :- points to the last byte of the operand */
1079 /*-----------------------------------------------------------------*/
1081 pointToEnd (asmop * aop)
1087 aop->coff = count = (aop->size - 1);
1093 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1097 emitcode ("inc", "dptr");
1104 /*-----------------------------------------------------------------*/
1105 /* reAdjustPreg - points a register back to where it should */
1106 /*-----------------------------------------------------------------*/
1108 reAdjustPreg (asmop * aop)
1110 if ((aop->coff==0) || aop->size <= 1)
1118 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1123 emitcode ("lcall", "__decdptr");
1130 #define AOP(op) op->aop
1131 #define AOP_TYPE(op) AOP(op)->type
1132 #define AOP_SIZE(op) AOP(op)->size
1133 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1134 AOP_TYPE(x) == AOP_R0))
1136 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1137 AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
1139 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1140 (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
1141 x->aopu.aop_reg[0] == mcs51_regWithIdx(R1_IDX) )))
1143 /*-----------------------------------------------------------------*/
1144 /* genNotFloat - generates not for float operations */
1145 /*-----------------------------------------------------------------*/
1147 genNotFloat (operand * op, operand * res)
1153 D(emitcode (";", "genNotFloat"));
1155 /* we will put 127 in the first byte of
1157 aopPut (AOP (res), "#127", 0);
1158 size = AOP_SIZE (op) - 1;
1161 l = aopGet (op->aop, offset++, FALSE, FALSE);
1166 emitcode ("orl", "a,%s",
1168 offset++, FALSE, FALSE));
1171 tlbl = newiTempLabel (NULL);
1172 aopPut (res->aop, one, 1);
1173 emitcode ("jz", "%05d$", (tlbl->key + 100));
1174 aopPut (res->aop, zero, 1);
1175 emitcode ("", "%05d$:", (tlbl->key + 100));
1177 size = res->aop->size - 2;
1179 /* put zeros in the rest */
1181 aopPut (res->aop, zero, offset++);
1184 /*-----------------------------------------------------------------*/
1185 /* opIsGptr: returns non-zero if the passed operand is */
1186 /* a generic pointer type. */
1187 /*-----------------------------------------------------------------*/
1189 opIsGptr (operand * op)
1191 sym_link *type = operandType (op);
1193 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1200 /*-----------------------------------------------------------------*/
1201 /* getDataSize - get the operand data size */
1202 /*-----------------------------------------------------------------*/
1204 getDataSize (operand * op)
1207 size = AOP_SIZE (op);
1208 if (size == GPTRSIZE)
1210 sym_link *type = operandType (op);
1211 if (IS_GENPTR (type))
1213 /* generic pointer; arithmetic operations
1214 * should ignore the high byte (pointer type).
1222 /*-----------------------------------------------------------------*/
1223 /* outAcc - output Acc */
1224 /*-----------------------------------------------------------------*/
1226 outAcc (operand * result)
1229 size = getDataSize (result);
1232 aopPut (AOP (result), "a", 0);
1235 /* unsigned or positive */
1238 aopPut (AOP (result), zero, offset++);
1243 /*-----------------------------------------------------------------*/
1244 /* outBitC - output a bit C */
1245 /*-----------------------------------------------------------------*/
1247 outBitC (operand * result)
1249 /* if the result is bit */
1250 if (AOP_TYPE (result) == AOP_CRY)
1251 aopPut (AOP (result), "c", 0);
1254 emitcode ("clr", "a");
1255 emitcode ("rlc", "a");
1260 /*-----------------------------------------------------------------*/
1261 /* toBoolean - emit code for orl a,operator(sizeop) */
1262 /*-----------------------------------------------------------------*/
1264 toBoolean (operand * oper)
1266 int size = AOP_SIZE (oper) - 1;
1268 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE));
1270 emitcode ("orl", "a,%s", aopGet (AOP (oper), offset++, FALSE, FALSE));
1274 /*-----------------------------------------------------------------*/
1275 /* genNot - generate code for ! operation */
1276 /*-----------------------------------------------------------------*/
1281 sym_link *optype = operandType (IC_LEFT (ic));
1283 D(emitcode (";", "genNot"));
1285 /* assign asmOps to operand & result */
1286 aopOp (IC_LEFT (ic), ic, FALSE);
1287 aopOp (IC_RESULT (ic), ic, TRUE);
1289 /* if in bit space then a special case */
1290 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1292 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1293 emitcode ("cpl", "c");
1294 outBitC (IC_RESULT (ic));
1298 /* if type float then do float */
1299 if (IS_FLOAT (optype))
1301 genNotFloat (IC_LEFT (ic), IC_RESULT (ic));
1305 toBoolean (IC_LEFT (ic));
1307 tlbl = newiTempLabel (NULL);
1308 emitcode ("cjne", "a,#0x01,%05d$", tlbl->key + 100);
1309 emitcode ("", "%05d$:", tlbl->key + 100);
1310 outBitC (IC_RESULT (ic));
1313 /* release the aops */
1314 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1315 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1319 /*-----------------------------------------------------------------*/
1320 /* genCpl - generate code for complement */
1321 /*-----------------------------------------------------------------*/
1329 D(emitcode (";", "genCpl"));
1331 /* assign asmOps to operand & result */
1332 aopOp (IC_LEFT (ic), ic, FALSE);
1333 aopOp (IC_RESULT (ic), ic, TRUE);
1335 /* if both are in bit space then
1337 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1338 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1341 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1342 emitcode ("cpl", "c");
1343 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1347 size = AOP_SIZE (IC_RESULT (ic));
1350 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1352 emitcode ("cpl", "a");
1353 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1358 /* release the aops */
1359 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1360 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1363 /*-----------------------------------------------------------------*/
1364 /* genUminusFloat - unary minus for floating points */
1365 /*-----------------------------------------------------------------*/
1367 genUminusFloat (operand * op, operand * result)
1369 int size, offset = 0;
1372 D(emitcode (";", "genUminusFloat"));
1374 /* for this we just need to flip the
1375 first it then copy the rest in place */
1376 size = AOP_SIZE (op) - 1;
1377 l = aopGet (AOP (op), 3, FALSE, FALSE);
1381 emitcode ("cpl", "acc.7");
1382 aopPut (AOP (result), "a", 3);
1386 aopPut (AOP (result),
1387 aopGet (AOP (op), offset, FALSE, FALSE),
1393 /*-----------------------------------------------------------------*/
1394 /* genUminus - unary minus code generation */
1395 /*-----------------------------------------------------------------*/
1397 genUminus (iCode * ic)
1400 sym_link *optype, *rtype;
1403 D(emitcode (";", "genUminus"));
1406 aopOp (IC_LEFT (ic), ic, FALSE);
1407 aopOp (IC_RESULT (ic), ic, TRUE);
1409 /* if both in bit space then special
1411 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1412 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1415 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1416 emitcode ("cpl", "c");
1417 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1421 optype = operandType (IC_LEFT (ic));
1422 rtype = operandType (IC_RESULT (ic));
1424 /* if float then do float stuff */
1425 if (IS_FLOAT (optype))
1427 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1431 /* otherwise subtract from zero */
1432 size = AOP_SIZE (IC_LEFT (ic));
1437 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE);
1438 if (!strcmp (l, "a"))
1442 emitcode ("cpl", "a");
1443 emitcode ("addc", "a,#0");
1449 emitcode ("clr", "a");
1450 emitcode ("subb", "a,%s", l);
1452 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1455 /* if any remaining bytes in the result */
1456 /* we just need to propagate the sign */
1457 if ((size = (AOP_SIZE (IC_RESULT (ic)) - AOP_SIZE (IC_LEFT (ic)))))
1459 emitcode ("rlc", "a");
1460 emitcode ("subb", "a,acc");
1462 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1466 /* release the aops */
1467 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1468 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1471 /*-----------------------------------------------------------------*/
1472 /* saveRegisters - will look for a call and save the registers */
1473 /*-----------------------------------------------------------------*/
1475 saveRegisters (iCode * lic)
1482 for (ic = lic; ic; ic = ic->next)
1483 if (ic->op == CALL || ic->op == PCALL)
1488 fprintf (stderr, "found parameter push with no function call\n");
1492 /* if the registers have been saved already or don't need to be then
1494 if (ic->regsSaved || IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
1495 IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic))))
1498 /* safe the registers in use at this time but skip the
1499 ones for the result */
1500 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1501 mcs51_rUmaskForOp (IC_RESULT(ic)));
1504 if (options.useXstack)
1506 if (bitVectBitValue (rsave, R0_IDX))
1507 emitcode ("mov", "b,r0");
1508 emitcode ("mov", "r0,%s", spname);
1509 for (i = 0; i < mcs51_nRegs; i++)
1511 if (bitVectBitValue (rsave, i))
1514 emitcode ("mov", "a,b");
1516 emitcode ("mov", "a,%s", mcs51_regWithIdx (i)->name);
1517 emitcode ("movx", "@r0,a");
1518 emitcode ("inc", "r0");
1521 emitcode ("mov", "%s,r0", spname);
1522 if (bitVectBitValue (rsave, R0_IDX))
1523 emitcode ("mov", "r0,b");
1526 for (i = 0; i < mcs51_nRegs; i++)
1528 if (bitVectBitValue (rsave, i))
1529 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
1533 /*-----------------------------------------------------------------*/
1534 /* unsaveRegisters - pop the pushed registers */
1535 /*-----------------------------------------------------------------*/
1537 unsaveRegisters (iCode * ic)
1542 /* restore the registers in use at this time but skip the
1543 ones for the result */
1544 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
1545 mcs51_rUmaskForOp (IC_RESULT(ic)));
1547 if (options.useXstack)
1549 emitcode ("mov", "r0,%s", spname);
1550 for (i = mcs51_nRegs; i >= 0; i--)
1552 if (bitVectBitValue (rsave, i))
1554 emitcode ("dec", "r0");
1555 emitcode ("movx", "a,@r0");
1557 emitcode ("mov", "b,a");
1559 emitcode ("mov", "%s,a", mcs51_regWithIdx (i)->name);
1563 emitcode ("mov", "%s,r0", spname);
1564 if (bitVectBitValue (rsave, R0_IDX))
1565 emitcode ("mov", "r0,b");
1568 for (i = mcs51_nRegs; i >= 0; i--)
1570 if (bitVectBitValue (rsave, i))
1571 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
1577 /*-----------------------------------------------------------------*/
1579 /*-----------------------------------------------------------------*/
1581 pushSide (operand * oper, int size)
1586 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE);
1587 if (AOP_TYPE (oper) != AOP_REG &&
1588 AOP_TYPE (oper) != AOP_DIR &&
1591 emitcode ("mov", "a,%s", l);
1592 emitcode ("push", "acc");
1595 emitcode ("push", "%s", l);
1599 /*-----------------------------------------------------------------*/
1600 /* assignResultValue - */
1601 /*-----------------------------------------------------------------*/
1603 assignResultValue (operand * oper)
1606 int size = AOP_SIZE (oper);
1609 aopPut (AOP (oper), fReturn[offset], offset);
1615 /*-----------------------------------------------------------------*/
1616 /* genXpush - pushes onto the external stack */
1617 /*-----------------------------------------------------------------*/
1619 genXpush (iCode * ic)
1621 asmop *aop = newAsmop (0);
1623 int size, offset = 0;
1625 D(emitcode (";", "genXpush"));
1627 aopOp (IC_LEFT (ic), ic, FALSE);
1628 r = getFreePtr (ic, &aop, FALSE);
1631 emitcode ("mov", "%s,_spx", r->name);
1633 size = AOP_SIZE (IC_LEFT (ic));
1637 char *l = aopGet (AOP (IC_LEFT (ic)),
1638 offset++, FALSE, FALSE);
1640 emitcode ("movx", "@%s,a", r->name);
1641 emitcode ("inc", "%s", r->name);
1646 emitcode ("mov", "_spx,%s", r->name);
1648 freeAsmop (NULL, aop, ic, TRUE);
1649 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1652 /*-----------------------------------------------------------------*/
1653 /* genIpush - genrate code for pushing this gets a little complex */
1654 /*-----------------------------------------------------------------*/
1656 genIpush (iCode * ic)
1658 int size, offset = 0;
1661 D(emitcode (";", "genIpush"));
1663 /* if this is not a parm push : ie. it is spill push
1664 and spill push is always done on the local stack */
1668 /* and the item is spilt then do nothing */
1669 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1672 aopOp (IC_LEFT (ic), ic, FALSE);
1673 size = AOP_SIZE (IC_LEFT (ic));
1674 /* push it on the stack */
1677 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1683 emitcode ("push", "%s", l);
1688 /* this is a paramter push: in this case we call
1689 the routine to find the call and save those
1690 registers that need to be saved */
1693 /* if use external stack then call the external
1694 stack pushing routine */
1695 if (options.useXstack)
1701 /* then do the push */
1702 aopOp (IC_LEFT (ic), ic, FALSE);
1705 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
1706 size = AOP_SIZE (IC_LEFT (ic));
1710 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE);
1711 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
1712 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
1715 emitcode ("mov", "a,%s", l);
1716 emitcode ("push", "acc");
1719 emitcode ("push", "%s", l);
1722 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1725 /*-----------------------------------------------------------------*/
1726 /* genIpop - recover the registers: can happen only for spilling */
1727 /*-----------------------------------------------------------------*/
1729 genIpop (iCode * ic)
1733 D(emitcode (";", "genIpop"));
1735 /* if the temp was not pushed then */
1736 if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
1739 aopOp (IC_LEFT (ic), ic, FALSE);
1740 size = AOP_SIZE (IC_LEFT (ic));
1741 offset = (size - 1);
1743 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
1746 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
1749 /*-----------------------------------------------------------------*/
1750 /* unsaveRBank - restores the resgister bank from stack */
1751 /*-----------------------------------------------------------------*/
1753 unsaveRBank (int bank, iCode * ic, bool popPsw)
1759 if (options.useXstack)
1763 /* Assume r0 is available for use. */
1764 r = mcs51_regWithIdx (R0_IDX);;
1769 r = getFreePtr (ic, &aop, FALSE);
1771 emitcode ("mov", "%s,_spx", r->name);
1776 if (options.useXstack)
1778 emitcode ("movx", "a,@%s", r->name);
1779 emitcode ("mov", "psw,a");
1780 emitcode ("dec", "%s", r->name);
1784 emitcode ("pop", "psw");
1788 for (i = (mcs51_nRegs - 1); i >= 0; i--)
1790 if (options.useXstack)
1792 emitcode ("movx", "a,@%s", r->name);
1793 emitcode ("mov", "(%s+%d),a",
1794 regs8051[i].base, 8 * bank + regs8051[i].offset);
1795 emitcode ("dec", "%s", r->name);
1799 emitcode ("pop", "(%s+%d)",
1800 regs8051[i].base, 8 * bank + regs8051[i].offset);
1803 if (options.useXstack)
1805 emitcode ("mov", "_spx,%s", r->name);
1810 freeAsmop (NULL, aop, ic, TRUE);
1814 /*-----------------------------------------------------------------*/
1815 /* saveRBank - saves an entire register bank on the stack */
1816 /*-----------------------------------------------------------------*/
1818 saveRBank (int bank, iCode * ic, bool pushPsw)
1824 if (options.useXstack)
1828 /* Assume r0 is available for use. */
1829 r = mcs51_regWithIdx (R0_IDX);;
1834 r = getFreePtr (ic, &aop, FALSE);
1836 emitcode ("mov", "%s,_spx", r->name);
1839 for (i = 0; i < mcs51_nRegs; i++)
1841 if (options.useXstack)
1843 emitcode ("inc", "%s", r->name);
1844 emitcode ("mov", "a,(%s+%d)",
1845 regs8051[i].base, 8 * bank + regs8051[i].offset);
1846 emitcode ("movx", "@%s,a", r->name);
1849 emitcode ("push", "(%s+%d)",
1850 regs8051[i].base, 8 * bank + regs8051[i].offset);
1855 if (options.useXstack)
1857 emitcode ("mov", "a,psw");
1858 emitcode ("movx", "@%s,a", r->name);
1859 emitcode ("inc", "%s", r->name);
1860 emitcode ("mov", "_spx,%s", r->name);
1865 emitcode ("push", "psw");
1868 emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
1873 freeAsmop (NULL, aop, ic, TRUE);
1882 /*-----------------------------------------------------------------*/
1883 /* genCall - generates a call statement */
1884 /*-----------------------------------------------------------------*/
1886 genCall (iCode * ic)
1889 bool restoreBank = FALSE;
1890 bool swapBanks = FALSE;
1892 D(emitcode(";", "genCall"));
1894 /* if send set is not empty the assign */
1899 for (sic = setFirstItem (_G.sendSet); sic;
1900 sic = setNextItem (_G.sendSet))
1902 int size, offset = 0;
1903 aopOp (IC_LEFT (sic), sic, FALSE);
1904 size = AOP_SIZE (IC_LEFT (sic));
1907 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
1909 if (strcmp (l, fReturn[offset]))
1910 emitcode ("mov", "%s,%s",
1915 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
1920 /* if we are calling a not _naked function that is not using
1921 the same register bank then we need to save the
1922 destination registers on the stack */
1923 dtype = operandType (IC_LEFT (ic));
1924 if (dtype && !IFFUNC_ISNAKED(dtype) &&
1925 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
1926 IFFUNC_ISISR (currFunc->type))
1930 /* This is unexpected; the bank should have been saved in
1933 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
1939 /* if caller saves & we have not saved then */
1945 emitcode ("mov", "psw,#0x%02x",
1946 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
1950 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
1951 OP_SYMBOL (IC_LEFT (ic))->rname :
1952 OP_SYMBOL (IC_LEFT (ic))->name));
1956 emitcode ("mov", "psw,#0x%02x",
1957 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
1960 /* if we need assign a result value */
1961 if ((IS_ITEMP (IC_RESULT (ic)) &&
1962 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
1963 OP_SYMBOL (IC_RESULT (ic))->accuse ||
1964 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
1965 IS_TRUE_SYMOP (IC_RESULT (ic)))
1969 aopOp (IC_RESULT (ic), ic, FALSE);
1972 assignResultValue (IC_RESULT (ic));
1974 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1977 /* adjust the stack for parameters if
1982 if (ic->parmBytes > 3)
1984 emitcode ("mov", "a,%s", spname);
1985 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
1986 emitcode ("mov", "%s,a", spname);
1989 for (i = 0; i < ic->parmBytes; i++)
1990 emitcode ("dec", "%s", spname);
1993 /* if we hade saved some registers then unsave them */
1994 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
1995 unsaveRegisters (ic);
1997 /* if register bank was saved then pop them */
1999 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2002 /*-----------------------------------------------------------------*/
2003 /* genPcall - generates a call by pointer statement */
2004 /*-----------------------------------------------------------------*/
2006 genPcall (iCode * ic)
2009 symbol *rlbl = newiTempLabel (NULL);
2010 bool restoreBank=FALSE;
2012 D(emitcode(";", "genPCall"));
2014 /* if caller saves & we have not saved then */
2018 /* if we are calling a function that is not using
2019 the same register bank then we need to save the
2020 destination registers on the stack */
2021 dtype = operandType (IC_LEFT (ic));
2022 if (dtype && !FUNC_ISNAKED(dtype) &&
2023 IFFUNC_ISISR (currFunc->type) &&
2024 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2025 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2029 /* push the return address on to the stack */
2030 emitcode ("mov", "a,#%05d$", (rlbl->key + 100));
2031 emitcode ("push", "acc");
2032 emitcode ("mov", "a,#(%05d$ >> 8)", (rlbl->key + 100));
2033 emitcode ("push", "acc");
2035 /* now push the calling address */
2036 aopOp (IC_LEFT (ic), ic, FALSE);
2038 pushSide (IC_LEFT (ic), FPTRSIZE);
2040 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2042 /* if send set is not empty the assign */
2047 for (sic = setFirstItem (_G.sendSet); sic;
2048 sic = setNextItem (_G.sendSet))
2050 int size, offset = 0;
2051 aopOp (IC_LEFT (sic), sic, FALSE);
2052 size = AOP_SIZE (IC_LEFT (sic));
2055 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2057 if (strcmp (l, fReturn[offset]))
2058 emitcode ("mov", "%s,%s",
2063 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2068 emitcode ("ret", "");
2069 emitcode ("", "%05d$:", (rlbl->key + 100));
2072 /* if we need assign a result value */
2073 if ((IS_ITEMP (IC_RESULT (ic)) &&
2074 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2075 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2076 IS_TRUE_SYMOP (IC_RESULT (ic)))
2080 aopOp (IC_RESULT (ic), ic, FALSE);
2083 assignResultValue (IC_RESULT (ic));
2085 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2088 /* adjust the stack for parameters if
2093 if (ic->parmBytes > 3)
2095 emitcode ("mov", "a,%s", spname);
2096 emitcode ("add", "a,#0x%02x", (-ic->parmBytes) & 0xff);
2097 emitcode ("mov", "%s,a", spname);
2100 for (i = 0; i < ic->parmBytes; i++)
2101 emitcode ("dec", "%s", spname);
2105 /* if register bank was saved then unsave them */
2107 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2109 /* if we hade saved some registers then
2111 if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
2112 unsaveRegisters (ic);
2115 /*-----------------------------------------------------------------*/
2116 /* resultRemat - result is rematerializable */
2117 /*-----------------------------------------------------------------*/
2119 resultRemat (iCode * ic)
2121 if (SKIP_IC (ic) || ic->op == IFX)
2124 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2126 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2127 if (sym->remat && !POINTER_SET (ic))
2134 #if defined(__BORLANDC__) || defined(_MSC_VER)
2135 #define STRCASECMP stricmp
2137 #define STRCASECMP strcasecmp
2140 /*-----------------------------------------------------------------*/
2141 /* inExcludeList - return 1 if the string is in exclude Reg list */
2142 /*-----------------------------------------------------------------*/
2144 inExcludeList (char *s)
2148 if (options.excludeRegs[i] &&
2149 STRCASECMP (options.excludeRegs[i], "none") == 0)
2152 for (i = 0; options.excludeRegs[i]; i++)
2154 if (options.excludeRegs[i] &&
2155 STRCASECMP (s, options.excludeRegs[i]) == 0)
2161 /*-----------------------------------------------------------------*/
2162 /* genFunction - generated code for function entry */
2163 /*-----------------------------------------------------------------*/
2165 genFunction (iCode * ic)
2169 bool switchedPSW = FALSE;
2172 /* create the function header */
2173 emitcode (";", "-----------------------------------------");
2174 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2175 emitcode (";", "-----------------------------------------");
2177 emitcode ("", "%s:", sym->rname);
2178 ftype = operandType (IC_LEFT (ic));
2180 if (IFFUNC_ISNAKED(ftype))
2182 emitcode(";", "naked function: no prologue.");
2186 /* if critical function then turn interrupts off */
2187 if (IFFUNC_ISCRITICAL (ftype))
2188 emitcode ("clr", "ea");
2190 /* here we need to generate the equates for the
2191 register bank if required */
2192 if (FUNC_REGBANK (ftype) != rbank)
2196 rbank = FUNC_REGBANK (ftype);
2197 for (i = 0; i < mcs51_nRegs; i++)
2199 if (strcmp (regs8051[i].base, "0") == 0)
2200 emitcode ("", "%s = 0x%02x",
2202 8 * rbank + regs8051[i].offset);
2204 emitcode ("", "%s = %s + 0x%02x",
2207 8 * rbank + regs8051[i].offset);
2211 /* if this is an interrupt service routine then
2212 save acc, b, dpl, dph */
2213 if (IFFUNC_ISISR (sym->type))
2216 if (!inExcludeList ("acc"))
2217 emitcode ("push", "acc");
2218 if (!inExcludeList ("b"))
2219 emitcode ("push", "b");
2220 if (!inExcludeList ("dpl"))
2221 emitcode ("push", "dpl");
2222 if (!inExcludeList ("dph"))
2223 emitcode ("push", "dph");
2224 /* if this isr has no bank i.e. is going to
2225 run with bank 0 , then we need to save more
2227 if (!FUNC_REGBANK (sym->type))
2230 /* if this function does not call any other
2231 function then we can be economical and
2232 save only those registers that are used */
2233 if (!IFFUNC_HASFCALL(sym->type))
2237 /* if any registers used */
2240 /* save the registers used */
2241 for (i = 0; i < sym->regsUsed->size; i++)
2243 if (bitVectBitValue (sym->regsUsed, i) ||
2244 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2245 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2252 /* this function has a function call cannot
2253 determines register usage so we will have to push the
2255 saveRBank (0, ic, FALSE);
2260 /* This ISR uses a non-zero bank.
2262 * We assume that the bank is available for our
2265 * However, if this ISR calls a function which uses some
2266 * other bank, we must save that bank entirely.
2268 unsigned long banksToSave = 0;
2270 if (IFFUNC_HASFCALL(sym->type))
2273 #define MAX_REGISTER_BANKS 4
2278 for (i = ic; i; i = i->next)
2280 if (i->op == ENDFUNCTION)
2282 /* we got to the end OK. */
2290 dtype = operandType (IC_LEFT(i));
2292 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
2294 /* Mark this bank for saving. */
2295 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
2297 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
2301 banksToSave |= (1 << FUNC_REGBANK(dtype));
2304 /* And note that we don't need to do it in
2312 /* This is a mess; we have no idea what
2313 * register bank the called function might
2316 * The only thing I can think of to do is
2317 * throw a warning and hope.
2319 werror(W_FUNCPTR_IN_USING_ISR);
2323 if (banksToSave && options.useXstack)
2325 /* Since we aren't passing it an ic,
2326 * saveRBank will assume r0 is available to abuse.
2328 * So switch to our (trashable) bank now, so
2329 * the caller's R0 isn't trashed.
2331 emitcode ("push", "psw");
2332 emitcode ("mov", "psw,#0x%02x",
2333 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2337 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
2339 if (banksToSave & (1 << ix))
2341 saveRBank(ix, NULL, FALSE);
2345 // jwk: this needs a closer look
2346 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
2351 /* if callee-save to be used for this function
2352 then save the registers being used in this function */
2353 if (IFFUNC_CALLEESAVES(sym->type))
2357 /* if any registers used */
2360 /* save the registers used */
2361 for (i = 0; i < sym->regsUsed->size; i++)
2363 if (bitVectBitValue (sym->regsUsed, i) ||
2364 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2366 emitcode ("push", "%s", mcs51_regWithIdx (i)->dname);
2374 /* set the register bank to the desired value */
2375 if ((FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2378 emitcode ("push", "psw");
2379 emitcode ("mov", "psw,#0x%02x", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
2382 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2385 if (options.useXstack)
2387 emitcode ("mov", "r0,%s", spname);
2388 emitcode ("mov", "a,_bp");
2389 emitcode ("movx", "@r0,a");
2390 emitcode ("inc", "%s", spname);
2394 /* set up the stack */
2395 emitcode ("push", "_bp"); /* save the callers stack */
2397 emitcode ("mov", "_bp,%s", spname);
2400 /* adjust the stack for the function */
2406 werror (W_STACK_OVERFLOW, sym->name);
2408 if (i > 3 && sym->recvSize < 4)
2411 emitcode ("mov", "a,sp");
2412 emitcode ("add", "a,#0x%02x", ((char) sym->stack & 0xff));
2413 emitcode ("mov", "sp,a");
2418 emitcode ("inc", "sp");
2424 emitcode ("mov", "a,_spx");
2425 emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
2426 emitcode ("mov", "_spx,a");
2431 /*-----------------------------------------------------------------*/
2432 /* genEndFunction - generates epilogue for functions */
2433 /*-----------------------------------------------------------------*/
2435 genEndFunction (iCode * ic)
2437 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
2439 if (IFFUNC_ISNAKED(sym->type))
2441 emitcode(";", "naked function: no epilogue.");
2445 if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
2447 emitcode ("mov", "%s,_bp", spname);
2450 /* if use external stack but some variables were
2451 added to the local stack then decrement the
2453 if (options.useXstack && sym->stack)
2455 emitcode ("mov", "a,sp");
2456 emitcode ("add", "a,#0x%02x", ((char) -sym->stack) & 0xff);
2457 emitcode ("mov", "sp,a");
2461 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
2463 if (options.useXstack)
2465 emitcode ("mov", "r0,%s", spname);
2466 emitcode ("movx", "a,@r0");
2467 emitcode ("mov", "_bp,a");
2468 emitcode ("dec", "%s", spname);
2472 emitcode ("pop", "_bp");
2476 /* restore the register bank */
2477 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
2479 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
2480 || !options.useXstack)
2482 /* Special case of ISR using non-zero bank with useXstack
2485 emitcode ("pop", "psw");
2489 if (IFFUNC_ISISR (sym->type))
2492 /* now we need to restore the registers */
2493 /* if this isr has no bank i.e. is going to
2494 run with bank 0 , then we need to save more
2496 if (!FUNC_REGBANK (sym->type))
2498 /* if this function does not call any other
2499 function then we can be economical and
2500 save only those registers that are used */
2501 if (!IFFUNC_HASFCALL(sym->type))
2505 /* if any registers used */
2508 /* save the registers used */
2509 for (i = sym->regsUsed->size; i >= 0; i--)
2511 if (bitVectBitValue (sym->regsUsed, i) ||
2512 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2513 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2520 /* this function has a function call cannot
2521 determines register usage so we will have to pop the
2523 unsaveRBank (0, ic, FALSE);
2528 /* This ISR uses a non-zero bank.
2530 * Restore any register banks saved by genFunction
2533 // jwk: this needs a closer look
2534 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
2537 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
2539 if (savedBanks & (1 << ix))
2541 unsaveRBank(ix, NULL, FALSE);
2545 if (options.useXstack)
2547 /* Restore bank AFTER calling unsaveRBank,
2548 * since it can trash r0.
2550 emitcode ("pop", "psw");
2554 if (!inExcludeList ("dph"))
2555 emitcode ("pop", "dph");
2556 if (!inExcludeList ("dpl"))
2557 emitcode ("pop", "dpl");
2558 if (!inExcludeList ("b"))
2559 emitcode ("pop", "b");
2560 if (!inExcludeList ("acc"))
2561 emitcode ("pop", "acc");
2563 if (IFFUNC_ISCRITICAL (sym->type))
2564 emitcode ("setb", "ea");
2566 /* if debug then send end of function */
2567 /* if (options.debug && currFunc) */
2568 if (options.debug && currFunc)
2571 emitcode ("", "C$%s$%d$%d$%d ==.",
2572 FileBaseName (ic->filename), currFunc->lastLine,
2573 ic->level, ic->block);
2574 if (IS_STATIC (currFunc->etype))
2575 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2577 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2581 emitcode ("reti", "");
2585 if (IFFUNC_ISCRITICAL (sym->type))
2586 emitcode ("setb", "ea");
2588 if (IFFUNC_CALLEESAVES(sym->type))
2592 /* if any registers used */
2595 /* save the registers used */
2596 for (i = sym->regsUsed->size; i >= 0; i--)
2598 if (bitVectBitValue (sym->regsUsed, i) ||
2599 (mcs51_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2600 emitcode ("pop", "%s", mcs51_regWithIdx (i)->dname);
2606 /* if debug then send end of function */
2607 if (options.debug && currFunc)
2610 emitcode ("", "C$%s$%d$%d$%d ==.",
2611 FileBaseName (ic->filename), currFunc->lastLine,
2612 ic->level, ic->block);
2613 if (IS_STATIC (currFunc->etype))
2614 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
2616 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
2620 emitcode ("ret", "");
2625 /*-----------------------------------------------------------------*/
2626 /* genRet - generate code for return statement */
2627 /*-----------------------------------------------------------------*/
2631 int size, offset = 0, pushed = 0;
2633 D(emitcode (";", "genRet"));
2635 /* if we have no return value then
2636 just generate the "ret" */
2640 /* we have something to return then
2641 move the return value into place */
2642 aopOp (IC_LEFT (ic), ic, FALSE);
2643 size = AOP_SIZE (IC_LEFT (ic));
2648 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
2651 l = aopGet (AOP (IC_LEFT (ic)), offset++,
2653 emitcode ("push", "%s", l);
2658 l = aopGet (AOP (IC_LEFT (ic)), offset,
2660 if (strcmp (fReturn[offset], l))
2661 emitcode ("mov", "%s,%s", fReturn[offset++], l);
2670 if (strcmp (fReturn[pushed], "a"))
2671 emitcode ("pop", fReturn[pushed]);
2673 emitcode ("pop", "acc");
2676 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2679 /* generate a jump to the return label
2680 if the next is not the return statement */
2681 if (!(ic->next && ic->next->op == LABEL &&
2682 IC_LABEL (ic->next) == returnLabel))
2684 emitcode ("ljmp", "%05d$", (returnLabel->key + 100));
2688 /*-----------------------------------------------------------------*/
2689 /* genLabel - generates a label */
2690 /*-----------------------------------------------------------------*/
2692 genLabel (iCode * ic)
2694 /* special case never generate */
2695 if (IC_LABEL (ic) == entryLabel)
2698 emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
2701 /*-----------------------------------------------------------------*/
2702 /* genGoto - generates a ljmp */
2703 /*-----------------------------------------------------------------*/
2705 genGoto (iCode * ic)
2707 emitcode ("ljmp", "%05d$", (IC_LABEL (ic)->key + 100));
2710 /*-----------------------------------------------------------------*/
2711 /* findLabelBackwards: walks back through the iCode chain looking */
2712 /* for the given label. Returns number of iCode instructions */
2713 /* between that label and given ic. */
2714 /* Returns zero if label not found. */
2715 /*-----------------------------------------------------------------*/
2717 findLabelBackwards (iCode * ic, int key)
2726 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
2728 /* printf("findLabelBackwards = %d\n", count); */
2736 /*-----------------------------------------------------------------*/
2737 /* genPlusIncr :- does addition with increment if possible */
2738 /*-----------------------------------------------------------------*/
2740 genPlusIncr (iCode * ic)
2742 unsigned int icount;
2743 unsigned int size = getDataSize (IC_RESULT (ic));
2745 /* will try to generate an increment */
2746 /* if the right side is not a literal
2748 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
2751 /* if the literal value of the right hand side
2752 is greater than 4 then it is not worth it */
2753 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
2756 D(emitcode (";", "genPlusIncr"));
2758 /* if increment 16 bits in register */
2759 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
2767 /* If the next instruction is a goto and the goto target
2768 * is < 10 instructions previous to this, we can generate
2769 * jumps straight to that target.
2771 if (ic->next && ic->next->op == GOTO
2772 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
2773 && labelRange <= 10)
2775 emitcode (";", "tail increment optimized");
2776 tlbl = IC_LABEL (ic->next);
2781 tlbl = newiTempLabel (NULL);
2784 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
2785 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2786 IS_AOP_PREG (IC_RESULT (ic)))
2787 emitcode ("cjne", "%s,#0x00,%05d$"
2788 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2792 emitcode ("clr", "a");
2793 emitcode ("cjne", "a,%s,%05d$"
2794 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
2798 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
2801 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2802 IS_AOP_PREG (IC_RESULT (ic)))
2803 emitcode ("cjne", "%s,#0x00,%05d$"
2804 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2807 emitcode ("cjne", "a,%s,%05d$"
2808 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
2811 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
2815 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
2816 IS_AOP_PREG (IC_RESULT (ic)))
2817 emitcode ("cjne", "%s,#0x00,%05d$"
2818 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2822 emitcode ("cjne", "a,%s,%05d$"
2823 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
2826 emitcode ("inc", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
2831 emitcode ("", "%05d$:", tlbl->key + 100);
2836 /* if the sizes are greater than 1 then we cannot */
2837 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
2838 AOP_SIZE (IC_LEFT (ic)) > 1)
2841 /* we can if the aops of the left & result match or
2842 if they are in registers and the registers are the
2844 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
2849 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2850 emitcode ("add", "a,#0x%02x", ((char) icount) & 0xff);
2851 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2857 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE));
2866 /*-----------------------------------------------------------------*/
2867 /* outBitAcc - output a bit in acc */
2868 /*-----------------------------------------------------------------*/
2870 outBitAcc (operand * result)
2872 symbol *tlbl = newiTempLabel (NULL);
2873 /* if the result is a bit */
2874 if (AOP_TYPE (result) == AOP_CRY)
2876 aopPut (AOP (result), "a", 0);
2880 emitcode ("jz", "%05d$", tlbl->key + 100);
2881 emitcode ("mov", "a,%s", one);
2882 emitcode ("", "%05d$:", tlbl->key + 100);
2887 /*-----------------------------------------------------------------*/
2888 /* genPlusBits - generates code for addition of two bits */
2889 /*-----------------------------------------------------------------*/
2891 genPlusBits (iCode * ic)
2893 D(emitcode (";", "genPlusBits"));
2895 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
2897 symbol *lbl = newiTempLabel (NULL);
2898 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2899 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
2900 emitcode ("cpl", "c");
2901 emitcode ("", "%05d$:", (lbl->key + 100));
2902 outBitC (IC_RESULT (ic));
2906 emitcode ("clr", "a");
2907 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
2908 emitcode ("rlc", "a");
2909 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
2910 emitcode ("addc", "a,#0x00");
2911 outAcc (IC_RESULT (ic));
2916 /* This is the original version of this code.
2918 * This is being kept around for reference,
2919 * because I am not entirely sure I got it right...
2922 adjustArithmeticResult (iCode * ic)
2924 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2925 AOP_SIZE (IC_LEFT (ic)) == 3 &&
2926 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2927 aopPut (AOP (IC_RESULT (ic)),
2928 aopGet (AOP (IC_LEFT (ic)), 2, FALSE, FALSE),
2931 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2932 AOP_SIZE (IC_RIGHT (ic)) == 3 &&
2933 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2934 aopPut (AOP (IC_RESULT (ic)),
2935 aopGet (AOP (IC_RIGHT (ic)), 2, FALSE, FALSE),
2938 if (AOP_SIZE (IC_RESULT (ic)) == 3 &&
2939 AOP_SIZE (IC_LEFT (ic)) < 3 &&
2940 AOP_SIZE (IC_RIGHT (ic)) < 3 &&
2941 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2942 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2945 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2946 aopPut (AOP (IC_RESULT (ic)), buffer, 2);
2950 /* This is the pure and virtuous version of this code.
2951 * I'm pretty certain it's right, but not enough to toss the old
2955 adjustArithmeticResult (iCode * ic)
2957 if (opIsGptr (IC_RESULT (ic)) &&
2958 opIsGptr (IC_LEFT (ic)) &&
2959 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
2961 aopPut (AOP (IC_RESULT (ic)),
2962 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2966 if (opIsGptr (IC_RESULT (ic)) &&
2967 opIsGptr (IC_RIGHT (ic)) &&
2968 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2970 aopPut (AOP (IC_RESULT (ic)),
2971 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE),
2975 if (opIsGptr (IC_RESULT (ic)) &&
2976 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
2977 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
2978 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
2979 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
2982 sprintf (buffer, "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
2983 aopPut (AOP (IC_RESULT (ic)), buffer, GPTRSIZE - 1);
2988 /*-----------------------------------------------------------------*/
2989 /* genPlus - generates code for addition */
2990 /*-----------------------------------------------------------------*/
2992 genPlus (iCode * ic)
2994 int size, offset = 0;
2996 /* special cases :- */
2998 D(emitcode (";", "genPlus"));
3000 aopOp (IC_LEFT (ic), ic, FALSE);
3001 aopOp (IC_RIGHT (ic), ic, FALSE);
3002 aopOp (IC_RESULT (ic), ic, TRUE);
3004 /* if literal, literal on the right or
3005 if left requires ACC or right is already
3007 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
3008 (AOP_NEEDSACC (IC_LEFT (ic))) ||
3009 AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
3011 operand *t = IC_RIGHT (ic);
3012 IC_RIGHT (ic) = IC_LEFT (ic);
3016 /* if both left & right are in bit
3018 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3019 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3025 /* if left in bit space & right literal */
3026 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3027 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
3029 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3030 /* if result in bit space */
3031 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3033 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
3034 emitcode ("cpl", "c");
3035 outBitC (IC_RESULT (ic));
3039 size = getDataSize (IC_RESULT (ic));
3042 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3043 emitcode ("addc", "a,#00");
3044 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3050 /* if I can do an increment instead
3051 of add then GOOD for ME */
3052 if (genPlusIncr (ic) == TRUE)
3055 size = getDataSize (IC_RESULT (ic));
3059 if (AOP_TYPE (IC_LEFT (ic)) == AOP_ACC)
3061 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3063 emitcode ("add", "a,%s",
3064 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3066 emitcode ("addc", "a,%s",
3067 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3071 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3073 emitcode ("add", "a,%s",
3074 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3076 emitcode ("addc", "a,%s",
3077 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3079 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3082 adjustArithmeticResult (ic);
3085 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3086 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3087 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3090 /*-----------------------------------------------------------------*/
3091 /* genMinusDec :- does subtraction with deccrement if possible */
3092 /*-----------------------------------------------------------------*/
3094 genMinusDec (iCode * ic)
3096 unsigned int icount;
3097 unsigned int size = getDataSize (IC_RESULT (ic));
3099 /* will try to generate an increment */
3100 /* if the right side is not a literal
3102 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3105 /* if the literal value of the right hand side
3106 is greater than 4 then it is not worth it */
3107 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3110 D(emitcode (";", "genMinusDec"));
3112 /* if decrement 16 bits in register */
3113 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3121 /* If the next instruction is a goto and the goto target
3122 * is <= 10 instructions previous to this, we can generate
3123 * jumps straight to that target.
3125 if (ic->next && ic->next->op == GOTO
3126 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3127 && labelRange <= 10)
3129 emitcode (";", "tail decrement optimized");
3130 tlbl = IC_LABEL (ic->next);
3135 tlbl = newiTempLabel (NULL);
3139 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE));
3140 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3141 IS_AOP_PREG (IC_RESULT (ic)))
3142 emitcode ("cjne", "%s,#0xff,%05d$"
3143 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3147 emitcode ("mov", "a,#0xff");
3148 emitcode ("cjne", "a,%s,%05d$"
3149 ,aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE)
3152 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE));
3155 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3156 IS_AOP_PREG (IC_RESULT (ic)))
3157 emitcode ("cjne", "%s,#0xff,%05d$"
3158 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3162 emitcode ("cjne", "a,%s,%05d$"
3163 ,aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE)
3166 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE));
3170 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3171 IS_AOP_PREG (IC_RESULT (ic)))
3172 emitcode ("cjne", "%s,#0xff,%05d$"
3173 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3177 emitcode ("cjne", "a,%s,%05d$"
3178 ,aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE)
3181 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE));
3185 emitcode ("", "%05d$:", tlbl->key + 100);
3190 /* if the sizes are greater than 1 then we cannot */
3191 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3192 AOP_SIZE (IC_LEFT (ic)) > 1)
3195 /* we can if the aops of the left & result match or
3196 if they are in registers and the registers are the
3198 if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3202 emitcode ("dec", "%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
3210 /*-----------------------------------------------------------------*/
3211 /* addSign - complete with sign */
3212 /*-----------------------------------------------------------------*/
3214 addSign (operand * result, int offset, int sign)
3216 int size = (getDataSize (result) - offset);
3221 emitcode ("rlc", "a");
3222 emitcode ("subb", "a,acc");
3224 aopPut (AOP (result), "a", offset++);
3228 aopPut (AOP (result), zero, offset++);
3232 /*-----------------------------------------------------------------*/
3233 /* genMinusBits - generates code for subtraction of two bits */
3234 /*-----------------------------------------------------------------*/
3236 genMinusBits (iCode * ic)
3238 symbol *lbl = newiTempLabel (NULL);
3240 D(emitcode (";", "genMinusBits"));
3242 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3244 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3245 emitcode ("jnb", "%s,%05d$", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3246 emitcode ("cpl", "c");
3247 emitcode ("", "%05d$:", (lbl->key + 100));
3248 outBitC (IC_RESULT (ic));
3252 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3253 emitcode ("subb", "a,acc");
3254 emitcode ("jnb", "%s,%05d$", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
3255 emitcode ("inc", "a");
3256 emitcode ("", "%05d$:", (lbl->key + 100));
3257 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3258 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
3262 /*-----------------------------------------------------------------*/
3263 /* genMinus - generates code for subtraction */
3264 /*-----------------------------------------------------------------*/
3266 genMinus (iCode * ic)
3268 int size, offset = 0;
3269 unsigned long lit = 0L;
3271 D(emitcode (";", "genMinus"));
3273 aopOp (IC_LEFT (ic), ic, FALSE);
3274 aopOp (IC_RIGHT (ic), ic, FALSE);
3275 aopOp (IC_RESULT (ic), ic, TRUE);
3277 /* special cases :- */
3278 /* if both left & right are in bit space */
3279 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
3280 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
3286 /* if I can do an decrement instead
3287 of subtract then GOOD for ME */
3288 if (genMinusDec (ic) == TRUE)
3291 size = getDataSize (IC_RESULT (ic));
3293 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3299 lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
3303 /* if literal, add a,#-lit, else normal subb */
3306 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE));
3307 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3308 emitcode ("subb", "a,%s",
3309 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE));
3312 /* first add without previous c */
3314 if (!size && lit==-1) {
3315 emitcode ("dec", "a");
3317 emitcode ("add", "a,#0x%02x",
3318 (unsigned int) (lit & 0x0FFL));
3321 emitcode ("addc", "a,#0x%02x",
3322 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3325 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
3328 adjustArithmeticResult (ic);
3331 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3332 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3333 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
3337 /*-----------------------------------------------------------------*/
3338 /* genMultbits :- multiplication of bits */
3339 /*-----------------------------------------------------------------*/
3341 genMultbits (operand * left,
3345 D(emitcode (";", "genMultbits"));
3347 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
3348 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
3353 /*-----------------------------------------------------------------*/
3354 /* genMultOneByte : 8*8=8/16 bit multiplication */
3355 /*-----------------------------------------------------------------*/
3357 genMultOneByte (operand * left,
3361 sym_link *opetype = operandType (result);
3363 int size=AOP_SIZE(result);
3365 D(emitcode (";", "genMultOneByte"));
3367 if (size<1 || size>2) {
3368 // this should never happen
3369 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
3370 AOP_SIZE(result), __FILE__, lineno);
3374 /* (if two literals: the value is computed before) */
3375 /* if one literal, literal on the right */
3376 if (AOP_TYPE (left) == AOP_LIT)
3381 //emitcode (";", "swapped left and right");
3384 if (SPEC_USIGN(opetype)
3385 // ignore the sign of left and right, what else can we do?
3386 || (SPEC_USIGN(operandType(left)) &&
3387 SPEC_USIGN(operandType(right)))) {
3388 // just an unsigned 8*8=8/16 multiply
3389 //emitcode (";","unsigned");
3390 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3391 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3392 emitcode ("mul", "ab");
3393 aopPut (AOP (result), "a", 0);
3395 aopPut (AOP (result), "b", 1);
3400 // we have to do a signed multiply
3402 //emitcode (";", "signed");
3403 emitcode ("clr", "F0"); // reset sign flag
3404 MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
3406 lbl=newiTempLabel(NULL);
3407 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3408 // left side is negative, 8-bit two's complement, this fails for -128
3409 emitcode ("setb", "F0"); // set sign flag
3410 emitcode ("cpl", "a");
3411 emitcode ("inc", "a");
3413 emitcode ("", "%05d$:", lbl->key+100);
3416 if (AOP_TYPE(right)==AOP_LIT) {
3417 signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
3418 /* AND literal negative */
3420 emitcode ("cpl", "F0"); // complement sign flag
3421 emitcode ("mov", "b,#0x%02x", -val);
3423 emitcode ("mov", "b,#0x%02x", val);
3426 lbl=newiTempLabel(NULL);
3427 emitcode ("mov", "b,a");
3428 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3429 emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
3430 // right side is negative, 8-bit two's complement
3431 emitcode ("cpl", "F0"); // complement sign flag
3432 emitcode ("cpl", "a");
3433 emitcode ("inc", "a");
3434 emitcode ("", "%05d$:", lbl->key+100);
3436 emitcode ("mul", "ab");
3438 lbl=newiTempLabel(NULL);
3439 emitcode ("jnb", "F0,%05d$", lbl->key+100);
3440 // only ONE op was negative, we have to do a 8/16-bit two's complement
3441 emitcode ("cpl", "a"); // lsb
3443 emitcode ("inc", "a");
3445 emitcode ("add", "a,#1");
3446 emitcode ("xch", "a,b");
3447 emitcode ("cpl", "a"); // msb
3448 emitcode ("addc", "a,#0");
3449 emitcode ("xch", "a,b");
3452 emitcode ("", "%05d$:", lbl->key+100);
3453 aopPut (AOP (result), "a", 0);
3455 aopPut (AOP (result), "b", 1);
3459 /*-----------------------------------------------------------------*/
3460 /* genMult - generates code for multiplication */
3461 /*-----------------------------------------------------------------*/
3463 genMult (iCode * ic)
3465 operand *left = IC_LEFT (ic);
3466 operand *right = IC_RIGHT (ic);
3467 operand *result = IC_RESULT (ic);
3469 D(emitcode (";", "genMult"));
3471 /* assign the amsops */
3472 aopOp (left, ic, FALSE);
3473 aopOp (right, ic, FALSE);
3474 aopOp (result, ic, TRUE);
3476 /* special cases first */
3478 if (AOP_TYPE (left) == AOP_CRY &&
3479 AOP_TYPE (right) == AOP_CRY)
3481 genMultbits (left, right, result);
3485 /* if both are of size == 1 */
3486 #if 0 // one of them can be a sloc shared with the result
3487 if (AOP_SIZE (left) == 1 && AOP_SIZE (right) == 1)
3489 if (getSize(operandType(left)) == 1 &&
3490 getSize(operandType(right)) == 1)
3493 genMultOneByte (left, right, result);
3497 /* should have been converted to function call */
3498 fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
3499 getSize(OP_SYMBOL(right)->type));
3503 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3504 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3505 freeAsmop (result, NULL, ic, TRUE);
3508 /*-----------------------------------------------------------------*/
3509 /* genDivbits :- division of bits */
3510 /*-----------------------------------------------------------------*/
3512 genDivbits (operand * left,
3519 D(emitcode (";", "genDivbits"));
3521 /* the result must be bit */
3522 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3523 l = aopGet (AOP (left), 0, FALSE, FALSE);
3527 emitcode ("div", "ab");
3528 emitcode ("rrc", "a");
3529 aopPut (AOP (result), "c", 0);
3532 /*-----------------------------------------------------------------*/
3533 /* genDivOneByte : 8 bit division */
3534 /*-----------------------------------------------------------------*/
3536 genDivOneByte (operand * left,
3540 sym_link *opetype = operandType (result);
3545 D(emitcode (";", "genDivOneByte"));
3547 size = AOP_SIZE (result) - 1;
3549 /* signed or unsigned */
3550 if (SPEC_USIGN (opetype))
3552 /* unsigned is easy */
3553 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3554 l = aopGet (AOP (left), 0, FALSE, FALSE);
3556 emitcode ("div", "ab");
3557 aopPut (AOP (result), "a", 0);
3559 aopPut (AOP (result), zero, offset++);
3563 /* signed is a little bit more difficult */
3565 /* save the signs of the operands */
3566 l = aopGet (AOP (left), 0, FALSE, FALSE);
3568 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
3569 emitcode ("push", "acc"); /* save it on the stack */
3571 /* now sign adjust for both left & right */
3572 l = aopGet (AOP (right), 0, FALSE, FALSE);
3574 lbl = newiTempLabel (NULL);
3575 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3576 emitcode ("cpl", "a");
3577 emitcode ("inc", "a");
3578 emitcode ("", "%05d$:", (lbl->key + 100));
3579 emitcode ("mov", "b,a");
3581 /* sign adjust left side */
3582 l = aopGet (AOP (left), 0, FALSE, FALSE);
3585 lbl = newiTempLabel (NULL);
3586 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3587 emitcode ("cpl", "a");
3588 emitcode ("inc", "a");
3589 emitcode ("", "%05d$:", (lbl->key + 100));
3591 /* now the division */
3592 emitcode ("div", "ab");
3593 /* we are interested in the lower order
3595 emitcode ("mov", "b,a");
3596 lbl = newiTempLabel (NULL);
3597 emitcode ("pop", "acc");
3598 /* if there was an over flow we don't
3599 adjust the sign of the result */
3600 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3601 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3603 emitcode ("clr", "a");
3604 emitcode ("subb", "a,b");
3605 emitcode ("mov", "b,a");
3606 emitcode ("", "%05d$:", (lbl->key + 100));
3608 /* now we are done */
3609 aopPut (AOP (result), "b", 0);
3612 emitcode ("mov", "c,b.7");
3613 emitcode ("subb", "a,acc");
3616 aopPut (AOP (result), "a", offset++);
3620 /*-----------------------------------------------------------------*/
3621 /* genDiv - generates code for division */
3622 /*-----------------------------------------------------------------*/
3626 operand *left = IC_LEFT (ic);
3627 operand *right = IC_RIGHT (ic);
3628 operand *result = IC_RESULT (ic);
3630 D(emitcode (";", "genDiv"));
3632 /* assign the amsops */
3633 aopOp (left, ic, FALSE);
3634 aopOp (right, ic, FALSE);
3635 aopOp (result, ic, TRUE);
3637 /* special cases first */
3639 if (AOP_TYPE (left) == AOP_CRY &&
3640 AOP_TYPE (right) == AOP_CRY)
3642 genDivbits (left, right, result);
3646 /* if both are of size == 1 */
3647 if (AOP_SIZE (left) == 1 &&
3648 AOP_SIZE (right) == 1)
3650 genDivOneByte (left, right, result);
3654 /* should have been converted to function call */
3657 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3658 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3659 freeAsmop (result, NULL, ic, TRUE);
3662 /*-----------------------------------------------------------------*/
3663 /* genModbits :- modulus of bits */
3664 /*-----------------------------------------------------------------*/
3666 genModbits (operand * left,
3673 D(emitcode (";", "genModbits"));
3675 /* the result must be bit */
3676 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3677 l = aopGet (AOP (left), 0, FALSE, FALSE);
3681 emitcode ("div", "ab");
3682 emitcode ("mov", "a,b");
3683 emitcode ("rrc", "a");
3684 aopPut (AOP (result), "c", 0);
3687 /*-----------------------------------------------------------------*/
3688 /* genModOneByte : 8 bit modulus */
3689 /*-----------------------------------------------------------------*/
3691 genModOneByte (operand * left,
3695 sym_link *opetype = operandType (result);
3699 D(emitcode (";", "genModOneByte"));
3701 /* signed or unsigned */
3702 if (SPEC_USIGN (opetype))
3704 /* unsigned is easy */
3705 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3706 l = aopGet (AOP (left), 0, FALSE, FALSE);
3708 emitcode ("div", "ab");
3709 aopPut (AOP (result), "b", 0);
3713 /* signed is a little bit more difficult */
3715 /* save the signs of the operands */
3716 l = aopGet (AOP (left), 0, FALSE, FALSE);
3719 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
3720 emitcode ("push", "acc"); /* save it on the stack */
3722 /* now sign adjust for both left & right */
3723 l = aopGet (AOP (right), 0, FALSE, FALSE);
3726 lbl = newiTempLabel (NULL);
3727 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3728 emitcode ("cpl", "a");
3729 emitcode ("inc", "a");
3730 emitcode ("", "%05d$:", (lbl->key + 100));
3731 emitcode ("mov", "b,a");
3733 /* sign adjust left side */
3734 l = aopGet (AOP (left), 0, FALSE, FALSE);
3737 lbl = newiTempLabel (NULL);
3738 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3739 emitcode ("cpl", "a");
3740 emitcode ("inc", "a");
3741 emitcode ("", "%05d$:", (lbl->key + 100));
3743 /* now the multiplication */
3744 emitcode ("div", "ab");
3745 /* we are interested in the lower order
3747 lbl = newiTempLabel (NULL);
3748 emitcode ("pop", "acc");
3749 /* if there was an over flow we don't
3750 adjust the sign of the result */
3751 emitcode ("jb", "ov,%05d$", (lbl->key + 100));
3752 emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
3754 emitcode ("clr", "a");
3755 emitcode ("subb", "a,b");
3756 emitcode ("mov", "b,a");
3757 emitcode ("", "%05d$:", (lbl->key + 100));
3759 /* now we are done */
3760 aopPut (AOP (result), "b", 0);
3764 /*-----------------------------------------------------------------*/
3765 /* genMod - generates code for division */
3766 /*-----------------------------------------------------------------*/
3770 operand *left = IC_LEFT (ic);
3771 operand *right = IC_RIGHT (ic);
3772 operand *result = IC_RESULT (ic);
3774 D(emitcode (";", "genMod"));
3776 /* assign the amsops */
3777 aopOp (left, ic, FALSE);
3778 aopOp (right, ic, FALSE);
3779 aopOp (result, ic, TRUE);
3781 /* special cases first */
3783 if (AOP_TYPE (left) == AOP_CRY &&
3784 AOP_TYPE (right) == AOP_CRY)
3786 genModbits (left, right, result);
3790 /* if both are of size == 1 */
3791 if (AOP_SIZE (left) == 1 &&
3792 AOP_SIZE (right) == 1)
3794 genModOneByte (left, right, result);
3798 /* should have been converted to function call */
3802 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3803 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3804 freeAsmop (result, NULL, ic, TRUE);
3807 /*-----------------------------------------------------------------*/
3808 /* genIfxJump :- will create a jump depending on the ifx */
3809 /*-----------------------------------------------------------------*/
3811 genIfxJump (iCode * ic, char *jval)
3814 symbol *tlbl = newiTempLabel (NULL);
3817 D(emitcode (";", "genIfxJump"));
3819 /* if true label then we jump if condition
3823 jlbl = IC_TRUE (ic);
3824 inst = ((strcmp (jval, "a") == 0 ? "jz" :
3825 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
3829 /* false label is present */
3830 jlbl = IC_FALSE (ic);
3831 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
3832 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
3834 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
3835 emitcode (inst, "%s,%05d$", jval, (tlbl->key + 100));
3837 emitcode (inst, "%05d$", tlbl->key + 100);
3838 emitcode ("ljmp", "%05d$", jlbl->key + 100);
3839 emitcode ("", "%05d$:", tlbl->key + 100);
3841 /* mark the icode as generated */
3845 /*-----------------------------------------------------------------*/
3846 /* genCmp :- greater or less than comparison */
3847 /*-----------------------------------------------------------------*/
3849 genCmp (operand * left, operand * right,
3850 operand * result, iCode * ifx, int sign, iCode *ic)
3852 int size, offset = 0;
3853 unsigned long lit = 0L;
3855 D(emitcode (";", "genCmp"));
3857 /* if left & right are bit variables */
3858 if (AOP_TYPE (left) == AOP_CRY &&
3859 AOP_TYPE (right) == AOP_CRY)
3861 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
3862 emitcode ("anl", "c,/%s", AOP (left)->aopu.aop_dir);
3866 /* subtract right from left if at the
3867 end the carry flag is set then we know that
3868 left is greater than right */
3869 size = max (AOP_SIZE (left), AOP_SIZE (right));
3871 /* if unsigned char cmp with lit, do cjne left,#right,zz */
3872 if ((size == 1) && !sign &&
3873 (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR))
3875 symbol *lbl = newiTempLabel (NULL);
3876 emitcode ("cjne", "%s,%s,%05d$",
3877 aopGet (AOP (left), offset, FALSE, FALSE),
3878 aopGet (AOP (right), offset, FALSE, FALSE),
3880 emitcode ("", "%05d$:", lbl->key + 100);
3884 if (AOP_TYPE (right) == AOP_LIT)
3886 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
3887 /* optimize if(x < 0) or if(x >= 0) */
3896 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
3897 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
3899 genIfxJump (ifx, "acc.7");
3903 emitcode ("rlc", "a");
3911 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
3912 if (sign && size == 0)
3914 emitcode ("xrl", "a,#0x80");
3915 if (AOP_TYPE (right) == AOP_LIT)
3917 unsigned long lit = (unsigned long)
3918 floatFromVal (AOP (right)->aopu.aop_lit);
3919 emitcode ("subb", "a,#0x%02x",
3920 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
3924 emitcode ("mov", "b,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3925 emitcode ("xrl", "b,#0x80");
3926 emitcode ("subb", "a,b");
3930 emitcode ("subb", "a,%s", aopGet (AOP (right), offset++, FALSE, FALSE));
3936 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3937 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
3938 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
3944 /* if the result is used in the next
3945 ifx conditional branch then generate
3946 code a little differently */
3948 genIfxJump (ifx, "c");
3951 /* leave the result in acc */
3955 /*-----------------------------------------------------------------*/
3956 /* genCmpGt :- greater than comparison */
3957 /*-----------------------------------------------------------------*/
3959 genCmpGt (iCode * ic, iCode * ifx)
3961 operand *left, *right, *result;
3962 sym_link *letype, *retype;
3965 D(emitcode (";", "genCmpGt"));
3967 left = IC_LEFT (ic);
3968 right = IC_RIGHT (ic);
3969 result = IC_RESULT (ic);
3971 letype = getSpec (operandType (left));
3972 retype = getSpec (operandType (right));
3973 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
3974 /* assign the amsops */
3975 aopOp (left, ic, FALSE);
3976 aopOp (right, ic, FALSE);
3977 aopOp (result, ic, TRUE);
3979 genCmp (right, left, result, ifx, sign,ic);
3981 freeAsmop (result, NULL, ic, TRUE);
3984 /*-----------------------------------------------------------------*/
3985 /* genCmpLt - less than comparisons */
3986 /*-----------------------------------------------------------------*/
3988 genCmpLt (iCode * ic, iCode * ifx)
3990 operand *left, *right, *result;
3991 sym_link *letype, *retype;
3994 D(emitcode (";", "genCmpLt"));
3996 left = IC_LEFT (ic);
3997 right = IC_RIGHT (ic);
3998 result = IC_RESULT (ic);
4000 letype = getSpec (operandType (left));
4001 retype = getSpec (operandType (right));
4002 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
4004 /* assign the amsops */
4005 aopOp (left, ic, FALSE);
4006 aopOp (right, ic, FALSE);
4007 aopOp (result, ic, TRUE);
4009 genCmp (left, right, result, ifx, sign,ic);
4011 freeAsmop (result, NULL, ic, TRUE);
4014 /*-----------------------------------------------------------------*/
4015 /* gencjneshort - compare and jump if not equal */
4016 /*-----------------------------------------------------------------*/
4018 gencjneshort (operand * left, operand * right, symbol * lbl)
4020 int size = max (AOP_SIZE (left), AOP_SIZE (right));
4022 unsigned long lit = 0L;
4024 /* if the left side is a literal or
4025 if the right is in a pointer register and left
4027 if ((AOP_TYPE (left) == AOP_LIT) ||
4028 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4034 if (AOP_TYPE (right) == AOP_LIT)
4035 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4037 /* if the right side is a literal then anything goes */
4038 if (AOP_TYPE (right) == AOP_LIT &&
4039 AOP_TYPE (left) != AOP_DIR)
4043 emitcode ("cjne", "%s,%s,%05d$",
4044 aopGet (AOP (left), offset, FALSE, FALSE),
4045 aopGet (AOP (right), offset, FALSE, FALSE),
4051 /* if the right side is in a register or in direct space or
4052 if the left is a pointer register & right is not */
4053 else if (AOP_TYPE (right) == AOP_REG ||
4054 AOP_TYPE (right) == AOP_DIR ||
4055 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
4056 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
4060 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4061 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
4062 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
4063 emitcode ("jnz", "%05d$", lbl->key + 100);
4065 emitcode ("cjne", "a,%s,%05d$",
4066 aopGet (AOP (right), offset, FALSE, TRUE),
4073 /* right is a pointer reg need both a & b */
4076 char *l = aopGet (AOP (left), offset, FALSE, FALSE);
4077 if (strcmp (l, "b"))
4078 emitcode ("mov", "b,%s", l);
4079 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4080 emitcode ("cjne", "a,b,%05d$", lbl->key + 100);
4086 /*-----------------------------------------------------------------*/
4087 /* gencjne - compare and jump if not equal */
4088 /*-----------------------------------------------------------------*/
4090 gencjne (operand * left, operand * right, symbol * lbl)
4092 symbol *tlbl = newiTempLabel (NULL);
4094 gencjneshort (left, right, lbl);
4096 emitcode ("mov", "a,%s", one);
4097 emitcode ("sjmp", "%05d$", tlbl->key + 100);
4098 emitcode ("", "%05d$:", lbl->key + 100);
4099 emitcode ("clr", "a");
4100 emitcode ("", "%05d$:", tlbl->key + 100);
4103 /*-----------------------------------------------------------------*/
4104 /* genCmpEq - generates code for equal to */
4105 /*-----------------------------------------------------------------*/
4107 genCmpEq (iCode * ic, iCode * ifx)
4109 operand *left, *right, *result;
4111 D(emitcode (";", "genCmpEq"));
4113 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4114 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4115 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4117 /* if literal, literal on the right or
4118 if the right is in a pointer register and left
4120 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
4121 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
4123 operand *t = IC_RIGHT (ic);
4124 IC_RIGHT (ic) = IC_LEFT (ic);
4128 if (ifx && !AOP_SIZE (result))
4131 /* if they are both bit variables */
4132 if (AOP_TYPE (left) == AOP_CRY &&
4133 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4135 if (AOP_TYPE (right) == AOP_LIT)
4137 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4140 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4141 emitcode ("cpl", "c");
4145 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4149 emitcode ("clr", "c");
4151 /* AOP_TYPE(right) == AOP_CRY */
4155 symbol *lbl = newiTempLabel (NULL);
4156 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4157 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4158 emitcode ("cpl", "c");
4159 emitcode ("", "%05d$:", (lbl->key + 100));
4161 /* if true label then we jump if condition
4163 tlbl = newiTempLabel (NULL);
4166 emitcode ("jnc", "%05d$", tlbl->key + 100);
4167 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4171 emitcode ("jc", "%05d$", tlbl->key + 100);
4172 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4174 emitcode ("", "%05d$:", tlbl->key + 100);
4178 tlbl = newiTempLabel (NULL);
4179 gencjneshort (left, right, tlbl);
4182 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
4183 emitcode ("", "%05d$:", tlbl->key + 100);
4187 symbol *lbl = newiTempLabel (NULL);
4188 emitcode ("sjmp", "%05d$", lbl->key + 100);
4189 emitcode ("", "%05d$:", tlbl->key + 100);
4190 emitcode ("ljmp", "%05d$", IC_FALSE (ifx)->key + 100);
4191 emitcode ("", "%05d$:", lbl->key + 100);
4194 /* mark the icode as generated */
4199 /* if they are both bit variables */
4200 if (AOP_TYPE (left) == AOP_CRY &&
4201 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
4203 if (AOP_TYPE (right) == AOP_LIT)
4205 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4208 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4209 emitcode ("cpl", "c");
4213 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4217 emitcode ("clr", "c");
4219 /* AOP_TYPE(right) == AOP_CRY */
4223 symbol *lbl = newiTempLabel (NULL);
4224 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4225 emitcode ("jb", "%s,%05d$", AOP (right)->aopu.aop_dir, (lbl->key + 100));
4226 emitcode ("cpl", "c");
4227 emitcode ("", "%05d$:", (lbl->key + 100));
4230 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4237 genIfxJump (ifx, "c");
4240 /* if the result is used in an arithmetic operation
4241 then put the result in place */
4246 gencjne (left, right, newiTempLabel (NULL));
4247 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
4249 aopPut (AOP (result), "a", 0);
4254 genIfxJump (ifx, "a");
4257 /* if the result is used in an arithmetic operation
4258 then put the result in place */
4259 if (AOP_TYPE (result) != AOP_CRY)
4261 /* leave the result in acc */
4265 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4266 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4267 freeAsmop (result, NULL, ic, TRUE);
4270 /*-----------------------------------------------------------------*/
4271 /* ifxForOp - returns the icode containing the ifx for operand */
4272 /*-----------------------------------------------------------------*/
4274 ifxForOp (operand * op, iCode * ic)
4276 /* if true symbol then needs to be assigned */
4277 if (IS_TRUE_SYMOP (op))
4280 /* if this has register type condition and
4281 the next instruction is ifx with the same operand
4282 and live to of the operand is upto the ifx only then */
4284 ic->next->op == IFX &&
4285 IC_COND (ic->next)->key == op->key &&
4286 OP_SYMBOL (op)->liveTo <= ic->next->seq)
4292 /*-----------------------------------------------------------------*/
4293 /* hasInc - operand is incremented before any other use */
4294 /*-----------------------------------------------------------------*/
4296 hasInc (operand *op, iCode *ic)
4298 sym_link *type = operandType(op);
4299 sym_link *retype = getSpec (type);
4300 iCode *lic = ic->next;
4303 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
4304 if (!IS_SYMOP(op)) return NULL;
4306 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
4307 isize = getSize(type->next);
4309 /* if operand of the form op = op + <sizeof *op> */
4310 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
4311 isOperandEqual(IC_RESULT(lic),op) &&
4312 isOperandLiteral(IC_RIGHT(lic)) &&
4313 operandLitValue(IC_RIGHT(lic)) == isize) {
4316 /* if the operand used or deffed */
4317 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
4320 /* if GOTO or IFX */
4321 if (lic->op == IFX || lic->op == GOTO) break;
4327 /*-----------------------------------------------------------------*/
4328 /* genAndOp - for && operation */
4329 /*-----------------------------------------------------------------*/
4331 genAndOp (iCode * ic)
4333 operand *left, *right, *result;
4336 D(emitcode (";", "genAndOp"));
4338 /* note here that && operations that are in an
4339 if statement are taken away by backPatchLabels
4340 only those used in arthmetic operations remain */
4341 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4342 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4343 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4345 /* if both are bit variables */
4346 if (AOP_TYPE (left) == AOP_CRY &&
4347 AOP_TYPE (right) == AOP_CRY)
4349 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4350 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4355 tlbl = newiTempLabel (NULL);
4357 emitcode ("jz", "%05d$", tlbl->key + 100);
4359 emitcode ("", "%05d$:", tlbl->key + 100);
4363 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4364 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4365 freeAsmop (result, NULL, ic, TRUE);
4369 /*-----------------------------------------------------------------*/
4370 /* genOrOp - for || operation */
4371 /*-----------------------------------------------------------------*/
4373 genOrOp (iCode * ic)
4375 operand *left, *right, *result;
4378 D(emitcode (";", "genOrOp"));
4380 /* note here that || operations that are in an
4381 if statement are taken away by backPatchLabels
4382 only those used in arthmetic operations remain */
4383 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4384 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4385 aopOp ((result = IC_RESULT (ic)), ic, FALSE);
4387 /* if both are bit variables */
4388 if (AOP_TYPE (left) == AOP_CRY &&
4389 AOP_TYPE (right) == AOP_CRY)
4391 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4392 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
4397 tlbl = newiTempLabel (NULL);
4399 emitcode ("jnz", "%05d$", tlbl->key + 100);
4401 emitcode ("", "%05d$:", tlbl->key + 100);
4405 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4406 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4407 freeAsmop (result, NULL, ic, TRUE);
4410 /*-----------------------------------------------------------------*/
4411 /* isLiteralBit - test if lit == 2^n */
4412 /*-----------------------------------------------------------------*/
4414 isLiteralBit (unsigned long lit)
4416 unsigned long pw[32] =
4417 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
4418 0x100L, 0x200L, 0x400L, 0x800L,
4419 0x1000L, 0x2000L, 0x4000L, 0x8000L,
4420 0x10000L, 0x20000L, 0x40000L, 0x80000L,
4421 0x100000L, 0x200000L, 0x400000L, 0x800000L,
4422 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
4423 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
4426 for (idx = 0; idx < 32; idx++)
4432 /*-----------------------------------------------------------------*/
4433 /* continueIfTrue - */
4434 /*-----------------------------------------------------------------*/
4436 continueIfTrue (iCode * ic)
4439 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4443 /*-----------------------------------------------------------------*/
4445 /*-----------------------------------------------------------------*/
4447 jumpIfTrue (iCode * ic)
4450 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4454 /*-----------------------------------------------------------------*/
4455 /* jmpTrueOrFalse - */
4456 /*-----------------------------------------------------------------*/
4458 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
4460 // ugly but optimized by peephole
4463 symbol *nlbl = newiTempLabel (NULL);
4464 emitcode ("sjmp", "%05d$", nlbl->key + 100);
4465 emitcode ("", "%05d$:", tlbl->key + 100);
4466 emitcode ("ljmp", "%05d$", IC_TRUE (ic)->key + 100);
4467 emitcode ("", "%05d$:", nlbl->key + 100);
4471 emitcode ("ljmp", "%05d$", IC_FALSE (ic)->key + 100);
4472 emitcode ("", "%05d$:", tlbl->key + 100);
4477 /*-----------------------------------------------------------------*/
4478 /* genAnd - code for and */
4479 /*-----------------------------------------------------------------*/
4481 genAnd (iCode * ic, iCode * ifx)
4483 operand *left, *right, *result;
4484 int size, offset = 0;
4485 unsigned long lit = 0L;
4489 D(emitcode (";", "genAnd"));
4491 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4492 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4493 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4496 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4498 AOP_TYPE (left), AOP_TYPE (right));
4499 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4501 AOP_SIZE (left), AOP_SIZE (right));
4504 /* if left is a literal & right is not then exchange them */
4505 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4506 AOP_NEEDSACC (left))
4508 operand *tmp = right;
4513 /* if result = right then exchange them */
4514 if (sameRegs (AOP (result), AOP (right)))
4516 operand *tmp = right;
4521 /* if right is bit then exchange them */
4522 if (AOP_TYPE (right) == AOP_CRY &&
4523 AOP_TYPE (left) != AOP_CRY)
4525 operand *tmp = right;
4529 if (AOP_TYPE (right) == AOP_LIT)
4530 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4532 size = AOP_SIZE (result);
4535 // result = bit & yy;
4536 if (AOP_TYPE (left) == AOP_CRY)
4538 // c = bit & literal;
4539 if (AOP_TYPE (right) == AOP_LIT)
4543 if (size && sameRegs (AOP (result), AOP (left)))
4546 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4551 if (size && (AOP_TYPE (result) == AOP_CRY))
4553 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
4556 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4561 emitcode ("clr", "c");
4566 if (AOP_TYPE (right) == AOP_CRY)
4569 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4570 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4575 MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
4577 emitcode ("rrc", "a");
4578 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
4586 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4587 genIfxJump (ifx, "c");
4591 // if(val & 0xZZ) - size = 0, ifx != FALSE -
4592 // bit = val & 0xZZ - size = 1, ifx = FALSE -
4593 if ((AOP_TYPE (right) == AOP_LIT) &&
4594 (AOP_TYPE (result) == AOP_CRY) &&
4595 (AOP_TYPE (left) != AOP_CRY))
4597 int posbit = isLiteralBit (lit);
4602 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE));
4605 emitcode ("mov", "c,acc.%d", posbit & 0x07);
4611 sprintf (buffer, "acc.%d", posbit & 0x07);
4612 genIfxJump (ifx, buffer);
4619 symbol *tlbl = newiTempLabel (NULL);
4620 int sizel = AOP_SIZE (left);
4622 emitcode ("setb", "c");
4625 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
4627 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
4629 if ((posbit = isLiteralBit (bytelit)) != 0)
4630 emitcode ("jb", "acc.%d,%05d$", (posbit - 1) & 0x07, tlbl->key + 100);
4633 if (bytelit != 0x0FFL)
4634 emitcode ("anl", "a,%s",
4635 aopGet (AOP (right), offset, FALSE, TRUE));
4636 emitcode ("jnz", "%05d$", tlbl->key + 100);
4641 // bit = left & literal
4644 emitcode ("clr", "c");
4645 emitcode ("", "%05d$:", tlbl->key + 100);
4647 // if(left & literal)
4651 jmpTrueOrFalse (ifx, tlbl);
4659 /* if left is same as result */
4660 if (sameRegs (AOP (result), AOP (left)))
4662 for (; size--; offset++)
4664 if (AOP_TYPE (right) == AOP_LIT)
4666 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4668 else if (bytelit == 0)
4669 aopPut (AOP (result), zero, offset);
4670 else if (IS_AOP_PREG (result))
4672 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4673 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4674 aopPut (AOP (result), "a", offset);
4677 emitcode ("anl", "%s,%s",
4678 aopGet (AOP (left), offset, FALSE, TRUE),
4679 aopGet (AOP (right), offset, FALSE, FALSE));
4683 if (AOP_TYPE (left) == AOP_ACC)
4684 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4687 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4688 if (IS_AOP_PREG (result))
4690 emitcode ("anl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4691 aopPut (AOP (result), "a", offset);
4695 emitcode ("anl", "%s,a",
4696 aopGet (AOP (left), offset, FALSE, TRUE));
4703 // left & result in different registers
4704 if (AOP_TYPE (result) == AOP_CRY)
4707 // if(size), result in bit
4708 // if(!size && ifx), conditional oper: if(left & right)
4709 symbol *tlbl = newiTempLabel (NULL);
4710 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
4712 emitcode ("setb", "c");
4715 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4716 emitcode ("anl", "a,%s",
4717 aopGet (AOP (right), offset, FALSE, FALSE));
4719 if (AOP_TYPE(left)==AOP_ACC) {
4720 emitcode("mov", "b,a");
4721 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4722 emitcode("anl", "a,b");
4724 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4725 emitcode ("anl", "a,%s",
4726 aopGet (AOP (left), offset, FALSE, FALSE));
4729 emitcode ("jnz", "%05d$", tlbl->key + 100);
4735 emitcode ("", "%05d$:", tlbl->key + 100);
4739 jmpTrueOrFalse (ifx, tlbl);
4743 for (; (size--); offset++)
4746 // result = left & right
4747 if (AOP_TYPE (right) == AOP_LIT)
4749 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
4751 aopPut (AOP (result),
4752 aopGet (AOP (left), offset, FALSE, FALSE),
4756 else if (bytelit == 0)
4758 aopPut (AOP (result), zero, offset);
4762 // faster than result <- left, anl result,right
4763 // and better if result is SFR
4764 if (AOP_TYPE (left) == AOP_ACC)
4765 emitcode ("anl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4768 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4769 emitcode ("anl", "a,%s",
4770 aopGet (AOP (left), offset, FALSE, FALSE));
4772 aopPut (AOP (result), "a", offset);
4778 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4779 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4780 freeAsmop (result, NULL, ic, TRUE);
4783 /*-----------------------------------------------------------------*/
4784 /* genOr - code for or */
4785 /*-----------------------------------------------------------------*/
4787 genOr (iCode * ic, iCode * ifx)
4789 operand *left, *right, *result;
4790 int size, offset = 0;
4791 unsigned long lit = 0L;
4793 D(emitcode (";", "genOr"));
4795 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
4796 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
4797 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
4800 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
4802 AOP_TYPE (left), AOP_TYPE (right));
4803 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
4805 AOP_SIZE (left), AOP_SIZE (right));
4808 /* if left is a literal & right is not then exchange them */
4809 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
4810 AOP_NEEDSACC (left))
4812 operand *tmp = right;
4817 /* if result = right then exchange them */
4818 if (sameRegs (AOP (result), AOP (right)))
4820 operand *tmp = right;
4825 /* if right is bit then exchange them */
4826 if (AOP_TYPE (right) == AOP_CRY &&
4827 AOP_TYPE (left) != AOP_CRY)
4829 operand *tmp = right;
4833 if (AOP_TYPE (right) == AOP_LIT)
4834 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
4836 size = AOP_SIZE (result);
4840 if (AOP_TYPE (left) == AOP_CRY)
4842 if (AOP_TYPE (right) == AOP_LIT)
4844 // c = bit & literal;
4847 // lit != 0 => result = 1
4848 if (AOP_TYPE (result) == AOP_CRY)
4851 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4853 continueIfTrue (ifx);
4856 emitcode ("setb", "c");
4860 // lit == 0 => result = left
4861 if (size && sameRegs (AOP (result), AOP (left)))
4863 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4868 if (AOP_TYPE (right) == AOP_CRY)
4871 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
4872 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
4877 symbol *tlbl = newiTempLabel (NULL);
4878 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
4879 emitcode ("setb", "c");
4880 emitcode ("jb", "%s,%05d$",
4881 AOP (left)->aopu.aop_dir, tlbl->key + 100);
4883 emitcode ("jnz", "%05d$", tlbl->key + 100);
4884 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4886 jmpTrueOrFalse (ifx, tlbl);
4892 emitcode ("", "%05d$:", tlbl->key + 100);
4901 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
4902 genIfxJump (ifx, "c");
4906 // if(val | 0xZZ) - size = 0, ifx != FALSE -
4907 // bit = val | 0xZZ - size = 1, ifx = FALSE -
4908 if ((AOP_TYPE (right) == AOP_LIT) &&
4909 (AOP_TYPE (result) == AOP_CRY) &&
4910 (AOP_TYPE (left) != AOP_CRY))
4916 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
4918 continueIfTrue (ifx);
4923 // lit = 0, result = boolean(left)
4925 emitcode ("setb", "c");
4929 symbol *tlbl = newiTempLabel (NULL);
4930 emitcode ("jnz", "%05d$", tlbl->key + 100);
4932 emitcode ("", "%05d$:", tlbl->key + 100);
4936 genIfxJump (ifx, "a");
4944 /* if left is same as result */
4945 if (sameRegs (AOP (result), AOP (left)))
4947 for (; size--; offset++)
4949 if (AOP_TYPE (right) == AOP_LIT)
4951 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
4953 else if (IS_AOP_PREG (left))
4955 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4956 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4957 aopPut (AOP (result), "a", offset);
4960 emitcode ("orl", "%s,%s",
4961 aopGet (AOP (left), offset, FALSE, TRUE),
4962 aopGet (AOP (right), offset, FALSE, FALSE));
4966 if (AOP_TYPE (left) == AOP_ACC)
4967 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
4970 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
4971 if (IS_AOP_PREG (left))
4973 emitcode ("orl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
4974 aopPut (AOP (result), "a", offset);
4977 emitcode ("orl", "%s,a",
4978 aopGet (AOP (left), offset, FALSE, TRUE));
4985 // left & result in different registers
4986 if (AOP_TYPE (result) == AOP_CRY)
4989 // if(size), result in bit
4990 // if(!size && ifx), conditional oper: if(left | right)
4991 symbol *tlbl = newiTempLabel (NULL);
4992 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
4994 emitcode ("setb", "c");
4997 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
4998 emitcode ("orl", "a,%s",
4999 aopGet (AOP (right), offset, FALSE, FALSE));
5001 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5002 emitcode ("orl", "a,%s",
5003 aopGet (AOP (left), offset, FALSE, FALSE));
5005 emitcode ("jnz", "%05d$", tlbl->key + 100);
5011 emitcode ("", "%05d$:", tlbl->key + 100);
5015 jmpTrueOrFalse (ifx, tlbl);
5018 for (; (size--); offset++)
5021 // result = left & right
5022 if (AOP_TYPE (right) == AOP_LIT)
5024 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5026 aopPut (AOP (result),
5027 aopGet (AOP (left), offset, FALSE, FALSE),
5032 // faster than result <- left, anl result,right
5033 // and better if result is SFR
5034 if (AOP_TYPE (left) == AOP_ACC)
5035 emitcode ("orl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5038 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5039 emitcode ("orl", "a,%s",
5040 aopGet (AOP (left), offset, FALSE, FALSE));
5042 aopPut (AOP (result), "a", offset);
5047 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5048 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5049 freeAsmop (result, NULL, ic, TRUE);
5052 /*-----------------------------------------------------------------*/
5053 /* genXor - code for xclusive or */
5054 /*-----------------------------------------------------------------*/
5056 genXor (iCode * ic, iCode * ifx)
5058 operand *left, *right, *result;
5059 int size, offset = 0;
5060 unsigned long lit = 0L;
5062 D(emitcode (";", "genXor"));
5064 aopOp ((left = IC_LEFT (ic)), ic, FALSE);
5065 aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
5066 aopOp ((result = IC_RESULT (ic)), ic, TRUE);
5069 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
5071 AOP_TYPE (left), AOP_TYPE (right));
5072 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
5074 AOP_SIZE (left), AOP_SIZE (right));
5077 /* if left is a literal & right is not ||
5078 if left needs acc & right does not */
5079 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
5080 (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
5082 operand *tmp = right;
5087 /* if result = right then exchange them */
5088 if (sameRegs (AOP (result), AOP (right)))
5090 operand *tmp = right;
5095 /* if right is bit then exchange them */
5096 if (AOP_TYPE (right) == AOP_CRY &&
5097 AOP_TYPE (left) != AOP_CRY)
5099 operand *tmp = right;
5103 if (AOP_TYPE (right) == AOP_LIT)
5104 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5106 size = AOP_SIZE (result);
5110 if (AOP_TYPE (left) == AOP_CRY)
5112 if (AOP_TYPE (right) == AOP_LIT)
5114 // c = bit & literal;
5117 // lit>>1 != 0 => result = 1
5118 if (AOP_TYPE (result) == AOP_CRY)
5121 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
5123 continueIfTrue (ifx);
5126 emitcode ("setb", "c");
5133 // lit == 0, result = left
5134 if (size && sameRegs (AOP (result), AOP (left)))
5136 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5140 // lit == 1, result = not(left)
5141 if (size && sameRegs (AOP (result), AOP (left)))
5143 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
5148 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5149 emitcode ("cpl", "c");
5158 symbol *tlbl = newiTempLabel (NULL);
5159 if (AOP_TYPE (right) == AOP_CRY)
5162 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5166 int sizer = AOP_SIZE (right);
5168 // if val>>1 != 0, result = 1
5169 emitcode ("setb", "c");
5172 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE));
5174 // test the msb of the lsb
5175 emitcode ("anl", "a,#0xfe");
5176 emitcode ("jnz", "%05d$", tlbl->key + 100);
5180 emitcode ("rrc", "a");
5182 emitcode ("jnb", "%s,%05d$", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
5183 emitcode ("cpl", "c");
5184 emitcode ("", "%05d$:", (tlbl->key + 100));
5191 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
5192 genIfxJump (ifx, "c");
5196 if (sameRegs (AOP (result), AOP (left)))
5198 /* if left is same as result */
5199 for (; size--; offset++)
5201 if (AOP_TYPE (right) == AOP_LIT)
5203 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5205 else if (IS_AOP_PREG (left))
5207 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5208 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5209 aopPut (AOP (result), "a", offset);
5212 emitcode ("xrl", "%s,%s",
5213 aopGet (AOP (left), offset, FALSE, TRUE),
5214 aopGet (AOP (right), offset, FALSE, FALSE));
5218 if (AOP_TYPE (left) == AOP_ACC)
5219 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5222 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5223 if (IS_AOP_PREG (left))
5225 emitcode ("xrl", "a,%s", aopGet (AOP (left), offset, FALSE, TRUE));
5226 aopPut (AOP (result), "a", offset);
5229 emitcode ("xrl", "%s,a",
5230 aopGet (AOP (left), offset, FALSE, TRUE));
5237 // left & result in different registers
5238 if (AOP_TYPE (result) == AOP_CRY)
5241 // if(size), result in bit
5242 // if(!size && ifx), conditional oper: if(left ^ right)
5243 symbol *tlbl = newiTempLabel (NULL);
5244 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
5246 emitcode ("setb", "c");
5249 if ((AOP_TYPE (right) == AOP_LIT) &&
5250 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
5252 MOVA (aopGet (AOP (left), offset, FALSE, FALSE));
5256 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
5257 emitcode ("xrl", "a,%s",
5258 aopGet (AOP (right), offset, FALSE, FALSE));
5260 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5261 emitcode ("xrl", "a,%s",
5262 aopGet (AOP (left), offset, FALSE, FALSE));
5265 emitcode ("jnz", "%05d$", tlbl->key + 100);
5271 emitcode ("", "%05d$:", tlbl->key + 100);
5275 jmpTrueOrFalse (ifx, tlbl);
5278 for (; (size--); offset++)
5281 // result = left & right
5282 if (AOP_TYPE (right) == AOP_LIT)
5284 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
5286 aopPut (AOP (result),
5287 aopGet (AOP (left), offset, FALSE, FALSE),
5292 // faster than result <- left, anl result,right
5293 // and better if result is SFR
5294 if (AOP_TYPE (left) == AOP_ACC)
5295 emitcode ("xrl", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE));
5298 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
5299 emitcode ("xrl", "a,%s",
5300 aopGet (AOP (left), offset, FALSE, TRUE));
5302 aopPut (AOP (result), "a", offset);
5307 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5308 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5309 freeAsmop (result, NULL, ic, TRUE);
5312 /*-----------------------------------------------------------------*/
5313 /* genInline - write the inline code out */
5314 /*-----------------------------------------------------------------*/
5316 genInline (iCode * ic)
5318 char *buffer, *bp, *bp1;
5320 D(emitcode (";", "genInline"));
5322 _G.inLine += (!options.asmpeep);
5324 buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
5325 strcpy (buffer, IC_INLINE (ic));
5327 /* emit each line as a code */
5352 /* emitcode("",buffer); */
5353 _G.inLine -= (!options.asmpeep);
5356 /*-----------------------------------------------------------------*/
5357 /* genRRC - rotate right with carry */
5358 /*-----------------------------------------------------------------*/
5362 operand *left, *result;
5363 int size, offset = 0;
5366 D(emitcode (";", "genRRC"));
5368 /* rotate right with carry */
5369 left = IC_LEFT (ic);
5370 result = IC_RESULT (ic);
5371 aopOp (left, ic, FALSE);
5372 aopOp (result, ic, FALSE);
5374 /* move it to the result */
5375 size = AOP_SIZE (result);
5377 if (size == 1) { /* special case for 1 byte */
5378 l = aopGet (AOP (left), offset, FALSE, FALSE);
5380 emitcode ("rr", "a");
5386 l = aopGet (AOP (left), offset, FALSE, FALSE);
5388 emitcode ("rrc", "a");
5389 if (AOP_SIZE (result) > 1)
5390 aopPut (AOP (result), "a", offset--);
5392 /* now we need to put the carry into the
5393 highest order byte of the result */
5394 if (AOP_SIZE (result) > 1)
5396 l = aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE);
5399 emitcode ("mov", "acc.7,c");
5401 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
5402 freeAsmop (left, NULL, ic, TRUE);
5403 freeAsmop (result, NULL, ic, TRUE);
5406 /*-----------------------------------------------------------------*/
5407 /* genRLC - generate code for rotate left with carry */
5408 /*-----------------------------------------------------------------*/
5412 operand *left, *result;
5413 int size, offset = 0;
5416 D(emitcode (";", "genRLC"));
5418 /* rotate right with carry */
5419 left = IC_LEFT (ic);
5420 result = IC_RESULT (ic);
5421 aopOp (left, ic, FALSE);
5422 aopOp (result, ic, FALSE);
5424 /* move it to the result */
5425 size = AOP_SIZE (result);
5429 l = aopGet (AOP (left), offset, FALSE, FALSE);
5431 if (size == 0) { /* special case for 1 byte */
5435 emitcode ("add", "a,acc");
5436 if (AOP_SIZE (result) > 1)
5437 aopPut (AOP (result), "a", offset++);
5440 l = aopGet (AOP (left), offset, FALSE, FALSE);
5442 emitcode ("rlc", "a");
5443 if (AOP_SIZE (result) > 1)
5444 aopPut (AOP (result), "a", offset++);
5447 /* now we need to put the carry into the
5448 highest order byte of the result */
5449 if (AOP_SIZE (result) > 1)
5451 l = aopGet (AOP (result), 0, FALSE, FALSE);
5454 emitcode ("mov", "acc.0,c");
5456 aopPut (AOP (result), "a", 0);
5457 freeAsmop (left, NULL, ic, TRUE);
5458 freeAsmop (result, NULL, ic, TRUE);
5461 /*-----------------------------------------------------------------*/
5462 /* genGetHbit - generates code get highest order bit */
5463 /*-----------------------------------------------------------------*/
5465 genGetHbit (iCode * ic)
5467 operand *left, *result;
5469 D(emitcode (";", "genGetHbit"));
5471 left = IC_LEFT (ic);
5472 result = IC_RESULT (ic);
5473 aopOp (left, ic, FALSE);
5474 aopOp (result, ic, FALSE);
5476 /* get the highest order byte into a */
5477 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE));
5478 if (AOP_TYPE (result) == AOP_CRY)
5480 emitcode ("rlc", "a");
5485 emitcode ("rl", "a");
5486 emitcode ("anl", "a,#0x01");
5491 freeAsmop (left, NULL, ic, TRUE);
5492 freeAsmop (result, NULL, ic, TRUE);
5495 /*-----------------------------------------------------------------*/
5496 /* AccRol - rotate left accumulator by known count */
5497 /*-----------------------------------------------------------------*/
5499 AccRol (int shCount)
5501 shCount &= 0x0007; // shCount : 0..7
5508 emitcode ("rl", "a");
5511 emitcode ("rl", "a");
5512 emitcode ("rl", "a");
5515 emitcode ("swap", "a");
5516 emitcode ("rr", "a");
5519 emitcode ("swap", "a");
5522 emitcode ("swap", "a");
5523 emitcode ("rl", "a");
5526 emitcode ("rr", "a");
5527 emitcode ("rr", "a");
5530 emitcode ("rr", "a");
5535 /*-----------------------------------------------------------------*/
5536 /* AccLsh - left shift accumulator by known count */
5537 /*-----------------------------------------------------------------*/
5539 AccLsh (int shCount)
5544 emitcode ("add", "a,acc");
5545 else if (shCount == 2)
5547 emitcode ("add", "a,acc");
5548 emitcode ("add", "a,acc");
5552 /* rotate left accumulator */
5554 /* and kill the lower order bits */
5555 emitcode ("anl", "a,#0x%02x", SLMask[shCount]);
5560 /*-----------------------------------------------------------------*/
5561 /* AccRsh - right shift accumulator by known count */
5562 /*-----------------------------------------------------------------*/
5564 AccRsh (int shCount)
5571 emitcode ("rrc", "a");
5575 /* rotate right accumulator */
5576 AccRol (8 - shCount);
5577 /* and kill the higher order bits */
5578 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5583 /*-----------------------------------------------------------------*/
5584 /* AccSRsh - signed right shift accumulator by known count */
5585 /*-----------------------------------------------------------------*/
5587 AccSRsh (int shCount)
5594 emitcode ("mov", "c,acc.7");
5595 emitcode ("rrc", "a");
5597 else if (shCount == 2)
5599 emitcode ("mov", "c,acc.7");
5600 emitcode ("rrc", "a");
5601 emitcode ("mov", "c,acc.7");
5602 emitcode ("rrc", "a");
5606 tlbl = newiTempLabel (NULL);
5607 /* rotate right accumulator */
5608 AccRol (8 - shCount);
5609 /* and kill the higher order bits */
5610 emitcode ("anl", "a,#0x%02x", SRMask[shCount]);
5611 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5612 emitcode ("orl", "a,#0x%02x",
5613 (unsigned char) ~SRMask[shCount]);
5614 emitcode ("", "%05d$:", tlbl->key + 100);
5619 /*-----------------------------------------------------------------*/
5620 /* shiftR1Left2Result - shift right one byte from left to result */
5621 /*-----------------------------------------------------------------*/
5623 shiftR1Left2Result (operand * left, int offl,
5624 operand * result, int offr,
5625 int shCount, int sign)
5627 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5628 /* shift right accumulator */
5633 aopPut (AOP (result), "a", offr);
5636 /*-----------------------------------------------------------------*/
5637 /* shiftL1Left2Result - shift left one byte from left to result */
5638 /*-----------------------------------------------------------------*/
5640 shiftL1Left2Result (operand * left, int offl,
5641 operand * result, int offr, int shCount)
5644 l = aopGet (AOP (left), offl, FALSE, FALSE);
5646 /* shift left accumulator */
5648 aopPut (AOP (result), "a", offr);
5651 /*-----------------------------------------------------------------*/
5652 /* movLeft2Result - move byte from left to result */
5653 /*-----------------------------------------------------------------*/
5655 movLeft2Result (operand * left, int offl,
5656 operand * result, int offr, int sign)
5659 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
5661 l = aopGet (AOP (left), offl, FALSE, FALSE);
5663 if (*l == '@' && (IS_AOP_PREG (result)))
5665 emitcode ("mov", "a,%s", l);
5666 aopPut (AOP (result), "a", offr);
5671 aopPut (AOP (result), l, offr);
5674 /* MSB sign in acc.7 ! */
5675 if (getDataSize (left) == offl + 1)
5677 emitcode ("mov", "a,%s", l);
5678 aopPut (AOP (result), "a", offr);
5685 /*-----------------------------------------------------------------*/
5686 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
5687 /*-----------------------------------------------------------------*/
5691 emitcode ("rrc", "a");
5692 emitcode ("xch", "a,%s", x);
5693 emitcode ("rrc", "a");
5694 emitcode ("xch", "a,%s", x);
5697 /*-----------------------------------------------------------------*/
5698 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
5699 /*-----------------------------------------------------------------*/
5703 emitcode ("xch", "a,%s", x);
5704 emitcode ("rlc", "a");
5705 emitcode ("xch", "a,%s", x);
5706 emitcode ("rlc", "a");
5709 /*-----------------------------------------------------------------*/
5710 /* AccAXLsh1 - left shift a:x<-0 by 1 */
5711 /*-----------------------------------------------------------------*/
5715 emitcode ("xch", "a,%s", x);
5716 emitcode ("add", "a,acc");
5717 emitcode ("xch", "a,%s", x);
5718 emitcode ("rlc", "a");
5721 /*-----------------------------------------------------------------*/
5722 /* AccAXLsh - left shift a:x by known count (0..7) */
5723 /*-----------------------------------------------------------------*/
5725 AccAXLsh (char *x, int shCount)
5740 case 5: // AAAAABBB:CCCCCDDD
5742 AccRol (shCount); // BBBAAAAA:CCCCCDDD
5744 emitcode ("anl", "a,#0x%02x",
5745 SLMask[shCount]); // BBB00000:CCCCCDDD
5747 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
5749 AccRol (shCount); // DDDCCCCC:BBB00000
5751 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
5753 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
5755 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
5757 emitcode ("anl", "a,#0x%02x",
5758 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
5760 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
5762 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
5765 case 6: // AAAAAABB:CCCCCCDD
5766 emitcode ("anl", "a,#0x%02x",
5767 SRMask[shCount]); // 000000BB:CCCCCCDD
5768 emitcode ("mov", "c,acc.0"); // c = B
5769 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
5771 AccAXRrl1 (x); // BCCCCCCD:D000000B
5772 AccAXRrl1 (x); // BBCCCCCC:DD000000
5774 emitcode("rrc","a");
5775 emitcode("xch","a,%s", x);
5776 emitcode("rrc","a");
5777 emitcode("mov","c,acc.0"); //<< get correct bit
5778 emitcode("xch","a,%s", x);
5780 emitcode("rrc","a");
5781 emitcode("xch","a,%s", x);
5782 emitcode("rrc","a");
5783 emitcode("xch","a,%s", x);
5786 case 7: // a:x <<= 7
5788 emitcode ("anl", "a,#0x%02x",
5789 SRMask[shCount]); // 0000000B:CCCCCCCD
5791 emitcode ("mov", "c,acc.0"); // c = B
5793 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
5795 AccAXRrl1 (x); // BCCCCCCC:D0000000
5803 /*-----------------------------------------------------------------*/
5804 /* AccAXRsh - right shift a:x known count (0..7) */
5805 /*-----------------------------------------------------------------*/
5807 AccAXRsh (char *x, int shCount)
5815 AccAXRrl1 (x); // 0->a:x
5820 AccAXRrl1 (x); // 0->a:x
5823 AccAXRrl1 (x); // 0->a:x
5828 case 5: // AAAAABBB:CCCCCDDD = a:x
5830 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
5832 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5834 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5836 emitcode ("anl", "a,#0x%02x",
5837 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5839 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5841 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5843 emitcode ("anl", "a,#0x%02x",
5844 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5846 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5848 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5850 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
5853 case 6: // AABBBBBB:CCDDDDDD
5855 emitcode ("mov", "c,acc.7");
5856 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5858 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5860 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5862 emitcode ("anl", "a,#0x%02x",
5863 SRMask[shCount]); // 000000AA:BBBBBBCC
5866 case 7: // ABBBBBBB:CDDDDDDD
5868 emitcode ("mov", "c,acc.7"); // c = A
5870 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5872 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5874 emitcode ("anl", "a,#0x%02x",
5875 SRMask[shCount]); // 0000000A:BBBBBBBC
5883 /*-----------------------------------------------------------------*/
5884 /* AccAXRshS - right shift signed a:x known count (0..7) */
5885 /*-----------------------------------------------------------------*/
5887 AccAXRshS (char *x, int shCount)
5895 emitcode ("mov", "c,acc.7");
5896 AccAXRrl1 (x); // s->a:x
5900 emitcode ("mov", "c,acc.7");
5901 AccAXRrl1 (x); // s->a:x
5903 emitcode ("mov", "c,acc.7");
5904 AccAXRrl1 (x); // s->a:x
5909 case 5: // AAAAABBB:CCCCCDDD = a:x
5911 tlbl = newiTempLabel (NULL);
5912 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
5914 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
5916 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
5918 emitcode ("anl", "a,#0x%02x",
5919 SRMask[shCount]); // 000CCCCC:BBBAAAAA
5921 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
5923 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
5925 emitcode ("anl", "a,#0x%02x",
5926 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
5928 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
5930 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
5932 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
5934 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5935 emitcode ("orl", "a,#0x%02x",
5936 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
5938 emitcode ("", "%05d$:", tlbl->key + 100);
5939 break; // SSSSAAAA:BBBCCCCC
5941 case 6: // AABBBBBB:CCDDDDDD
5943 tlbl = newiTempLabel (NULL);
5944 emitcode ("mov", "c,acc.7");
5945 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
5947 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
5949 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
5951 emitcode ("anl", "a,#0x%02x",
5952 SRMask[shCount]); // 000000AA:BBBBBBCC
5954 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5955 emitcode ("orl", "a,#0x%02x",
5956 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
5958 emitcode ("", "%05d$:", tlbl->key + 100);
5960 case 7: // ABBBBBBB:CDDDDDDD
5962 tlbl = newiTempLabel (NULL);
5963 emitcode ("mov", "c,acc.7"); // c = A
5965 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
5967 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
5969 emitcode ("anl", "a,#0x%02x",
5970 SRMask[shCount]); // 0000000A:BBBBBBBC
5972 emitcode ("jnb", "acc.%d,%05d$", 7 - shCount, tlbl->key + 100);
5973 emitcode ("orl", "a,#0x%02x",
5974 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
5976 emitcode ("", "%05d$:", tlbl->key + 100);
5983 /*-----------------------------------------------------------------*/
5984 /* shiftL2Left2Result - shift left two bytes from left to result */
5985 /*-----------------------------------------------------------------*/
5987 shiftL2Left2Result (operand * left, int offl,
5988 operand * result, int offr, int shCount)
5990 if (sameRegs (AOP (result), AOP (left)) &&
5991 ((offl + MSB16) == offr))
5993 /* don't crash result[offr] */
5994 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
5995 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
5999 movLeft2Result (left, offl, result, offr, 0);
6000 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6002 /* ax << shCount (x = lsb(result)) */
6003 AccAXLsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6004 aopPut (AOP (result), "a", offr + MSB16);
6008 /*-----------------------------------------------------------------*/
6009 /* shiftR2Left2Result - shift right two bytes from left to result */
6010 /*-----------------------------------------------------------------*/
6012 shiftR2Left2Result (operand * left, int offl,
6013 operand * result, int offr,
6014 int shCount, int sign)
6016 if (sameRegs (AOP (result), AOP (left)) &&
6017 ((offl + MSB16) == offr))
6019 /* don't crash result[offr] */
6020 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6021 emitcode ("xch", "a,%s", aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6025 movLeft2Result (left, offl, result, offr, 0);
6026 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE));
6028 /* a:x >> shCount (x = lsb(result)) */
6030 AccAXRshS (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6032 AccAXRsh (aopGet (AOP (result), offr, FALSE, FALSE), shCount);
6033 if (getDataSize (result) > 1)
6034 aopPut (AOP (result), "a", offr + MSB16);
6037 /*-----------------------------------------------------------------*/
6038 /* shiftLLeftOrResult - shift left one byte from left, or to result */
6039 /*-----------------------------------------------------------------*/
6041 shiftLLeftOrResult (operand * left, int offl,
6042 operand * result, int offr, int shCount)
6044 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6045 /* shift left accumulator */
6047 /* or with result */
6048 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6049 /* back to result */
6050 aopPut (AOP (result), "a", offr);
6053 /*-----------------------------------------------------------------*/
6054 /* shiftRLeftOrResult - shift right one byte from left,or to result */
6055 /*-----------------------------------------------------------------*/
6057 shiftRLeftOrResult (operand * left, int offl,
6058 operand * result, int offr, int shCount)
6060 MOVA (aopGet (AOP (left), offl, FALSE, FALSE));
6061 /* shift right accumulator */
6063 /* or with result */
6064 emitcode ("orl", "a,%s", aopGet (AOP (result), offr, FALSE, FALSE));
6065 /* back to result */
6066 aopPut (AOP (result), "a", offr);
6069 /*-----------------------------------------------------------------*/
6070 /* genlshOne - left shift a one byte quantity by known count */
6071 /*-----------------------------------------------------------------*/
6073 genlshOne (operand * result, operand * left, int shCount)
6075 D(emitcode (";", "genlshOne"));
6077 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6080 /*-----------------------------------------------------------------*/
6081 /* genlshTwo - left shift two bytes by known amount != 0 */
6082 /*-----------------------------------------------------------------*/
6084 genlshTwo (operand * result, operand * left, int shCount)
6088 D(emitcode (";", "genlshTwo"));
6090 size = getDataSize (result);
6092 /* if shCount >= 8 */
6100 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6102 movLeft2Result (left, LSB, result, MSB16, 0);
6104 aopPut (AOP (result), zero, LSB);
6107 /* 1 <= shCount <= 7 */
6111 shiftL1Left2Result (left, LSB, result, LSB, shCount);
6113 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6117 /*-----------------------------------------------------------------*/
6118 /* shiftLLong - shift left one long from left to result */
6119 /* offl = LSB or MSB16 */
6120 /*-----------------------------------------------------------------*/
6122 shiftLLong (operand * left, operand * result, int offr)
6125 int size = AOP_SIZE (result);
6127 if (size >= LSB + offr)
6129 l = aopGet (AOP (left), LSB, FALSE, FALSE);
6131 emitcode ("add", "a,acc");
6132 if (sameRegs (AOP (left), AOP (result)) &&
6133 size >= MSB16 + offr && offr != LSB)
6134 emitcode ("xch", "a,%s",
6135 aopGet (AOP (left), LSB + offr, FALSE, FALSE));
6137 aopPut (AOP (result), "a", LSB + offr);
6140 if (size >= MSB16 + offr)
6142 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
6144 l = aopGet (AOP (left), MSB16, FALSE, FALSE);
6147 emitcode ("rlc", "a");
6148 if (sameRegs (AOP (left), AOP (result)) &&
6149 size >= MSB24 + offr && offr != LSB)
6150 emitcode ("xch", "a,%s",
6151 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE));
6153 aopPut (AOP (result), "a", MSB16 + offr);
6156 if (size >= MSB24 + offr)
6158 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
6160 l = aopGet (AOP (left), MSB24, FALSE, FALSE);
6163 emitcode ("rlc", "a");
6164 if (sameRegs (AOP (left), AOP (result)) &&
6165 size >= MSB32 + offr && offr != LSB)
6166 emitcode ("xch", "a,%s",
6167 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE));
6169 aopPut (AOP (result), "a", MSB24 + offr);
6172 if (size > MSB32 + offr)
6174 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
6176 l = aopGet (AOP (left), MSB32, FALSE, FALSE);
6179 emitcode ("rlc", "a");
6180 aopPut (AOP (result), "a", MSB32 + offr);
6183 aopPut (AOP (result), zero, LSB);
6186 /*-----------------------------------------------------------------*/
6187 /* genlshFour - shift four byte by a known amount != 0 */
6188 /*-----------------------------------------------------------------*/
6190 genlshFour (operand * result, operand * left, int shCount)
6194 D(emitcode (";", "genlshFour"));
6196 size = AOP_SIZE (result);
6198 /* if shifting more that 3 bytes */
6203 /* lowest order of left goes to the highest
6204 order of the destination */
6205 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
6207 movLeft2Result (left, LSB, result, MSB32, 0);
6208 aopPut (AOP (result), zero, LSB);
6209 aopPut (AOP (result), zero, MSB16);
6210 aopPut (AOP (result), zero, MSB24);
6214 /* more than two bytes */
6215 else if (shCount >= 16)
6217 /* lower order two bytes goes to higher order two bytes */
6219 /* if some more remaining */
6221 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
6224 movLeft2Result (left, MSB16, result, MSB32, 0);
6225 movLeft2Result (left, LSB, result, MSB24, 0);
6227 aopPut (AOP (result), zero, MSB16);
6228 aopPut (AOP (result), zero, LSB);
6232 /* if more than 1 byte */
6233 else if (shCount >= 8)
6235 /* lower order three bytes goes to higher order three bytes */
6240 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6242 movLeft2Result (left, LSB, result, MSB16, 0);
6248 movLeft2Result (left, MSB24, result, MSB32, 0);
6249 movLeft2Result (left, MSB16, result, MSB24, 0);
6250 movLeft2Result (left, LSB, result, MSB16, 0);
6251 aopPut (AOP (result), zero, LSB);
6253 else if (shCount == 1)
6254 shiftLLong (left, result, MSB16);
6257 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
6258 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
6259 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
6260 aopPut (AOP (result), zero, LSB);
6265 /* 1 <= shCount <= 7 */
6266 else if (shCount <= 2)
6268 shiftLLong (left, result, LSB);
6270 shiftLLong (result, result, LSB);
6272 /* 3 <= shCount <= 7, optimize */
6275 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
6276 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
6277 shiftL2Left2Result (left, LSB, result, LSB, shCount);
6281 /*-----------------------------------------------------------------*/
6282 /* genLeftShiftLiteral - left shifting by known count */
6283 /*-----------------------------------------------------------------*/
6285 genLeftShiftLiteral (operand * left,
6290 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6293 D(emitcode (";", "genLeftShiftLiteral"));
6295 freeAsmop (right, NULL, ic, TRUE);
6297 aopOp (left, ic, FALSE);
6298 aopOp (result, ic, FALSE);
6300 size = getSize (operandType (result));
6303 emitcode ("; shift left ", "result %d, left %d", size,
6307 /* I suppose that the left size >= result size */
6312 movLeft2Result (left, size, result, size, 0);
6316 else if (shCount >= (size * 8))
6318 aopPut (AOP (result), zero, size);
6324 genlshOne (result, left, shCount);
6328 genlshTwo (result, left, shCount);
6332 genlshFour (result, left, shCount);
6335 fprintf(stderr, "*** ack! mystery literal shift!\n");
6339 freeAsmop (left, NULL, ic, TRUE);
6340 freeAsmop (result, NULL, ic, TRUE);
6343 /*-----------------------------------------------------------------*/
6344 /* genLeftShift - generates code for left shifting */
6345 /*-----------------------------------------------------------------*/
6347 genLeftShift (iCode * ic)
6349 operand *left, *right, *result;
6352 symbol *tlbl, *tlbl1;
6354 D(emitcode (";", "genLeftShift"));
6356 right = IC_RIGHT (ic);
6357 left = IC_LEFT (ic);
6358 result = IC_RESULT (ic);
6360 aopOp (right, ic, FALSE);
6362 /* if the shift count is known then do it
6363 as efficiently as possible */
6364 if (AOP_TYPE (right) == AOP_LIT)
6366 genLeftShiftLiteral (left, right, result, ic);
6370 /* shift count is unknown then we have to form
6371 a loop get the loop count in B : Note: we take
6372 only the lower order byte since shifting
6373 more that 32 bits make no sense anyway, ( the
6374 largest size of an object can be only 32 bits ) */
6376 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6377 emitcode ("inc", "b");
6378 freeAsmop (right, NULL, ic, TRUE);
6379 aopOp (left, ic, FALSE);
6380 aopOp (result, ic, FALSE);
6382 /* now move the left to the result if they are not the
6384 if (!sameRegs (AOP (left), AOP (result)) &&
6385 AOP_SIZE (result) > 1)
6388 size = AOP_SIZE (result);
6392 l = aopGet (AOP (left), offset, FALSE, TRUE);
6393 if (*l == '@' && (IS_AOP_PREG (result)))
6396 emitcode ("mov", "a,%s", l);
6397 aopPut (AOP (result), "a", offset);
6400 aopPut (AOP (result), l, offset);
6405 tlbl = newiTempLabel (NULL);
6406 size = AOP_SIZE (result);
6408 tlbl1 = newiTempLabel (NULL);
6410 /* if it is only one byte then */
6413 symbol *tlbl1 = newiTempLabel (NULL);
6415 l = aopGet (AOP (left), 0, FALSE, FALSE);
6417 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6418 emitcode ("", "%05d$:", tlbl->key + 100);
6419 emitcode ("add", "a,acc");
6420 emitcode ("", "%05d$:", tlbl1->key + 100);
6421 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6422 aopPut (AOP (result), "a", 0);
6426 reAdjustPreg (AOP (result));
6428 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6429 emitcode ("", "%05d$:", tlbl->key + 100);
6430 l = aopGet (AOP (result), offset, FALSE, FALSE);
6432 emitcode ("add", "a,acc");
6433 aopPut (AOP (result), "a", offset++);
6436 l = aopGet (AOP (result), offset, FALSE, FALSE);
6438 emitcode ("rlc", "a");
6439 aopPut (AOP (result), "a", offset++);
6441 reAdjustPreg (AOP (result));
6443 emitcode ("", "%05d$:", tlbl1->key + 100);
6444 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6446 freeAsmop (left, NULL, ic, TRUE);
6447 freeAsmop (result, NULL, ic, TRUE);
6450 /*-----------------------------------------------------------------*/
6451 /* genrshOne - right shift a one byte quantity by known count */
6452 /*-----------------------------------------------------------------*/
6454 genrshOne (operand * result, operand * left,
6455 int shCount, int sign)
6457 D(emitcode (";", "genrshOne"));
6459 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
6462 /*-----------------------------------------------------------------*/
6463 /* genrshTwo - right shift two bytes by known amount != 0 */
6464 /*-----------------------------------------------------------------*/
6466 genrshTwo (operand * result, operand * left,
6467 int shCount, int sign)
6469 D(emitcode (";", "genrshTwo"));
6471 /* if shCount >= 8 */
6476 shiftR1Left2Result (left, MSB16, result, LSB,
6479 movLeft2Result (left, MSB16, result, LSB, sign);
6480 addSign (result, MSB16, sign);
6483 /* 1 <= shCount <= 7 */
6485 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
6488 /*-----------------------------------------------------------------*/
6489 /* shiftRLong - shift right one long from left to result */
6490 /* offl = LSB or MSB16 */
6491 /*-----------------------------------------------------------------*/
6493 shiftRLong (operand * left, int offl,
6494 operand * result, int sign)
6496 int isSameRegs=sameRegs(AOP(left),AOP(result));
6498 if (isSameRegs && offl>1) {
6499 // we are in big trouble, but this shouldn't happen
6500 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
6503 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
6508 emitcode ("rlc", "a");
6509 emitcode ("subb", "a,acc");
6510 emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
6512 aopPut (AOP(result), zero, MSB32);
6517 emitcode ("clr", "c");
6519 emitcode ("mov", "c,acc.7");
6522 emitcode ("rrc", "a");
6524 if (isSameRegs && offl==MSB16) {
6525 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
6527 aopPut (AOP (result), "a", MSB32);
6528 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
6531 emitcode ("rrc", "a");
6532 if (isSameRegs && offl==1) {
6533 emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
6535 aopPut (AOP (result), "a", MSB24);
6536 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
6538 emitcode ("rrc", "a");
6539 aopPut (AOP (result), "a", MSB16 - offl);
6543 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE));
6544 emitcode ("rrc", "a");
6545 aopPut (AOP (result), "a", LSB);
6549 /*-----------------------------------------------------------------*/
6550 /* genrshFour - shift four byte by a known amount != 0 */
6551 /*-----------------------------------------------------------------*/
6553 genrshFour (operand * result, operand * left,
6554 int shCount, int sign)
6556 D(emitcode (";", "genrshFour"));
6558 /* if shifting more that 3 bytes */
6563 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
6565 movLeft2Result (left, MSB32, result, LSB, sign);
6566 addSign (result, MSB16, sign);
6568 else if (shCount >= 16)
6572 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
6575 movLeft2Result (left, MSB24, result, LSB, 0);
6576 movLeft2Result (left, MSB32, result, MSB16, sign);
6578 addSign (result, MSB24, sign);
6580 else if (shCount >= 8)
6584 shiftRLong (left, MSB16, result, sign);
6585 else if (shCount == 0)
6587 movLeft2Result (left, MSB16, result, LSB, 0);
6588 movLeft2Result (left, MSB24, result, MSB16, 0);
6589 movLeft2Result (left, MSB32, result, MSB24, sign);
6590 addSign (result, MSB32, sign);
6594 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
6595 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
6596 /* the last shift is signed */
6597 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
6598 addSign (result, MSB32, sign);
6602 { /* 1 <= shCount <= 7 */
6605 shiftRLong (left, LSB, result, sign);
6607 shiftRLong (result, LSB, result, sign);
6611 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
6612 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
6613 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
6618 /*-----------------------------------------------------------------*/
6619 /* genRightShiftLiteral - right shifting by known count */
6620 /*-----------------------------------------------------------------*/
6622 genRightShiftLiteral (operand * left,
6628 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
6631 D(emitcode (";", "genRightShiftLiteral"));
6633 freeAsmop (right, NULL, ic, TRUE);
6635 aopOp (left, ic, FALSE);
6636 aopOp (result, ic, FALSE);
6639 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
6643 size = getDataSize (left);
6644 /* test the LEFT size !!! */
6646 /* I suppose that the left size >= result size */
6649 size = getDataSize (result);
6651 movLeft2Result (left, size, result, size, 0);
6654 else if (shCount >= (size * 8))
6657 /* get sign in acc.7 */
6658 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE));
6659 addSign (result, LSB, sign);
6666 genrshOne (result, left, shCount, sign);
6670 genrshTwo (result, left, shCount, sign);
6674 genrshFour (result, left, shCount, sign);
6680 freeAsmop (left, NULL, ic, TRUE);
6681 freeAsmop (result, NULL, ic, TRUE);
6685 /*-----------------------------------------------------------------*/
6686 /* genSignedRightShift - right shift of signed number */
6687 /*-----------------------------------------------------------------*/
6689 genSignedRightShift (iCode * ic)
6691 operand *right, *left, *result;
6694 symbol *tlbl, *tlbl1;
6696 D(emitcode (";", "genSignedRightShift"));
6698 /* we do it the hard way put the shift count in b
6699 and loop thru preserving the sign */
6701 right = IC_RIGHT (ic);
6702 left = IC_LEFT (ic);
6703 result = IC_RESULT (ic);
6705 aopOp (right, ic, FALSE);
6708 if (AOP_TYPE (right) == AOP_LIT)
6710 genRightShiftLiteral (left, right, result, ic, 1);
6713 /* shift count is unknown then we have to form
6714 a loop get the loop count in B : Note: we take
6715 only the lower order byte since shifting
6716 more that 32 bits make no sense anyway, ( the
6717 largest size of an object can be only 32 bits ) */
6719 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6720 emitcode ("inc", "b");
6721 freeAsmop (right, NULL, ic, TRUE);
6722 aopOp (left, ic, FALSE);
6723 aopOp (result, ic, FALSE);
6725 /* now move the left to the result if they are not the
6727 if (!sameRegs (AOP (left), AOP (result)) &&
6728 AOP_SIZE (result) > 1)
6731 size = AOP_SIZE (result);
6735 l = aopGet (AOP (left), offset, FALSE, TRUE);
6736 if (*l == '@' && IS_AOP_PREG (result))
6739 emitcode ("mov", "a,%s", l);
6740 aopPut (AOP (result), "a", offset);
6743 aopPut (AOP (result), l, offset);
6748 /* mov the highest order bit to OVR */
6749 tlbl = newiTempLabel (NULL);
6750 tlbl1 = newiTempLabel (NULL);
6752 size = AOP_SIZE (result);
6754 emitcode ("mov", "a,%s", aopGet (AOP (left), offset, FALSE, FALSE));
6755 emitcode ("rlc", "a");
6756 emitcode ("mov", "ov,c");
6757 /* if it is only one byte then */
6760 l = aopGet (AOP (left), 0, FALSE, FALSE);
6762 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6763 emitcode ("", "%05d$:", tlbl->key + 100);
6764 emitcode ("mov", "c,ov");
6765 emitcode ("rrc", "a");
6766 emitcode ("", "%05d$:", tlbl1->key + 100);
6767 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6768 aopPut (AOP (result), "a", 0);
6772 reAdjustPreg (AOP (result));
6773 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6774 emitcode ("", "%05d$:", tlbl->key + 100);
6775 emitcode ("mov", "c,ov");
6778 l = aopGet (AOP (result), offset, FALSE, FALSE);
6780 emitcode ("rrc", "a");
6781 aopPut (AOP (result), "a", offset--);
6783 reAdjustPreg (AOP (result));
6784 emitcode ("", "%05d$:", tlbl1->key + 100);
6785 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6788 freeAsmop (left, NULL, ic, TRUE);
6789 freeAsmop (result, NULL, ic, TRUE);
6792 /*-----------------------------------------------------------------*/
6793 /* genRightShift - generate code for right shifting */
6794 /*-----------------------------------------------------------------*/
6796 genRightShift (iCode * ic)
6798 operand *right, *left, *result;
6802 symbol *tlbl, *tlbl1;
6804 D(emitcode (";", "genRightShift"));
6806 /* if signed then we do it the hard way preserve the
6807 sign bit moving it inwards */
6808 retype = getSpec (operandType (IC_RESULT (ic)));
6810 if (!SPEC_USIGN (retype))
6812 genSignedRightShift (ic);
6816 /* signed & unsigned types are treated the same : i.e. the
6817 signed is NOT propagated inwards : quoting from the
6818 ANSI - standard : "for E1 >> E2, is equivalent to division
6819 by 2**E2 if unsigned or if it has a non-negative value,
6820 otherwise the result is implementation defined ", MY definition
6821 is that the sign does not get propagated */
6823 right = IC_RIGHT (ic);
6824 left = IC_LEFT (ic);
6825 result = IC_RESULT (ic);
6827 aopOp (right, ic, FALSE);
6829 /* if the shift count is known then do it
6830 as efficiently as possible */
6831 if (AOP_TYPE (right) == AOP_LIT)
6833 genRightShiftLiteral (left, right, result, ic, 0);
6837 /* shift count is unknown then we have to form
6838 a loop get the loop count in B : Note: we take
6839 only the lower order byte since shifting
6840 more that 32 bits make no sense anyway, ( the
6841 largest size of an object can be only 32 bits ) */
6843 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
6844 emitcode ("inc", "b");
6845 freeAsmop (right, NULL, ic, TRUE);
6846 aopOp (left, ic, FALSE);
6847 aopOp (result, ic, FALSE);
6849 /* now move the left to the result if they are not the
6851 if (!sameRegs (AOP (left), AOP (result)) &&
6852 AOP_SIZE (result) > 1)
6855 size = AOP_SIZE (result);
6859 l = aopGet (AOP (left), offset, FALSE, TRUE);
6860 if (*l == '@' && IS_AOP_PREG (result))
6863 emitcode ("mov", "a,%s", l);
6864 aopPut (AOP (result), "a", offset);
6867 aopPut (AOP (result), l, offset);
6872 tlbl = newiTempLabel (NULL);
6873 tlbl1 = newiTempLabel (NULL);
6874 size = AOP_SIZE (result);
6877 /* if it is only one byte then */
6880 l = aopGet (AOP (left), 0, FALSE, FALSE);
6882 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6883 emitcode ("", "%05d$:", tlbl->key + 100);
6885 emitcode ("rrc", "a");
6886 emitcode ("", "%05d$:", tlbl1->key + 100);
6887 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6888 aopPut (AOP (result), "a", 0);
6892 reAdjustPreg (AOP (result));
6893 emitcode ("sjmp", "%05d$", tlbl1->key + 100);
6894 emitcode ("", "%05d$:", tlbl->key + 100);
6898 l = aopGet (AOP (result), offset, FALSE, FALSE);
6900 emitcode ("rrc", "a");
6901 aopPut (AOP (result), "a", offset--);
6903 reAdjustPreg (AOP (result));
6905 emitcode ("", "%05d$:", tlbl1->key + 100);
6906 emitcode ("djnz", "b,%05d$", tlbl->key + 100);
6909 freeAsmop (left, NULL, ic, TRUE);
6910 freeAsmop (result, NULL, ic, TRUE);
6913 /*-----------------------------------------------------------------*/
6914 /* genUnpackBits - generates code for unpacking bits */
6915 /*-----------------------------------------------------------------*/
6917 genUnpackBits (operand * result, char *rname, int ptype)
6925 D(emitcode (";", "genUnpackBits"));
6927 etype = getSpec (operandType (result));
6928 rsize = getSize (operandType (result));
6929 /* read the first byte */
6935 emitcode ("mov", "a,@%s", rname);
6939 emitcode ("movx", "a,@%s", rname);
6943 emitcode ("movx", "a,@dptr");
6947 emitcode ("clr", "a");
6948 emitcode ("movc", "a,@a+dptr");
6952 emitcode ("lcall", "__gptrget");
6956 rlen = SPEC_BLEN (etype);
6958 /* if we have bitdisplacement then it fits */
6959 /* into this byte completely or if length is */
6960 /* less than a byte */
6961 if ((shCnt = SPEC_BSTR (etype)) ||
6962 (SPEC_BLEN (etype) <= 8))
6965 /* shift right acc */
6968 emitcode ("anl", "a,#0x%02x",
6969 ((unsigned char) -1) >> (8 - SPEC_BLEN (etype)));
6970 aopPut (AOP (result), "a", offset++);
6974 /* bit field did not fit in a byte */
6975 aopPut (AOP (result), "a", offset++);
6984 emitcode ("inc", "%s", rname);
6985 emitcode ("mov", "a,@%s", rname);
6989 emitcode ("inc", "%s", rname);
6990 emitcode ("movx", "a,@%s", rname);
6994 emitcode ("inc", "dptr");
6995 emitcode ("movx", "a,@dptr");
6999 emitcode ("clr", "a");
7000 emitcode ("inc", "dptr");
7001 emitcode ("movc", "a,@a+dptr");
7005 emitcode ("inc", "dptr");
7006 emitcode ("lcall", "__gptrget");
7011 /* if we are done */
7015 aopPut (AOP (result), "a", offset++);
7021 // emitcode("anl","a,#0x%02x",((unsigned char)-1)>>(rlen));
7023 aopPut (AOP (result), "a", offset++);
7031 aopPut (AOP (result), zero, offset++);
7037 /*-----------------------------------------------------------------*/
7038 /* genDataPointerGet - generates code when ptr offset is known */
7039 /*-----------------------------------------------------------------*/
7041 genDataPointerGet (operand * left,
7047 int size, offset = 0;
7049 D(emitcode (";", "genDataPointerGet"));
7051 aopOp (result, ic, TRUE);
7053 /* get the string representation of the name */
7054 l = aopGet (AOP (left), 0, FALSE, TRUE);
7055 size = AOP_SIZE (result);
7059 sprintf (buffer, "(%s + %d)", l + 1, offset);
7061 sprintf (buffer, "%s", l + 1);
7062 aopPut (AOP (result), buffer, offset++);
7065 freeAsmop (left, NULL, ic, TRUE);
7066 freeAsmop (result, NULL, ic, TRUE);
7069 /*-----------------------------------------------------------------*/
7070 /* genNearPointerGet - emitcode for near pointer fetch */
7071 /*-----------------------------------------------------------------*/
7073 genNearPointerGet (operand * left,
7081 sym_link *rtype, *retype;
7082 sym_link *ltype = operandType (left);
7085 D(emitcode (";", "genNearPointerGet"));
7087 rtype = operandType (result);
7088 retype = getSpec (rtype);
7090 aopOp (left, ic, FALSE);
7092 /* if left is rematerialisable and
7093 result is not bit variable type and
7094 the left is pointer to data space i.e
7095 lower 128 bytes of space */
7096 if (AOP_TYPE (left) == AOP_IMMD &&
7097 !IS_BITVAR (retype) &&
7098 DCL_TYPE (ltype) == POINTER)
7100 genDataPointerGet (left, result, ic);
7104 /* if the value is already in a pointer register
7105 then don't need anything more */
7106 if (!AOP_INPREG (AOP (left)))
7108 /* otherwise get a free pointer register */
7110 preg = getFreePtr (ic, &aop, FALSE);
7111 emitcode ("mov", "%s,%s",
7113 aopGet (AOP (left), 0, FALSE, TRUE));
7117 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7119 //aopOp (result, ic, FALSE);
7120 aopOp (result, ic, result?TRUE:FALSE);
7122 /* if bitfield then unpack the bits */
7123 if (IS_BITVAR (retype))
7124 genUnpackBits (result, rname, POINTER);
7127 /* we have can just get the values */
7128 int size = AOP_SIZE (result);
7133 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
7136 emitcode ("mov", "a,@%s", rname);
7137 aopPut (AOP (result), "a", offset);
7141 sprintf (buffer, "@%s", rname);
7142 aopPut (AOP (result), buffer, offset);
7146 emitcode ("inc", "%s", rname);
7150 /* now some housekeeping stuff */
7151 if (aop) /* we had to allocate for this iCode */
7153 if (pi) { /* post increment present */
7154 aopPut(AOP ( left ),rname,0);
7156 freeAsmop (NULL, aop, ic, TRUE);
7160 /* we did not allocate which means left
7161 already in a pointer register, then
7162 if size > 0 && this could be used again
7163 we have to point it back to where it
7165 if ((AOP_SIZE (result) > 1 &&
7166 !OP_SYMBOL (left)->remat &&
7167 (OP_SYMBOL (left)->liveTo > ic->seq ||
7171 int size = AOP_SIZE (result) - 1;
7173 emitcode ("dec", "%s", rname);
7178 freeAsmop (left, NULL, ic, TRUE);
7179 freeAsmop (result, NULL, ic, TRUE);
7180 if (pi) pi->generated = 1;
7183 /*-----------------------------------------------------------------*/
7184 /* genPagedPointerGet - emitcode for paged pointer fetch */
7185 /*-----------------------------------------------------------------*/
7187 genPagedPointerGet (operand * left,
7195 sym_link *rtype, *retype;
7197 D(emitcode (";", "genPagedPointerGet"));
7199 rtype = operandType (result);
7200 retype = getSpec (rtype);
7202 aopOp (left, ic, FALSE);
7204 /* if the value is already in a pointer register
7205 then don't need anything more */
7206 if (!AOP_INPREG (AOP (left)))
7208 /* otherwise get a free pointer register */
7210 preg = getFreePtr (ic, &aop, FALSE);
7211 emitcode ("mov", "%s,%s",
7213 aopGet (AOP (left), 0, FALSE, TRUE));
7217 rname = aopGet (AOP (left), 0, FALSE, FALSE);
7219 aopOp (result, ic, FALSE);
7221 /* if bitfield then unpack the bits */
7222 if (IS_BITVAR (retype))
7223 genUnpackBits (result, rname, PPOINTER);
7226 /* we have can just get the values */
7227 int size = AOP_SIZE (result);
7233 emitcode ("movx", "a,@%s", rname);
7234 aopPut (AOP (result), "a", offset);
7239 emitcode ("inc", "%s", rname);
7243 /* now some housekeeping stuff */
7244 if (aop) /* we had to allocate for this iCode */
7246 if (pi) aopPut ( AOP (left), rname, 0);
7247 freeAsmop (NULL, aop, ic, TRUE);
7251 /* we did not allocate which means left
7252 already in a pointer register, then
7253 if size > 0 && this could be used again
7254 we have to point it back to where it
7256 if ((AOP_SIZE (result) > 1 &&
7257 !OP_SYMBOL (left)->remat &&
7258 (OP_SYMBOL (left)->liveTo > ic->seq ||
7262 int size = AOP_SIZE (result) - 1;
7264 emitcode ("dec", "%s", rname);
7269 freeAsmop (left, NULL, ic, TRUE);
7270 freeAsmop (result, NULL, ic, TRUE);
7271 if (pi) pi->generated = 1;
7275 /*-----------------------------------------------------------------*/
7276 /* genFarPointerGet - gget value from far space */
7277 /*-----------------------------------------------------------------*/
7279 genFarPointerGet (operand * left,
7280 operand * result, iCode * ic, iCode * pi)
7283 sym_link *retype = getSpec (operandType (result));
7285 D(emitcode (";", "genFarPointerGet"));
7287 aopOp (left, ic, FALSE);
7289 /* if the operand is already in dptr
7290 then we do nothing else we move the value to dptr */
7291 if (AOP_TYPE (left) != AOP_STR)
7293 /* if this is remateriazable */
7294 if (AOP_TYPE (left) == AOP_IMMD)
7295 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7297 { /* we need to get it byte by byte */
7298 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7299 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7302 /* so dptr know contains the address */
7303 aopOp (result, ic, FALSE);
7305 /* if bit then unpack */
7306 if (IS_BITVAR (retype))
7307 genUnpackBits (result, "dptr", FPOINTER);
7310 size = AOP_SIZE (result);
7315 emitcode ("movx", "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 /* genCodePointerGet - gget value from code space */
7333 /*-----------------------------------------------------------------*/
7335 genCodePointerGet (operand * left,
7336 operand * result, iCode * ic, iCode *pi)
7339 sym_link *retype = getSpec (operandType (result));
7341 D(emitcode (";", "genCodePointerGet"));
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)
7351 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7353 { /* we need to get it byte by byte */
7354 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7355 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7358 /* so dptr know contains the address */
7359 aopOp (result, ic, FALSE);
7361 /* if bit then unpack */
7362 if (IS_BITVAR (retype))
7363 genUnpackBits (result, "dptr", CPOINTER);
7366 size = AOP_SIZE (result);
7371 emitcode ("clr", "a");
7372 emitcode ("movc", "a,@a+dptr");
7373 aopPut (AOP (result), "a", offset++);
7375 emitcode ("inc", "dptr");
7379 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7380 aopPut ( AOP (left), "dpl", 0);
7381 aopPut ( AOP (left), "dph", 1);
7384 freeAsmop (left, NULL, ic, TRUE);
7385 freeAsmop (result, NULL, ic, TRUE);
7388 /*-----------------------------------------------------------------*/
7389 /* genGenPointerGet - gget value from generic pointer space */
7390 /*-----------------------------------------------------------------*/
7392 genGenPointerGet (operand * left,
7393 operand * result, iCode * ic, iCode *pi)
7396 sym_link *retype = getSpec (operandType (result));
7398 D(emitcode (";", "genGenPointerGet"));
7400 aopOp (left, ic, FALSE);
7402 /* if the operand is already in dptr
7403 then we do nothing else we move the value to dptr */
7404 if (AOP_TYPE (left) != AOP_STR)
7406 /* if this is remateriazable */
7407 if (AOP_TYPE (left) == AOP_IMMD)
7409 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE));
7410 if (AOP(left)->aopu.aop_immd.from_cast_remat)
7411 emitcode ("mov", "b,%s",aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE));
7413 emitcode ("mov", "b,#%d", pointerCode (retype));
7416 { /* we need to get it byte by byte */
7417 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE));
7418 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE));
7419 emitcode ("mov", "b,%s", aopGet (AOP (left), 2, FALSE, FALSE));
7422 /* so dptr know contains the address */
7423 aopOp (result, ic, FALSE);
7425 /* if bit then unpack */
7426 if (IS_BITVAR (retype))
7427 genUnpackBits (result, "dptr", GPOINTER);
7430 size = AOP_SIZE (result);
7435 emitcode ("lcall", "__gptrget");
7436 aopPut (AOP (result), "a", offset++);
7438 emitcode ("inc", "dptr");
7442 if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
7443 aopPut ( AOP (left), "dpl", 0);
7444 aopPut ( AOP (left), "dph", 1);
7445 aopPut ( AOP (left), "b", 2);
7448 freeAsmop (left, NULL, ic, TRUE);
7449 freeAsmop (result, NULL, ic, TRUE);
7452 /*-----------------------------------------------------------------*/
7453 /* genPointerGet - generate code for pointer get */
7454 /*-----------------------------------------------------------------*/
7456 genPointerGet (iCode * ic, iCode *pi)
7458 operand *left, *result;
7459 sym_link *type, *etype;
7462 D(emitcode (";", "genPointerGet"));
7464 left = IC_LEFT (ic);
7465 result = IC_RESULT (ic);
7467 /* depending on the type of pointer we need to
7468 move it to the correct pointer register */
7469 type = operandType (left);
7470 etype = getSpec (type);
7471 /* if left is of type of pointer then it is simple */
7472 if (IS_PTR (type) && !IS_FUNC (type->next))
7473 p_type = DCL_TYPE (type);
7476 /* we have to go by the storage class */
7477 p_type = PTR_TYPE (SPEC_OCLS (etype));
7480 /* special case when cast remat */
7481 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
7482 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
7483 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
7484 type = type = operandType (left);
7485 p_type = DCL_TYPE (type);
7487 /* now that we have the pointer type we assign
7488 the pointer values */
7494 genNearPointerGet (left, result, ic, pi);
7498 genPagedPointerGet (left, result, ic, pi);
7502 genFarPointerGet (left, result, ic, pi);
7506 genCodePointerGet (left, result, ic, pi);
7510 genGenPointerGet (left, result, ic, pi);
7516 /*-----------------------------------------------------------------*/
7517 /* genPackBits - generates code for packed bit storage */
7518 /*-----------------------------------------------------------------*/
7520 genPackBits (sym_link * etype,
7522 char *rname, int p_type)
7530 D(emitcode (";", "genPackBits"));
7532 blen = SPEC_BLEN (etype);
7533 bstr = SPEC_BSTR (etype);
7535 l = aopGet (AOP (right), offset++, FALSE, FALSE);
7538 /* if the bit lenth is less than or */
7539 /* it exactly fits a byte then */
7540 if (SPEC_BLEN (etype) <= 8)
7542 shCount = SPEC_BSTR (etype);
7544 /* shift left acc */
7547 if (SPEC_BLEN (etype) < 8)
7548 { /* if smaller than a byte */
7554 emitcode ("mov", "b,a");
7555 emitcode ("mov", "a,@%s", rname);
7559 emitcode ("mov", "b,a");
7560 emitcode ("movx", "a,@dptr");
7564 emitcode ("push", "b");
7565 emitcode ("push", "acc");
7566 emitcode ("lcall", "__gptrget");
7567 emitcode ("pop", "b");
7571 emitcode ("anl", "a,#0x%02x", (unsigned char)
7572 ((unsigned char) (0xFF << (blen + bstr)) |
7573 (unsigned char) (0xFF >> (8 - bstr))));
7574 emitcode ("orl", "a,b");
7575 if (p_type == GPOINTER)
7576 emitcode ("pop", "b");
7583 emitcode ("mov", "@%s,a", rname);
7587 emitcode ("movx", "@dptr,a");
7591 emitcode ("lcall", "__gptrput");
7596 if (SPEC_BLEN (etype) <= 8)
7599 emitcode ("inc", "%s", rname);
7600 rLen = SPEC_BLEN (etype);
7602 /* now generate for lengths greater than one byte */
7606 l = aopGet (AOP (right), offset++, FALSE, TRUE);
7618 emitcode ("mov", "@%s,a", rname);
7621 emitcode ("mov", "@%s,%s", rname, l);
7626 emitcode ("movx", "@dptr,a");
7631 emitcode ("lcall", "__gptrput");
7634 emitcode ("inc", "%s", rname);
7639 /* last last was not complete */
7642 /* save the byte & read byte */
7646 emitcode ("mov", "b,a");
7647 emitcode ("mov", "a,@%s", rname);
7651 emitcode ("mov", "b,a");
7652 emitcode ("movx", "a,@dptr");
7656 emitcode ("push", "b");
7657 emitcode ("push", "acc");
7658 emitcode ("lcall", "__gptrget");
7659 emitcode ("pop", "b");
7663 emitcode ("anl", "a,#0x%02x", (((unsigned char) -1 << rLen) & 0xff));
7664 emitcode ("orl", "a,b");
7667 if (p_type == GPOINTER)
7668 emitcode ("pop", "b");
7674 emitcode ("mov", "@%s,a", rname);
7678 emitcode ("movx", "@dptr,a");
7682 emitcode ("lcall", "__gptrput");
7686 /*-----------------------------------------------------------------*/
7687 /* genDataPointerSet - remat pointer to data space */
7688 /*-----------------------------------------------------------------*/
7690 genDataPointerSet (operand * right,
7694 int size, offset = 0;
7695 char *l, buffer[256];
7697 D(emitcode (";", "genDataPointerSet"));
7699 aopOp (right, ic, FALSE);
7701 l = aopGet (AOP (result), 0, FALSE, TRUE);
7702 size = AOP_SIZE (right);
7706 sprintf (buffer, "(%s + %d)", l + 1, offset);
7708 sprintf (buffer, "%s", l + 1);
7709 emitcode ("mov", "%s,%s", buffer,
7710 aopGet (AOP (right), offset++, FALSE, FALSE));
7713 freeAsmop (right, NULL, ic, TRUE);
7714 freeAsmop (result, NULL, ic, TRUE);
7717 /*-----------------------------------------------------------------*/
7718 /* genNearPointerSet - emitcode for near pointer put */
7719 /*-----------------------------------------------------------------*/
7721 genNearPointerSet (operand * right,
7729 sym_link *retype, *letype;
7730 sym_link *ptype = operandType (result);
7732 D(emitcode (";", "genNearPointerSet"));
7734 retype = getSpec (operandType (right));
7735 letype = getSpec (ptype);
7736 aopOp (result, ic, FALSE);
7738 /* if the result is rematerializable &
7739 in data space & not a bit variable */
7740 if (AOP_TYPE (result) == AOP_IMMD &&
7741 DCL_TYPE (ptype) == POINTER &&
7742 !IS_BITVAR (retype) &&
7743 !IS_BITVAR (letype))
7745 genDataPointerSet (right, result, ic);
7749 /* if the value is already in a pointer register
7750 then don't need anything more */
7751 if (!AOP_INPREG (AOP (result)))
7754 //AOP_TYPE (result) == AOP_STK
7758 // Aha, it is a pointer, just in disguise.
7759 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7762 fprintf(stderr, "probable internal error: unexpected rname @ %s:%d\n",
7763 __FILE__, __LINE__);
7768 rname++; // skip the '@'.
7773 /* otherwise get a free pointer register */
7775 preg = getFreePtr (ic, &aop, FALSE);
7776 emitcode ("mov", "%s,%s",
7778 aopGet (AOP (result), 0, FALSE, TRUE));
7784 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7787 aopOp (right, ic, FALSE);
7789 /* if bitfield then unpack the bits */
7790 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7791 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
7794 /* we have can just get the values */
7795 int size = AOP_SIZE (right);
7800 l = aopGet (AOP (right), offset, FALSE, TRUE);
7804 emitcode ("mov", "@%s,a", rname);
7807 emitcode ("mov", "@%s,%s", rname, l);
7809 emitcode ("inc", "%s", rname);
7814 /* now some housekeeping stuff */
7815 if (aop) /* we had to allocate for this iCode */
7817 if (pi) aopPut (AOP (result),rname,0);
7818 freeAsmop (NULL, aop, ic, TRUE);
7822 /* we did not allocate which means left
7823 already in a pointer register, then
7824 if size > 0 && this could be used again
7825 we have to point it back to where it
7827 if ((AOP_SIZE (right) > 1 &&
7828 !OP_SYMBOL (result)->remat &&
7829 (OP_SYMBOL (result)->liveTo > ic->seq ||
7833 int size = AOP_SIZE (right) - 1;
7835 emitcode ("dec", "%s", rname);
7840 if (pi) pi->generated = 1;
7841 freeAsmop (result, NULL, ic, TRUE);
7842 freeAsmop (right, NULL, ic, TRUE);
7845 /*-----------------------------------------------------------------*/
7846 /* genPagedPointerSet - emitcode for Paged pointer put */
7847 /*-----------------------------------------------------------------*/
7849 genPagedPointerSet (operand * right,
7857 sym_link *retype, *letype;
7859 D(emitcode (";", "genPagedPointerSet"));
7861 retype = getSpec (operandType (right));
7862 letype = getSpec (operandType (result));
7864 aopOp (result, ic, FALSE);
7866 /* if the value is already in a pointer register
7867 then don't need anything more */
7868 if (!AOP_INPREG (AOP (result)))
7870 /* otherwise get a free pointer register */
7872 preg = getFreePtr (ic, &aop, FALSE);
7873 emitcode ("mov", "%s,%s",
7875 aopGet (AOP (result), 0, FALSE, TRUE));
7879 rname = aopGet (AOP (result), 0, FALSE, FALSE);
7881 aopOp (right, ic, FALSE);
7883 /* if bitfield then unpack the bits */
7884 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7885 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
7888 /* we have can just get the values */
7889 int size = AOP_SIZE (right);
7894 l = aopGet (AOP (right), offset, FALSE, TRUE);
7897 emitcode ("movx", "@%s,a", rname);
7900 emitcode ("inc", "%s", rname);
7906 /* now some housekeeping stuff */
7907 if (aop) /* we had to allocate for this iCode */
7909 if (pi) aopPut (AOP (result),rname,0);
7910 freeAsmop (NULL, aop, ic, TRUE);
7914 /* we did not allocate which means left
7915 already in a pointer register, then
7916 if size > 0 && this could be used again
7917 we have to point it back to where it
7919 if (AOP_SIZE (right) > 1 &&
7920 !OP_SYMBOL (result)->remat &&
7921 (OP_SYMBOL (result)->liveTo > ic->seq ||
7924 int size = AOP_SIZE (right) - 1;
7926 emitcode ("dec", "%s", rname);
7931 if (pi) pi->generated = 1;
7932 freeAsmop (result, NULL, ic, TRUE);
7933 freeAsmop (right, NULL, ic, TRUE);
7938 /*-----------------------------------------------------------------*/
7939 /* genFarPointerSet - set value from far space */
7940 /*-----------------------------------------------------------------*/
7942 genFarPointerSet (operand * right,
7943 operand * result, iCode * ic, iCode * pi)
7946 sym_link *retype = getSpec (operandType (right));
7947 sym_link *letype = getSpec (operandType (result));
7949 D(emitcode (";", "genFarPointerSet"));
7951 aopOp (result, ic, FALSE);
7953 /* if the operand is already in dptr
7954 then we do nothing else we move the value to dptr */
7955 if (AOP_TYPE (result) != AOP_STR)
7957 /* if this is remateriazable */
7958 if (AOP_TYPE (result) == AOP_IMMD)
7959 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
7961 { /* we need to get it byte by byte */
7962 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
7963 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
7966 /* so dptr know contains the address */
7967 aopOp (right, ic, FALSE);
7969 /* if bit then unpack */
7970 if (IS_BITVAR (retype) || IS_BITVAR (letype))
7971 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
7974 size = AOP_SIZE (right);
7979 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
7981 emitcode ("movx", "@dptr,a");
7983 emitcode ("inc", "dptr");
7986 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
7987 aopPut (AOP(result),"dpl",0);
7988 aopPut (AOP(result),"dph",1);
7991 freeAsmop (result, NULL, ic, TRUE);
7992 freeAsmop (right, NULL, ic, TRUE);
7995 /*-----------------------------------------------------------------*/
7996 /* genGenPointerSet - set value from generic pointer space */
7997 /*-----------------------------------------------------------------*/
7999 genGenPointerSet (operand * right,
8000 operand * result, iCode * ic, iCode * pi)
8003 sym_link *retype = getSpec (operandType (right));
8004 sym_link *letype = getSpec (operandType (result));
8006 D(emitcode (";", "genGenPointerSet"));
8008 aopOp (result, ic, FALSE);
8010 /* if the operand is already in dptr
8011 then we do nothing else we move the value to dptr */
8012 if (AOP_TYPE (result) != AOP_STR)
8014 /* if this is remateriazable */
8015 if (AOP_TYPE (result) == AOP_IMMD)
8017 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE));
8018 if (AOP(result)->aopu.aop_immd.from_cast_remat)
8019 emitcode ("mov", "b,%s",aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE));
8021 emitcode ("mov", "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE));
8024 { /* we need to get it byte by byte */
8025 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE));
8026 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE));
8027 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE));
8030 /* so dptr know contains the address */
8031 aopOp (right, ic, FALSE);
8033 /* if bit then unpack */
8034 if (IS_BITVAR (retype) || IS_BITVAR (letype))
8035 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
8038 size = AOP_SIZE (right);
8043 char *l = aopGet (AOP (right), offset++, FALSE, FALSE);
8045 emitcode ("lcall", "__gptrput");
8047 emitcode ("inc", "dptr");
8051 if (pi && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD) {
8052 aopPut (AOP(result),"dpl",0);
8053 aopPut (AOP(result),"dph",1);
8054 aopPut (AOP(result),"b",2);
8057 freeAsmop (result, NULL, ic, TRUE);
8058 freeAsmop (right, NULL, ic, TRUE);
8061 /*-----------------------------------------------------------------*/
8062 /* genPointerSet - stores the value into a pointer location */
8063 /*-----------------------------------------------------------------*/
8065 genPointerSet (iCode * ic, iCode *pi)
8067 operand *right, *result;
8068 sym_link *type, *etype;
8071 D(emitcode (";", "genPointerSet"));
8073 right = IC_RIGHT (ic);
8074 result = IC_RESULT (ic);
8076 /* depending on the type of pointer we need to
8077 move it to the correct pointer register */
8078 type = operandType (result);
8079 etype = getSpec (type);
8080 /* if left is of type of pointer then it is simple */
8081 if (IS_PTR (type) && !IS_FUNC (type->next))
8083 p_type = DCL_TYPE (type);
8087 /* we have to go by the storage class */
8088 p_type = PTR_TYPE (SPEC_OCLS (etype));
8091 /* special case when cast remat */
8092 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
8093 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
8094 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
8095 type = type = operandType (result);
8096 p_type = DCL_TYPE (type);
8098 /* now that we have the pointer type we assign
8099 the pointer values */
8105 genNearPointerSet (right, result, ic, pi);
8109 genPagedPointerSet (right, result, ic, pi);
8113 genFarPointerSet (right, result, ic, pi);
8117 genGenPointerSet (right, result, ic, pi);
8123 /*-----------------------------------------------------------------*/
8124 /* genIfx - generate code for Ifx statement */
8125 /*-----------------------------------------------------------------*/
8127 genIfx (iCode * ic, iCode * popIc)
8129 operand *cond = IC_COND (ic);
8132 D(emitcode (";", "genIfx"));
8134 aopOp (cond, ic, FALSE);
8136 /* get the value into acc */
8137 if (AOP_TYPE (cond) != AOP_CRY)
8141 /* the result is now in the accumulator */
8142 freeAsmop (cond, NULL, ic, TRUE);
8144 /* if there was something to be popped then do it */
8148 /* if the condition is a bit variable */
8149 if (isbit && IS_ITEMP (cond) &&
8151 genIfxJump (ic, SPIL_LOC (cond)->rname);
8152 else if (isbit && !IS_ITEMP (cond))
8153 genIfxJump (ic, OP_SYMBOL (cond)->rname);
8155 genIfxJump (ic, "a");
8160 /*-----------------------------------------------------------------*/
8161 /* genAddrOf - generates code for address of */
8162 /*-----------------------------------------------------------------*/
8164 genAddrOf (iCode * ic)
8166 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
8169 D(emitcode (";", "genAddrOf"));
8171 aopOp (IC_RESULT (ic), ic, FALSE);
8173 /* if the operand is on the stack then we
8174 need to get the stack offset of this
8178 /* if it has an offset then we need to compute
8182 emitcode ("mov", "a,_bp");
8183 emitcode ("add", "a,#0x%02x", ((sym->stack < 0) ?
8184 ((char) (sym->stack - _G.nRegsSaved)) :
8185 ((char) sym->stack)) & 0xff);
8186 aopPut (AOP (IC_RESULT (ic)), "a", 0);
8190 /* we can just move _bp */
8191 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
8193 /* fill the result with zero */
8194 size = AOP_SIZE (IC_RESULT (ic)) - 1;
8199 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
8205 /* object not on stack then we need the name */
8206 size = AOP_SIZE (IC_RESULT (ic));
8211 char s[SDCC_NAME_MAX];
8213 sprintf (s, "#(%s >> %d)",
8217 sprintf (s, "#%s", sym->rname);
8218 aopPut (AOP (IC_RESULT (ic)), s, offset++);
8222 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8226 /*-----------------------------------------------------------------*/
8227 /* genFarFarAssign - assignment when both are in far space */
8228 /*-----------------------------------------------------------------*/
8230 genFarFarAssign (operand * result, operand * right, iCode * ic)
8232 int size = AOP_SIZE (right);
8236 D(emitcode (";", "genFarFarAssign"));
8238 /* first push the right side on to the stack */
8241 l = aopGet (AOP (right), offset++, FALSE, FALSE);
8243 emitcode ("push", "acc");
8246 freeAsmop (right, NULL, ic, FALSE);
8247 /* now assign DPTR to result */
8248 aopOp (result, ic, FALSE);
8249 size = AOP_SIZE (result);
8252 emitcode ("pop", "acc");
8253 aopPut (AOP (result), "a", --offset);
8255 freeAsmop (result, NULL, ic, FALSE);
8259 /*-----------------------------------------------------------------*/
8260 /* genAssign - generate code for assignment */
8261 /*-----------------------------------------------------------------*/
8263 genAssign (iCode * ic)
8265 operand *result, *right;
8267 unsigned long lit = 0L;
8269 D(emitcode(";","genAssign"));
8271 result = IC_RESULT (ic);
8272 right = IC_RIGHT (ic);
8274 /* if they are the same */
8275 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8278 aopOp (right, ic, FALSE);
8280 /* special case both in far space */
8281 if (AOP_TYPE (right) == AOP_DPTR &&
8282 IS_TRUE_SYMOP (result) &&
8283 isOperandInFarSpace (result))
8286 genFarFarAssign (result, right, ic);
8290 aopOp (result, ic, TRUE);
8292 /* if they are the same registers */
8293 if (sameRegs (AOP (right), AOP (result)))
8296 /* if the result is a bit */
8297 if (AOP_TYPE (result) == AOP_CRY)
8300 /* if the right size is a literal then
8301 we know what the value is */
8302 if (AOP_TYPE (right) == AOP_LIT)
8304 if (((int) operandLitValue (right)))
8305 aopPut (AOP (result), one, 0);
8307 aopPut (AOP (result), zero, 0);
8311 /* the right is also a bit variable */
8312 if (AOP_TYPE (right) == AOP_CRY)
8314 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8315 aopPut (AOP (result), "c", 0);
8321 aopPut (AOP (result), "a", 0);
8325 /* bit variables done */
8327 size = AOP_SIZE (result);
8329 if (AOP_TYPE (right) == AOP_LIT)
8330 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
8332 (AOP_TYPE (result) != AOP_REG) &&
8333 (AOP_TYPE (right) == AOP_LIT) &&
8334 !IS_FLOAT (operandType (right)) &&
8337 emitcode ("clr", "a");
8340 if ((unsigned int) ((lit >> (size * 8)) & 0x0FFL) == 0)
8341 aopPut (AOP (result), "a", size);
8343 aopPut (AOP (result),
8344 aopGet (AOP (right), size, FALSE, FALSE),
8352 aopPut (AOP (result),
8353 aopGet (AOP (right), offset, FALSE, FALSE),
8360 freeAsmop (right, NULL, ic, TRUE);
8361 freeAsmop (result, NULL, ic, TRUE);
8364 /*-----------------------------------------------------------------*/
8365 /* genJumpTab - genrates code for jump table */
8366 /*-----------------------------------------------------------------*/
8368 genJumpTab (iCode * ic)
8373 D(emitcode (";", "genJumpTab"));
8375 aopOp (IC_JTCOND (ic), ic, FALSE);
8376 /* get the condition into accumulator */
8377 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE);
8379 /* multiply by three */
8380 emitcode ("add", "a,acc");
8381 emitcode ("add", "a,%s", aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE));
8382 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
8384 jtab = newiTempLabel (NULL);
8385 emitcode ("mov", "dptr,#%05d$", jtab->key + 100);
8386 emitcode ("jmp", "@a+dptr");
8387 emitcode ("", "%05d$:", jtab->key + 100);
8388 /* now generate the jump labels */
8389 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
8390 jtab = setNextItem (IC_JTLABELS (ic)))
8391 emitcode ("ljmp", "%05d$", jtab->key + 100);
8395 /*-----------------------------------------------------------------*/
8396 /* genCast - gen code for casting */
8397 /*-----------------------------------------------------------------*/
8399 genCast (iCode * ic)
8401 operand *result = IC_RESULT (ic);
8402 sym_link *ctype = operandType (IC_LEFT (ic));
8403 sym_link *rtype = operandType (IC_RIGHT (ic));
8404 operand *right = IC_RIGHT (ic);
8407 D(emitcode(";", "genCast"));
8409 /* if they are equivalent then do nothing */
8410 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
8413 aopOp (right, ic, FALSE);
8414 aopOp (result, ic, FALSE);
8416 /* if the result is a bit */
8417 // if (AOP_TYPE (result) == AOP_CRY /* works only for true symbols */
8418 if (IS_BITVAR(OP_SYMBOL(result)->type))
8420 /* if the right size is a literal then
8421 we know what the value is */
8422 if (AOP_TYPE (right) == AOP_LIT)
8424 if (((int) operandLitValue (right)))
8425 aopPut (AOP (result), one, 0);
8427 aopPut (AOP (result), zero, 0);
8432 /* the right is also a bit variable */
8433 if (AOP_TYPE (right) == AOP_CRY)
8435 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
8436 aopPut (AOP (result), "c", 0);
8442 aopPut (AOP (result), "a", 0);
8446 /* if they are the same size : or less */
8447 if (AOP_SIZE (result) <= AOP_SIZE (right))
8450 /* if they are in the same place */
8451 if (sameRegs (AOP (right), AOP (result)))
8454 /* if they in different places then copy */
8455 size = AOP_SIZE (result);
8459 aopPut (AOP (result),
8460 aopGet (AOP (right), offset, FALSE, FALSE),
8468 /* if the result is of type pointer */
8473 sym_link *type = operandType (right);
8474 sym_link *etype = getSpec (type);
8476 /* pointer to generic pointer */
8477 if (IS_GENPTR (ctype))
8482 p_type = DCL_TYPE (type);
8485 if (SPEC_SCLS(etype)==S_REGISTER) {
8486 // let's assume it is a generic pointer
8489 /* we have to go by the storage class */
8490 p_type = PTR_TYPE (SPEC_OCLS (etype));
8494 /* the first two bytes are known */
8495 size = GPTRSIZE - 1;
8499 aopPut (AOP (result),
8500 aopGet (AOP (right), offset, FALSE, FALSE),
8504 /* the last byte depending on type */
8520 case PPOINTER: // what the fck is this?
8525 /* this should never happen */
8526 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8527 "got unknown pointer type");
8530 aopPut (AOP (result), l, GPTRSIZE - 1);
8534 /* just copy the pointers */
8535 size = AOP_SIZE (result);
8539 aopPut (AOP (result),
8540 aopGet (AOP (right), offset, FALSE, FALSE),
8547 /* so we now know that the size of destination is greater
8548 than the size of the source */
8549 /* we move to result for the size of source */
8550 size = AOP_SIZE (right);
8554 aopPut (AOP (result),
8555 aopGet (AOP (right), offset, FALSE, FALSE),
8560 /* now depending on the sign of the source && destination */
8561 size = AOP_SIZE (result) - AOP_SIZE (right);
8562 /* if unsigned or not an integral type */
8563 if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
8566 aopPut (AOP (result), zero, offset++);
8570 /* we need to extend the sign :{ */
8571 char *l = aopGet (AOP (right), AOP_SIZE (right) - 1,
8574 emitcode ("rlc", "a");
8575 emitcode ("subb", "a,acc");
8577 aopPut (AOP (result), "a", offset++);
8580 /* we are done hurray !!!! */
8583 freeAsmop (right, NULL, ic, TRUE);
8584 freeAsmop (result, NULL, ic, TRUE);
8588 /*-----------------------------------------------------------------*/
8589 /* genDjnz - generate decrement & jump if not zero instrucion */
8590 /*-----------------------------------------------------------------*/
8592 genDjnz (iCode * ic, iCode * ifx)
8598 D(emitcode (";", "genDjnz"));
8600 /* if the if condition has a false label
8601 then we cannot save */
8605 /* if the minus is not of the form
8607 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
8608 !IS_OP_LITERAL (IC_RIGHT (ic)))
8611 if (operandLitValue (IC_RIGHT (ic)) != 1)
8614 /* if the size of this greater than one then no
8616 if (getSize (operandType (IC_RESULT (ic))) > 1)
8619 /* otherwise we can save BIG */
8620 lbl = newiTempLabel (NULL);
8621 lbl1 = newiTempLabel (NULL);
8623 aopOp (IC_RESULT (ic), ic, FALSE);
8625 if (AOP_NEEDSACC(IC_RESULT(ic)))
8627 /* If the result is accessed indirectly via
8628 * the accumulator, we must explicitly write
8629 * it back after the decrement.
8631 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
8633 if (strcmp(rByte, "a"))
8635 /* Something is hopelessly wrong */
8636 fprintf(stderr, "*** warning: internal error at %s:%d\n",
8637 __FILE__, __LINE__);
8638 /* We can just give up; the generated code will be inefficient,
8641 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8644 emitcode ("dec", "%s", rByte);
8645 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
8646 emitcode ("jnz", "%05d$", lbl->key + 100);
8648 else if (IS_AOP_PREG (IC_RESULT (ic)))
8650 emitcode ("dec", "%s",
8651 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8652 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
8653 emitcode ("jnz", "%05d$", lbl->key + 100);
8657 emitcode ("djnz", "%s,%05d$", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE),
8660 emitcode ("sjmp", "%05d$", lbl1->key + 100);
8661 emitcode ("", "%05d$:", lbl->key + 100);
8662 emitcode ("ljmp", "%05d$", IC_TRUE (ifx)->key + 100);
8663 emitcode ("", "%05d$:", lbl1->key + 100);
8665 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8670 /*-----------------------------------------------------------------*/
8671 /* genReceive - generate code for a receive iCode */
8672 /*-----------------------------------------------------------------*/
8674 genReceive (iCode * ic)
8676 D(emitcode (";", "genReceive"));
8678 if (isOperandInFarSpace (IC_RESULT (ic)) &&
8679 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
8680 IS_TRUE_SYMOP (IC_RESULT (ic))))
8683 int size = getSize (operandType (IC_RESULT (ic)));
8684 int offset = fReturnSizeMCS51 - size;
8687 emitcode ("push", "%s", (strcmp (fReturn[fReturnSizeMCS51 - offset - 1], "a") ?
8688 fReturn[fReturnSizeMCS51 - offset - 1] : "acc"));
8691 aopOp (IC_RESULT (ic), ic, FALSE);
8692 size = AOP_SIZE (IC_RESULT (ic));
8696 emitcode ("pop", "acc");
8697 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
8704 aopOp (IC_RESULT (ic), ic, FALSE);
8706 assignResultValue (IC_RESULT (ic));
8709 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
8712 /*-----------------------------------------------------------------*/
8713 /* gen51AggregateAssign - copy complete array's or structures */
8714 /*-----------------------------------------------------------------*/
8715 void gen51AggregateAssign(iCode *ic) {
8716 operand *left=IC_LEFT(ic);
8717 operand *right=IC_RIGHT(ic);
8718 char *fromName=OP_SYMBOL(right)->rname;
8719 char *toName=OP_SYMBOL(left)->rname;
8720 int fromSize=getSize(OP_SYMBOL(right)->type);
8721 int toSize=getSize(OP_SYMBOL(left)->type);
8724 D(emitcode (";", "gen51AggregateAssign"));
8726 if (SPEC_OCLS(OP_SYMBOL(left)->etype)!=xdata ||
8727 SPEC_OCLS(OP_SYMBOL(right)->etype)!=code) {
8728 // well, this code isn't used yet from anywhere else as for initialising
8729 fprintf (stderr, "*** error: %s:%d can only assign aggregates from cseg to xseg for now\n", ic->filename, ic->lineno);
8733 if (fromSize!=toSize) {
8734 fprintf (stderr, "*** error: %s:%d aggregates have different size\n",
8735 ic->filename, ic->lineno);
8740 // use the generic memcpy() for now
8741 emitcode (";", "initialize %s", OP_SYMBOL(IC_LEFT(ic))->name);
8742 emitcode ("mov", "dptr,#_memcpy_PARM_2");
8743 emitcode ("mov", "a,#%s", fromName);
8744 emitcode ("movx", "@dptr,a");
8745 emitcode ("inc", "dptr");
8746 emitcode ("mov", "a,#(%s>>8)", fromName);
8747 emitcode ("movx", "@dptr,a");
8748 emitcode ("inc", "dptr");
8749 emitcode ("mov", "a,#%02x; only from cseg for now", 2);
8750 emitcode ("movx", "@dptr,a");
8751 emitcode ("mov", "dptr,#_memcpy_PARM_3");
8752 emitcode ("mov", "a,#(%d>>0); number of bytes", count);
8753 emitcode ("movx", "@dptr,a");
8754 emitcode ("inc", "dptr");
8755 emitcode ("mov", "a,#(%d>>8)", count);
8756 emitcode ("movx", "@dptr,a");
8757 emitcode ("mov", "dptr,#%s", toName);
8758 emitcode ("mov", "b,#%02x; only to xseg for now", 1);
8759 emitcode ("lcall", "_memcpy");
8761 // more efficient, but will require the native_memcpy_cs2xs
8762 emitcode ("mov", "r0,#%s", fromName);
8763 emitcode ("mov", "r1,#(%s>>8)", fromName);
8764 emitcode ("mov", "r2,#%s", toName);
8765 emitcode ("mov", "r3,#(%s>>8)", toName);
8766 emitcode ("mov", "r4,#%d", count);
8767 emitcode ("mov", "r5,#(%d>>8)", count);
8768 emitcode ("lcall", "_native_memcpy_cs2xs");
8772 /*-----------------------------------------------------------------*/
8773 /* gen51Code - generate code for 8051 based controllers */
8774 /*-----------------------------------------------------------------*/
8776 gen51Code (iCode * lic)
8781 lineHead = lineCurr = NULL;
8783 /* print the allocation information */
8785 printAllocInfo (currFunc, codeOutFile);
8786 /* if debug information required */
8787 /* if (options.debug && currFunc) { */
8788 if (options.debug && currFunc)
8790 cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
8792 if (IS_STATIC (currFunc->etype))
8793 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
8795 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
8798 /* stack pointer name */
8799 if (options.useXstack)
8805 for (ic = lic; ic; ic = ic->next)
8808 if (cln != ic->lineno)
8813 emitcode ("", "C$%s$%d$%d$%d ==.",
8814 FileBaseName (ic->filename), ic->lineno,
8815 ic->level, ic->block);
8818 emitcode (";", "%s %d", ic->filename, ic->lineno);
8821 /* if the result is marked as
8822 spilt and rematerializable or code for
8823 this has already been generated then
8825 if (resultRemat (ic) || ic->generated)
8828 /* depending on the operation */
8848 /* IPOP happens only when trying to restore a
8849 spilt live range, if there is an ifx statement
8850 following this pop then the if statement might
8851 be using some of the registers being popped which
8852 would destory the contents of the register so
8853 we need to check for this condition and handle it */
8855 ic->next->op == IFX &&
8856 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
8857 genIfx (ic->next, ic);
8875 genEndFunction (ic);
8895 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
8912 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
8916 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
8923 /* note these two are xlated by algebraic equivalence
8924 during parsing SDCC.y */
8925 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
8926 "got '>=' or '<=' shouldn't have come here");
8930 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
8942 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
8946 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
8950 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
8977 case GET_VALUE_AT_ADDRESS:
8978 genPointerGet (ic, hasInc(IC_LEFT(ic),ic));
8982 if (POINTER_SET (ic))
8983 genPointerSet (ic, hasInc (IC_RESULT(ic),ic));
9009 addSet (&_G.sendSet, ic);
9013 gen51AggregateAssign(ic);
9022 /* now we are ready to call the
9023 peep hole optimizer */
9024 if (!options.nopeep)
9025 peepHole (&lineHead);
9027 /* now do the actual printing */
9028 printLine (lineHead, codeOutFile);