1 /*-------------------------------------------------------------------------
2 gen.c - source file for code generation for DS80C390
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)
7 DS390 adaptation by Kevin Vigor <kevin@vigor.nu>
9 This program is free software; you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation; either version 2, or (at your option) any
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 In other words, you are welcome to use, share and improve this program.
24 You are forbidden to forbid anyone else to use, share and improve
25 what you give them. Help stamp out software-hoarding!
26 -------------------------------------------------------------------------*/
36 #include "SDCCglobl.h"
39 #define BETTER_LITERAL_SHIFT
41 char *aopLiteral (value * val, int offset);
44 /* this is the down and dirty file with all kinds of
45 kludgy & hacky stuff. This is what it is all about
46 CODE GENERATION for a specific MCU . some of the
47 routines may be reusable, will have to see */
49 static char *zero = "#0";
50 static char *one = "#1";
55 #define TR_DPTR(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_DPTR1 %s ", s); }
56 #define TR_AP(s) if (options.model != MODEL_FLAT24) { emitcode(";", " Use_AP %s ", s); }
58 unsigned fReturnSizeDS390 = 5; /* shared with ralloc.c */
59 static char *fReturn24[] =
60 {"dpl", "dph", "dpx", "b", "a"};
61 static char *fReturn16[] =
62 {"dpl", "dph", "b", "a"};
63 static char **fReturn = fReturn24;
64 static char *accUse[] =
66 static char *dptrn[2][3];
67 static char *javaRet[] = { "r0","r1","r2","r3"};
68 static short rbank = -1;
85 static char *rb1regs[] = {
86 "b1_0","b1_1","b1_2","b1_3","b1_4","b1_5","b1_6","b1_7"
89 static void saveRBank (int, iCode *, bool);
91 #define RESULTONSTACK(x) \
92 (IC_RESULT(x) && IC_RESULT(x)->aop && \
93 IC_RESULT(x)->aop->type == AOP_STK )
95 #define MOVA(x) _movA(x)
96 #define MOVB(x) _movB(x)
98 #define CLRC emitcode("clr","c")
99 #define SETC emitcode("setb","c")
101 // A scratch register which will be used to hold
102 // result bytes from operands in far space via DPTR2.
103 #define DP2_RESULT_REG "_ap"
105 static lineNode *lineHead = NULL;
106 static lineNode *lineCurr = NULL;
108 static unsigned char SLMask[] =
109 {0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
110 0xE0, 0xC0, 0x80, 0x00};
111 static unsigned char SRMask[] =
112 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
113 0x07, 0x03, 0x01, 0x00};
119 #define PROTECT_SP {if (options.protect_sp_update) { \
120 symbol *lbl = newiTempLabel(NULL); \
121 emitcode ("setb","F1"); \
122 emitcode ("jbc","EA,!tlabel",lbl->key+100); \
123 emitcode ("clr","F1"); \
124 emitcode ("","!tlabeldef",lbl->key+100); \
126 #define UNPROTECT_SP { if (options.protect_sp_update) { \
127 symbol *lbl = newiTempLabel(NULL); \
128 emitcode ("jnb","F1,!tlabel",lbl->key+100); \
129 emitcode ("setb","EA"); \
130 emitcode ("","!tlabeldef",lbl->key+100); \
134 /*-----------------------------------------------------------------*/
135 /* emitcode - writes the code into a file : for now it is simple */
136 /*-----------------------------------------------------------------*/
138 emitcode (char *inst, char *fmt,...)
141 char lb[INITIAL_INLINEASM];
150 SNPRINTF (lb, sizeof(lb), "%s\t", inst);
154 SNPRINTF (lb, sizeof(lb), "%s", inst);
157 tvsprintf (lb + strlen(lb), sizeof(lb) - strlen(lb),
162 tvsprintf (lb, sizeof(lb), fmt, ap);
166 while (isspace (*lbp))
173 lineCurr = (lineCurr ?
174 connectLine (lineCurr, newLineNode (lb)) :
175 (lineHead = newLineNode (lb)));
178 lineCurr->isInline = _G.inLine;
179 lineCurr->isDebug = _G.debugLine;
184 // Move the passed value into A unless it is already there.
189 if (strcmp(s,"a") && strcmp(s,"acc"))
191 emitcode("mov","a,%s",s);
196 // Move the passed value into B unless it is already there.
203 emitcode("mov","b,%s",s);
207 /*-----------------------------------------------------------------*/
208 /* getFreePtr - returns r0 or r1 whichever is free or can be pushed */
209 /*-----------------------------------------------------------------*/
211 getFreePtr (iCode * ic, asmop ** aopp, bool result)
216 /* the logic: if r0 & r1 used in the instruction
217 then we are in trouble otherwise */
219 /* first check if r0 & r1 are used by this
220 instruction, in which case we are in trouble */
221 r0iu = bitVectBitValue (ic->rUsed, R0_IDX);
222 r1iu = bitVectBitValue (ic->rUsed, R1_IDX);
227 r0ou = bitVectBitValue (ic->rMask, R0_IDX);
228 r1ou = bitVectBitValue (ic->rMask, R1_IDX);
230 /* if no usage of r0 then return it */
233 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
234 (*aopp)->type = AOP_R0;
236 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
239 /* if no usage of r1 then return it */
242 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
243 (*aopp)->type = AOP_R1;
245 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R1_IDX);
248 /* now we know they both have usage */
249 /* if r0 not used in this instruction */
252 /* push it if not already pushed */
255 emitcode ("push", "%s",
256 ds390_regWithIdx (R0_IDX)->dname);
260 ic->rUsed = bitVectSetBit (ic->rUsed, R0_IDX);
261 (*aopp)->type = AOP_R0;
263 return (*aopp)->aopu.aop_ptr = ds390_regWithIdx (R0_IDX);
266 /* if r1 not used then */
270 /* push it if not already pushed */
273 emitcode ("push", "%s",
274 ds390_regWithIdx (R1_IDX)->dname);
278 ic->rUsed = bitVectSetBit (ic->rUsed, R1_IDX);
279 (*aopp)->type = AOP_R1;
280 return ds390_regWithIdx (R1_IDX);
284 /* I said end of world but not quite end of world yet */
285 /* if this is a result then we can push it on the stack */
288 (*aopp)->type = AOP_STK;
292 /* other wise this is true end of the world */
293 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
294 "getFreePtr should never reach here");
297 return NULL; // notreached, but makes compiler happy.
300 /*-----------------------------------------------------------------*/
301 /* newAsmop - creates a new asmOp */
302 /*-----------------------------------------------------------------*/
304 newAsmop (short type)
308 aop = Safe_calloc (1, sizeof (asmop));
313 static int _currentDPS; /* Current processor DPS. */
314 static int _desiredDPS; /* DPS value compiler thinks we should be using. */
315 static int _lazyDPS = 0; /* if non-zero, we are doing lazy evaluation of DPS changes. */
317 /*-----------------------------------------------------------------*/
318 /* genSetDPTR: generate code to select which DPTR is in use (zero */
319 /* selects standard DPTR (DPL/DPH/DPX), non-zero selects DS390 */
320 /* alternate DPTR (DPL1/DPH1/DPX1). */
321 /*-----------------------------------------------------------------*/
326 /* If we are doing lazy evaluation, simply note the desired
327 * change, but don't emit any code yet.
337 emitcode ("mov", "dps,#0");
342 emitcode ("mov", "dps,#1");
346 /*-----------------------------------------------------------------*/
347 /* _startLazyDPSEvaluation: call to start doing lazy DPS evaluation */
349 /* Any code that operates on DPTR (NB: not on the individual */
350 /* components, like DPH) *must* call _flushLazyDPS() before using */
351 /* DPTR within a lazy DPS evaluation block. */
353 /* Note that aopPut and aopGet already contain the proper calls to */
354 /* _flushLazyDPS, so it is safe to use these calls within a lazy */
355 /* DPS evaluation block. */
357 /* Also, _flushLazyDPS must be called before any flow control */
358 /* operations that could potentially branch out of the block. */
360 /* Lazy DPS evaluation is simply an optimization (though an */
361 /* important one), so if in doubt, leave it out. */
362 /*-----------------------------------------------------------------*/
364 _startLazyDPSEvaluation (void)
368 #ifdef BETTER_LITERAL_SHIFT
375 /*-----------------------------------------------------------------*/
376 /* _flushLazyDPS: emit code to force the actual DPS setting to the */
377 /* desired one. Call before using DPTR within a lazy DPS evaluation */
379 /*-----------------------------------------------------------------*/
389 if (_desiredDPS != _currentDPS)
393 emitcode ("inc", "dps");
397 emitcode ("dec", "dps");
399 _currentDPS = _desiredDPS;
403 /*-----------------------------------------------------------------*/
404 /* _endLazyDPSEvaluation: end lazy DPS evaluation block. */
406 /* Forces us back to the safe state (standard DPTR selected). */
407 /*-----------------------------------------------------------------*/
409 _endLazyDPSEvaluation (void)
411 #ifdef BETTER_LITERAL_SHIFT
430 /*-----------------------------------------------------------------*/
431 /* pointerCode - returns the code for a pointer type */
432 /*-----------------------------------------------------------------*/
434 pointerCode (sym_link * etype)
437 return PTR_TYPE (SPEC_OCLS (etype));
441 /*-----------------------------------------------------------------*/
442 /* leftRightUseAcc - returns size of accumulator use by operands */
443 /*-----------------------------------------------------------------*/
445 leftRightUseAcc(iCode *ic)
454 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
455 "null iCode pointer");
462 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
465 size = getSize (OP_SYMBOL (op)->type);
470 else if (ic->op == JUMPTABLE)
473 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
476 size = getSize (OP_SYMBOL (op)->type);
484 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
487 size = getSize (OP_SYMBOL (op)->type);
492 if (IS_SYMOP (op) && OP_SYMBOL (op) && OP_SYMBOL (op)->accuse)
495 size = getSize (OP_SYMBOL (op)->type);
507 /*-----------------------------------------------------------------*/
508 /* aopForSym - for a true symbol */
509 /*-----------------------------------------------------------------*/
511 aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
514 memmap *space = SPEC_OCLS (sym->etype);
515 int accuse = leftRightUseAcc (ic);
517 /* if already has one */
521 /* assign depending on the storage class */
522 /* if it is on the stack or indirectly addressable */
523 /* space we need to assign either r0 or r1 to it */
524 if ((sym->onStack && !options.stack10bit) || sym->iaccess)
526 sym->aop = aop = newAsmop (0);
527 aop->aopu.aop_ptr = getFreePtr (ic, &aop, result);
528 aop->size = getSize (sym->type);
530 /* now assign the address of the variable to
531 the pointer register */
532 if (aop->type != AOP_STK)
537 if (_G.accInUse || accuse)
538 emitcode ("push", "acc");
540 if (_G.bInUse || (accuse>1))
541 emitcode ("push", "b");
543 emitcode ("mov", "a,_bp");
544 emitcode ("add", "a,#!constbyte",
546 ((char) (sym->stack - _G.nRegsSaved)) :
547 ((char) sym->stack)) & 0xff);
548 emitcode ("mov", "%s,a",
549 aop->aopu.aop_ptr->name);
551 if (_G.bInUse || (accuse>1))
552 emitcode ("pop", "b");
554 if (_G.accInUse || accuse)
555 emitcode ("pop", "acc");
558 emitcode ("mov", "%s,#%s",
559 aop->aopu.aop_ptr->name,
561 aop->paged = space->paged;
564 aop->aopu.aop_stk = sym->stack;
568 if (sym->onStack && options.stack10bit)
570 short stack_val = -((sym->stack < 0) ?
571 ((short) (sym->stack - _G.nRegsSaved)) :
572 ((short) sym->stack)) ;
573 if (useDP2 && _G.dptr1InUse) {
574 emitcode ("push","dpl1");
575 emitcode ("push","dph1");
576 emitcode ("push","dpx1");
577 } else if (_G.dptrInUse ) {
578 emitcode ("push","dpl");
579 emitcode ("push","dph");
580 emitcode ("push","dpx");
582 /* It's on the 10 bit stack, which is located in
585 if (stack_val < 0 && stack_val > -5) { /* between -5 & -1 */
587 if (options.model == MODEL_FLAT24)
589 emitcode ("mov", "dpx1,#!constbyte",
590 (options.stack_loc >> 16) & 0xff);
592 emitcode ("mov", "dph1,_bpx+1");
594 emitcode ("mov", "dpl1,_bpx");
595 emitcode ("mov","dps,#1");
597 if (options.model == MODEL_FLAT24)
599 emitcode ("mov", "dpx,#!constbyte",
600 (options.stack_loc >> 16) & 0xff);
602 emitcode ("mov", "dph,_bpx+1");
603 emitcode ("mov", "dpl,_bpx");
605 stack_val = -stack_val;
606 while (stack_val--) {
607 emitcode ("inc","dptr");
610 emitcode("mov","dps,#0");
613 if (_G.accInUse || accuse)
614 emitcode ("push", "acc");
616 if (_G.bInUse || (accuse>1))
617 emitcode ("push", "b");
619 emitcode ("mov", "a,_bpx");
620 emitcode ("clr","c");
621 emitcode ("subb", "a,#!constbyte", stack_val & 0xff);
622 emitcode ("mov","b,a");
623 emitcode ("mov","a,_bpx+1");
624 emitcode ("subb","a,#!constbyte",(stack_val >> 8) & 0xff);
626 if (options.model == MODEL_FLAT24)
628 emitcode ("mov", "dpx1,#!constbyte",
629 (options.stack_loc >> 16) & 0xff);
631 emitcode ("mov", "dph1,a");
632 emitcode ("mov", "dpl1,b");
634 if (options.model == MODEL_FLAT24)
636 emitcode ("mov", "dpx,#!constbyte",
637 (options.stack_loc >> 16) & 0xff);
639 emitcode ("mov", "dph,a");
640 emitcode ("mov", "dpl,b");
643 if (_G.bInUse || (accuse>1))
644 emitcode ("pop", "b");
646 if (_G.accInUse || accuse)
647 emitcode ("pop", "acc");
649 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
650 aop->size = getSize (sym->type);
654 /* if in bit space */
655 if (IN_BITSPACE (space))
657 sym->aop = aop = newAsmop (AOP_CRY);
658 aop->aopu.aop_dir = sym->rname;
659 aop->size = getSize (sym->type);
662 /* if it is in direct space */
663 if (IN_DIRSPACE (space))
665 sym->aop = aop = newAsmop (AOP_DIR);
666 aop->aopu.aop_dir = sym->rname;
667 aop->size = getSize (sym->type);
671 /* special case for a function */
672 if (IS_FUNC (sym->type) && !(sym->isitmp))
674 sym->aop = aop = newAsmop (AOP_IMMD);
675 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(sym->rname);
676 aop->size = FPTRSIZE;
680 /* only remaining is far space */
681 /* in which case DPTR gets the address */
682 sym->aop = aop = newAsmop ((short) (useDP2 ? AOP_DPTR2 : AOP_DPTR));
687 emitcode ("mov", "dptr,#%s", sym->rname);
692 emitcode ("mov", "dptr,#%s", sym->rname);
694 aop->size = getSize (sym->type);
696 /* if it is in code space */
697 if (IN_CODESPACE (space))
703 /*-----------------------------------------------------------------*/
704 /* aopForRemat - rematerialzes an object */
705 /*-----------------------------------------------------------------*/
707 aopForRemat (symbol * sym)
709 iCode *ic = sym->rematiCode;
710 asmop *aop = newAsmop (AOP_IMMD);
717 val += (int) operandLitValue (IC_RIGHT (ic));
718 else if (ic->op == '-')
719 val -= (int) operandLitValue (IC_RIGHT (ic));
720 else if (IS_CAST_ICODE(ic)) {
721 sym_link *from_type = operandType(IC_RIGHT(ic));
722 aop->aopu.aop_immd.from_cast_remat = 1;
723 ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
724 ptr_type = DCL_TYPE(from_type);
725 if (ptr_type == IPOINTER) {
732 ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
737 SNPRINTF (buffer, sizeof(buffer),
739 OP_SYMBOL (IC_LEFT (ic))->rname,
740 val >= 0 ? '+' : '-',
741 abs (val) & 0xffffff);
745 if (IS_ASSIGN_ICODE(ic) && isOperandLiteral(IC_RIGHT(ic)))
747 SNPRINTF(buffer, sizeof(buffer),
748 "0x%x",(int) operandLitValue (IC_RIGHT (ic)));
752 strncpyz (buffer, OP_SYMBOL (IC_LEFT (ic))->rname, sizeof(buffer));
756 aop->aopu.aop_immd.aop_immd1 = Safe_strdup(buffer);
757 /* set immd2 field if required */
758 if (aop->aopu.aop_immd.from_cast_remat)
760 tsprintf(buffer, sizeof(buffer), "#!constbyte",ptr_type);
761 aop->aopu.aop_immd.aop_immd2 = Safe_strdup(buffer);
767 /*-----------------------------------------------------------------*/
768 /* aopHasRegs - returns true if aop has regs between from-to */
769 /*-----------------------------------------------------------------*/
770 static int aopHasRegs(asmop *aop, int from, int to)
774 if (aop->type != AOP_REG) return 0; /* if not assigned to regs */
776 for (; size < aop->size ; size++) {
778 for (reg = from ; reg <= to ; reg++)
779 if (aop->aopu.aop_reg[size] == ds390_regWithIdx(reg)) return 1;
784 /*-----------------------------------------------------------------*/
785 /* regsInCommon - two operands have some registers in common */
786 /*-----------------------------------------------------------------*/
788 regsInCommon (operand * op1, operand * op2)
793 /* if they have registers in common */
794 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
797 sym1 = OP_SYMBOL (op1);
798 sym2 = OP_SYMBOL (op2);
800 if (sym1->nRegs == 0 || sym2->nRegs == 0)
803 for (i = 0; i < sym1->nRegs; i++)
809 for (j = 0; j < sym2->nRegs; j++)
814 if (sym2->regs[j] == sym1->regs[i])
822 /*-----------------------------------------------------------------*/
823 /* operandsEqu - equivalent */
824 /*-----------------------------------------------------------------*/
826 operandsEqu (operand * op1, operand * op2)
830 /* if they not symbols */
831 if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
834 sym1 = OP_SYMBOL (op1);
835 sym2 = OP_SYMBOL (op2);
837 /* if both are itemps & one is spilt
838 and the other is not then false */
839 if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
840 sym1->isspilt != sym2->isspilt)
843 /* if they are the same */
847 if (strcmp (sym1->rname, sym2->rname) == 0)
851 /* if left is a tmp & right is not */
852 if (IS_ITEMP (op1) &&
855 (sym1->usl.spillLoc == sym2))
858 if (IS_ITEMP (op2) &&
862 (sym2->usl.spillLoc == sym1))
868 /*-----------------------------------------------------------------*/
869 /* sameRegs - two asmops have the same registers */
870 /*-----------------------------------------------------------------*/
872 sameRegs (asmop * aop1, asmop * aop2)
878 if (aop1->type == AOP_DPTR || aop1->type == AOP_DPTR2)
885 if (aop1->type != AOP_REG ||
886 aop2->type != AOP_REG)
889 if (aop1->size != aop2->size)
892 for (i = 0; i < aop1->size; i++)
893 if (aop1->aopu.aop_reg[i] !=
894 aop2->aopu.aop_reg[i])
900 /*-----------------------------------------------------------------*/
901 /* aopOp - allocates an asmop for an operand : */
902 /*-----------------------------------------------------------------*/
904 aopOp (operand * op, iCode * ic, bool result, bool useDP2)
913 /* if this a literal */
914 if (IS_OP_LITERAL (op))
916 op->aop = aop = newAsmop (AOP_LIT);
917 aop->aopu.aop_lit = op->operand.valOperand;
918 aop->size = getSize (operandType (op));
922 /* if already has a asmop then continue */
926 /* if the underlying symbol has a aop */
927 if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
929 op->aop = OP_SYMBOL (op)->aop;
933 /* if this is a true symbol */
934 if (IS_TRUE_SYMOP (op))
936 op->aop = aopForSym (ic, OP_SYMBOL (op), result, useDP2);
940 /* this is a temporary : this has
946 e) can be a return use only */
948 sym = OP_SYMBOL (op);
951 /* if the type is a conditional */
952 if (sym->regType == REG_CND)
954 aop = op->aop = sym->aop = newAsmop (AOP_CRY);
959 /* if it is spilt then two situations
961 b) has a spill location */
962 if (sym->isspilt || sym->nRegs == 0)
965 /* rematerialize it NOW */
968 sym->aop = op->aop = aop =
970 aop->size = getSize (sym->type);
977 aop = op->aop = sym->aop = newAsmop (AOP_ACC);
978 aop->size = getSize (sym->type);
979 for (i = 0; i < 2; i++)
980 aop->aopu.aop_str[i] = accUse[i];
990 /* a AOP_STR uses DPTR, but DPTR is already in use;
993 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"AOP_STR with DPTR in use!");
996 aop = op->aop = sym->aop = newAsmop (AOP_STR);
997 aop->size = getSize (sym->type);
998 for (i = 0; i < (int) fReturnSizeDS390; i++)
999 aop->aopu.aop_str[i] = fReturn[i];
1003 if (sym->dptr) { /* has been allocated to a DPTRn */
1004 aop = op->aop = sym->aop = newAsmop (AOP_DPTRn);
1005 aop->size = getSize (sym->type);
1006 aop->aopu.dptr = sym->dptr;
1009 /* else spill location */
1010 if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
1011 /* force a new aop if sizes differ */
1012 sym->usl.spillLoc->aop = NULL;
1014 sym->aop = op->aop = aop =
1015 aopForSym (ic, sym->usl.spillLoc, result, useDP2);
1016 aop->size = getSize (sym->type);
1020 /* must be in a register */
1021 sym->aop = op->aop = aop = newAsmop (AOP_REG);
1022 aop->size = sym->nRegs;
1023 for (i = 0; i < sym->nRegs; i++)
1024 aop->aopu.aop_reg[i] = sym->regs[i];
1027 /*-----------------------------------------------------------------*/
1028 /* freeAsmop - free up the asmop given to an operand */
1029 /*----------------------------------------------------------------*/
1031 freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
1048 /* depending on the asmop type only three cases need work AOP_RO
1049 , AOP_R1 && AOP_STK */
1057 emitcode ("pop", "ar0");
1061 bitVectUnSetBit (ic->rUsed, R0_IDX);
1069 emitcode ("pop", "ar1");
1073 bitVectUnSetBit (ic->rUsed, R1_IDX);
1079 int stk = aop->aopu.aop_stk + aop->size;
1080 bitVectUnSetBit (ic->rUsed, R0_IDX);
1081 bitVectUnSetBit (ic->rUsed, R1_IDX);
1083 getFreePtr (ic, &aop, FALSE);
1085 if (options.stack10bit)
1087 /* I'm not sure what to do here yet... */
1090 "*** Warning: probably generating bad code for "
1091 "10 bit stack mode.\n");
1096 emitcode ("mov", "a,_bp");
1097 emitcode ("add", "a,#!constbyte", ((char) stk) & 0xff);
1098 emitcode ("mov", "%s,a", aop->aopu.aop_ptr->name);
1102 emitcode ("mov", "%s,_bp", aop->aopu.aop_ptr->name);
1107 emitcode ("pop", "acc");
1108 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1111 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1114 freeAsmop (op, NULL, ic, TRUE);
1117 emitcode ("pop", "ar0");
1123 emitcode ("pop", "ar1");
1128 if (_G.dptr1InUse) {
1129 emitcode ("pop","dpx1");
1130 emitcode ("pop","dph1");
1131 emitcode ("pop","dpl1");
1136 emitcode ("pop","dpx");
1137 emitcode ("pop","dph");
1138 emitcode ("pop","dpl");
1143 /* all other cases just dealloc */
1149 OP_SYMBOL (op)->aop = NULL;
1150 /* if the symbol has a spill */
1152 SPIL_LOC (op)->aop = NULL;
1157 #define DEFAULT_ACC_WARNING 0
1158 static int saveAccWarn = DEFAULT_ACC_WARNING;
1160 /*-------------------------------------------------------------------*/
1161 /* aopGet - for fetching value of the aop */
1163 /* Set saveAcc to NULL if you are sure it is OK to clobber the value */
1164 /* in the accumulator. Set it to the name of a free register */
1165 /* if acc must be preserved; the register will be used to preserve */
1166 /* acc temporarily and to return the result byte. */
1167 /*-------------------------------------------------------------------*/
1176 /* offset is greater than
1178 if (offset > (aop->size - 1) &&
1179 aop->type != AOP_LIT)
1182 /* depending on type */
1188 /* if we need to increment it */
1189 while (offset > aop->coff)
1191 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1195 while (offset < aop->coff)
1197 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1204 emitcode ("movx", "a,@%s", aop->aopu.aop_ptr->name);
1205 return (dname ? "acc" : "a");
1207 SNPRINTF (buffer, sizeof(buffer), "@%s", aop->aopu.aop_ptr->name);
1208 return Safe_strdup(buffer);
1211 assert(offset <= 3);
1212 return dptrn[aop->aopu.dptr][offset];
1217 if (aop->type == AOP_DPTR2)
1225 // if (aop->type != AOP_DPTR2)
1227 // if (saveAccWarn) { fprintf(stderr, "saveAcc for DPTR...\n"); }
1228 // emitcode(";", "spanky: saveAcc for DPTR");
1231 emitcode ("xch", "a, %s", saveAcc);
1236 while (offset > aop->coff)
1238 emitcode ("inc", "dptr");
1242 while (offset < aop->coff)
1244 emitcode ("lcall", "__decdptr");
1251 emitcode ("clr", "a");
1252 emitcode ("movc", "a,@a+dptr");
1256 emitcode ("movx", "a,@dptr");
1259 if (aop->type == AOP_DPTR2)
1267 emitcode ("xch", "a, %s", saveAcc);
1268 // if (strcmp(saveAcc, "_ap"))
1270 // emitcode(";", "spiffy: non _ap return from aopGet.");
1275 return (dname ? "acc" : "a");
1278 if (aop->aopu.aop_immd.from_cast_remat && (offset == (aop->size-1)))
1280 SNPRINTF(buffer, sizeof(buffer),
1281 "%s",aop->aopu.aop_immd.aop_immd2);
1285 SNPRINTF(buffer, sizeof(buffer),
1286 "#%s", aop->aopu.aop_immd.aop_immd1);
1292 tsprintf(buffer, sizeof(buffer),
1293 "#!his",aop->aopu.aop_immd.aop_immd1);
1296 tsprintf(buffer, sizeof(buffer),
1297 "#!hihis",aop->aopu.aop_immd.aop_immd1);
1300 tsprintf(buffer, sizeof(buffer),
1301 "#!hihihis",aop->aopu.aop_immd.aop_immd1);
1303 default: /* should not need this (just in case) */
1304 SNPRINTF (buffer, sizeof(buffer),
1306 aop->aopu.aop_immd.aop_immd1,
1312 SNPRINTF (buffer, sizeof(buffer),
1313 "#%s", aop->aopu.aop_immd.aop_immd1);
1315 return Safe_strdup(buffer);
1320 SNPRINTF (buffer, sizeof(buffer),
1327 SNPRINTF(buffer, sizeof(buffer),
1328 "%s", aop->aopu.aop_dir);
1331 return Safe_strdup(buffer);
1335 return aop->aopu.aop_reg[offset]->dname;
1337 return aop->aopu.aop_reg[offset]->name;
1340 emitcode ("clr", "a");
1341 emitcode ("mov", "c,%s", aop->aopu.aop_dir);
1342 emitcode ("rlc", "a");
1343 return (dname ? "acc" : "a");
1346 if (!offset && dname)
1348 return aop->aopu.aop_str[offset];
1351 return aopLiteral (aop->aopu.aop_lit, offset);
1355 if (strcmp (aop->aopu.aop_str[offset], "a") == 0 &&
1359 return aop->aopu.aop_str[offset];
1363 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1364 "aopget got unsupported aop->type");
1367 return NULL; // not reached, but makes compiler happy.
1369 /*-----------------------------------------------------------------*/
1370 /* aopPut - puts a string for a aop */
1371 /*-----------------------------------------------------------------*/
1373 aopPut (asmop * aop, char *s, int offset)
1375 if (aop->size && offset > (aop->size - 1))
1377 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1378 "aopPut got offset > aop->size");
1382 /* will assign value to value */
1383 /* depending on where it is ofcourse */
1389 SNPRINTF (buffer, sizeof(buffer),
1391 aop->aopu.aop_dir, offset);
1395 SNPRINTF (buffer, sizeof(buffer),
1396 "%s", aop->aopu.aop_dir);
1400 if (strcmp (buffer, s))
1402 emitcode ("mov", "%s,%s", buffer, s);
1407 if (strcmp (aop->aopu.aop_reg[offset]->name, s) != 0 &&
1408 strcmp (aop->aopu.aop_reg[offset]->dname, s) != 0)
1411 strcmp (s, "r0") == 0 ||
1412 strcmp (s, "r1") == 0 ||
1413 strcmp (s, "r2") == 0 ||
1414 strcmp (s, "r3") == 0 ||
1415 strcmp (s, "r4") == 0 ||
1416 strcmp (s, "r5") == 0 ||
1417 strcmp (s, "r6") == 0 ||
1418 strcmp (s, "r7") == 0)
1420 emitcode ("mov", "%s,%s",
1421 aop->aopu.aop_reg[offset]->dname, s);
1425 emitcode ("mov", "%s,%s",
1426 aop->aopu.aop_reg[offset]->name, s);
1432 emitcode ("mov","%s,%s",dptrn[aop->aopu.dptr][offset],s);
1438 if (aop->type == AOP_DPTR2)
1446 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1447 "aopPut writting to code space");
1451 while (offset > aop->coff)
1454 emitcode ("inc", "dptr");
1457 while (offset < aop->coff)
1460 emitcode ("lcall", "__decdptr");
1465 /* if not in accumulater */
1468 emitcode ("movx", "@dptr,a");
1470 if (aop->type == AOP_DPTR2)
1478 while (offset > aop->coff)
1481 emitcode ("inc", "%s", aop->aopu.aop_ptr->name);
1483 while (offset < aop->coff)
1486 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1493 emitcode ("movx", "@%s,a", aop->aopu.aop_ptr->name);
1499 emitcode ("mov", "@%s,a", aop->aopu.aop_ptr->name);
1501 else if (strcmp (s, "r0") == 0 ||
1502 strcmp (s, "r1") == 0 ||
1503 strcmp (s, "r2") == 0 ||
1504 strcmp (s, "r3") == 0 ||
1505 strcmp (s, "r4") == 0 ||
1506 strcmp (s, "r5") == 0 ||
1507 strcmp (s, "r6") == 0 ||
1508 strcmp (s, "r7") == 0)
1511 SNPRINTF(buff, sizeof(buff),
1513 emitcode ("mov", "@%s,%s",
1514 aop->aopu.aop_ptr->name, buff);
1518 emitcode ("mov", "@%s,%s", aop->aopu.aop_ptr->name, s);
1523 if (strcmp (s, "a") == 0)
1524 emitcode ("push", "acc");
1528 emitcode ("push", "acc");
1530 emitcode ("push", s);
1536 /* if bit variable */
1537 if (!aop->aopu.aop_dir)
1539 emitcode ("clr", "a");
1540 emitcode ("rlc", "a");
1545 emitcode ("clr", "%s", aop->aopu.aop_dir);
1547 emitcode ("setb", "%s", aop->aopu.aop_dir);
1548 else if (!strcmp (s, "c"))
1549 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1552 if (strcmp (s, "a"))
1557 /* set C, if a >= 1 */
1558 emitcode ("add", "a,#!constbyte",0xff);
1559 emitcode ("mov", "%s,c", aop->aopu.aop_dir);
1567 if (strcmp (aop->aopu.aop_str[offset], s))
1568 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1573 if (!offset && (strcmp (s, "acc") == 0))
1576 if (strcmp (aop->aopu.aop_str[offset], s))
1577 emitcode ("mov", "%s,%s", aop->aopu.aop_str[offset], s);
1581 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
1582 "aopPut got unsupported aop->type");
1589 /*--------------------------------------------------------------------*/
1590 /* reAdjustPreg - points a register back to where it should (coff==0) */
1591 /*--------------------------------------------------------------------*/
1593 reAdjustPreg (asmop * aop)
1595 if ((aop->coff==0) || (aop->size <= 1)) {
1604 emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
1608 if (aop->type == AOP_DPTR2)
1615 emitcode ("lcall", "__decdptr");
1618 if (aop->type == AOP_DPTR2)
1628 #define AOP(op) op->aop
1629 #define AOP_TYPE(op) AOP(op)->type
1630 #define AOP_SIZE(op) AOP(op)->size
1631 #define IS_AOP_PREG(x) (AOP(x) && (AOP_TYPE(x) == AOP_R1 || \
1632 AOP_TYPE(x) == AOP_R0))
1634 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY || \
1635 AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
1638 #define AOP_INPREG(x) (x && (x->type == AOP_REG && \
1639 (x->aopu.aop_reg[0] == ds390_regWithIdx(R0_IDX) || \
1640 x->aopu.aop_reg[0] == ds390_regWithIdx(R1_IDX) )))
1641 #define AOP_INDPTRn(x) (AOP_TYPE(x) == AOP_DPTRn)
1642 #define AOP_USESDPTR(x) ((AOP_TYPE(x) == AOP_DPTR) || (AOP_TYPE(x) == AOP_STR))
1643 #define AOP_USESDPTR2(x) ((AOP_TYPE(x) == AOP_DPTR2) || (AOP_TYPE(x) == AOP_DPTRn))
1645 // The following two macros can be used even if the aop has not yet been aopOp'd.
1646 #define AOP_IS_STR(x) (IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
1647 #define AOP_IS_DPTRn(x) (IS_SYMOP(x) && OP_SYMBOL(x)->dptr)
1649 /* Workaround for DS80C390 bug: div ab may return bogus results
1650 * if A is accessed in instruction immediately before the div.
1652 * Will be fixed in B4 rev of processor, Dallas claims.
1655 #define LOAD_AB_FOR_DIV(LEFT, RIGHT, L) \
1656 if (!AOP_NEEDSACC(RIGHT)) \
1658 /* We can load A first, then B, since \
1659 * B (the RIGHT operand) won't clobber A, \
1660 * thus avoiding touching A right before the div. \
1662 D(emitcode(";", "DS80C390 div bug: rearranged ops.");); \
1663 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1665 L = aopGet(AOP(RIGHT),0,FALSE,FALSE,"b"); \
1670 /* Just stuff in a nop after loading A. */ \
1671 emitcode("mov","b,%s",aopGet(AOP(RIGHT),0,FALSE,FALSE,NULL));\
1672 L = aopGet(AOP(LEFT),0,FALSE,FALSE,NULL); \
1674 emitcode("nop", "; workaround for DS80C390 div bug."); \
1678 /*-----------------------------------------------------------------*/
1679 /* opIsGptr: returns non-zero if the passed operand is */
1680 /* a generic pointer type. */
1681 /*-----------------------------------------------------------------*/
1683 opIsGptr (operand * op)
1685 sym_link *type = operandType (op);
1687 if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
1694 /*-----------------------------------------------------------------*/
1695 /* getDataSize - get the operand data size */
1696 /*-----------------------------------------------------------------*/
1698 getDataSize (operand * op)
1701 size = AOP_SIZE (op);
1702 if (size == GPTRSIZE)
1704 sym_link *type = operandType (op);
1705 if (IS_GENPTR (type))
1707 /* generic pointer; arithmetic operations
1708 * should ignore the high byte (pointer type).
1716 /*-----------------------------------------------------------------*/
1717 /* outAcc - output Acc */
1718 /*-----------------------------------------------------------------*/
1720 outAcc (operand * result)
1723 size = getDataSize (result);
1726 aopPut (AOP (result), "a", 0);
1729 /* unsigned or positive */
1732 aopPut (AOP (result), zero, offset++);
1737 /*-----------------------------------------------------------------*/
1738 /* outBitC - output a bit C */
1739 /*-----------------------------------------------------------------*/
1741 outBitC (operand * result)
1743 /* if the result is bit */
1744 if (AOP_TYPE (result) == AOP_CRY)
1746 aopPut (AOP (result), "c", 0);
1750 emitcode ("clr", "a");
1751 emitcode ("rlc", "a");
1756 /*-----------------------------------------------------------------*/
1757 /* toBoolean - emit code for orl a,operator(sizeop) */
1758 /*-----------------------------------------------------------------*/
1760 toBoolean (operand * oper)
1762 int size = AOP_SIZE (oper) - 1;
1766 /* The generic part of a generic pointer should
1767 * not participate in it's truth value.
1769 * i.e. 0x10000000 is zero.
1771 if (opIsGptr (oper))
1773 D (emitcode (";", "toBoolean: generic ptr special case."););
1777 _startLazyDPSEvaluation ();
1778 if (AOP_NEEDSACC (oper) && size)
1783 emitcode ("push", "b");
1785 MOVB (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1789 MOVA (aopGet (AOP (oper), 0, FALSE, FALSE, NULL));
1796 emitcode ("orl", "b,%s",
1797 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1801 emitcode ("orl", "a,%s",
1802 aopGet (AOP (oper), offset++, FALSE, FALSE, NULL));
1805 _endLazyDPSEvaluation ();
1809 emitcode ("mov", "a,b");
1812 emitcode ("pop", "b");
1819 /*-----------------------------------------------------------------*/
1820 /* genNot - generate code for ! operation */
1821 /*-----------------------------------------------------------------*/
1827 D (emitcode (";", "genNot "););
1829 /* assign asmOps to operand & result */
1830 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1831 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1833 /* if in bit space then a special case */
1834 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1836 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1837 emitcode ("cpl", "c");
1838 outBitC (IC_RESULT (ic));
1842 toBoolean (IC_LEFT (ic));
1844 tlbl = newiTempLabel (NULL);
1845 emitcode ("cjne", "a,#1,!tlabel", tlbl->key + 100);
1846 emitcode ("", "!tlabeldef", tlbl->key + 100);
1847 outBitC (IC_RESULT (ic));
1850 /* release the aops */
1851 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1852 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1856 /*-----------------------------------------------------------------*/
1857 /* genCpl - generate code for complement */
1858 /*-----------------------------------------------------------------*/
1866 D (emitcode (";", "genCpl "););
1869 /* assign asmOps to operand & result */
1870 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1871 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1873 /* special case if in bit space */
1874 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY) {
1875 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY) {
1876 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1877 emitcode ("cpl", "c");
1878 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1881 tlbl=newiTempLabel(NULL);
1882 emitcode ("cjne", "%s,#0x01,%05d$",
1883 aopGet(AOP(IC_LEFT(ic)), 0, FALSE,FALSE,NULL), tlbl->key+100);
1884 emitcode ("", "%05d$:", tlbl->key+100);
1885 outBitC (IC_RESULT(ic));
1889 size = AOP_SIZE (IC_RESULT (ic));
1890 _startLazyDPSEvaluation ();
1893 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
1894 emitcode ("cpl", "a");
1895 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1897 _endLazyDPSEvaluation ();
1901 /* release the aops */
1902 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
1903 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
1906 /*-----------------------------------------------------------------*/
1907 /* genUminusFloat - unary minus for floating points */
1908 /*-----------------------------------------------------------------*/
1910 genUminusFloat (operand * op, operand * result)
1912 int size, offset = 0;
1914 D(emitcode (";", "genUminusFloat"););
1916 /* for this we just copy and then flip the bit */
1918 _startLazyDPSEvaluation ();
1919 size = AOP_SIZE (op) - 1;
1923 aopPut (AOP (result),
1924 aopGet (AOP (op), offset, FALSE, FALSE, NULL),
1929 MOVA(aopGet (AOP (op), offset, FALSE, FALSE, NULL));
1931 emitcode ("cpl", "acc.7");
1932 aopPut (AOP (result), "a", offset);
1933 _endLazyDPSEvaluation ();
1936 /*-----------------------------------------------------------------*/
1937 /* genUminus - unary minus code generation */
1938 /*-----------------------------------------------------------------*/
1940 genUminus (iCode * ic)
1945 D (emitcode (";", "genUminus "););
1948 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
1949 aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR(IC_LEFT (ic)));
1951 /* if both in bit space then special
1953 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY &&
1954 AOP_TYPE (IC_LEFT (ic)) == AOP_CRY)
1957 emitcode ("mov", "c,%s", IC_LEFT (ic)->aop->aopu.aop_dir);
1958 emitcode ("cpl", "c");
1959 emitcode ("mov", "%s,c", IC_RESULT (ic)->aop->aopu.aop_dir);
1963 optype = operandType (IC_LEFT (ic));
1965 /* if float then do float stuff */
1966 if (IS_FLOAT (optype))
1968 genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
1972 /* otherwise subtract from zero */
1973 size = AOP_SIZE (IC_LEFT (ic));
1975 _startLazyDPSEvaluation ();
1978 char *l = aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL);
1979 if (!strcmp (l, "a"))
1983 emitcode ("cpl", "a");
1984 emitcode ("addc", "a,#0");
1990 emitcode ("clr", "a");
1991 emitcode ("subb", "a,%s", l);
1993 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
1995 _endLazyDPSEvaluation ();
1997 /* if any remaining bytes in the result */
1998 /* we just need to propagate the sign */
1999 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic)))) != 0)
2001 emitcode ("rlc", "a");
2002 emitcode ("subb", "a,acc");
2004 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
2008 /* release the aops */
2009 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? 0 : 1));
2010 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2013 /*-----------------------------------------------------------------*/
2014 /* savermask - saves registers in the mask */
2015 /*-----------------------------------------------------------------*/
2016 static void savermask(bitVect *rs_mask)
2019 if (options.useXstack) {
2020 if (bitVectBitValue (rs_mask, R0_IDX))
2021 emitcode ("mov", "b,r0");
2022 emitcode ("mov", "r0,%s", spname);
2023 for (i = 0; i < ds390_nRegs; i++) {
2024 if (bitVectBitValue (rs_mask, i)) {
2026 emitcode ("mov", "a,b");
2028 emitcode ("mov", "a,%s", ds390_regWithIdx (i)->name);
2029 emitcode ("movx", "@r0,a");
2030 emitcode ("inc", "r0");
2033 emitcode ("mov", "%s,r0", spname);
2034 if (bitVectBitValue (rs_mask, R0_IDX))
2035 emitcode ("mov", "r0,b");
2037 for (i = 0; i < ds390_nRegs; i++) {
2038 if (bitVectBitValue (rs_mask, i))
2039 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2044 /*-----------------------------------------------------------------*/
2045 /* saveRegisters - will look for a call and save the registers */
2046 /*-----------------------------------------------------------------*/
2048 saveRegisters (iCode * lic)
2054 for (ic = lic; ic; ic = ic->next)
2055 if (ic->op == CALL || ic->op == PCALL)
2060 fprintf (stderr, "found parameter push with no function call\n");
2064 /* if the registers have been saved already then
2067 || (IS_SYMOP(IC_LEFT(ic)) && IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT(ic))) && !TARGET_IS_DS400) )
2070 /* special case if DPTR alive across a function call then must save it
2071 even though callee saves */
2072 if (IS_SYMOP(IC_LEFT(ic)) &&
2073 IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2075 rsave = newBitVect(ic->rMask->size);
2076 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2077 if (bitVectBitValue(ic->rMask,i))
2078 rsave = bitVectSetBit(rsave,i);
2080 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2082 /* safe the registers in use at this time but skip the
2083 ones for the result */
2084 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2085 ds390_rUmaskForOp (IC_RESULT(ic)));
2091 /*-----------------------------------------------------------------*/
2092 /* usavermask - restore registers with mask */
2093 /*-----------------------------------------------------------------*/
2094 static void unsavermask(bitVect *rs_mask)
2097 if (options.useXstack) {
2098 emitcode ("mov", "r0,%s", spname);
2099 for (i = ds390_nRegs; i >= 0; i--) {
2100 if (bitVectBitValue (rs_mask, i)) {
2101 emitcode ("dec", "r0");
2102 emitcode ("movx", "a,@r0");
2104 emitcode ("mov", "b,a");
2106 emitcode ("mov", "%s,a", ds390_regWithIdx (i)->name);
2109 emitcode ("mov", "%s,r0", spname);
2110 if (bitVectBitValue (rs_mask, R0_IDX))
2111 emitcode ("mov", "r0,b");
2113 for (i = ds390_nRegs; i >= 0; i--) {
2114 if (bitVectBitValue (rs_mask, i))
2115 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
2120 /*-----------------------------------------------------------------*/
2121 /* unsaveRegisters - pop the pushed registers */
2122 /*-----------------------------------------------------------------*/
2124 unsaveRegisters (iCode * ic)
2128 if (IFFUNC_CALLEESAVES(OP_SYMBOL (IC_LEFT (ic))->type)) {
2130 rsave = newBitVect(ic->rMask->size);
2131 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
2132 if (bitVectBitValue(ic->rMask,i))
2133 rsave = bitVectSetBit(rsave,i);
2135 rsave = bitVectCplAnd(rsave,ds390_rUmaskForOp (IC_RESULT(ic)));
2137 /* restore the registers in use at this time but skip the
2138 ones for the result */
2139 rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
2140 ds390_rUmaskForOp (IC_RESULT(ic)));
2146 /*-----------------------------------------------------------------*/
2148 /*-----------------------------------------------------------------*/
2150 pushSide (operand * oper, int size)
2153 _startLazyDPSEvaluation ();
2156 char *l = aopGet (AOP (oper), offset++, FALSE, TRUE, NULL);
2157 if (AOP_TYPE (oper) != AOP_REG &&
2158 AOP_TYPE (oper) != AOP_DIR &&
2161 emitcode ("mov", "a,%s", l);
2162 emitcode ("push", "acc");
2165 emitcode ("push", "%s", l);
2167 _endLazyDPSEvaluation ();
2170 /*-----------------------------------------------------------------*/
2171 /* assignResultValue - */
2172 /*-----------------------------------------------------------------*/
2174 assignResultValue (operand * oper)
2177 int size = AOP_SIZE (oper);
2178 bool pushedAcc = FALSE;
2180 if (size == fReturnSizeDS390)
2182 /* I don't think this case can ever happen... */
2183 /* ACC is the last part of this. If writing the result
2184 * uses AC, we must preserve it.
2186 if (AOP_NEEDSACC(oper))
2188 emitcode(";", "assignResultValue special case for ACC.");
2189 emitcode("push", "acc");
2196 _startLazyDPSEvaluation ();
2199 aopPut (AOP (oper), fReturn[offset], offset);
2202 _endLazyDPSEvaluation ();
2206 emitcode("pop", "acc");
2207 aopPut(AOP(oper), "a", offset);
2212 /*-----------------------------------------------------------------*/
2213 /* genXpush - pushes onto the external stack */
2214 /*-----------------------------------------------------------------*/
2216 genXpush (iCode * ic)
2218 asmop *aop = newAsmop (0);
2220 int size, offset = 0;
2222 D (emitcode (";", "genXpush ");
2225 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2226 r = getFreePtr (ic, &aop, FALSE);
2229 emitcode ("mov", "%s,_spx", r->name);
2231 size = AOP_SIZE (IC_LEFT (ic));
2232 _startLazyDPSEvaluation ();
2236 MOVA (aopGet (AOP (IC_LEFT (ic)),
2237 offset++, FALSE, FALSE, NULL));
2238 emitcode ("movx", "@%s,a", r->name);
2239 emitcode ("inc", "%s", r->name);
2242 _endLazyDPSEvaluation ();
2245 emitcode ("mov", "_spx,%s", r->name);
2247 freeAsmop (NULL, aop, ic, TRUE);
2248 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2251 /*-----------------------------------------------------------------*/
2252 /* genIpush - generate code for pushing this gets a little complex */
2253 /*-----------------------------------------------------------------*/
2255 genIpush (iCode * ic)
2257 int size, offset = 0;
2260 D (emitcode (";", "genIpush ");
2263 /* if this is not a parm push : ie. it is spill push
2264 and spill push is always done on the local stack */
2268 /* and the item is spilt then do nothing */
2269 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL(IC_LEFT(ic))->dptr)
2272 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2273 size = AOP_SIZE (IC_LEFT (ic));
2274 /* push it on the stack */
2275 _startLazyDPSEvaluation ();
2278 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2284 emitcode ("push", "%s", l);
2286 _endLazyDPSEvaluation ();
2290 /* this is a paramter push: in this case we call
2291 the routine to find the call and save those
2292 registers that need to be saved */
2295 /* if use external stack then call the external
2296 stack pushing routine */
2297 if (options.useXstack)
2303 /* then do the push */
2304 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2306 // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
2307 size = AOP_SIZE (IC_LEFT (ic));
2309 _startLazyDPSEvaluation ();
2312 l = aopGet (AOP (IC_LEFT (ic)), offset++, FALSE, TRUE, NULL);
2313 if (AOP_TYPE (IC_LEFT (ic)) != AOP_REG &&
2314 AOP_TYPE (IC_LEFT (ic)) != AOP_DIR &&
2317 emitcode ("mov", "a,%s", l);
2318 emitcode ("push", "acc");
2322 emitcode ("push", "%s", l);
2325 _endLazyDPSEvaluation ();
2327 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2330 /*-----------------------------------------------------------------*/
2331 /* genIpop - recover the registers: can happen only for spilling */
2332 /*-----------------------------------------------------------------*/
2334 genIpop (iCode * ic)
2338 D (emitcode (";", "genIpop ");
2342 /* if the temp was not pushed then */
2343 if (OP_SYMBOL (IC_LEFT (ic))->isspilt || OP_SYMBOL (IC_LEFT (ic))->dptr)
2346 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2347 size = AOP_SIZE (IC_LEFT (ic));
2348 offset = (size - 1);
2349 _startLazyDPSEvaluation ();
2352 emitcode ("pop", "%s", aopGet (AOP (IC_LEFT (ic)), offset--,
2353 FALSE, TRUE, NULL));
2355 _endLazyDPSEvaluation ();
2357 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2360 /*-----------------------------------------------------------------*/
2361 /* unsaveRBank - restores the resgister bank from stack */
2362 /*-----------------------------------------------------------------*/
2364 unsaveRBank (int bank, iCode * ic, bool popPsw)
2370 if (options.useXstack)
2374 /* Assume r0 is available for use. */
2375 r = ds390_regWithIdx (R0_IDX);;
2380 r = getFreePtr (ic, &aop, FALSE);
2382 emitcode ("mov", "%s,_spx", r->name);
2387 if (options.useXstack)
2389 emitcode ("movx", "a,@%s", r->name);
2390 emitcode ("mov", "psw,a");
2391 emitcode ("dec", "%s", r->name);
2395 emitcode ("pop", "psw");
2399 for (i = 7; i >= 0; i--) /* only R7-R0 needs to be popped */
2401 if (options.useXstack)
2403 emitcode ("movx", "a,@%s", r->name);
2404 emitcode ("mov", "(%s+%d),a",
2405 regs390[i].base, 8 * bank + regs390[i].offset);
2406 emitcode ("dec", "%s", r->name);
2410 emitcode ("pop", "(%s+%d)",
2411 regs390[i].base, 8 * bank + regs390[i].offset);
2414 if (options.useXstack)
2416 emitcode ("mov", "_spx,%s", r->name);
2421 freeAsmop (NULL, aop, ic, TRUE);
2425 /*-----------------------------------------------------------------*/
2426 /* saveRBank - saves an entire register bank on the stack */
2427 /*-----------------------------------------------------------------*/
2429 saveRBank (int bank, iCode * ic, bool pushPsw)
2435 if (options.useXstack)
2439 /* Assume r0 is available for use. */
2440 r = ds390_regWithIdx (R0_IDX);;
2445 r = getFreePtr (ic, &aop, FALSE);
2447 emitcode ("mov", "%s,_spx", r->name);
2450 for (i = 0; i < 8 ; i++) /* only R0-R7 needs saving */
2452 if (options.useXstack)
2454 emitcode ("inc", "%s", r->name);
2455 emitcode ("mov", "a,(%s+%d)",
2456 regs390[i].base, 8 * bank + regs390[i].offset);
2457 emitcode ("movx", "@%s,a", r->name);
2460 emitcode ("push", "(%s+%d)",
2461 regs390[i].base, 8 * bank + regs390[i].offset);
2466 if (options.useXstack)
2468 emitcode ("mov", "a,psw");
2469 emitcode ("movx", "@%s,a", r->name);
2470 emitcode ("inc", "%s", r->name);
2471 emitcode ("mov", "_spx,%s", r->name);
2475 emitcode ("push", "psw");
2478 emitcode ("mov", "psw,#!constbyte", (bank << 3) & 0x00ff);
2483 freeAsmop (NULL, aop, ic, TRUE);
2492 /*-----------------------------------------------------------------*/
2493 /* genSend - gen code for SEND */
2494 /*-----------------------------------------------------------------*/
2495 static void genSend(set *sendSet)
2499 static int rb1_count = 0;
2501 for (sic = setFirstItem (sendSet); sic;
2502 sic = setNextItem (sendSet)) {
2503 int size, offset = 0;
2505 size=getSize(operandType(IC_LEFT(sic)));
2506 D (emitcode (";", "genSend argreg = %d, size = %d ",sic->argreg,size));
2507 if (sendCount == 0) { /* first parameter */
2508 // we know that dpl(hxb) is the result, so
2510 _startLazyDPSEvaluation ();
2512 aopOp (IC_LEFT (sic), sic, FALSE,
2513 (AOP_IS_STR(IC_LEFT(sic)) ? FALSE : TRUE));
2515 aopOp (IC_LEFT (sic), sic, FALSE, FALSE);
2518 char *l = aopGet (AOP (IC_LEFT (sic)), offset,
2519 FALSE, FALSE, NULL);
2520 if (strcmp (l, fReturn[offset])) {
2521 emitcode ("mov", "%s,%s",
2527 _endLazyDPSEvaluation ();
2528 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2530 } else { /* if more parameter in registers */
2531 aopOp (IC_LEFT (sic), sic, FALSE, TRUE);
2533 emitcode ("mov","b1_%d,%s",rb1_count++,aopGet (AOP (IC_LEFT (sic)), offset++,
2534 FALSE, FALSE, NULL));
2536 freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
2543 adjustEsp(const char *reg)
2545 emitcode ("anl","%s,#3", reg);
2546 if (TARGET_IS_DS400)
2548 emitcode ("orl","%s,#!constbyte",
2550 (options.stack_loc >> 8) & 0xff);
2554 /*-----------------------------------------------------------------*/
2555 /* genCall - generates a call statement */
2556 /*-----------------------------------------------------------------*/
2558 genCall (iCode * ic)
2561 bool restoreBank = FALSE;
2562 bool swapBanks = FALSE;
2564 D (emitcode (";", "genCall "););
2566 /* if we are calling a not _naked function that is not using
2567 the same register bank then we need to save the
2568 destination registers on the stack */
2569 dtype = operandType (IC_LEFT (ic));
2570 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2571 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype)) &&
2572 IFFUNC_ISISR (currFunc->type))
2576 /* This is unexpected; the bank should have been saved in
2579 saveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2585 /* if caller saves & we have not saved then */
2589 /* if send set is not empty the assign */
2590 /* We've saved all the registers we care about;
2591 * therefore, we may clobber any register not used
2592 * in the calling convention (i.e. anything not in
2597 if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
2598 genSend(reverseSet(_G.sendSet));
2600 genSend(_G.sendSet);
2607 emitcode ("mov", "psw,#!constbyte",
2608 ((FUNC_REGBANK(dtype)) << 3) & 0xff);
2612 emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
2613 OP_SYMBOL (IC_LEFT (ic))->rname :
2614 OP_SYMBOL (IC_LEFT (ic))->name));
2618 emitcode ("mov", "psw,#!constbyte",
2619 ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
2622 /* if we need assign a result value */
2623 if ((IS_ITEMP (IC_RESULT (ic)) &&
2624 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2625 OP_SYMBOL (IC_RESULT (ic))->accuse ||
2626 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2627 IS_TRUE_SYMOP (IC_RESULT (ic)))
2629 if (isOperandInFarSpace (IC_RESULT (ic))
2630 && getSize (operandType (IC_RESULT (ic))) <= 2)
2632 int size = getSize (operandType (IC_RESULT (ic)));
2634 /* Special case for 1 or 2 byte return in far space. */
2638 emitcode ("mov", "b,%s", fReturn[1]);
2641 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
2642 aopPut (AOP (IC_RESULT (ic)), "a", 0);
2646 aopPut (AOP (IC_RESULT (ic)), "b", 1);
2648 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2653 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2656 assignResultValue (IC_RESULT (ic));
2658 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2662 /* adjust the stack for parameters if
2664 if (ic->parmBytes) {
2666 if (options.stack10bit) {
2667 if (ic->parmBytes <= 10) {
2668 emitcode(";","stack adjustment for parms");
2669 for (i=0; i < ic->parmBytes ; i++) {
2670 emitcode("pop","acc");
2674 emitcode ("clr","c");
2675 emitcode ("mov","a,sp");
2676 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2677 emitcode ("mov","sp,a");
2678 emitcode ("mov","a,esp");
2680 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2681 emitcode ("mov","esp,a");
2685 if (ic->parmBytes > 3) {
2686 emitcode ("mov", "a,%s", spname);
2687 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2688 emitcode ("mov", "%s,a", spname);
2690 for (i = 0; i < ic->parmBytes; i++)
2691 emitcode ("dec", "%s", spname);
2695 /* if we hade saved some registers then unsave them */
2697 unsaveRegisters (ic);
2699 /* if register bank was saved then pop them */
2701 unsaveRBank (FUNC_REGBANK (dtype), ic, FALSE);
2704 /*-----------------------------------------------------------------*/
2705 /* genPcall - generates a call by pointer statement */
2706 /*-----------------------------------------------------------------*/
2708 genPcall (iCode * ic)
2711 symbol *rlbl = newiTempLabel (NULL);
2712 bool restoreBank=FALSE;
2714 D (emitcode (";", "genPcall ");
2718 /* if caller saves & we have not saved then */
2722 /* if we are calling a function that is not using
2723 the same register bank then we need to save the
2724 destination registers on the stack */
2725 dtype = operandType (IC_LEFT (ic));
2726 if (currFunc && dtype && (!IFFUNC_ISNAKED(dtype) || TARGET_IS_DS400) &&
2727 IFFUNC_ISISR (currFunc->type) &&
2728 (FUNC_REGBANK (currFunc->type) != FUNC_REGBANK (dtype))) {
2729 saveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2733 /* push the return address on to the stack */
2734 emitcode ("mov", "a,#!tlabel", (rlbl->key + 100));
2735 emitcode ("push", "acc");
2736 emitcode ("mov", "a,#!hil", (rlbl->key + 100));
2737 emitcode ("push", "acc");
2739 if (options.model == MODEL_FLAT24)
2741 emitcode ("mov", "a,#!hihil", (rlbl->key + 100));
2742 emitcode ("push", "acc");
2745 /* now push the calling address */
2746 aopOp (IC_LEFT (ic), ic, FALSE, FALSE);
2748 pushSide (IC_LEFT (ic), FPTRSIZE);
2750 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
2752 /* if send set is not empty the assign */
2755 genSend(reverseSet(_G.sendSet));
2759 emitcode ("ret", "");
2760 emitcode ("", "!tlabeldef", (rlbl->key + 100));
2763 /* if we need assign a result value */
2764 if ((IS_ITEMP (IC_RESULT (ic)) &&
2765 (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
2766 OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
2767 IS_TRUE_SYMOP (IC_RESULT (ic)))
2771 aopOp (IC_RESULT (ic), ic, FALSE, TRUE);
2774 assignResultValue (IC_RESULT (ic));
2776 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
2779 /* adjust the stack for parameters if
2784 if (options.stack10bit) {
2785 if (ic->parmBytes <= 10) {
2786 emitcode(";","stack adjustment for parms");
2787 for (i=0; i < ic->parmBytes ; i++) {
2788 emitcode("pop","acc");
2792 emitcode ("clr","c");
2793 emitcode ("mov","a,sp");
2794 emitcode ("subb","a,#!constbyte",ic->parmBytes & 0xff);
2795 emitcode ("mov","sp,a");
2796 emitcode ("mov","a,esp");
2798 emitcode ("subb","a,#!constbyte",(ic->parmBytes >> 8) & 0xff);
2799 emitcode ("mov","esp,a");
2803 if (ic->parmBytes > 3) {
2804 emitcode ("mov", "a,%s", spname);
2805 emitcode ("add", "a,#!constbyte", (-ic->parmBytes) & 0xff);
2806 emitcode ("mov", "%s,a", spname);
2809 for (i = 0; i < ic->parmBytes; i++)
2810 emitcode ("dec", "%s", spname);
2814 /* if register bank was saved then unsave them */
2816 unsaveRBank (FUNC_REGBANK (dtype), ic, TRUE);
2818 /* if we hade saved some registers then
2821 unsaveRegisters (ic);
2825 /*-----------------------------------------------------------------*/
2826 /* resultRemat - result is rematerializable */
2827 /*-----------------------------------------------------------------*/
2829 resultRemat (iCode * ic)
2831 if (SKIP_IC (ic) || ic->op == IFX)
2834 if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
2836 symbol *sym = OP_SYMBOL (IC_RESULT (ic));
2837 if (sym->remat && !POINTER_SET (ic))
2844 #if defined(__BORLANDC__) || defined(_MSC_VER)
2845 #define STRCASECMP stricmp
2847 #define STRCASECMP strcasecmp
2850 /*-----------------------------------------------------------------*/
2851 /* inExcludeList - return 1 if the string is in exclude Reg list */
2852 /*-----------------------------------------------------------------*/
2854 regsCmp(void *p1, void *p2)
2856 return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
2860 inExcludeList (char *s)
2862 const char *p = setFirstItem(options.excludeRegsSet);
2864 if (p == NULL || STRCASECMP(p, "none") == 0)
2868 return isinSetWith(options.excludeRegsSet, s, regsCmp);
2871 /*-----------------------------------------------------------------*/
2872 /* genFunction - generated code for function entry */
2873 /*-----------------------------------------------------------------*/
2875 genFunction (iCode * ic)
2879 bool switchedPSW = FALSE;
2881 D (emitcode (";", "genFunction "););
2884 /* create the function header */
2885 emitcode (";", "-----------------------------------------");
2886 emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
2887 emitcode (";", "-----------------------------------------");
2889 emitcode ("", "%s:", sym->rname);
2890 ftype = operandType (IC_LEFT (ic));
2892 if (IFFUNC_ISNAKED(ftype))
2894 emitcode(";", "naked function: no prologue.");
2898 if (options.stack_probe)
2899 emitcode ("lcall","__stack_probe");
2900 /* if critical function then turn interrupts off */
2901 if (IFFUNC_ISCRITICAL (ftype))
2902 emitcode ("clr", "ea");
2904 /* here we need to generate the equates for the
2905 register bank if required */
2906 if (FUNC_REGBANK (ftype) != rbank)
2910 rbank = FUNC_REGBANK (ftype);
2911 for (i = 0; i < ds390_nRegs; i++)
2913 if (regs390[i].print) {
2914 if (strcmp (regs390[i].base, "0") == 0)
2915 emitcode ("", "%s !equ !constbyte",
2917 8 * rbank + regs390[i].offset);
2919 emitcode ("", "%s !equ %s + !constbyte",
2922 8 * rbank + regs390[i].offset);
2927 /* if this is an interrupt service routine then
2928 save acc, b, dpl, dph */
2929 if (IFFUNC_ISISR (sym->type))
2931 if (!inExcludeList ("acc"))
2932 emitcode ("push", "acc");
2933 if (!inExcludeList ("b"))
2934 emitcode ("push", "b");
2935 if (!inExcludeList ("dpl"))
2936 emitcode ("push", "dpl");
2937 if (!inExcludeList ("dph"))
2938 emitcode ("push", "dph");
2939 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
2941 emitcode ("push", "dpx");
2942 /* Make sure we're using standard DPTR */
2943 emitcode ("push", "dps");
2944 emitcode ("mov", "dps,#0");
2945 if (options.stack10bit)
2947 /* This ISR could conceivably use DPTR2. Better save it. */
2948 emitcode ("push", "dpl1");
2949 emitcode ("push", "dph1");
2950 emitcode ("push", "dpx1");
2951 emitcode ("push", DP2_RESULT_REG);
2954 /* if this isr has no bank i.e. is going to
2955 run with bank 0 , then we need to save more
2957 if (!FUNC_REGBANK (sym->type))
2961 /* if this function does not call any other
2962 function then we can be economical and
2963 save only those registers that are used */
2964 if (!IFFUNC_HASFCALL(sym->type))
2967 /* if any registers used */
2970 /* save the registers used */
2971 for (i = 0; i < sym->regsUsed->size; i++)
2973 if (bitVectBitValue (sym->regsUsed, i) ||
2974 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
2975 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
2982 /* this function has a function call cannot
2983 determines register usage so we will have to push the
2985 saveRBank (0, ic, FALSE);
2986 if (options.parms_in_bank1) {
2987 for (i=0; i < 8 ; i++ ) {
2988 emitcode ("push","%s",rb1regs[i]);
2995 /* This ISR uses a non-zero bank.
2997 * We assume that the bank is available for our
3000 * However, if this ISR calls a function which uses some
3001 * other bank, we must save that bank entirely.
3003 unsigned long banksToSave = 0;
3005 if (IFFUNC_HASFCALL(sym->type))
3008 #define MAX_REGISTER_BANKS 4
3013 for (i = ic; i; i = i->next)
3015 if (i->op == ENDFUNCTION)
3017 /* we got to the end OK. */
3025 dtype = operandType (IC_LEFT(i));
3027 && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
3029 /* Mark this bank for saving. */
3030 if (FUNC_REGBANK(dtype) >= MAX_REGISTER_BANKS)
3032 werror(E_NO_SUCH_BANK, FUNC_REGBANK(dtype));
3036 banksToSave |= (1 << FUNC_REGBANK(dtype));
3039 /* And note that we don't need to do it in
3047 /* This is a mess; we have no idea what
3048 * register bank the called function might
3051 * The only thing I can think of to do is
3052 * throw a warning and hope.
3054 werror(W_FUNCPTR_IN_USING_ISR);
3058 if (banksToSave && options.useXstack)
3060 /* Since we aren't passing it an ic,
3061 * saveRBank will assume r0 is available to abuse.
3063 * So switch to our (trashable) bank now, so
3064 * the caller's R0 isn't trashed.
3066 emitcode ("push", "psw");
3067 emitcode ("mov", "psw,#!constbyte",
3068 (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3072 for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
3074 if (banksToSave & (1 << ix))
3076 saveRBank(ix, NULL, FALSE);
3080 // TODO: this needs a closer look
3081 SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
3086 /* if callee-save to be used for this function
3087 then save the registers being used in this function */
3088 if (IFFUNC_CALLEESAVES(sym->type))
3092 /* if any registers used */
3095 /* save the registers used */
3096 for (i = 0; i < sym->regsUsed->size; i++)
3098 if (bitVectBitValue (sym->regsUsed, i) ||
3099 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3101 emitcode ("push", "%s", ds390_regWithIdx (i)->dname);
3109 /* set the register bank to the desired value */
3110 if ((FUNC_REGBANK (sym->type) || FUNC_ISISR (sym->type))
3113 emitcode ("push", "psw");
3114 emitcode ("mov", "psw,#!constbyte", (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
3117 if ( (IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3118 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3119 if (options.stack10bit) {
3120 emitcode ("push","_bpx");
3121 emitcode ("push","_bpx+1");
3122 emitcode ("mov","_bpx,%s",spname);
3123 emitcode ("mov","_bpx+1,esp");
3124 adjustEsp("_bpx+1");
3126 if (options.useXstack) {
3127 emitcode ("mov", "r0,%s", spname);
3128 emitcode ("mov", "a,_bp");
3129 emitcode ("movx", "@r0,a");
3130 emitcode ("inc", "%s", spname);
3132 /* set up the stack */
3133 emitcode ("push", "_bp"); /* save the callers stack */
3135 emitcode ("mov", "_bp,%s", spname);
3139 /* adjust the stack for the function */
3142 if (options.stack10bit) {
3143 if ( i > 1024) werror (W_STACK_OVERFLOW, sym->name);
3144 assert (sym->recvSize <= 4);
3145 if (sym->stack <= 8) {
3146 while (i--) emitcode ("push","acc");
3149 emitcode ("mov","a,sp");
3150 emitcode ("add","a,#!constbyte", ((short) sym->stack & 0xff));
3151 emitcode ("mov","sp,a");
3152 emitcode ("mov","a,esp");
3154 emitcode ("addc","a,#!constbyte", (((short) sym->stack) >> 8) & 0xff);
3155 emitcode ("mov","esp,a");
3160 werror (W_STACK_OVERFLOW, sym->name);
3162 if (i > 3 && sym->recvSize < 4) {
3164 emitcode ("mov", "a,sp");
3165 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
3166 emitcode ("mov", "sp,a");
3170 emitcode ("inc", "sp");
3177 emitcode ("mov", "a,_spx");
3178 emitcode ("add", "a,#!constbyte", ((char) sym->xstack & 0xff));
3179 emitcode ("mov", "_spx,a");
3184 /*-----------------------------------------------------------------*/
3185 /* genEndFunction - generates epilogue for functions */
3186 /*-----------------------------------------------------------------*/
3188 genEndFunction (iCode * ic)
3190 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
3192 D (emitcode (";", "genEndFunction "););
3194 if (IFFUNC_ISNAKED(sym->type))
3196 emitcode(";", "naked function: no epilogue.");
3200 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3201 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3203 if (options.stack10bit) {
3205 emitcode ("mov", "sp,_bpx", spname);
3206 emitcode ("mov", "esp,_bpx+1", spname);
3209 emitcode ("mov", "%s,_bp", spname);
3213 /* if use external stack but some variables were
3214 added to the local stack then decrement the
3216 if (options.useXstack && sym->stack) {
3217 emitcode ("mov", "a,sp");
3218 emitcode ("add", "a,#!constbyte", ((char) -sym->stack) & 0xff);
3219 emitcode ("mov", "sp,a");
3223 if ((IFFUNC_ISREENT (sym->type) || options.stackAuto) &&
3224 (sym->stack || FUNC_HASSTACKPARM(sym->type))) {
3226 if (options.useXstack) {
3227 emitcode ("mov", "r0,%s", spname);
3228 emitcode ("movx", "a,@r0");
3229 emitcode ("mov", "_bp,a");
3230 emitcode ("dec", "%s", spname);
3232 if (options.stack10bit) {
3233 emitcode ("pop", "_bpx+1");
3234 emitcode ("pop", "_bpx");
3236 emitcode ("pop", "_bp");
3241 /* restore the register bank */
3242 if (FUNC_REGBANK (sym->type) || IFFUNC_ISISR (sym->type))
3244 if (!FUNC_REGBANK (sym->type) || !IFFUNC_ISISR (sym->type)
3245 || !options.useXstack)
3247 /* Special case of ISR using non-zero bank with useXstack
3250 emitcode ("pop", "psw");
3254 if (IFFUNC_ISISR (sym->type))
3257 /* now we need to restore the registers */
3258 /* if this isr has no bank i.e. is going to
3259 run with bank 0 , then we need to save more
3261 if (!FUNC_REGBANK (sym->type))
3264 /* if this function does not call any other
3265 function then we can be economical and
3266 save only those registers that are used */
3267 if (!IFFUNC_HASFCALL(sym->type))
3270 /* if any registers used */
3273 /* save the registers used */
3274 for (i = sym->regsUsed->size; i >= 0; i--)
3276 if (bitVectBitValue (sym->regsUsed, i) ||
3277 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3278 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3285 /* this function has a function call cannot
3286 determines register usage so we will have to pop the
3288 if (options.parms_in_bank1) {
3289 for (i = 7 ; i >= 0 ; i-- ) {
3290 emitcode ("pop","%s",rb1regs[i]);
3293 unsaveRBank (0, ic, FALSE);
3298 /* This ISR uses a non-zero bank.
3300 * Restore any register banks saved by genFunction
3303 unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
3306 for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
3308 if (savedBanks & (1 << ix))
3310 unsaveRBank(ix, NULL, FALSE);
3314 if (options.useXstack)
3316 /* Restore bank AFTER calling unsaveRBank,
3317 * since it can trash r0.
3319 emitcode ("pop", "psw");
3323 if (options.model == MODEL_FLAT24 && !inExcludeList ("dpx"))
3325 if (options.stack10bit)
3327 emitcode ("pop", DP2_RESULT_REG);
3328 emitcode ("pop", "dpx1");
3329 emitcode ("pop", "dph1");
3330 emitcode ("pop", "dpl1");
3332 emitcode ("pop", "dps");
3333 emitcode ("pop", "dpx");
3335 if (!inExcludeList ("dph"))
3336 emitcode ("pop", "dph");
3337 if (!inExcludeList ("dpl"))
3338 emitcode ("pop", "dpl");
3339 if (!inExcludeList ("b"))
3340 emitcode ("pop", "b");
3341 if (!inExcludeList ("acc"))
3342 emitcode ("pop", "acc");
3344 if (IFFUNC_ISCRITICAL (sym->type))
3345 emitcode ("setb", "ea");
3347 /* if debug then send end of function */
3348 if (options.debug && currFunc) {
3350 emitcode ("", "C$%s$%d$%d$%d ==.",
3351 FileBaseName (ic->filename), currFunc->lastLine,
3352 ic->level, ic->block);
3353 if (IS_STATIC (currFunc->etype))
3354 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3356 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3360 emitcode ("reti", "");
3364 if (IFFUNC_ISCRITICAL (sym->type))
3365 emitcode ("setb", "ea");
3367 if (IFFUNC_CALLEESAVES(sym->type))
3371 /* if any registers used */
3374 /* save the registers used */
3375 for (i = sym->regsUsed->size; i >= 0; i--)
3377 if (bitVectBitValue (sym->regsUsed, i) ||
3378 (ds390_ptrRegReq && (i == R0_IDX || i == R1_IDX)))
3379 emitcode ("pop", "%s", ds390_regWithIdx (i)->dname);
3385 /* if debug then send end of function */
3386 if (options.debug && currFunc)
3389 emitcode ("", "C$%s$%d$%d$%d ==.",
3390 FileBaseName (ic->filename), currFunc->lastLine,
3391 ic->level, ic->block);
3392 if (IS_STATIC (currFunc->etype))
3393 emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
3395 emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
3399 emitcode ("ret", "");
3404 /*-----------------------------------------------------------------*/
3405 /* genJavaNativeRet - generate code for return JavaNative */
3406 /*-----------------------------------------------------------------*/
3407 static void genJavaNativeRet(iCode *ic)
3411 aopOp (IC_LEFT (ic), ic, FALSE,
3412 AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE);
3413 size = AOP_SIZE (IC_LEFT (ic));
3417 /* it is assigned to GPR0-R3 then push them */
3418 if (aopHasRegs(AOP(IC_LEFT(ic)),R0_IDX,R1_IDX) ||
3419 aopHasRegs(AOP(IC_LEFT(ic)),R2_IDX,R3_IDX)) {
3420 for (i = 0 ; i < size ; i++ ) {
3421 emitcode ("push","%s",
3422 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3424 for (i = (size-1) ; i >= 0 ; i--) {
3425 emitcode ("pop","a%s",javaRet[i]);
3428 for (i = 0 ; i < size ; i++)
3429 emitcode ("mov","%s,%s",javaRet[i],
3430 aopGet(AOP(IC_LEFT(ic)),i,FALSE,TRUE,DP2_RESULT_REG));
3432 for (i = size ; i < 4 ; i++ )
3433 emitcode ("mov","%s,#0",javaRet[i]);
3437 /*-----------------------------------------------------------------*/
3438 /* genRet - generate code for return statement */
3439 /*-----------------------------------------------------------------*/
3443 int size, offset = 0, pushed = 0;
3445 D (emitcode (";", "genRet "););
3447 /* if we have no return value then
3448 just generate the "ret" */
3452 /* if this is a JavaNative function then return
3453 value in different register */
3454 if (IFFUNC_ISJAVANATIVE(currFunc->type)) {
3455 genJavaNativeRet(ic);
3458 /* we have something to return then
3459 move the return value into place */
3460 aopOp (IC_LEFT (ic), ic, FALSE,
3461 (AOP_IS_STR(IC_LEFT(ic)) ? FALSE :TRUE));
3462 size = AOP_SIZE (IC_LEFT (ic));
3464 _startLazyDPSEvaluation ();
3468 if (AOP_TYPE (IC_LEFT (ic)) == AOP_DPTR)
3470 l = aopGet (AOP (IC_LEFT (ic)), offset++,
3472 emitcode ("push", "%s", l);
3477 /* Since A is the last element of fReturn,
3478 * is is OK to clobber it in the aopGet.
3480 l = aopGet (AOP (IC_LEFT (ic)), offset,
3481 FALSE, FALSE, NULL);
3482 if (strcmp (fReturn[offset], l))
3483 emitcode ("mov", "%s,%s", fReturn[offset++], l);
3486 _endLazyDPSEvaluation ();
3493 if (strcmp (fReturn[pushed], "a"))
3494 emitcode ("pop", fReturn[pushed]);
3496 emitcode ("pop", "acc");
3499 freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
3502 /* generate a jump to the return label
3503 if the next is not the return statement */
3504 if (!(ic->next && ic->next->op == LABEL &&
3505 IC_LABEL (ic->next) == returnLabel))
3507 emitcode ("ljmp", "!tlabel", (returnLabel->key + 100));
3511 /*-----------------------------------------------------------------*/
3512 /* genLabel - generates a label */
3513 /*-----------------------------------------------------------------*/
3515 genLabel (iCode * ic)
3517 /* special case never generate */
3518 if (IC_LABEL (ic) == entryLabel)
3521 D (emitcode (";", "genLabel ");
3524 emitcode ("", "!tlabeldef", (IC_LABEL (ic)->key + 100));
3527 /*-----------------------------------------------------------------*/
3528 /* genGoto - generates a ljmp */
3529 /*-----------------------------------------------------------------*/
3531 genGoto (iCode * ic)
3533 D (emitcode (";", "genGoto ");
3535 emitcode ("ljmp", "!tlabel", (IC_LABEL (ic)->key + 100));
3538 /*-----------------------------------------------------------------*/
3539 /* findLabelBackwards: walks back through the iCode chain looking */
3540 /* for the given label. Returns number of iCode instructions */
3541 /* between that label and given ic. */
3542 /* Returns zero if label not found. */
3543 /*-----------------------------------------------------------------*/
3545 findLabelBackwards (iCode * ic, int key)
3554 /* If we have any pushes or pops, we cannot predict the distance.
3555 I don't like this at all, this should be dealt with in the
3557 if (ic->op == IPUSH || ic->op == IPOP) {
3561 if (ic->op == LABEL && IC_LABEL (ic)->key == key)
3563 /* printf("findLabelBackwards = %d\n", count); */
3571 /*-----------------------------------------------------------------*/
3572 /* genPlusIncr :- does addition with increment if possible */
3573 /*-----------------------------------------------------------------*/
3575 genPlusIncr (iCode * ic)
3577 unsigned int icount;
3578 unsigned int size = getDataSize (IC_RESULT (ic));
3580 /* will try to generate an increment */
3581 /* if the right side is not a literal
3583 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
3586 /* if the literal value of the right hand side
3587 is greater than 4 then it is not worth it */
3588 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
3591 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
3592 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
3594 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
3598 /* if increment 16 bits in register */
3600 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3601 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3602 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
3611 /* If the next instruction is a goto and the goto target
3612 * is <= 5 instructions previous to this, we can generate
3613 * jumps straight to that target.
3615 if (ic->next && ic->next->op == GOTO
3616 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
3619 D(emitcode (";", "tail increment optimized (range %d)", labelRange););
3620 tlbl = IC_LABEL (ic->next);
3625 tlbl = newiTempLabel (NULL);
3629 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
3630 emitcode ("inc", "%s", l);
3632 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3633 IS_AOP_PREG (IC_RESULT (ic)))
3635 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3639 emitcode ("clr", "a");
3640 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3643 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
3644 emitcode ("inc", "%s", l);
3647 if (!strcmp(l, "acc"))
3649 emitcode("jnz", "!tlabel", tlbl->key + 100);
3651 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3652 IS_AOP_PREG (IC_RESULT (ic)))
3654 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3658 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3661 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
3662 emitcode ("inc", "%s", l);
3666 if (!strcmp(l, "acc"))
3668 emitcode("jnz", "!tlabel", tlbl->key + 100);
3670 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
3671 IS_AOP_PREG (IC_RESULT (ic)))
3673 emitcode ("cjne", "%s,#0,!tlabel", l, tlbl->key + 100);
3677 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
3680 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
3681 emitcode ("inc", "%s", l); }
3685 emitcode ("", "!tlabeldef", tlbl->key + 100);
3690 if (AOP_TYPE(IC_RESULT(ic))==AOP_STR && IS_ITEMP(IC_RESULT(ic)) &&
3691 !AOP_USESDPTR(IC_LEFT(ic)) && icount <= 5 && size <= 3 &&
3692 options.model == MODEL_FLAT24 ) {
3696 emitcode ("mov","dpx,%s",aopGet(AOP (IC_LEFT (ic)), 2, FALSE, FALSE, NULL));
3698 emitcode ("mov","dph,%s",aopGet(AOP (IC_LEFT (ic)), 1, FALSE, FALSE, NULL));
3700 emitcode ("mov","dpl,%s",aopGet(AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3703 while (icount--) emitcode ("inc","dptr");
3707 if (AOP_INDPTRn(IC_LEFT(ic)) && AOP_INDPTRn(IC_RESULT(ic)) &&
3708 AOP(IC_LEFT(ic))->aopu.dptr == AOP(IC_RESULT(ic))->aopu.dptr &&
3710 emitcode ("mov","dps,#!constbyte",AOP(IC_LEFT(ic))->aopu.dptr);
3711 while (icount--) emitcode ("inc","dptr");
3712 emitcode ("mov","dps,#0");
3716 /* if the sizes are greater than 1 then we cannot */
3717 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
3718 AOP_SIZE (IC_LEFT (ic)) > 1)
3721 /* we can if the aops of the left & result match or
3722 if they are in registers and the registers are the
3725 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
3726 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
3727 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
3732 MOVA (aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3733 emitcode ("add", "a,#!constbyte", ((char) icount) & 0xff);
3734 aopPut (AOP (IC_RESULT (ic)), "a", 0);
3739 _startLazyDPSEvaluation ();
3742 emitcode ("inc", "%s", aopGet (AOP (IC_LEFT (ic)), 0, FALSE, FALSE, NULL));
3744 _endLazyDPSEvaluation ();
3753 /*-----------------------------------------------------------------*/
3754 /* outBitAcc - output a bit in acc */
3755 /*-----------------------------------------------------------------*/
3757 outBitAcc (operand * result)
3759 symbol *tlbl = newiTempLabel (NULL);
3760 /* if the result is a bit */
3761 if (AOP_TYPE (result) == AOP_CRY)
3763 aopPut (AOP (result), "a", 0);
3767 emitcode ("jz", "!tlabel", tlbl->key + 100);
3768 emitcode ("mov", "a,%s", one);
3769 emitcode ("", "!tlabeldef", tlbl->key + 100);
3774 /*-----------------------------------------------------------------*/
3775 /* genPlusBits - generates code for addition of two bits */
3776 /*-----------------------------------------------------------------*/
3778 genPlusBits (iCode * ic)
3780 D (emitcode (";", "genPlusBits "););
3782 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
3784 symbol *lbl = newiTempLabel (NULL);
3785 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3786 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
3787 emitcode ("cpl", "c");
3788 emitcode ("", "!tlabeldef", (lbl->key + 100));
3789 outBitC (IC_RESULT (ic));
3793 emitcode ("clr", "a");
3794 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
3795 emitcode ("rlc", "a");
3796 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
3797 emitcode ("addc", "a,#0");
3798 outAcc (IC_RESULT (ic));
3803 adjustArithmeticResult (iCode * ic)
3805 if (opIsGptr (IC_RESULT (ic)) &&
3806 opIsGptr (IC_LEFT (ic)) &&
3807 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))))
3809 aopPut (AOP (IC_RESULT (ic)),
3810 aopGet (AOP (IC_LEFT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3814 if (opIsGptr (IC_RESULT (ic)) &&
3815 opIsGptr (IC_RIGHT (ic)) &&
3816 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3818 aopPut (AOP (IC_RESULT (ic)),
3819 aopGet (AOP (IC_RIGHT (ic)), GPTRSIZE - 1, FALSE, FALSE, NULL),
3823 if (opIsGptr (IC_RESULT (ic)) &&
3824 AOP_SIZE (IC_LEFT (ic)) < GPTRSIZE &&
3825 AOP_SIZE (IC_RIGHT (ic)) < GPTRSIZE &&
3826 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_LEFT (ic))) &&
3827 !sameRegs (AOP (IC_RESULT (ic)), AOP (IC_RIGHT (ic))))
3830 SNPRINTF (buff, sizeof(buff),
3831 "#%d", pointerCode (getSpec (operandType (IC_LEFT (ic)))));
3832 aopPut (AOP (IC_RESULT (ic)), buff, GPTRSIZE - 1);
3836 // The guts of AOP_OP_3_NOFATAL. Generates the left & right opcodes of an IC,
3837 // generates the result if possible. If result is generated, returns TRUE; otherwise
3838 // returns false and caller must deal with fact that result isn't aopOp'd.
3839 bool aopOp3(iCode * ic)
3841 bool dp1InUse, dp2InUse;
3844 // First, generate the right opcode. DPTR may be used if neither left nor result are
3847 // D(emitcode(";", "aopOp3: AOP_IS_STR left: %s right: %s result: %s",
3848 // AOP_IS_STR(IC_LEFT(ic)) ? "true" : "false",
3849 // AOP_IS_STR(IC_RIGHT(ic)) ? "true" : "false",
3850 // AOP_IS_STR(IC_RESULT(ic)) ? "true" : "false");
3852 // D(emitcode(";", "aopOp3: AOP_IS_DPTRn left: %s right: %s result: %s",
3853 // AOP_IS_DPTRn(IC_LEFT(ic)) ? "true" : "false",
3854 // AOP_IS_DPTRn(IC_RIGHT(ic)) ? "true" : "false",
3855 // AOP_IS_DPTRn(IC_RESULT(ic)) ? "true" : "false");
3858 // Right uses DPTR unless left or result is an AOP_STR; however,
3859 // if right is an AOP_STR, it must use DPTR regardless.
3860 if ((AOP_IS_STR(IC_LEFT(ic)) || AOP_IS_STR(IC_RESULT(ic)))
3861 && !AOP_IS_STR(IC_RIGHT(ic)))
3870 aopOp (IC_RIGHT(ic),ic,FALSE, useDp2);
3872 // if the right used DPTR, left MUST use DPTR2.
3873 // if the right used DPTR2, left MUST use DPTR.
3874 // if both are still available, we prefer to use DPTR. But if result is an AOP_STR
3875 // and left is not an AOP_STR, then we will get better code if we use DP2 for left,
3876 // enabling us to assign DPTR to result.
3878 if (AOP_USESDPTR(IC_RIGHT(ic)))
3882 else if (AOP_USESDPTR2(IC_RIGHT(ic)))
3888 if (AOP_IS_STR(IC_RESULT(ic)) && !AOP_IS_STR(IC_LEFT(ic)))
3898 aopOp(IC_LEFT(ic), ic, FALSE, useDp2);
3900 // We've op'd the left & right. So, if left or right are the same operand as result,
3901 // we know aopOp will succeed, and we can just do it & bail.
3902 if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
3903 isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
3905 // D(emitcode(";", "aopOp3: (left | right) & result equal"););
3906 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
3910 // Note which dptrs are currently in use.
3911 dp1InUse = AOP_USESDPTR(IC_LEFT(ic)) || AOP_USESDPTR(IC_RIGHT(ic));
3912 dp2InUse = AOP_USESDPTR2(IC_LEFT(ic)) || AOP_USESDPTR2(IC_RIGHT(ic));
3914 // OK, now if either left or right uses DPTR and the result is an AOP_STR, we cannot
3916 if (dp1InUse && AOP_IS_STR(IC_RESULT(ic)))
3921 // Likewise, if left or right uses DPTR2 and the result is a DPTRn, we cannot generate it.
3922 if (dp2InUse && AOP_IS_DPTRn(IC_RESULT(ic)))
3927 // or, if both dp1 & dp2 are in use and the result needs a dptr, we're out of luck
3928 if (dp1InUse && dp2InUse && isOperandInFarSpace(IC_RESULT(ic)))
3933 aopOp (IC_RESULT(ic),ic,TRUE, dp1InUse);
3935 // Some sanity checking...
3936 if (dp1InUse && AOP_USESDPTR(IC_RESULT(ic)))
3939 "Internal error: got unexpected DPTR (%s:%d %s:%d)\n",
3940 __FILE__, __LINE__, ic->filename, ic->lineno);
3941 emitcode(";", ">>> unexpected DPTR here.");
3944 if (dp2InUse && AOP_USESDPTR2(IC_RESULT(ic)))
3947 "Internal error: got unexpected DPTR2 (%s:%d %s:%d)\n",
3948 __FILE__, __LINE__, ic->filename, ic->lineno);
3949 emitcode(";", ">>> unexpected DPTR2 here.");
3955 // Macro to aopOp all three operands of an ic. If this cannot be done,
3956 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
3957 // will be set TRUE. The caller must then handle the case specially, noting
3958 // that the IC_RESULT operand is not aopOp'd.
3960 #define AOP_OP_3_NOFATAL(ic, rc) \
3961 do { rc = !aopOp3(ic); } while (0)
3963 // aopOp the left & right operands of an ic.
3964 #define AOP_OP_2(ic) \
3965 aopOp (IC_RIGHT(ic),ic,FALSE, AOP_IS_STR(IC_LEFT(ic))); \
3966 aopOp (IC_LEFT(ic),ic,FALSE, AOP_USESDPTR(IC_RIGHT(ic)));
3968 // convienience macro.
3969 #define AOP_SET_LOCALS(ic) \
3970 left = IC_LEFT(ic); \
3971 right = IC_RIGHT(ic); \
3972 result = IC_RESULT(ic);
3975 // Given an integer value of pushedSize bytes on the stack,
3976 // adjust it to be resultSize bytes, either by discarding
3977 // the most significant bytes or by zero-padding.
3979 // On exit from this macro, pushedSize will have been adjusted to
3980 // equal resultSize, and ACC may be trashed.
3981 #define ADJUST_PUSHED_RESULT(pushedSize, resultSize) \
3982 /* If the pushed data is bigger than the result, \
3983 * simply discard unused bytes. Icky, but works. \
3985 while (pushedSize > resultSize) \
3987 D (emitcode (";", "discarding unused result byte."););\
3988 emitcode ("pop", "acc"); \
3991 if (pushedSize < resultSize) \
3993 emitcode ("clr", "a"); \
3994 /* Conversly, we haven't pushed enough here. \
3995 * just zero-pad, and all is well. \
3997 while (pushedSize < resultSize) \
3999 emitcode("push", "acc"); \
4003 assert(pushedSize == resultSize);
4005 /*-----------------------------------------------------------------*/
4006 /* genPlus - generates code for addition */
4007 /*-----------------------------------------------------------------*/
4009 genPlus (iCode * ic)
4011 int size, offset = 0;
4015 D (emitcode (";", "genPlus "););
4017 /* special cases :- */
4018 if ( AOP_IS_STR(IC_LEFT(ic)) &&
4019 isOperandLiteral(IC_RIGHT(ic)) && OP_SYMBOL(IC_RESULT(ic))->ruonly) {
4020 aopOp (IC_RIGHT (ic), ic, TRUE, FALSE);
4021 size = (int)floatFromVal (AOP (IC_RIGHT(ic))->aopu.aop_lit);
4023 while (size--) emitcode ("inc","dptr");
4025 emitcode ("mov","a,dpl");
4026 emitcode ("add","a,#!constbyte",size & 0xff);
4027 emitcode ("mov","dpl,a");
4028 emitcode ("mov","a,dph");
4029 emitcode ("addc","a,#!constbyte",(size >> 8) & 0xff);
4030 emitcode ("mov","dph,a");
4031 emitcode ("mov","a,dpx");
4032 emitcode ("addc","a,#!constbyte",(size >> 16) & 0xff);
4033 emitcode ("mov","dpx,a");
4035 freeAsmop (IC_RIGHT (ic), NULL, ic, FALSE);
4038 if ( IS_SYMOP(IC_LEFT(ic)) &&
4039 OP_SYMBOL(IC_LEFT(ic))->remat &&
4040 isOperandInFarSpace(IC_RIGHT(ic))) {
4041 operand *op = IC_RIGHT(ic);
4042 IC_RIGHT(ic) = IC_LEFT(ic);
4046 AOP_OP_3_NOFATAL (ic, pushResult);
4050 D (emitcode (";", "genPlus: must push result: 3 ops in far space"););
4055 /* if literal, literal on the right or
4056 if left requires ACC or right is already
4058 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
4059 || ((AOP_NEEDSACC (IC_LEFT (ic))) && !(AOP_NEEDSACC (IC_RIGHT (ic))))
4060 || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC)
4062 operand *t = IC_RIGHT (ic);
4063 IC_RIGHT (ic) = IC_LEFT (ic);
4065 emitcode (";", "Swapped plus args.");
4068 /* if both left & right are in bit
4070 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4071 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4077 /* if left in bit space & right literal */
4078 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4079 AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT)
4081 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4082 /* if result in bit space */
4083 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4085 if ((unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) != 0L)
4086 emitcode ("cpl", "c");
4087 outBitC (IC_RESULT (ic));
4091 size = getDataSize (IC_RESULT (ic));
4092 _startLazyDPSEvaluation ();
4095 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4096 emitcode ("addc", "a,#0");
4097 aopPut (AOP (IC_RESULT (ic)), "a", offset++);
4099 _endLazyDPSEvaluation ();
4104 /* if I can do an increment instead
4105 of add then GOOD for ME */
4106 if (genPlusIncr (ic) == TRUE)
4108 emitcode (";", "did genPlusIncr");
4113 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4115 _startLazyDPSEvaluation ();
4118 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && !AOP_NEEDSACC(IC_RIGHT(ic)))
4120 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4122 emitcode ("add", "a,%s",
4123 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4125 emitcode ("addc", "a,%s",
4126 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4130 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC && (offset == 0))
4132 /* right is going to use ACC or we would have taken the
4135 assert(AOP_NEEDSACC(IC_RIGHT(ic)));
4137 D(emitcode(";", "+ AOP_ACC special case."););
4138 emitcode("xch", "a, %s", DP2_RESULT_REG);
4140 MOVA (aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4143 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC)
4146 emitcode("add", "a, %s", DP2_RESULT_REG);
4150 emitcode ("add", "a,%s",
4151 aopGet (AOP(IC_LEFT(ic)), offset, FALSE, FALSE,
4157 emitcode ("addc", "a,%s",
4158 aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE,
4164 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4168 emitcode ("push", "acc");
4172 _endLazyDPSEvaluation ();
4176 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4178 size = getDataSize (IC_LEFT (ic));
4179 rSize = getDataSize (IC_RESULT (ic));
4181 ADJUST_PUSHED_RESULT(size, rSize);
4183 _startLazyDPSEvaluation ();
4186 emitcode ("pop", "acc");
4187 aopPut (AOP (IC_RESULT (ic)), "a", size);
4189 _endLazyDPSEvaluation ();
4192 adjustArithmeticResult (ic);
4195 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4196 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4197 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4200 /*-----------------------------------------------------------------*/
4201 /* genMinusDec :- does subtraction with deccrement if possible */
4202 /*-----------------------------------------------------------------*/
4204 genMinusDec (iCode * ic)
4206 unsigned int icount;
4207 unsigned int size = getDataSize (IC_RESULT (ic));
4209 /* will try to generate an increment */
4210 /* if the right side is not a literal
4212 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4215 /* if the literal value of the right hand side
4216 is greater than 4 then it is not worth it */
4217 if ((icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit)) > 4)
4220 if (size == 1 && AOP(IC_LEFT(ic)) == AOP(IC_RESULT(ic)) &&
4221 AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) {
4223 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE,NULL));
4227 /* if decrement 16 bits in register */
4228 if (AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4229 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4230 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
4239 /* If the next instruction is a goto and the goto target
4240 * is <= 5 instructions previous to this, we can generate
4241 * jumps straight to that target.
4243 if (ic->next && ic->next->op == GOTO
4244 && (labelRange = findLabelBackwards (ic, IC_LABEL (ic->next)->key)) != 0
4247 emitcode (";", "tail decrement optimized (range %d)", labelRange);
4248 tlbl = IC_LABEL (ic->next);
4253 tlbl = newiTempLabel (NULL);
4257 l = aopGet (AOP (IC_RESULT (ic)), LSB, FALSE, FALSE, NULL);
4258 emitcode ("dec", "%s", l);
4260 if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4261 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4262 IS_AOP_PREG (IC_RESULT (ic)))
4264 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4268 emitcode ("mov", "a,#!constbyte",0xff);
4269 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4271 l = aopGet (AOP (IC_RESULT (ic)), MSB16, FALSE, FALSE, NULL);
4272 emitcode ("dec", "%s", l);
4275 if (!strcmp(l, "acc"))
4277 emitcode("jnz", "!tlabel", tlbl->key + 100);
4279 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4280 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4281 IS_AOP_PREG (IC_RESULT (ic)))
4283 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4287 emitcode ("mov", "a,#!constbyte",0xff);
4288 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4290 l = aopGet (AOP (IC_RESULT (ic)), MSB24, FALSE, FALSE, NULL);
4291 emitcode ("dec", "%s", l);
4295 if (!strcmp(l, "acc"))
4297 emitcode("jnz", "!tlabel", tlbl->key + 100);
4299 else if (AOP_TYPE (IC_RESULT (ic)) == AOP_REG ||
4300 AOP_TYPE (IC_RESULT (ic)) == AOP_DPTR ||
4301 IS_AOP_PREG (IC_RESULT (ic)))
4303 emitcode ("cjne", "%s,#!constbyte,!tlabel", l, 0xff, tlbl->key + 100);
4307 emitcode ("mov", "a,#!constbyte",0xff);
4308 emitcode ("cjne", "a,%s,!tlabel", l, tlbl->key + 100);
4310 l = aopGet (AOP (IC_RESULT (ic)), MSB32, FALSE, FALSE, NULL);
4311 emitcode ("dec", "%s", l);
4315 emitcode ("", "!tlabeldef", tlbl->key + 100);
4320 /* if the sizes are greater than 1 then we cannot */
4321 if (AOP_SIZE (IC_RESULT (ic)) > 1 ||
4322 AOP_SIZE (IC_LEFT (ic)) > 1)
4325 /* we can if the aops of the left & result match or
4326 if they are in registers and the registers are the
4329 AOP_TYPE (IC_LEFT (ic)) == AOP_REG &&
4330 AOP_TYPE (IC_RESULT (ic)) == AOP_REG &&
4331 sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
4334 _startLazyDPSEvaluation ();
4337 emitcode ("dec", "%s",
4338 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
4340 _endLazyDPSEvaluation ();
4348 /*-----------------------------------------------------------------*/
4349 /* addSign - complete with sign */
4350 /*-----------------------------------------------------------------*/
4352 addSign (operand * result, int offset, int sign)
4354 int size = (getDataSize (result) - offset);
4357 _startLazyDPSEvaluation();
4360 emitcode ("rlc", "a");
4361 emitcode ("subb", "a,acc");
4364 aopPut (AOP (result), "a", offset++);
4371 aopPut (AOP (result), zero, offset++);
4374 _endLazyDPSEvaluation();
4378 /*-----------------------------------------------------------------*/
4379 /* genMinusBits - generates code for subtraction of two bits */
4380 /*-----------------------------------------------------------------*/
4382 genMinusBits (iCode * ic)
4384 symbol *lbl = newiTempLabel (NULL);
4386 D (emitcode (";", "genMinusBits "););
4388 if (AOP_TYPE (IC_RESULT (ic)) == AOP_CRY)
4390 emitcode ("mov", "c,%s", AOP (IC_LEFT (ic))->aopu.aop_dir);
4391 emitcode ("jnb", "%s,!tlabel", AOP (IC_RIGHT (ic))->aopu.aop_dir, (lbl->key + 100));
4392 emitcode ("cpl", "c");
4393 emitcode ("", "!tlabeldef", (lbl->key + 100));
4394 outBitC (IC_RESULT (ic));
4398 emitcode ("mov", "c,%s", AOP (IC_RIGHT (ic))->aopu.aop_dir);
4399 emitcode ("subb", "a,acc");
4400 emitcode ("jnb", "%s,!tlabel", AOP (IC_LEFT (ic))->aopu.aop_dir, (lbl->key + 100));
4401 emitcode ("inc", "a");
4402 emitcode ("", "!tlabeldef", (lbl->key + 100));
4403 aopPut (AOP (IC_RESULT (ic)), "a", 0);
4404 addSign (IC_RESULT (ic), MSB16, SPEC_USIGN (getSpec (operandType (IC_RESULT (ic)))));
4408 /*-----------------------------------------------------------------*/
4409 /* genMinus - generates code for subtraction */
4410 /*-----------------------------------------------------------------*/
4412 genMinus (iCode * ic)
4414 int size, offset = 0;
4419 D (emitcode (";", "genMinus "););
4421 AOP_OP_3_NOFATAL(ic, pushResult);
4425 /* special cases :- */
4426 /* if both left & right are in bit space */
4427 if (AOP_TYPE (IC_LEFT (ic)) == AOP_CRY &&
4428 AOP_TYPE (IC_RIGHT (ic)) == AOP_CRY)
4434 /* if I can do an decrement instead
4435 of subtract then GOOD for ME */
4436 if (genMinusDec (ic) == TRUE)
4441 size = getDataSize (pushResult ? IC_LEFT (ic) : IC_RESULT (ic));
4443 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
4449 lit = (long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
4454 /* if literal, add a,#-lit, else normal subb */
4455 _startLazyDPSEvaluation ();
4457 if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT) {
4458 if (AOP_USESDPTR(IC_RIGHT(ic))) {
4459 emitcode ("mov","b,%s",
4460 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE, NULL));
4461 MOVA(aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4462 emitcode ("subb","a,b");
4464 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4465 emitcode ("subb", "a,%s",
4466 aopGet (AOP (IC_RIGHT (ic)), offset, FALSE, FALSE,
4470 MOVA (aopGet (AOP (IC_LEFT (ic)), offset, FALSE, FALSE, NULL));
4471 /* first add without previous c */
4473 if (!size && lit==-1) {
4474 emitcode ("dec", "a");
4476 emitcode ("add", "a,#!constbyte",
4477 (unsigned int) (lit & 0x0FFL));
4480 emitcode ("addc", "a,#!constbyte",
4481 (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
4486 emitcode ("push", "acc");
4488 aopPut (AOP (IC_RESULT (ic)), "a", offset);
4492 _endLazyDPSEvaluation ();
4496 aopOp (IC_RESULT (ic), ic, TRUE, FALSE);
4498 size = getDataSize (IC_LEFT (ic));
4499 rSize = getDataSize (IC_RESULT (ic));
4501 ADJUST_PUSHED_RESULT(size, rSize);
4503 _startLazyDPSEvaluation ();
4506 emitcode ("pop", "acc");
4507 aopPut (AOP (IC_RESULT (ic)), "a", size);
4509 _endLazyDPSEvaluation ();
4512 adjustArithmeticResult (ic);
4515 freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4516 freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4517 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
4521 /*-----------------------------------------------------------------*/
4522 /* genMultbits :- multiplication of bits */
4523 /*-----------------------------------------------------------------*/
4525 genMultbits (operand * left,
4530 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
4531 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
4532 aopOp(result, ic, TRUE, FALSE);
4537 /*-----------------------------------------------------------------*/
4538 /* genMultOneByte : 8*8=8/16 bit multiplication */
4539 /*-----------------------------------------------------------------*/
4541 genMultOneByte (operand * left,
4546 sym_link *opetype = operandType (result);
4550 /* (if two literals: the value is computed before) */
4551 /* if one literal, literal on the right */
4552 if (AOP_TYPE (left) == AOP_LIT)
4557 emitcode (";", "swapped left and right");
4560 if (SPEC_USIGN(opetype)
4561 // ignore the sign of left and right, what else can we do?
4562 || (SPEC_USIGN(operandType(left)) &&
4563 SPEC_USIGN(operandType(right)))) {
4564 // just an unsigned 8*8=8/16 multiply
4565 //emitcode (";","unsigned");
4566 emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4567 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4568 emitcode ("mul", "ab");
4570 _G.accInUse++; _G.bInUse++;
4571 aopOp(result, ic, TRUE, FALSE);
4573 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4575 // this should never happen
4576 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4577 AOP_SIZE(result), __FILE__, lineno);
4581 aopPut (AOP (result), "a", 0);
4582 _G.accInUse--; _G.bInUse--;
4583 if (AOP_SIZE(result)==2)
4585 aopPut (AOP (result), "b", 1);
4590 // we have to do a signed multiply
4592 emitcode (";", "signed");
4593 emitcode ("clr", "F0"); // reset sign flag
4594 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4596 lbl=newiTempLabel(NULL);
4597 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4598 // left side is negative, 8-bit two's complement, this fails for -128
4599 emitcode ("setb", "F0"); // set sign flag
4600 emitcode ("cpl", "a");
4601 emitcode ("inc", "a");
4603 emitcode ("", "!tlabeldef", lbl->key+100);
4606 if (AOP_TYPE(right)==AOP_LIT) {
4607 signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
4608 /* AND literal negative */
4609 if ((int) val < 0) {
4610 emitcode ("cpl", "F0"); // complement sign flag
4611 emitcode ("mov", "b,#!constbyte", -val);
4613 emitcode ("mov", "b,#!constbyte", val);
4616 lbl=newiTempLabel(NULL);
4617 emitcode ("mov", "b,a");
4618 emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4619 emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
4620 // right side is negative, 8-bit two's complement
4621 emitcode ("cpl", "F0"); // complement sign flag
4622 emitcode ("cpl", "a");
4623 emitcode ("inc", "a");
4624 emitcode ("", "!tlabeldef", lbl->key+100);
4626 emitcode ("mul", "ab");
4628 _G.accInUse++;_G.bInUse++;
4629 aopOp(result, ic, TRUE, FALSE);
4631 if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2)
4633 // this should never happen
4634 fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
4635 AOP_SIZE(result), __FILE__, lineno);
4639 lbl=newiTempLabel(NULL);
4640 emitcode ("jnb", "F0,!tlabel", lbl->key+100);
4641 // only ONE op was negative, we have to do a 8/16-bit two's complement
4642 emitcode ("cpl", "a"); // lsb
4643 if (AOP_SIZE(result)==1) {
4644 emitcode ("inc", "a");
4646 emitcode ("add", "a,#1");
4647 emitcode ("xch", "a,b");
4648 emitcode ("cpl", "a"); // msb
4649 emitcode ("addc", "a,#0");
4650 emitcode ("xch", "a,b");
4653 emitcode ("", "!tlabeldef", lbl->key+100);
4654 aopPut (AOP (result), "a", 0);
4655 _G.accInUse--;_G.bInUse--;
4656 if (AOP_SIZE(result)==2) {
4657 aopPut (AOP (result), "b", 1);
4661 /*-----------------------------------------------------------------*/
4662 /* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply */
4663 /*-----------------------------------------------------------------*/
4664 static void genMultTwoByte (operand *left, operand *right,
4665 operand *result, iCode *ic)
4667 sym_link *retype = getSpec(operandType(right));
4668 sym_link *letype = getSpec(operandType(left));
4669 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4672 if (AOP_TYPE (left) == AOP_LIT) {
4677 /* save EA bit in F1 */
4678 lbl = newiTempLabel(NULL);
4679 emitcode ("setb","F1");
4680 emitcode ("jbc","EA,!tlabel",lbl->key+100);
4681 emitcode ("clr","F1");
4682 emitcode("","!tlabeldef",lbl->key+100);
4684 /* load up MB with right */
4686 emitcode("clr","F0");
4687 if (AOP_TYPE(right) == AOP_LIT) {
4688 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
4690 emitcode("setb","F0");
4693 emitcode ("mov","mb,#!constbyte",val & 0xff);
4694 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
4696 lbl = newiTempLabel(NULL);
4697 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4698 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4699 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4700 emitcode ("xch", "a,b");
4701 emitcode ("cpl","a");
4702 emitcode ("add", "a,#1");
4703 emitcode ("xch", "a,b");
4704 emitcode ("cpl", "a"); // msb
4705 emitcode ("addc", "a,#0");
4706 emitcode ("setb","F0");
4707 emitcode ("","!tlabeldef",lbl->key+100);
4708 emitcode ("mov","mb,b");
4709 emitcode ("mov","mb,a");
4712 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
4713 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
4715 /* load up MA with left */
4717 lbl = newiTempLabel(NULL);
4718 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4719 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4720 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
4721 emitcode ("xch", "a,b");
4722 emitcode ("cpl","a");
4723 emitcode ("add", "a,#1");
4724 emitcode ("xch", "a,b");
4725 emitcode ("cpl", "a"); // msb
4726 emitcode ("addc","a,#0");
4727 emitcode ("jbc","F0,!tlabel",lbl->key+100);
4728 emitcode ("setb","F0");
4729 emitcode ("","!tlabeldef",lbl->key+100);
4730 emitcode ("mov","ma,b");
4731 emitcode ("mov","ma,a");
4733 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
4734 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
4736 /* wait for multiplication to finish */
4737 lbl = newiTempLabel(NULL);
4738 emitcode("","!tlabeldef", lbl->key+100);
4739 emitcode("mov","a,mcnt1");
4740 emitcode("anl","a,#!constbyte",0x80);
4741 emitcode("jnz","!tlabel",lbl->key+100);
4743 freeAsmop (left, NULL, ic, TRUE);
4744 freeAsmop (right, NULL, ic,TRUE);
4745 aopOp(result, ic, TRUE, FALSE);
4747 /* if unsigned then simple */
4749 emitcode ("mov","a,ma");
4750 if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
4751 emitcode ("mov","a,ma");
4752 if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
4753 aopPut(AOP(result),"ma",1);
4754 aopPut(AOP(result),"ma",0);
4756 emitcode("push","ma");
4757 emitcode("push","ma");
4758 emitcode("push","ma");
4760 /* negate result if needed */
4761 lbl = newiTempLabel(NULL);
4762 emitcode("jnb","F0,!tlabel",lbl->key+100);
4763 emitcode("cpl","a");
4764 emitcode("add","a,#1");
4765 emitcode("","!tlabeldef", lbl->key+100);
4766 if (AOP_TYPE(result) == AOP_ACC)
4768 D(emitcode(";", "ACC special case."););
4769 /* We know result is the only live aop, and
4770 * it's obviously not a DPTR2, so AP is available.
4772 emitcode("mov", "%s,acc", DP2_RESULT_REG);
4776 aopPut(AOP(result),"a",0);
4779 emitcode("pop","acc");
4780 lbl = newiTempLabel(NULL);
4781 emitcode("jnb","F0,!tlabel",lbl->key+100);
4782 emitcode("cpl","a");
4783 emitcode("addc","a,#0");
4784 emitcode("","!tlabeldef", lbl->key+100);
4785 aopPut(AOP(result),"a",1);
4786 emitcode("pop","acc");
4787 if (AOP_SIZE(result) >= 3) {
4788 lbl = newiTempLabel(NULL);
4789 emitcode("jnb","F0,!tlabel",lbl->key+100);
4790 emitcode("cpl","a");
4791 emitcode("addc","a,#0");
4792 emitcode("","!tlabeldef", lbl->key+100);
4793 aopPut(AOP(result),"a",2);
4795 emitcode("pop","acc");
4796 if (AOP_SIZE(result) >= 4) {
4797 lbl = newiTempLabel(NULL);
4798 emitcode("jnb","F0,!tlabel",lbl->key+100);
4799 emitcode("cpl","a");
4800 emitcode("addc","a,#0");
4801 emitcode("","!tlabeldef", lbl->key+100);
4802 aopPut(AOP(result),"a",3);
4804 if (AOP_TYPE(result) == AOP_ACC)
4806 /* We stashed the result away above. */
4807 emitcode("mov", "acc,%s", DP2_RESULT_REG);
4811 freeAsmop (result, NULL, ic, TRUE);
4813 /* restore EA bit in F1 */
4814 lbl = newiTempLabel(NULL);
4815 emitcode ("jnb","F1,!tlabel",lbl->key+100);
4816 emitcode ("setb","EA");
4817 emitcode("","!tlabeldef",lbl->key+100);
4821 /*-----------------------------------------------------------------*/
4822 /* genMult - generates code for multiplication */
4823 /*-----------------------------------------------------------------*/
4825 genMult (iCode * ic)
4827 operand *left = IC_LEFT (ic);
4828 operand *right = IC_RIGHT (ic);
4829 operand *result = IC_RESULT (ic);
4831 D (emitcode (";", "genMult "););
4833 /* assign the amsops */
4836 /* special cases first */
4838 if (AOP_TYPE (left) == AOP_CRY &&
4839 AOP_TYPE (right) == AOP_CRY)
4841 genMultbits (left, right, result, ic);
4845 /* if both are of size == 1 */
4846 if (AOP_SIZE (left) == 1 &&
4847 AOP_SIZE (right) == 1)
4849 genMultOneByte (left, right, result, ic);
4853 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
4854 /* use the ds390 ARITHMETIC accel UNIT */
4855 genMultTwoByte (left, right, result, ic);
4858 /* should have been converted to function call */
4862 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4863 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
4864 freeAsmop (result, NULL, ic, TRUE);
4867 /*-----------------------------------------------------------------*/
4868 /* genDivbits :- division of bits */
4869 /*-----------------------------------------------------------------*/
4871 genDivbits (operand * left,
4879 /* the result must be bit */
4880 LOAD_AB_FOR_DIV (left, right, l);
4881 emitcode ("div", "ab");
4882 emitcode ("rrc", "a");
4883 aopOp(result, ic, TRUE, FALSE);
4885 aopPut (AOP (result), "c", 0);
4888 /*-----------------------------------------------------------------*/
4889 /* genDivOneByte : 8 bit division */
4890 /*-----------------------------------------------------------------*/
4892 genDivOneByte (operand * left,
4897 sym_link *opetype = operandType (result);
4903 /* signed or unsigned */
4904 if (SPEC_USIGN (opetype))
4906 /* unsigned is easy */
4907 LOAD_AB_FOR_DIV (left, right, l);
4908 emitcode ("div", "ab");
4911 aopOp(result, ic, TRUE, FALSE);
4912 aopPut (AOP (result), "a", 0);
4915 size = AOP_SIZE (result) - 1;
4919 aopPut (AOP (result), zero, offset++);
4924 /* signed is a little bit more difficult */
4926 /* save the signs of the operands */
4927 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4928 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
4929 emitcode ("push", "acc"); /* save it on the stack */
4931 /* now sign adjust for both left & right */
4932 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
4933 lbl = newiTempLabel (NULL);
4934 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4935 emitcode ("cpl", "a");
4936 emitcode ("inc", "a");
4937 emitcode ("", "!tlabeldef", (lbl->key + 100));
4938 emitcode ("mov", "b,a");
4940 /* sign adjust left side */
4941 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
4943 lbl = newiTempLabel (NULL);
4944 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4945 emitcode ("cpl", "a");
4946 emitcode ("inc", "a");
4947 emitcode ("", "!tlabeldef", (lbl->key + 100));
4949 /* now the division */
4950 emitcode ("nop", "; workaround for DS80C390 div bug.");
4951 emitcode ("div", "ab");
4952 /* we are interested in the lower order
4954 emitcode ("mov", "b,a");
4955 lbl = newiTempLabel (NULL);
4956 emitcode ("pop", "acc");
4957 /* if there was an over flow we don't
4958 adjust the sign of the result */
4959 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
4960 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
4962 emitcode ("clr", "a");
4963 emitcode ("subb", "a,b");
4964 emitcode ("mov", "b,a");
4965 emitcode ("", "!tlabeldef", (lbl->key + 100));
4967 /* now we are done */
4968 _G.accInUse++; _G.bInUse++;
4969 aopOp(result, ic, TRUE, FALSE);
4971 aopPut (AOP (result), "b", 0);
4973 size = AOP_SIZE (result) - 1;
4977 emitcode ("mov", "c,b.7");
4978 emitcode ("subb", "a,acc");
4982 aopPut (AOP (result), "a", offset++);
4984 _G.accInUse--; _G.bInUse--;
4988 /*-----------------------------------------------------------------*/
4989 /* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide */
4990 /*-----------------------------------------------------------------*/
4991 static void genDivTwoByte (operand *left, operand *right,
4992 operand *result, iCode *ic)
4994 sym_link *retype = getSpec(operandType(right));
4995 sym_link *letype = getSpec(operandType(left));
4996 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
4999 /* save EA bit in F1 */
5000 lbl = newiTempLabel(NULL);
5001 emitcode ("setb","F1");
5002 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5003 emitcode ("clr","F1");
5004 emitcode("","!tlabeldef",lbl->key+100);
5006 /* load up MA with left */
5008 emitcode("clr","F0");
5009 lbl = newiTempLabel(NULL);
5010 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5011 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5012 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5013 emitcode ("xch", "a,b");
5014 emitcode ("cpl","a");
5015 emitcode ("add", "a,#1");
5016 emitcode ("xch", "a,b");
5017 emitcode ("cpl", "a"); // msb
5018 emitcode ("addc","a,#0");
5019 emitcode ("setb","F0");
5020 emitcode ("","!tlabeldef",lbl->key+100);
5021 emitcode ("mov","ma,b");
5022 emitcode ("mov","ma,a");
5024 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5025 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5028 /* load up MB with right */
5030 if (AOP_TYPE(right) == AOP_LIT) {
5031 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5033 lbl = newiTempLabel(NULL);
5034 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5035 emitcode("setb","F0");
5036 emitcode ("","!tlabeldef",lbl->key+100);
5039 emitcode ("mov","mb,#!constbyte",val & 0xff);
5040 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5042 lbl = newiTempLabel(NULL);
5043 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5044 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5045 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5046 emitcode ("xch", "a,b");
5047 emitcode ("cpl","a");
5048 emitcode ("add", "a,#1");
5049 emitcode ("xch", "a,b");
5050 emitcode ("cpl", "a"); // msb
5051 emitcode ("addc", "a,#0");
5052 emitcode ("jbc","F0,!tlabel",lbl->key+100);
5053 emitcode ("setb","F0");
5054 emitcode ("","!tlabeldef",lbl->key+100);
5055 emitcode ("mov","mb,b");
5056 emitcode ("mov","mb,a");
5059 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5060 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5063 /* wait for multiplication to finish */
5064 lbl = newiTempLabel(NULL);
5065 emitcode("","!tlabeldef", lbl->key+100);
5066 emitcode("mov","a,mcnt1");
5067 emitcode("anl","a,#!constbyte",0x80);
5068 emitcode("jnz","!tlabel",lbl->key+100);
5070 freeAsmop (left, NULL, ic, TRUE);
5071 freeAsmop (right, NULL, ic,TRUE);
5072 aopOp(result, ic, TRUE, FALSE);
5074 /* if unsigned then simple */
5076 aopPut(AOP(result),"ma",1);
5077 aopPut(AOP(result),"ma",0);
5079 emitcode("push","ma");
5081 /* negate result if needed */
5082 lbl = newiTempLabel(NULL);
5083 emitcode("jnb","F0,!tlabel",lbl->key+100);
5084 emitcode("cpl","a");
5085 emitcode("add","a,#1");
5086 emitcode("","!tlabeldef", lbl->key+100);
5087 aopPut(AOP(result),"a",0);
5088 emitcode("pop","acc");
5089 lbl = newiTempLabel(NULL);
5090 emitcode("jnb","F0,!tlabel",lbl->key+100);
5091 emitcode("cpl","a");
5092 emitcode("addc","a,#0");
5093 emitcode("","!tlabeldef", lbl->key+100);
5094 aopPut(AOP(result),"a",1);
5096 freeAsmop (result, NULL, ic, TRUE);
5097 /* restore EA bit in F1 */
5098 lbl = newiTempLabel(NULL);
5099 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5100 emitcode ("setb","EA");
5101 emitcode("","!tlabeldef",lbl->key+100);
5105 /*-----------------------------------------------------------------*/
5106 /* genDiv - generates code for division */
5107 /*-----------------------------------------------------------------*/
5111 operand *left = IC_LEFT (ic);
5112 operand *right = IC_RIGHT (ic);
5113 operand *result = IC_RESULT (ic);
5115 D (emitcode (";", "genDiv "););
5117 /* assign the amsops */
5120 /* special cases first */
5122 if (AOP_TYPE (left) == AOP_CRY &&
5123 AOP_TYPE (right) == AOP_CRY)
5125 genDivbits (left, right, result, ic);
5129 /* if both are of size == 1 */
5130 if (AOP_SIZE (left) == 1 &&
5131 AOP_SIZE (right) == 1)
5133 genDivOneByte (left, right, result, ic);
5137 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5138 /* use the ds390 ARITHMETIC accel UNIT */
5139 genDivTwoByte (left, right, result, ic);
5142 /* should have been converted to function call */
5145 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5146 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5147 freeAsmop (result, NULL, ic, TRUE);
5150 /*-----------------------------------------------------------------*/
5151 /* genModbits :- modulus of bits */
5152 /*-----------------------------------------------------------------*/
5154 genModbits (operand * left,
5162 /* the result must be bit */
5163 LOAD_AB_FOR_DIV (left, right, l);
5164 emitcode ("div", "ab");
5165 emitcode ("mov", "a,b");
5166 emitcode ("rrc", "a");
5167 aopOp(result, ic, TRUE, FALSE);
5168 aopPut (AOP (result), "c", 0);
5171 /*-----------------------------------------------------------------*/
5172 /* genModOneByte : 8 bit modulus */
5173 /*-----------------------------------------------------------------*/
5175 genModOneByte (operand * left,
5180 sym_link *opetype = operandType (result);
5184 /* signed or unsigned */
5185 if (SPEC_USIGN (opetype))
5187 /* unsigned is easy */
5188 LOAD_AB_FOR_DIV (left, right, l);
5189 emitcode ("div", "ab");
5190 aopOp(result, ic, TRUE, FALSE);
5191 aopPut (AOP (result), "b", 0);
5195 /* signed is a little bit more difficult */
5197 /* save the signs of the operands */
5198 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5200 emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
5201 emitcode ("push", "acc"); /* save it on the stack */
5203 /* now sign adjust for both left & right */
5204 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
5206 lbl = newiTempLabel (NULL);
5207 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5208 emitcode ("cpl", "a");
5209 emitcode ("inc", "a");
5210 emitcode ("", "!tlabeldef", (lbl->key + 100));
5211 emitcode ("mov", "b,a");
5213 /* sign adjust left side */
5214 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
5216 lbl = newiTempLabel (NULL);
5217 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5218 emitcode ("cpl", "a");
5219 emitcode ("inc", "a");
5220 emitcode ("", "!tlabeldef", (lbl->key + 100));
5222 /* now the multiplication */
5223 emitcode ("nop", "; workaround for DS80C390 div bug.");
5224 emitcode ("div", "ab");
5225 /* we are interested in the lower order
5227 lbl = newiTempLabel (NULL);
5228 emitcode ("pop", "acc");
5229 /* if there was an over flow we don't
5230 adjust the sign of the result */
5231 emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
5232 emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
5234 emitcode ("clr", "a");
5235 emitcode ("subb", "a,b");
5236 emitcode ("mov", "b,a");
5237 emitcode ("", "!tlabeldef", (lbl->key + 100));
5240 /* now we are done */
5241 aopOp(result, ic, TRUE, FALSE);
5242 aopPut (AOP (result), "b", 0);
5247 /*-----------------------------------------------------------------*/
5248 /* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus */
5249 /*-----------------------------------------------------------------*/
5250 static void genModTwoByte (operand *left, operand *right,
5251 operand *result, iCode *ic)
5253 sym_link *retype = getSpec(operandType(right));
5254 sym_link *letype = getSpec(operandType(left));
5255 int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
5258 /* load up MA with left */
5259 /* save EA bit in F1 */
5260 lbl = newiTempLabel(NULL);
5261 emitcode ("setb","F1");
5262 emitcode ("jbc","EA,!tlabel",lbl->key+100);
5263 emitcode ("clr","F1");
5264 emitcode("","!tlabeldef",lbl->key+100);
5267 lbl = newiTempLabel(NULL);
5268 emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5269 emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5270 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5271 emitcode ("xch", "a,b");
5272 emitcode ("cpl","a");
5273 emitcode ("add", "a,#1");
5274 emitcode ("xch", "a,b");
5275 emitcode ("cpl", "a"); // msb
5276 emitcode ("addc","a,#0");
5277 emitcode ("","!tlabeldef",lbl->key+100);
5278 emitcode ("mov","ma,b");
5279 emitcode ("mov","ma,a");
5281 emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,NULL));
5282 emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,NULL));
5285 /* load up MB with right */
5287 if (AOP_TYPE(right) == AOP_LIT) {
5288 int val=(int)floatFromVal (AOP (right)->aopu.aop_lit);
5292 emitcode ("mov","mb,#!constbyte",val & 0xff);
5293 emitcode ("mov","mb,#!constbyte",(val >> 8) & 0xff);
5295 lbl = newiTempLabel(NULL);
5296 emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5297 emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5298 emitcode ("jnb","acc.7,!tlabel",lbl->key+100);
5299 emitcode ("xch", "a,b");
5300 emitcode ("cpl","a");
5301 emitcode ("add", "a,#1");
5302 emitcode ("xch", "a,b");
5303 emitcode ("cpl", "a"); // msb
5304 emitcode ("addc", "a,#0");
5305 emitcode ("","!tlabeldef",lbl->key+100);
5306 emitcode ("mov","mb,b");
5307 emitcode ("mov","mb,a");
5310 emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,NULL));
5311 emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,NULL));
5314 /* wait for multiplication to finish */
5315 lbl = newiTempLabel(NULL);
5316 emitcode("","!tlabeldef", lbl->key+100);
5317 emitcode("mov","a,mcnt1");
5318 emitcode("anl","a,#!constbyte",0x80);
5319 emitcode("jnz","!tlabel",lbl->key+100);
5321 freeAsmop (left, NULL, ic, TRUE);
5322 freeAsmop (right, NULL, ic,TRUE);
5323 aopOp(result, ic, TRUE, FALSE);
5325 aopPut(AOP(result),"mb",1);
5326 aopPut(AOP(result),"mb",0);
5327 freeAsmop (result, NULL, ic, TRUE);
5329 /* restore EA bit in F1 */
5330 lbl = newiTempLabel(NULL);
5331 emitcode ("jnb","F1,!tlabel",lbl->key+100);
5332 emitcode ("setb","EA");
5333 emitcode("","!tlabeldef",lbl->key+100);
5337 /*-----------------------------------------------------------------*/
5338 /* genMod - generates code for division */
5339 /*-----------------------------------------------------------------*/
5343 operand *left = IC_LEFT (ic);
5344 operand *right = IC_RIGHT (ic);
5345 operand *result = IC_RESULT (ic);
5347 D (emitcode (";", "genMod "); );
5349 /* assign the amsops */
5352 /* special cases first */
5354 if (AOP_TYPE (left) == AOP_CRY &&
5355 AOP_TYPE (right) == AOP_CRY)
5357 genModbits (left, right, result, ic);
5361 /* if both are of size == 1 */
5362 if (AOP_SIZE (left) == 1 &&
5363 AOP_SIZE (right) == 1)
5365 genModOneByte (left, right, result, ic);
5369 if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
5370 /* use the ds390 ARITHMETIC accel UNIT */
5371 genModTwoByte (left, right, result, ic);
5375 /* should have been converted to function call */
5379 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5380 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5381 freeAsmop (result, NULL, ic, TRUE);
5384 /*-----------------------------------------------------------------*/
5385 /* genIfxJump :- will create a jump depending on the ifx */
5386 /*-----------------------------------------------------------------*/
5388 genIfxJump (iCode * ic, char *jval)
5391 symbol *tlbl = newiTempLabel (NULL);
5394 D (emitcode (";", "genIfxJump"););
5396 /* if true label then we jump if condition
5400 jlbl = IC_TRUE (ic);
5401 inst = ((strcmp (jval, "a") == 0 ? "jz" :
5402 (strcmp (jval, "c") == 0 ? "jnc" : "jnb")));
5406 /* false label is present */
5407 jlbl = IC_FALSE (ic);
5408 inst = ((strcmp (jval, "a") == 0 ? "jnz" :
5409 (strcmp (jval, "c") == 0 ? "jc" : "jb")));
5411 if (strcmp (inst, "jb") == 0 || strcmp (inst, "jnb") == 0)
5412 emitcode (inst, "%s,!tlabel", jval, (tlbl->key + 100));
5414 emitcode (inst, "!tlabel", tlbl->key + 100);
5415 emitcode ("ljmp", "!tlabel", jlbl->key + 100);
5416 emitcode ("", "!tlabeldef", tlbl->key + 100);
5418 /* mark the icode as generated */
5422 /*-----------------------------------------------------------------*/
5423 /* genCmp :- greater or less than comparison */
5424 /*-----------------------------------------------------------------*/
5426 genCmp (operand * left, operand * right,
5427 iCode * ic, iCode * ifx, int sign)
5429 int size, offset = 0;
5430 unsigned long lit = 0L;
5433 D (emitcode (";", "genCmp"););
5435 result = IC_RESULT (ic);
5437 /* if left & right are bit variables */
5438 if (AOP_TYPE (left) == AOP_CRY &&
5439 AOP_TYPE (right) == AOP_CRY)
5441 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
5442 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
5446 /* subtract right from left if at the
5447 end the carry flag is set then we know that
5448 left is greater than right */
5449 size = max (AOP_SIZE (left), AOP_SIZE (right));
5451 /* if unsigned char cmp with lit, do cjne left,#right,zz */
5452 if ((size == 1) && !sign
5453 && (AOP_TYPE (right) == AOP_LIT && AOP_TYPE (left) != AOP_DIR && AOP_TYPE (left) != AOP_STR))
5455 symbol *lbl = newiTempLabel (NULL);
5456 emitcode ("cjne", "%s,%s,!tlabel",
5457 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
5458 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5460 emitcode ("", "!tlabeldef", lbl->key + 100);
5464 if (AOP_TYPE (right) == AOP_LIT)
5466 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5467 /* optimize if(x < 0) or if(x >= 0) */
5476 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
5478 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5479 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5481 aopOp (result, ic, FALSE, FALSE);
5483 if (!(AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result)) && ifx)
5485 freeAsmop (result, NULL, ic, TRUE);
5486 genIfxJump (ifx, "acc.7");
5491 emitcode ("rlc", "a");
5493 goto release_freedLR;
5501 // emitcode (";", "genCmp #1: %d/%d/%d", size, sign, offset);
5502 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5503 // emitcode (";", "genCmp #2");
5504 if (sign && (size == 0))
5506 // emitcode (";", "genCmp #3");
5507 emitcode ("xrl", "a,#!constbyte",0x80);
5508 if (AOP_TYPE (right) == AOP_LIT)
5510 unsigned long lit = (unsigned long)
5511 floatFromVal (AOP (right)->aopu.aop_lit);
5512 // emitcode (";", "genCmp #3.1");
5513 emitcode ("subb", "a,#!constbyte",
5514 0x80 ^ (unsigned int) ((lit >> (offset * 8)) & 0x0FFL));
5518 // emitcode (";", "genCmp #3.2");
5520 MOVB(aopGet (AOP (right), offset++, FALSE, FALSE, "b"));
5521 saveAccWarn = DEFAULT_ACC_WARNING;
5522 emitcode ("xrl", "b,#!constbyte",0x80);
5523 emitcode ("subb", "a,b");
5530 // emitcode (";", "genCmp #4");
5532 s = aopGet (AOP (right), offset++, FALSE, FALSE, "b");
5533 saveAccWarn = DEFAULT_ACC_WARNING;
5535 emitcode ("subb", "a,%s", s);
5542 /* Don't need the left & right operands any more; do need the result. */
5543 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5544 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5546 aopOp (result, ic, FALSE, FALSE);
5550 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5556 /* if the result is used in the next
5557 ifx conditional branch then generate
5558 code a little differently */
5561 genIfxJump (ifx, "c");
5567 /* leave the result in acc */
5569 freeAsmop (result, NULL, ic, TRUE);
5572 /*-----------------------------------------------------------------*/
5573 /* genCmpGt :- greater than comparison */
5574 /*-----------------------------------------------------------------*/
5576 genCmpGt (iCode * ic, iCode * ifx)
5578 operand *left, *right;
5579 sym_link *letype, *retype;
5582 D (emitcode (";", "genCmpGt ");
5585 left = IC_LEFT (ic);
5586 right = IC_RIGHT (ic);
5588 letype = getSpec (operandType (left));
5589 retype = getSpec (operandType (right));
5590 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5592 /* assign the left & right amsops */
5595 genCmp (right, left, ic, ifx, sign);
5598 /*-----------------------------------------------------------------*/
5599 /* genCmpLt - less than comparisons */
5600 /*-----------------------------------------------------------------*/
5602 genCmpLt (iCode * ic, iCode * ifx)
5604 operand *left, *right;
5605 sym_link *letype, *retype;
5608 D (emitcode (";", "genCmpLt "););
5610 left = IC_LEFT (ic);
5611 right = IC_RIGHT (ic);
5613 letype = getSpec (operandType (left));
5614 retype = getSpec (operandType (right));
5615 sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
5617 /* assign the left & right amsops */
5620 genCmp (left, right, ic, ifx, sign);
5623 /*-----------------------------------------------------------------*/
5624 /* gencjneshort - compare and jump if not equal */
5625 /*-----------------------------------------------------------------*/
5627 gencjneshort (operand * left, operand * right, symbol * lbl)
5629 int size = max (AOP_SIZE (left), AOP_SIZE (right));
5631 unsigned long lit = 0L;
5633 D (emitcode (";", "gencjneshort");
5636 /* if the left side is a literal or
5637 if the right is in a pointer register and left
5639 if ((AOP_TYPE (left) == AOP_LIT) ||
5640 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5647 if (AOP_TYPE (right) == AOP_LIT)
5648 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
5650 if (opIsGptr (left) || opIsGptr (right))
5652 /* We are comparing a generic pointer to something.
5653 * Exclude the generic type byte from the comparison.
5656 D (emitcode (";", "cjneshort: generic ptr special case."););
5660 /* if the right side is a literal then anything goes */
5661 if (AOP_TYPE (right) == AOP_LIT &&
5662 AOP_TYPE (left) != AOP_DIR)
5666 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5667 emitcode ("cjne", "a,%s,!tlabel",
5668 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
5674 /* if the right side is in a register or in direct space or
5675 if the left is a pointer register & right is not */
5676 else if (AOP_TYPE (right) == AOP_REG ||
5677 AOP_TYPE (right) == AOP_DIR ||
5678 (AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) ||
5679 (IS_AOP_PREG (left) && !IS_AOP_PREG (right)))
5683 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5684 if ((AOP_TYPE (left) == AOP_DIR && AOP_TYPE (right) == AOP_LIT) &&
5685 ((unsigned int) ((lit >> (offset * 8)) & 0x0FFL) == 0))
5686 emitcode ("jnz", "!tlabel", lbl->key + 100);
5688 emitcode ("cjne", "a,%s,!tlabel",
5689 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG),
5696 /* right is a pointer reg need both a & b */
5699 MOVB (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
5700 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
5701 emitcode ("cjne", "a,b,!tlabel", lbl->key + 100);
5707 /*-----------------------------------------------------------------*/
5708 /* gencjne - compare and jump if not equal */
5709 /*-----------------------------------------------------------------*/
5711 gencjne (operand * left, operand * right, symbol * lbl)
5713 symbol *tlbl = newiTempLabel (NULL);
5715 D (emitcode (";", "gencjne");
5718 gencjneshort (left, right, lbl);
5720 emitcode ("mov", "a,%s", one);
5721 emitcode ("sjmp", "!tlabel", tlbl->key + 100);
5722 emitcode ("", "!tlabeldef", lbl->key + 100);
5723 emitcode ("clr", "a");
5724 emitcode ("", "!tlabeldef", tlbl->key + 100);
5727 /*-----------------------------------------------------------------*/
5728 /* genCmpEq - generates code for equal to */
5729 /*-----------------------------------------------------------------*/
5731 genCmpEq (iCode * ic, iCode * ifx)
5733 operand *left, *right, *result;
5735 D (emitcode (";", "genCmpEq ");
5739 AOP_SET_LOCALS (ic);
5741 /* if literal, literal on the right or
5742 if the right is in a pointer register and left
5744 if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
5745 (IS_AOP_PREG (right) && !IS_AOP_PREG (left)))
5747 operand *t = IC_RIGHT (ic);
5748 IC_RIGHT (ic) = IC_LEFT (ic);
5752 if (ifx && /* !AOP_SIZE(result) */
5753 OP_SYMBOL (result) &&
5754 OP_SYMBOL (result)->regType == REG_CND)
5757 /* if they are both bit variables */
5758 if (AOP_TYPE (left) == AOP_CRY &&
5759 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5761 if (AOP_TYPE (right) == AOP_LIT)
5763 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5766 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5767 emitcode ("cpl", "c");
5771 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5775 emitcode ("clr", "c");
5777 /* AOP_TYPE(right) == AOP_CRY */
5781 symbol *lbl = newiTempLabel (NULL);
5782 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5783 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5784 emitcode ("cpl", "c");
5785 emitcode ("", "!tlabeldef", (lbl->key + 100));
5787 /* if true label then we jump if condition
5789 tlbl = newiTempLabel (NULL);
5792 emitcode ("jnc", "!tlabel", tlbl->key + 100);
5793 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5797 emitcode ("jc", "!tlabel", tlbl->key + 100);
5798 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5800 emitcode ("", "!tlabeldef", tlbl->key + 100);
5804 tlbl = newiTempLabel (NULL);
5805 gencjneshort (left, right, tlbl);
5808 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
5809 emitcode ("", "!tlabeldef", tlbl->key + 100);
5813 symbol *lbl = newiTempLabel (NULL);
5814 emitcode ("sjmp", "!tlabel", lbl->key + 100);
5815 emitcode ("", "!tlabeldef", tlbl->key + 100);
5816 emitcode ("ljmp", "!tlabel", IC_FALSE (ifx)->key + 100);
5817 emitcode ("", "!tlabeldef", lbl->key + 100);
5820 /* mark the icode as generated */
5823 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5824 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5828 /* if they are both bit variables */
5829 if (AOP_TYPE (left) == AOP_CRY &&
5830 ((AOP_TYPE (right) == AOP_CRY) || (AOP_TYPE (right) == AOP_LIT)))
5832 if (AOP_TYPE (right) == AOP_LIT)
5834 unsigned long lit = (unsigned long) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
5837 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5838 emitcode ("cpl", "c");
5842 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5846 emitcode ("clr", "c");
5848 /* AOP_TYPE(right) == AOP_CRY */
5852 symbol *lbl = newiTempLabel (NULL);
5853 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5854 emitcode ("jb", "%s,!tlabel", AOP (right)->aopu.aop_dir, (lbl->key + 100));
5855 emitcode ("cpl", "c");
5856 emitcode ("", "!tlabeldef", (lbl->key + 100));
5859 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5860 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5862 aopOp (result, ic, TRUE, FALSE);
5865 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5872 genIfxJump (ifx, "c");
5875 /* if the result is used in an arithmetic operation
5876 then put the result in place */
5881 gencjne (left, right, newiTempLabel (NULL));
5883 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5884 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5886 aopOp (result, ic, TRUE, FALSE);
5888 if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
5890 aopPut (AOP (result), "a", 0);
5895 genIfxJump (ifx, "a");
5898 /* if the result is used in an arithmetic operation
5899 then put the result in place */
5900 if (AOP_TYPE (result) != AOP_CRY)
5902 /* leave the result in acc */
5906 freeAsmop (result, NULL, ic, TRUE);
5909 /*-----------------------------------------------------------------*/
5910 /* ifxForOp - returns the icode containing the ifx for operand */
5911 /*-----------------------------------------------------------------*/
5913 ifxForOp (operand * op, iCode * ic)
5915 /* if true symbol then needs to be assigned */
5916 if (IS_TRUE_SYMOP (op))
5919 /* if this has register type condition and
5920 the next instruction is ifx with the same operand
5921 and live to of the operand is upto the ifx only then */
5923 ic->next->op == IFX &&
5924 IC_COND (ic->next)->key == op->key &&
5925 OP_SYMBOL (op)->liveTo <= ic->next->seq)
5930 /*-----------------------------------------------------------------*/
5931 /* hasInc - operand is incremented before any other use */
5932 /*-----------------------------------------------------------------*/
5934 hasInc (operand *op, iCode *ic, int osize)
5936 sym_link *type = operandType(op);
5937 sym_link *retype = getSpec (type);
5938 iCode *lic = ic->next;
5941 /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
5942 if (!IS_SYMOP(op)) return NULL;
5944 if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
5945 if (IS_AGGREGATE(type->next)) return NULL;
5946 if (osize != (isize = getSize(type->next))) return NULL;
5949 /* if operand of the form op = op + <sizeof *op> */
5950 if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
5951 isOperandEqual(IC_RESULT(lic),op) &&
5952 isOperandLiteral(IC_RIGHT(lic)) &&
5953 operandLitValue(IC_RIGHT(lic)) == isize) {
5956 /* if the operand used or deffed */
5957 if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
5960 /* if GOTO or IFX */
5961 if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
5967 /*-----------------------------------------------------------------*/
5968 /* genAndOp - for && operation */
5969 /*-----------------------------------------------------------------*/
5971 genAndOp (iCode * ic)
5973 operand *left, *right, *result;
5976 D (emitcode (";", "genAndOp "););
5978 /* note here that && operations that are in an
5979 if statement are taken away by backPatchLabels
5980 only those used in arthmetic operations remain */
5982 AOP_SET_LOCALS (ic);
5984 /* if both are bit variables */
5985 if (AOP_TYPE (left) == AOP_CRY &&
5986 AOP_TYPE (right) == AOP_CRY)
5988 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
5989 emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
5990 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5991 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
5993 aopOp (result,ic,FALSE, FALSE);
5998 tlbl = newiTempLabel (NULL);
6000 emitcode ("jz", "!tlabel", tlbl->key + 100);
6002 emitcode ("", "!tlabeldef", tlbl->key + 100);
6003 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6004 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6006 aopOp (result,ic,FALSE, FALSE);
6009 freeAsmop (result, NULL, ic, TRUE);
6013 /*-----------------------------------------------------------------*/
6014 /* genOrOp - for || operation */
6015 /*-----------------------------------------------------------------*/
6017 genOrOp (iCode * ic)
6019 operand *left, *right, *result;
6022 D (emitcode (";", "genOrOp "););
6024 /* note here that || operations that are in an
6025 if statement are taken away by backPatchLabels
6026 only those used in arthmetic operations remain */
6028 AOP_SET_LOCALS (ic);
6030 /* if both are bit variables */
6031 if (AOP_TYPE (left) == AOP_CRY &&
6032 AOP_TYPE (right) == AOP_CRY)
6034 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6035 emitcode ("orl", "c,%s", AOP (right)->aopu.aop_dir);
6036 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6037 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6039 aopOp (result,ic,FALSE, FALSE);
6045 tlbl = newiTempLabel (NULL);
6047 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6049 emitcode ("", "!tlabeldef", tlbl->key + 100);
6050 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6051 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6053 aopOp (result,ic,FALSE, FALSE);
6058 freeAsmop (result, NULL, ic, TRUE);
6061 /*-----------------------------------------------------------------*/
6062 /* isLiteralBit - test if lit == 2^n */
6063 /*-----------------------------------------------------------------*/
6065 isLiteralBit (unsigned long lit)
6067 unsigned long pw[32] =
6068 {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
6069 0x100L, 0x200L, 0x400L, 0x800L,
6070 0x1000L, 0x2000L, 0x4000L, 0x8000L,
6071 0x10000L, 0x20000L, 0x40000L, 0x80000L,
6072 0x100000L, 0x200000L, 0x400000L, 0x800000L,
6073 0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
6074 0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
6077 for (idx = 0; idx < 32; idx++)
6083 /*-----------------------------------------------------------------*/
6084 /* continueIfTrue - */
6085 /*-----------------------------------------------------------------*/
6087 continueIfTrue (iCode * ic)
6090 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6094 /*-----------------------------------------------------------------*/
6096 /*-----------------------------------------------------------------*/
6098 jumpIfTrue (iCode * ic)
6101 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6105 /*-----------------------------------------------------------------*/
6106 /* jmpTrueOrFalse - */
6107 /*-----------------------------------------------------------------*/
6109 jmpTrueOrFalse (iCode * ic, symbol * tlbl)
6111 // ugly but optimized by peephole
6114 symbol *nlbl = newiTempLabel (NULL);
6115 emitcode ("sjmp", "!tlabel", nlbl->key + 100);
6116 emitcode ("", "!tlabeldef", tlbl->key + 100);
6117 emitcode ("ljmp", "!tlabel", IC_TRUE (ic)->key + 100);
6118 emitcode ("", "!tlabeldef", nlbl->key + 100);
6122 emitcode ("ljmp", "!tlabel", IC_FALSE (ic)->key + 100);
6123 emitcode ("", "!tlabeldef", tlbl->key + 100);
6128 // Generate code to perform a bit-wise logic operation
6129 // on two operands in far space (assumed to already have been
6130 // aopOp'd by the AOP_OP_3_NOFATAL macro), storing the result
6131 // in far space. This requires pushing the result on the stack
6132 // then popping it into the result.
6134 genFarFarLogicOp(iCode *ic, char *logicOp)
6136 int size, resultSize, compSize;
6140 D(emitcode(";", "%s special case for 3 far operands.", logicOp););
6141 compSize = AOP_SIZE(IC_LEFT(ic)) < AOP_SIZE(IC_RIGHT(ic)) ?
6142 AOP_SIZE(IC_LEFT(ic)) : AOP_SIZE(IC_RIGHT(ic));
6144 _startLazyDPSEvaluation();
6145 for (size = compSize; (size--); offset++)
6147 MOVA (aopGet (AOP (IC_LEFT(ic)), offset, FALSE, FALSE, NULL));
6148 emitcode ("mov", "%s, acc", DP2_RESULT_REG);
6149 MOVA (aopGet (AOP (IC_RIGHT(ic)), offset, FALSE, FALSE, NULL));
6151 emitcode (logicOp, "a,%s", DP2_RESULT_REG);
6152 emitcode ("push", "acc");
6154 _endLazyDPSEvaluation();
6156 freeAsmop (IC_LEFT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6157 freeAsmop (IC_RIGHT(ic), NULL, ic, RESULTONSTACK (ic) ? FALSE : TRUE);
6158 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
6160 resultSize = AOP_SIZE(IC_RESULT(ic));
6162 ADJUST_PUSHED_RESULT(compSize, resultSize);
6164 _startLazyDPSEvaluation();
6167 emitcode ("pop", "acc");
6168 aopPut (AOP (IC_RESULT (ic)), "a", compSize);
6170 _endLazyDPSEvaluation();
6171 freeAsmop(IC_RESULT (ic), NULL, ic, TRUE);
6175 /*-----------------------------------------------------------------*/
6176 /* genAnd - code for and */
6177 /*-----------------------------------------------------------------*/
6179 genAnd (iCode * ic, iCode * ifx)
6181 operand *left, *right, *result;
6182 int size, offset = 0;
6183 unsigned long lit = 0L;
6188 D (emitcode (";", "genAnd "););
6190 AOP_OP_3_NOFATAL (ic, pushResult);
6191 AOP_SET_LOCALS (ic);
6195 genFarFarLogicOp(ic, "anl");
6200 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6202 AOP_TYPE (left), AOP_TYPE (right));
6203 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6205 AOP_SIZE (left), AOP_SIZE (right));
6208 /* if left is a literal & right is not then exchange them */
6209 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6210 #ifdef LOGIC_OPS_BROKEN
6211 || AOP_NEEDSACC (left)
6215 operand *tmp = right;
6220 /* if result = right then exchange them */
6221 if (sameRegs (AOP (result), AOP (right)))
6223 operand *tmp = right;
6228 /* if right is bit then exchange them */
6229 if (AOP_TYPE (right) == AOP_CRY &&
6230 AOP_TYPE (left) != AOP_CRY)
6232 operand *tmp = right;
6236 if (AOP_TYPE (right) == AOP_LIT)
6237 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6239 size = AOP_SIZE (result);
6242 // result = bit & yy;
6243 if (AOP_TYPE (left) == AOP_CRY)
6245 // c = bit & literal;
6246 if (AOP_TYPE (right) == AOP_LIT)
6250 if (size && sameRegs (AOP (result), AOP (left)))
6253 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6258 if (size && (AOP_TYPE (result) == AOP_CRY))
6260 emitcode ("clr", "%s", AOP (result)->aopu.aop_dir);
6263 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6268 emitcode ("clr", "c");
6273 if (AOP_TYPE (right) == AOP_CRY)
6276 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6277 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6282 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
6284 emitcode ("rrc", "a");
6285 emitcode ("anl", "c,%s", AOP (left)->aopu.aop_dir);
6293 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6294 genIfxJump (ifx, "c");
6298 // if(val & 0xZZ) - size = 0, ifx != FALSE -
6299 // bit = val & 0xZZ - size = 1, ifx = FALSE -
6300 if ((AOP_TYPE (right) == AOP_LIT) &&
6301 (AOP_TYPE (result) == AOP_CRY) &&
6302 (AOP_TYPE (left) != AOP_CRY))
6304 int posbit = isLiteralBit (lit);
6309 MOVA (aopGet (AOP (left), posbit >> 3, FALSE, FALSE, NULL));
6312 emitcode ("mov", "c,acc.%d", posbit & 0x07);
6318 SNPRINTF (buff, sizeof(buff),
6319 "acc.%d", posbit & 0x07);
6320 genIfxJump (ifx, buff);
6324 emitcode ("anl","a,#!constbyte",1 << (posbit & 0x07));
6331 symbol *tlbl = newiTempLabel (NULL);
6332 int sizel = AOP_SIZE (left);
6334 emitcode ("setb", "c");
6337 if ((bytelit = ((lit >> (offset * 8)) & 0x0FFL)) != 0x0L)
6339 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6341 if ((posbit = isLiteralBit (bytelit)) != 0)
6342 emitcode ("jb", "acc.%d,!tlabel", (posbit - 1) & 0x07, tlbl->key + 100);
6345 if (bytelit != 0x0FFL)
6346 emitcode ("anl", "a,%s",
6347 aopGet (AOP (right), offset, FALSE, TRUE, DP2_RESULT_REG));
6348 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6353 // bit = left & literal
6356 emitcode ("clr", "c");
6357 emitcode ("", "!tlabeldef", tlbl->key + 100);
6359 // if(left & literal)
6363 jmpTrueOrFalse (ifx, tlbl);
6371 /* if left is same as result */
6372 if (sameRegs (AOP (result), AOP (left)))
6374 for (; size--; offset++)
6376 if (AOP_TYPE (right) == AOP_LIT)
6378 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6380 else if (bytelit == 0)
6381 aopPut (AOP (result), zero, offset);
6382 else if (IS_AOP_PREG (result))
6384 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6385 emitcode ("anl", "a,%s",
6386 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6387 aopPut (AOP (result), "a", offset);
6390 emitcode ("anl", "%s,%s",
6391 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6392 aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6396 if (AOP_TYPE (left) == AOP_ACC)
6397 emitcode ("anl", "a,%s",
6398 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6401 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6402 if (IS_AOP_PREG (result))
6404 emitcode ("anl", "a,%s",
6405 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6406 aopPut (AOP (result), "a", offset);
6409 emitcode ("anl", "%s,a",
6410 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6417 // left & result in different registers
6418 if (AOP_TYPE (result) == AOP_CRY)
6421 // if(size), result in bit
6422 // if(!size && ifx), conditional oper: if(left & right)
6423 symbol *tlbl = newiTempLabel (NULL);
6424 int sizer = min (AOP_SIZE (left), AOP_SIZE (right));
6426 emitcode ("setb", "c");
6429 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6430 emitcode ("anl", "a,%s",
6431 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6433 if (AOP_TYPE(left)==AOP_ACC) {
6434 emitcode("mov", "b,a");
6435 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6436 emitcode("anl", "a,b");
6438 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6439 emitcode ("anl", "a,%s",
6440 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6443 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6449 emitcode ("", "!tlabeldef", tlbl->key + 100);
6453 jmpTrueOrFalse (ifx, tlbl);
6457 for (; (size--); offset++)
6460 // result = left & right
6461 if (AOP_TYPE (right) == AOP_LIT)
6463 if ((bytelit = (int) ((lit >> (offset * 8)) & 0x0FFL)) == 0x0FF)
6465 aopPut (AOP (result),
6466 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6470 else if (bytelit == 0)
6472 aopPut (AOP (result), zero, offset);
6475 D (emitcode (";", "better literal AND."););
6476 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6477 emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
6478 FALSE, FALSE, DP2_RESULT_REG));
6483 // faster than result <- left, anl result,right
6484 // and better if result is SFR
6485 if (AOP_TYPE (left) == AOP_ACC)
6487 emitcode ("anl", "a,%s",
6488 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6492 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6493 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6495 emitcode("mov", "b,a");
6499 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6500 emitcode ("anl", "a,%s", rOp);
6503 aopPut (AOP (result), "a", offset);
6509 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6510 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6511 freeAsmop (result, NULL, ic, TRUE);
6515 /*-----------------------------------------------------------------*/
6516 /* genOr - code for or */
6517 /*-----------------------------------------------------------------*/
6519 genOr (iCode * ic, iCode * ifx)
6521 operand *left, *right, *result;
6522 int size, offset = 0;
6523 unsigned long lit = 0L;
6526 D (emitcode (";", "genOr "););
6528 AOP_OP_3_NOFATAL (ic, pushResult);
6529 AOP_SET_LOCALS (ic);
6533 genFarFarLogicOp(ic, "orl");
6539 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6541 AOP_TYPE (left), AOP_TYPE (right));
6542 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6544 AOP_SIZE (left), AOP_SIZE (right));
6547 /* if left is a literal & right is not then exchange them */
6548 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6549 #ifdef LOGIC_OPS_BROKEN
6550 || AOP_NEEDSACC (left) // I think this is a net loss now.
6554 operand *tmp = right;
6559 /* if result = right then exchange them */
6560 if (sameRegs (AOP (result), AOP (right)))
6562 operand *tmp = right;
6567 /* if right is bit then exchange them */
6568 if (AOP_TYPE (right) == AOP_CRY &&
6569 AOP_TYPE (left) != AOP_CRY)
6571 operand *tmp = right;
6575 if (AOP_TYPE (right) == AOP_LIT)
6576 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6578 size = AOP_SIZE (result);
6582 if (AOP_TYPE (left) == AOP_CRY)
6584 if (AOP_TYPE (right) == AOP_LIT)
6586 // c = bit & literal;
6589 // lit != 0 => result = 1
6590 if (AOP_TYPE (result) == AOP_CRY)
6593 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6595 continueIfTrue (ifx);
6598 emitcode ("setb", "c");
6602 // lit == 0 => result = left
6603 if (size && sameRegs (AOP (result), AOP (left)))
6605 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6610 if (AOP_TYPE (right) == AOP_CRY)
6613 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6614 emitcode ("orl", "c,%s", AOP (left)->aopu.aop_dir);
6619 symbol *tlbl = newiTempLabel (NULL);
6620 if (!((AOP_TYPE (result) == AOP_CRY) && ifx))
6621 emitcode ("setb", "c");
6622 emitcode ("jb", "%s,!tlabel",
6623 AOP (left)->aopu.aop_dir, tlbl->key + 100);
6625 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6626 if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6628 jmpTrueOrFalse (ifx, tlbl);
6634 emitcode ("", "!tlabeldef", tlbl->key + 100);
6643 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6644 genIfxJump (ifx, "c");
6648 // if(val | 0xZZ) - size = 0, ifx != FALSE -
6649 // bit = val | 0xZZ - size = 1, ifx = FALSE -
6650 if ((AOP_TYPE (right) == AOP_LIT) &&
6651 (AOP_TYPE (result) == AOP_CRY) &&
6652 (AOP_TYPE (left) != AOP_CRY))
6658 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6660 continueIfTrue (ifx);
6665 // lit = 0, result = boolean(left)
6667 emitcode ("setb", "c");
6671 symbol *tlbl = newiTempLabel (NULL);
6672 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6674 emitcode ("", "!tlabeldef", tlbl->key + 100);
6678 genIfxJump (ifx, "a");
6686 /* if left is same as result */
6687 if (sameRegs (AOP (result), AOP (left)))
6689 for (; size--; offset++)
6691 if (AOP_TYPE (right) == AOP_LIT)
6693 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6699 if (IS_AOP_PREG (left))
6701 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6702 emitcode ("orl", "a,%s",
6703 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6704 aopPut (AOP (result), "a", offset);
6708 emitcode ("orl", "%s,%s",
6709 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
6710 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6716 if (AOP_TYPE (left) == AOP_ACC)
6718 emitcode ("orl", "a,%s",
6719 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6723 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6724 if (IS_AOP_PREG (left))
6726 emitcode ("orl", "a,%s",
6727 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6728 aopPut (AOP (result), "a", offset);
6732 emitcode ("orl", "%s,a",
6733 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6741 // left & result in different registers
6742 if (AOP_TYPE (result) == AOP_CRY)
6745 // if(size), result in bit
6746 // if(!size && ifx), conditional oper: if(left | right)
6747 symbol *tlbl = newiTempLabel (NULL);
6748 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
6750 emitcode ("setb", "c");
6753 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
6754 emitcode ("orl", "a,%s",
6755 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
6757 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6758 emitcode ("orl", "a,%s",
6759 aopGet (AOP (left), offset, FALSE, FALSE, DP2_RESULT_REG));
6761 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6767 emitcode ("", "!tlabeldef", tlbl->key + 100);
6771 jmpTrueOrFalse (ifx, tlbl);
6775 _startLazyDPSEvaluation();
6776 for (; (size--); offset++)
6779 // result = left & right
6780 if (AOP_TYPE (right) == AOP_LIT)
6782 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6784 aopPut (AOP (result),
6785 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
6789 D (emitcode (";", "better literal OR."););
6790 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6791 emitcode ("orl", "a, %s",
6792 aopGet (AOP (right), offset,
6793 FALSE, FALSE, DP2_RESULT_REG));
6798 // faster than result <- left, anl result,right
6799 // and better if result is SFR
6800 if (AOP_TYPE (left) == AOP_ACC)
6802 emitcode ("orl", "a,%s",
6803 aopGet (AOP (right), offset,
6804 FALSE, FALSE, DP2_RESULT_REG));
6808 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
6810 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
6812 emitcode("mov", "b,a");
6816 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
6817 emitcode ("orl", "a,%s", rOp);
6820 aopPut (AOP (result), "a", offset);
6822 _endLazyDPSEvaluation();
6827 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6828 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
6829 freeAsmop (result, NULL, ic, TRUE);
6832 /*-----------------------------------------------------------------*/
6833 /* genXor - code for xclusive or */
6834 /*-----------------------------------------------------------------*/
6836 genXor (iCode * ic, iCode * ifx)
6838 operand *left, *right, *result;
6839 int size, offset = 0;
6840 unsigned long lit = 0L;
6843 D (emitcode (";", "genXor "););
6845 AOP_OP_3_NOFATAL (ic, pushResult);
6846 AOP_SET_LOCALS (ic);
6850 genFarFarLogicOp(ic, "xrl");
6855 emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
6857 AOP_TYPE (left), AOP_TYPE (right));
6858 emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
6860 AOP_SIZE (left), AOP_SIZE (right));
6863 /* if left is a literal & right is not ||
6864 if left needs acc & right does not */
6865 if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
6866 #ifdef LOGIC_OPS_BROKEN
6867 || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
6871 operand *tmp = right;
6876 /* if result = right then exchange them */
6877 if (sameRegs (AOP (result), AOP (right)))
6879 operand *tmp = right;
6884 /* if right is bit then exchange them */
6885 if (AOP_TYPE (right) == AOP_CRY &&
6886 AOP_TYPE (left) != AOP_CRY)
6888 operand *tmp = right;
6892 if (AOP_TYPE (right) == AOP_LIT)
6893 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
6895 size = AOP_SIZE (result);
6899 if (AOP_TYPE (left) == AOP_CRY)
6901 if (AOP_TYPE (right) == AOP_LIT)
6903 // c = bit & literal;
6906 // lit>>1 != 0 => result = 1
6907 if (AOP_TYPE (result) == AOP_CRY)
6910 emitcode ("setb", "%s", AOP (result)->aopu.aop_dir);
6912 continueIfTrue (ifx);
6915 emitcode ("setb", "c");
6922 // lit == 0, result = left
6923 if (size && sameRegs (AOP (result), AOP (left)))
6925 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6929 // lit == 1, result = not(left)
6930 if (size && sameRegs (AOP (result), AOP (left)))
6932 emitcode ("cpl", "%s", AOP (result)->aopu.aop_dir);
6937 emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
6938 emitcode ("cpl", "c");
6947 symbol *tlbl = newiTempLabel (NULL);
6948 if (AOP_TYPE (right) == AOP_CRY)
6951 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
6955 int sizer = AOP_SIZE (right);
6957 // if val>>1 != 0, result = 1
6958 emitcode ("setb", "c");
6961 MOVA (aopGet (AOP (right), sizer - 1, FALSE, FALSE, NULL));
6963 // test the msb of the lsb
6964 emitcode ("anl", "a,#!constbyte",0xfe);
6965 emitcode ("jnz", "!tlabel", tlbl->key + 100);
6969 emitcode ("rrc", "a");
6971 emitcode ("jnb", "%s,!tlabel", AOP (left)->aopu.aop_dir, (tlbl->key + 100));
6972 emitcode ("cpl", "c");
6973 emitcode ("", "!tlabeldef", (tlbl->key + 100));
6980 else if ((AOP_TYPE (result) == AOP_CRY) && ifx)
6981 genIfxJump (ifx, "c");
6985 if (sameRegs (AOP (result), AOP (left)))
6987 /* if left is same as result */
6988 for (; size--; offset++)
6990 if (AOP_TYPE (right) == AOP_LIT)
6992 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
6994 else if (IS_AOP_PREG (left))
6996 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
6997 emitcode ("xrl", "a,%s",
6998 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
6999 aopPut (AOP (result), "a", offset);
7002 emitcode ("xrl", "%s,%s",
7003 aopGet (AOP (left), offset, FALSE, TRUE, NULL),
7004 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7008 if (AOP_TYPE (left) == AOP_ACC)
7009 emitcode ("xrl", "a,%s",
7010 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7013 MOVA (aopGet (AOP (right), offset, FALSE, FALSE, NULL));
7014 if (IS_AOP_PREG (left))
7016 emitcode ("xrl", "a,%s",
7017 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7018 aopPut (AOP (result), "a", offset);
7021 emitcode ("xrl", "%s,a",
7022 aopGet (AOP (left), offset, FALSE, TRUE, DP2_RESULT_REG));
7029 // left & result in different registers
7030 if (AOP_TYPE (result) == AOP_CRY)
7033 // if(size), result in bit
7034 // if(!size && ifx), conditional oper: if(left ^ right)
7035 symbol *tlbl = newiTempLabel (NULL);
7036 int sizer = max (AOP_SIZE (left), AOP_SIZE (right));
7039 emitcode ("setb", "c");
7042 if ((AOP_TYPE (right) == AOP_LIT) &&
7043 (((lit >> (offset * 8)) & 0x0FFL) == 0x00L))
7045 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7049 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
7050 emitcode ("xrl", "a,%s",
7051 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7053 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7054 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7056 emitcode("mov", "b,a");
7060 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7061 emitcode ("xrl", "a,%s", rOp);
7064 emitcode ("jnz", "!tlabel", tlbl->key + 100);
7070 emitcode ("", "!tlabeldef", tlbl->key + 100);
7074 jmpTrueOrFalse (ifx, tlbl);
7078 for (; (size--); offset++)
7081 // result = left & right
7082 if (AOP_TYPE (right) == AOP_LIT)
7084 if (((lit >> (offset * 8)) & 0x0FFL) == 0x00L)
7086 aopPut (AOP (result),
7087 aopGet (AOP (left), offset, FALSE, FALSE, NULL),
7091 D (emitcode (";", "better literal XOR."););
7092 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7093 emitcode ("xrl", "a, %s",
7094 aopGet (AOP (right), offset, FALSE, FALSE, DP2_RESULT_REG));
7098 // faster than result <- left, anl result,right
7099 // and better if result is SFR
7100 if (AOP_TYPE (left) == AOP_ACC)
7102 emitcode ("xrl", "a,%s",
7103 aopGet (AOP (right), offset,
7104 FALSE, FALSE, DP2_RESULT_REG));
7108 char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, NULL);
7109 if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
7111 emitcode("mov", "b,a");
7115 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7116 emitcode ("xrl", "a,%s", rOp);
7119 aopPut (AOP (result), "a", offset);
7126 freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7127 freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
7128 freeAsmop (result, NULL, ic, TRUE);
7131 /*-----------------------------------------------------------------*/
7132 /* genInline - write the inline code out */
7133 /*-----------------------------------------------------------------*/
7135 genInline (iCode * ic)
7137 char *buffer, *bp, *bp1;
7139 D (emitcode (";", "genInline "); );
7141 _G.inLine += (!options.asmpeep);
7143 buffer = Safe_strdup(IC_INLINE(ic));
7147 /* emit each line as a code */
7172 /* emitcode("",buffer); */
7173 _G.inLine -= (!options.asmpeep);
7176 /*-----------------------------------------------------------------*/
7177 /* genRRC - rotate right with carry */
7178 /*-----------------------------------------------------------------*/
7182 operand *left, *result;
7185 D (emitcode (";", "genRRC "););
7187 /* rotate right with carry */
7188 left = IC_LEFT (ic);
7189 result = IC_RESULT (ic);
7190 aopOp (left, ic, FALSE, FALSE);
7191 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7193 /* move it to the result */
7194 size = AOP_SIZE (result);
7198 _startLazyDPSEvaluation ();
7201 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
7202 emitcode ("rrc", "a");
7203 if (AOP_SIZE (result) > 1)
7204 aopPut (AOP (result), "a", offset--);
7206 _endLazyDPSEvaluation ();
7208 /* now we need to put the carry into the
7209 highest order byte of the result */
7210 if (AOP_SIZE (result) > 1)
7212 MOVA (aopGet (AOP (result), AOP_SIZE (result) - 1, FALSE, FALSE, NULL));
7214 emitcode ("mov", "acc.7,c");
7215 aopPut (AOP (result), "a", AOP_SIZE (result) - 1);
7216 freeAsmop (left, NULL, ic, TRUE);
7217 freeAsmop (result, NULL, ic, TRUE);
7220 /*-----------------------------------------------------------------*/
7221 /* genRLC - generate code for rotate left with carry */
7222 /*-----------------------------------------------------------------*/
7226 operand *left, *result;
7230 D (emitcode (";", "genRLC "););
7232 /* rotate right with carry */
7233 left = IC_LEFT (ic);
7234 result = IC_RESULT (ic);
7235 aopOp (left, ic, FALSE, FALSE);
7236 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7238 /* move it to the result */
7239 size = AOP_SIZE (result);
7243 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7245 emitcode ("add", "a,acc");
7246 if (AOP_SIZE (result) > 1)
7248 aopPut (AOP (result), "a", offset++);
7251 _startLazyDPSEvaluation ();
7254 l = aopGet (AOP (left), offset, FALSE, FALSE, NULL);
7256 emitcode ("rlc", "a");
7257 if (AOP_SIZE (result) > 1)
7258 aopPut (AOP (result), "a", offset++);
7260 _endLazyDPSEvaluation ();
7262 /* now we need to put the carry into the
7263 highest order byte of the result */
7264 if (AOP_SIZE (result) > 1)
7266 l = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
7269 emitcode ("mov", "acc.0,c");
7270 aopPut (AOP (result), "a", 0);
7271 freeAsmop (left, NULL, ic, TRUE);
7272 freeAsmop (result, NULL, ic, TRUE);
7275 /*-----------------------------------------------------------------*/
7276 /* genGetHbit - generates code get highest order bit */
7277 /*-----------------------------------------------------------------*/
7279 genGetHbit (iCode * ic)
7281 operand *left, *result;
7282 left = IC_LEFT (ic);
7283 result = IC_RESULT (ic);
7284 aopOp (left, ic, FALSE, FALSE);
7285 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
7287 D (emitcode (";", "genGetHbit "););
7289 /* get the highest order byte into a */
7290 MOVA (aopGet (AOP (left), AOP_SIZE (left) - 1, FALSE, FALSE, NULL));
7291 if (AOP_TYPE (result) == AOP_CRY)
7293 emitcode ("rlc", "a");
7298 emitcode ("rl", "a");
7299 emitcode ("anl", "a,#1");
7304 freeAsmop (left, NULL, ic, TRUE);
7305 freeAsmop (result, NULL, ic, TRUE);
7308 /*-----------------------------------------------------------------*/
7309 /* AccRol - rotate left accumulator by known count */
7310 /*-----------------------------------------------------------------*/
7312 AccRol (int shCount)
7314 shCount &= 0x0007; // shCount : 0..7
7321 emitcode ("rl", "a");
7324 emitcode ("rl", "a");
7325 emitcode ("rl", "a");
7328 emitcode ("swap", "a");
7329 emitcode ("rr", "a");
7332 emitcode ("swap", "a");
7335 emitcode ("swap", "a");
7336 emitcode ("rl", "a");
7339 emitcode ("rr", "a");
7340 emitcode ("rr", "a");
7343 emitcode ("rr", "a");
7348 /*-----------------------------------------------------------------*/
7349 /* AccLsh - left shift accumulator by known count */
7350 /*-----------------------------------------------------------------*/
7352 AccLsh (int shCount)
7357 emitcode ("add", "a,acc");
7358 else if (shCount == 2)
7360 emitcode ("add", "a,acc");
7361 emitcode ("add", "a,acc");
7365 /* rotate left accumulator */
7367 /* and kill the lower order bits */
7368 emitcode ("anl", "a,#!constbyte", SLMask[shCount]);
7373 /*-----------------------------------------------------------------*/
7374 /* AccRsh - right shift accumulator by known count */
7375 /*-----------------------------------------------------------------*/
7377 AccRsh (int shCount)
7384 emitcode ("rrc", "a");
7388 /* rotate right accumulator */
7389 AccRol (8 - shCount);
7390 /* and kill the higher order bits */
7391 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7396 #ifdef BETTER_LITERAL_SHIFT
7397 /*-----------------------------------------------------------------*/
7398 /* AccSRsh - signed right shift accumulator by known count */
7399 /*-----------------------------------------------------------------*/
7401 AccSRsh (int shCount)
7408 emitcode ("mov", "c,acc.7");
7409 emitcode ("rrc", "a");
7411 else if (shCount == 2)
7413 emitcode ("mov", "c,acc.7");
7414 emitcode ("rrc", "a");
7415 emitcode ("mov", "c,acc.7");
7416 emitcode ("rrc", "a");
7420 tlbl = newiTempLabel (NULL);
7421 /* rotate right accumulator */
7422 AccRol (8 - shCount);
7423 /* and kill the higher order bits */
7424 emitcode ("anl", "a,#!constbyte", SRMask[shCount]);
7425 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7426 emitcode ("orl", "a,#!constbyte",
7427 (unsigned char) ~SRMask[shCount]);
7428 emitcode ("", "!tlabeldef", tlbl->key + 100);
7434 #ifdef BETTER_LITERAL_SHIFT
7435 /*-----------------------------------------------------------------*/
7436 /* shiftR1Left2Result - shift right one byte from left to result */
7437 /*-----------------------------------------------------------------*/
7439 shiftR1Left2Result (operand * left, int offl,
7440 operand * result, int offr,
7441 int shCount, int sign)
7443 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7444 /* shift right accumulator */
7449 aopPut (AOP (result), "a", offr);
7453 #ifdef BETTER_LITERAL_SHIFT
7454 /*-----------------------------------------------------------------*/
7455 /* shiftL1Left2Result - shift left one byte from left to result */
7456 /*-----------------------------------------------------------------*/
7458 shiftL1Left2Result (operand * left, int offl,
7459 operand * result, int offr, int shCount)
7461 MOVA(aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7462 /* shift left accumulator */
7464 aopPut (AOP (result), "a", offr);
7468 #ifdef BETTER_LITERAL_SHIFT
7469 /*-----------------------------------------------------------------*/
7470 /* movLeft2Result - move byte from left to result */
7471 /*-----------------------------------------------------------------*/
7473 movLeft2Result (operand * left, int offl,
7474 operand * result, int offr, int sign)
7477 if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
7479 l = aopGet (AOP (left), offl, FALSE, FALSE, NULL);
7481 if (*l == '@' && (IS_AOP_PREG (result)))
7483 emitcode ("mov", "a,%s", l);
7484 aopPut (AOP (result), "a", offr);
7490 aopPut (AOP (result), l, offr);
7494 /* MSB sign in acc.7 ! */
7495 if (getDataSize (left) == offl + 1)
7497 emitcode ("mov", "a,%s", l);
7498 aopPut (AOP (result), "a", offr);
7506 #ifdef BETTER_LITERAL_SHIFT
7507 /*-----------------------------------------------------------------*/
7508 /* AccAXRrl1 - right rotate c->a:x->c by 1 */
7509 /*-----------------------------------------------------------------*/
7513 emitcode ("rrc", "a");
7514 emitcode ("xch", "a,%s", x);
7515 emitcode ("rrc", "a");
7516 emitcode ("xch", "a,%s", x);
7520 #ifdef BETTER_LITERAL_SHIFT
7522 /*-----------------------------------------------------------------*/
7523 /* AccAXLrl1 - left rotate c<-a:x<-c by 1 */
7524 /*-----------------------------------------------------------------*/
7528 emitcode ("xch", "a,%s", x);
7529 emitcode ("rlc", "a");
7530 emitcode ("xch", "a,%s", x);
7531 emitcode ("rlc", "a");
7535 #ifdef BETTER_LITERAL_SHIFT
7536 /*-----------------------------------------------------------------*/
7537 /* AccAXLsh1 - left shift a:x<-0 by 1 */
7538 /*-----------------------------------------------------------------*/
7542 emitcode ("xch", "a,%s", x);
7543 emitcode ("add", "a,acc");
7544 emitcode ("xch", "a,%s", x);
7545 emitcode ("rlc", "a");
7549 #ifdef BETTER_LITERAL_SHIFT
7550 /*-----------------------------------------------------------------*/
7551 /* AccAXLsh - left shift a:x by known count (0..7) */
7552 /*-----------------------------------------------------------------*/
7554 AccAXLsh (char *x, int shCount)
7569 case 5: // AAAAABBB:CCCCCDDD
7571 AccRol (shCount); // BBBAAAAA:CCCCCDDD
7573 emitcode ("anl", "a,#!constbyte",
7574 SLMask[shCount]); // BBB00000:CCCCCDDD
7576 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBB00000
7578 AccRol (shCount); // DDDCCCCC:BBB00000
7580 emitcode ("xch", "a,%s", x); // BBB00000:DDDCCCCC
7582 emitcode ("xrl", "a,%s", x); // (BBB^DDD)CCCCC:DDDCCCCC
7584 emitcode ("xch", "a,%s", x); // DDDCCCCC:(BBB^DDD)CCCCC
7586 emitcode ("anl", "a,#!constbyte",
7587 SLMask[shCount]); // DDD00000:(BBB^DDD)CCCCC
7589 emitcode ("xch", "a,%s", x); // (BBB^DDD)CCCCC:DDD00000
7591 emitcode ("xrl", "a,%s", x); // BBBCCCCC:DDD00000
7594 case 6: // AAAAAABB:CCCCCCDD
7595 emitcode ("anl", "a,#!constbyte",
7596 SRMask[shCount]); // 000000BB:CCCCCCDD
7597 emitcode ("mov", "c,acc.0"); // c = B
7598 emitcode ("xch", "a,%s", x); // CCCCCCDD:000000BB
7600 AccAXRrl1 (x); // BCCCCCCD:D000000B
7601 AccAXRrl1 (x); // BBCCCCCC:DD000000
7603 emitcode("rrc","a");
7604 emitcode("xch","a,%s", x);
7605 emitcode("rrc","a");
7606 emitcode("mov","c,acc.0"); //<< get correct bit
7607 emitcode("xch","a,%s", x);
7609 emitcode("rrc","a");
7610 emitcode("xch","a,%s", x);
7611 emitcode("rrc","a");
7612 emitcode("xch","a,%s", x);
7615 case 7: // a:x <<= 7
7617 emitcode ("anl", "a,#!constbyte",
7618 SRMask[shCount]); // 0000000B:CCCCCCCD
7620 emitcode ("mov", "c,acc.0"); // c = B
7622 emitcode ("xch", "a,%s", x); // CCCCCCCD:0000000B
7624 AccAXRrl1 (x); // BCCCCCCC:D0000000
7633 #ifdef BETTER_LITERAL_SHIFT
7635 /*-----------------------------------------------------------------*/
7636 /* AccAXRsh - right shift a:x known count (0..7) */
7637 /*-----------------------------------------------------------------*/
7639 AccAXRsh (char *x, int shCount)
7647 AccAXRrl1 (x); // 0->a:x
7652 AccAXRrl1 (x); // 0->a:x
7655 AccAXRrl1 (x); // 0->a:x
7660 case 5: // AAAAABBB:CCCCCDDD = a:x
7662 AccRol (8 - shCount); // BBBAAAAA:DDDCCCCC
7664 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7666 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7668 emitcode ("anl", "a,#!constbyte",
7669 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7671 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7673 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7675 emitcode ("anl", "a,#!constbyte",
7676 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7678 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7680 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7682 emitcode ("xch", "a,%s", x); // 000AAAAA:BBBCCCCC
7685 case 6: // AABBBBBB:CCDDDDDD
7687 emitcode ("mov", "c,acc.7");
7688 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7690 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7692 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7694 emitcode ("anl", "a,#!constbyte",
7695 SRMask[shCount]); // 000000AA:BBBBBBCC
7698 case 7: // ABBBBBBB:CDDDDDDD
7700 emitcode ("mov", "c,acc.7"); // c = A
7702 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7704 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7706 emitcode ("anl", "a,#!constbyte",
7707 SRMask[shCount]); // 0000000A:BBBBBBBC
7716 #ifdef BETTER_LITERAL_SHIFT
7717 /*-----------------------------------------------------------------*/
7718 /* AccAXRshS - right shift signed a:x known count (0..7) */
7719 /*-----------------------------------------------------------------*/
7721 AccAXRshS (char *x, int shCount)
7729 emitcode ("mov", "c,acc.7");
7730 AccAXRrl1 (x); // s->a:x
7734 emitcode ("mov", "c,acc.7");
7735 AccAXRrl1 (x); // s->a:x
7737 emitcode ("mov", "c,acc.7");
7738 AccAXRrl1 (x); // s->a:x
7743 case 5: // AAAAABBB:CCCCCDDD = a:x
7745 tlbl = newiTempLabel (NULL);
7746 AccRol (8 - shCount); // BBBAAAAA:CCCCCDDD
7748 emitcode ("xch", "a,%s", x); // CCCCCDDD:BBBAAAAA
7750 AccRol (8 - shCount); // DDDCCCCC:BBBAAAAA
7752 emitcode ("anl", "a,#!constbyte",
7753 SRMask[shCount]); // 000CCCCC:BBBAAAAA
7755 emitcode ("xrl", "a,%s", x); // BBB(CCCCC^AAAAA):BBBAAAAA
7757 emitcode ("xch", "a,%s", x); // BBBAAAAA:BBB(CCCCC^AAAAA)
7759 emitcode ("anl", "a,#!constbyte",
7760 SRMask[shCount]); // 000AAAAA:BBB(CCCCC^AAAAA)
7762 emitcode ("xch", "a,%s", x); // BBB(CCCCC^AAAAA):000AAAAA
7764 emitcode ("xrl", "a,%s", x); // BBBCCCCC:000AAAAA
7766 emitcode ("xch", "a,%s", x); // 000SAAAA:BBBCCCCC
7768 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7769 emitcode ("orl", "a,#!constbyte",
7770 (unsigned char) ~SRMask[shCount]); // 111AAAAA:BBBCCCCC
7772 emitcode ("", "!tlabeldef", tlbl->key + 100);
7773 break; // SSSSAAAA:BBBCCCCC
7775 case 6: // AABBBBBB:CCDDDDDD
7777 tlbl = newiTempLabel (NULL);
7778 emitcode ("mov", "c,acc.7");
7779 AccAXLrl1 (x); // ABBBBBBC:CDDDDDDA
7781 AccAXLrl1 (x); // BBBBBBCC:DDDDDDAA
7783 emitcode ("xch", "a,%s", x); // DDDDDDAA:BBBBBBCC
7785 emitcode ("anl", "a,#!constbyte",
7786 SRMask[shCount]); // 000000AA:BBBBBBCC
7788 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7789 emitcode ("orl", "a,#!constbyte",
7790 (unsigned char) ~SRMask[shCount]); // 111111AA:BBBBBBCC
7792 emitcode ("", "!tlabeldef", tlbl->key + 100);
7794 case 7: // ABBBBBBB:CDDDDDDD
7796 tlbl = newiTempLabel (NULL);
7797 emitcode ("mov", "c,acc.7"); // c = A
7799 AccAXLrl1 (x); // BBBBBBBC:DDDDDDDA
7801 emitcode ("xch", "a,%s", x); // DDDDDDDA:BBBBBBCC
7803 emitcode ("anl", "a,#!constbyte",
7804 SRMask[shCount]); // 0000000A:BBBBBBBC
7806 emitcode ("jnb", "acc.%d,!tlabel", 7 - shCount, tlbl->key + 100);
7807 emitcode ("orl", "a,#!constbyte",
7808 (unsigned char) ~SRMask[shCount]); // 1111111A:BBBBBBBC
7810 emitcode ("", "!tlabeldef", tlbl->key + 100);
7818 #ifdef BETTER_LITERAL_SHIFT
7820 _loadLeftIntoAx(char **lsb,
7826 // Get the initial value from left into a pair of registers.
7827 // MSB must be in A, LSB can be any register.
7829 // If the result is held in registers, it is an optimization
7830 // if the LSB can be held in the register which will hold the,
7831 // result LSB since this saves us from having to copy it into
7832 // the result following AccAXLsh.
7834 // If the result is addressed indirectly, this is not a gain.
7835 if (AOP_NEEDSACC(result))
7839 _startLazyDPSEvaluation();
7840 if (AOP_TYPE(left) == AOP_DPTR2)
7843 MOVA(aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL));
7844 // get LSB in DP2_RESULT_REG.
7845 leftByte = aopGet(AOP(left), offl, FALSE, FALSE, DP2_RESULT_REG);
7846 assert(!strcmp(leftByte, DP2_RESULT_REG));
7850 // get LSB into DP2_RESULT_REG
7851 leftByte = aopGet (AOP(left), offl, FALSE, FALSE, NULL);
7852 if (strcmp(leftByte, DP2_RESULT_REG))
7855 emitcode("mov","%s,%s", DP2_RESULT_REG, leftByte);
7858 leftByte = aopGet(AOP(left), offl + MSB16, FALSE, FALSE, NULL);
7859 assert(strcmp(leftByte, DP2_RESULT_REG));
7862 _endLazyDPSEvaluation();
7863 *lsb = DP2_RESULT_REG;
7867 if (sameRegs (AOP (result), AOP (left)) &&
7868 ((offl + MSB16) == offr))
7870 /* don't crash result[offr] */
7871 MOVA(aopGet(AOP(left), offl, FALSE, FALSE, NULL));
7872 emitcode ("xch", "a,%s",
7873 aopGet(AOP(left), offl + MSB16, FALSE, FALSE, DP2_RESULT_REG));
7877 movLeft2Result (left, offl, result, offr, 0);
7878 MOVA (aopGet (AOP (left), offl + MSB16, FALSE, FALSE, NULL));
7880 *lsb = aopGet(AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG);
7881 assert(strcmp(*lsb,"a"));
7886 _storeAxResults(char *lsb,
7890 _startLazyDPSEvaluation();
7891 if (AOP_NEEDSACC(result))
7893 /* We have to explicitly update the result LSB.
7895 emitcode("xch","a,%s", lsb);
7896 aopPut(AOP(result), "a", offr);
7897 emitcode("mov","a,%s", lsb);
7899 if (getDataSize (result) > 1)
7901 aopPut (AOP (result), "a", offr + MSB16);
7903 _endLazyDPSEvaluation();
7906 /*-----------------------------------------------------------------*/
7907 /* shiftL2Left2Result - shift left two bytes from left to result */
7908 /*-----------------------------------------------------------------*/
7910 shiftL2Left2Result (operand * left, int offl,
7911 operand * result, int offr, int shCount)
7915 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7917 AccAXLsh (lsb, shCount);
7919 _storeAxResults(lsb, result, offr);
7923 #ifdef BETTER_LITERAL_SHIFT
7924 /*-----------------------------------------------------------------*/
7925 /* shiftR2Left2Result - shift right two bytes from left to result */
7926 /*-----------------------------------------------------------------*/
7928 shiftR2Left2Result (operand * left, int offl,
7929 operand * result, int offr,
7930 int shCount, int sign)
7934 _loadLeftIntoAx(&lsb, left, result, offl, offr);
7936 /* a:x >> shCount (x = lsb(result)) */
7939 AccAXRshS(lsb, shCount);
7943 AccAXRsh(lsb, shCount);
7946 _storeAxResults(lsb, result, offr);
7950 /*-----------------------------------------------------------------*/
7951 /* shiftLLeftOrResult - shift left one byte from left, or to result */
7952 /*-----------------------------------------------------------------*/
7954 shiftLLeftOrResult (operand * left, int offl,
7955 operand * result, int offr, int shCount)
7957 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7958 /* shift left accumulator */
7960 /* or with result */
7961 emitcode ("orl", "a,%s",
7962 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7963 /* back to result */
7964 aopPut (AOP (result), "a", offr);
7969 /*-----------------------------------------------------------------*/
7970 /* shiftRLeftOrResult - shift right one byte from left,or to result */
7971 /*-----------------------------------------------------------------*/
7973 shiftRLeftOrResult (operand * left, int offl,
7974 operand * result, int offr, int shCount)
7976 MOVA (aopGet (AOP (left), offl, FALSE, FALSE, NULL));
7977 /* shift right accumulator */
7979 /* or with result */
7980 emitcode ("orl", "a,%s",
7981 aopGet (AOP (result), offr, FALSE, FALSE, DP2_RESULT_REG));
7982 /* back to result */
7983 aopPut (AOP (result), "a", offr);
7987 #ifdef BETTER_LITERAL_SHIFT
7988 /*-----------------------------------------------------------------*/
7989 /* genlshOne - left shift a one byte quantity by known count */
7990 /*-----------------------------------------------------------------*/
7992 genlshOne (operand * result, operand * left, int shCount)
7994 D (emitcode (";", "genlshOne "););
7995 shiftL1Left2Result (left, LSB, result, LSB, shCount);
7999 #ifdef BETTER_LITERAL_SHIFT
8000 /*-----------------------------------------------------------------*/
8001 /* genlshTwo - left shift two bytes by known amount != 0 */
8002 /*-----------------------------------------------------------------*/
8004 genlshTwo (operand * result, operand * left, int shCount)
8008 D (emitcode (";", "genlshTwo "););
8010 size = getDataSize (result);
8012 /* if shCount >= 8 */
8017 _startLazyDPSEvaluation();
8023 _endLazyDPSEvaluation();
8024 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8025 aopPut (AOP (result), zero, LSB);
8029 movLeft2Result (left, LSB, result, MSB16, 0);
8030 aopPut (AOP (result), zero, LSB);
8031 _endLazyDPSEvaluation();
8036 aopPut (AOP (result), zero, LSB);
8037 _endLazyDPSEvaluation();
8041 /* 1 <= shCount <= 7 */
8046 shiftL1Left2Result (left, LSB, result, LSB, shCount);
8050 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8058 /*-----------------------------------------------------------------*/
8059 /* shiftLLong - shift left one long from left to result */
8060 /* offl = LSB or MSB16 */
8061 /*-----------------------------------------------------------------*/
8063 shiftLLong (operand * left, operand * result, int offr)
8066 int size = AOP_SIZE (result);
8068 if (size >= LSB + offr)
8070 l = aopGet (AOP (left), LSB, FALSE, FALSE, NULL);
8072 emitcode ("add", "a,acc");
8073 if (sameRegs (AOP (left), AOP (result)) &&
8074 size >= MSB16 + offr && offr != LSB)
8075 emitcode ("xch", "a,%s",
8076 aopGet (AOP (left), LSB + offr, FALSE, FALSE, DP2_RESULT_REG));
8078 aopPut (AOP (result), "a", LSB + offr);
8081 if (size >= MSB16 + offr)
8083 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB16 + offr && offr != LSB))
8085 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, TRUE));
8087 emitcode ("rlc", "a");
8088 if (sameRegs (AOP (left), AOP (result)) &&
8089 size >= MSB24 + offr && offr != LSB)
8090 emitcode ("xch", "a,%s",
8091 aopGet (AOP (left), MSB16 + offr, FALSE, FALSE, DP2_RESULT_REG));
8093 aopPut (AOP (result), "a", MSB16 + offr);
8096 if (size >= MSB24 + offr)
8098 if (!(sameRegs (AOP (left), AOP (left)) && size >= MSB24 + offr && offr != LSB))
8100 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8102 emitcode ("rlc", "a");
8103 if (sameRegs (AOP (left), AOP (result)) &&
8104 size >= MSB32 + offr && offr != LSB)
8105 emitcode ("xch", "a,%s",
8106 aopGet (AOP (left), MSB24 + offr, FALSE, FALSE, DP2_RESULT_REG));
8108 aopPut (AOP (result), "a", MSB24 + offr);
8111 if (size > MSB32 + offr)
8113 if (!(sameRegs (AOP (result), AOP (left)) && size >= MSB32 + offr && offr != LSB))
8115 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8117 emitcode ("rlc", "a");
8118 aopPut (AOP (result), "a", MSB32 + offr);
8121 aopPut (AOP (result), zero, LSB);
8127 /*-----------------------------------------------------------------*/
8128 /* genlshFour - shift four byte by a known amount != 0 */
8129 /*-----------------------------------------------------------------*/
8131 genlshFour (operand * result, operand * left, int shCount)
8135 D (emitcode (";", "genlshFour ");
8138 size = AOP_SIZE (result);
8140 /* if shifting more that 3 bytes */
8145 /* lowest order of left goes to the highest
8146 order of the destination */
8147 shiftL1Left2Result (left, LSB, result, MSB32, shCount);
8149 movLeft2Result (left, LSB, result, MSB32, 0);
8150 aopPut (AOP (result), zero, LSB);
8151 aopPut (AOP (result), zero, MSB16);
8152 aopPut (AOP (result), zero, MSB24);
8156 /* more than two bytes */
8157 else if (shCount >= 16)
8159 /* lower order two bytes goes to higher order two bytes */
8161 /* if some more remaining */
8163 shiftL2Left2Result (left, LSB, result, MSB24, shCount);
8166 movLeft2Result (left, MSB16, result, MSB32, 0);
8167 movLeft2Result (left, LSB, result, MSB24, 0);
8169 aopPut (AOP (result), zero, MSB16);
8170 aopPut (AOP (result), zero, LSB);
8174 /* if more than 1 byte */
8175 else if (shCount >= 8)
8177 /* lower order three bytes goes to higher order three bytes */
8182 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8184 movLeft2Result (left, LSB, result, MSB16, 0);
8190 movLeft2Result (left, MSB24, result, MSB32, 0);
8191 movLeft2Result (left, MSB16, result, MSB24, 0);
8192 movLeft2Result (left, LSB, result, MSB16, 0);
8193 aopPut (AOP (result), zero, LSB);
8195 else if (shCount == 1)
8196 shiftLLong (left, result, MSB16);
8199 shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
8200 shiftL1Left2Result (left, LSB, result, MSB16, shCount);
8201 shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
8202 aopPut (AOP (result), zero, LSB);
8207 /* 1 <= shCount <= 7 */
8208 else if (shCount <= 2)
8210 shiftLLong (left, result, LSB);
8212 shiftLLong (result, result, LSB);
8214 /* 3 <= shCount <= 7, optimize */
8217 shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
8218 shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
8219 shiftL2Left2Result (left, LSB, result, LSB, shCount);
8224 #ifdef BETTER_LITERAL_SHIFT
8225 /*-----------------------------------------------------------------*/
8226 /* genLeftShiftLiteral - left shifting by known count */
8227 /*-----------------------------------------------------------------*/
8229 genLeftShiftLiteral (operand * left,
8234 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8237 size = getSize (operandType (result));
8239 D(emitcode (";", "genLeftShiftLiteral (%d), size %d", shCount, size););
8241 /* We only handle certain easy cases so far. */
8243 && (shCount < (size * 8))
8247 D(emitcode (";", "genLeftShiftLiteral wimping out"););
8251 freeAsmop (right, NULL, ic, TRUE);
8253 aopOp(left, ic, FALSE, FALSE);
8254 aopOp(result, ic, FALSE, AOP_USESDPTR(left));
8257 if (IS_SYMOP(left) && OP_SYMBOL(left)->aop)
8259 emitcode(";", "left (%s) is %d", OP_SYMBOL(left)->rname, AOP_TYPE(left));
8260 if (!IS_TRUE_SYMOP(left) && OP_SYMBOL(left)->usl.spillLoc)
8262 emitcode(";", "\taka %s", OP_SYMBOL(left)->usl.spillLoc->rname);
8265 if (IS_SYMOP(result) && OP_SYMBOL(result)->aop)
8267 emitcode(";", "result (%s) is %d", OP_SYMBOL(result)->rname, AOP_TYPE(result));
8268 if (!IS_TRUE_SYMOP(result) && OP_SYMBOL(result)->usl.spillLoc)
8270 emitcode(";", "\taka %s", OP_SYMBOL(result)->usl.spillLoc->rname);
8276 emitcode ("; shift left ", "result %d, left %d", size,
8280 /* I suppose that the left size >= result size */
8283 _startLazyDPSEvaluation();
8286 movLeft2Result (left, size, result, size, 0);
8288 _endLazyDPSEvaluation();
8290 else if (shCount >= (size * 8))
8292 _startLazyDPSEvaluation();
8295 aopPut (AOP (result), zero, size);
8297 _endLazyDPSEvaluation();
8304 genlshOne (result, left, shCount);
8308 genlshTwo (result, left, shCount);
8312 genlshFour (result, left, shCount);
8316 fprintf(stderr, "*** ack! mystery literal shift!\n");
8320 freeAsmop (left, NULL, ic, TRUE);
8321 freeAsmop (result, NULL, ic, TRUE);
8326 /*-----------------------------------------------------------------*/
8327 /* genLeftShift - generates code for left shifting */
8328 /*-----------------------------------------------------------------*/
8330 genLeftShift (iCode * ic)
8332 operand *left, *right, *result;
8335 symbol *tlbl, *tlbl1;
8337 D (emitcode (";", "genLeftShift "););
8339 right = IC_RIGHT (ic);
8340 left = IC_LEFT (ic);
8341 result = IC_RESULT (ic);
8343 aopOp (right, ic, FALSE, FALSE);
8346 #ifdef BETTER_LITERAL_SHIFT
8347 /* if the shift count is known then do it
8348 as efficiently as possible */
8349 if (AOP_TYPE (right) == AOP_LIT)
8351 if (genLeftShiftLiteral (left, right, result, ic))
8358 /* shift count is unknown then we have to form
8359 a loop get the loop count in B : Note: we take
8360 only the lower order byte since shifting
8361 more that 32 bits make no sense anyway, ( the
8362 largest size of an object can be only 32 bits ) */
8364 if (AOP_TYPE (right) == AOP_LIT)
8366 /* Really should be handled by genLeftShiftLiteral,
8367 * but since I'm too lazy to fix that today, at least we can make
8368 * some small improvement.
8370 emitcode("mov", "b,#!constbyte",
8371 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8375 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8376 emitcode ("inc", "b");
8378 freeAsmop (right, NULL, ic, TRUE);
8379 aopOp (left, ic, FALSE, FALSE);
8380 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8382 /* now move the left to the result if they are not the
8384 if (!sameRegs (AOP (left), AOP (result)) &&
8385 AOP_SIZE (result) > 1)
8388 size = AOP_SIZE (result);
8390 _startLazyDPSEvaluation ();
8393 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8394 if (*l == '@' && (IS_AOP_PREG (result)))
8397 emitcode ("mov", "a,%s", l);
8398 aopPut (AOP (result), "a", offset);
8401 aopPut (AOP (result), l, offset);
8404 _endLazyDPSEvaluation ();
8407 tlbl = newiTempLabel (NULL);
8408 size = AOP_SIZE (result);
8410 tlbl1 = newiTempLabel (NULL);
8412 /* if it is only one byte then */
8415 symbol *tlbl1 = newiTempLabel (NULL);
8417 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8418 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8419 emitcode ("", "!tlabeldef", tlbl->key + 100);
8420 emitcode ("add", "a,acc");
8421 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8422 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8423 aopPut (AOP (result), "a", 0);
8427 reAdjustPreg (AOP (result));
8429 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8430 emitcode ("", "!tlabeldef", tlbl->key + 100);
8431 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8432 emitcode ("add", "a,acc");
8433 aopPut (AOP (result), "a", offset++);
8434 _startLazyDPSEvaluation ();
8437 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8438 emitcode ("rlc", "a");
8439 aopPut (AOP (result), "a", offset++);
8441 _endLazyDPSEvaluation ();
8442 reAdjustPreg (AOP (result));
8444 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8445 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8447 freeAsmop (left, NULL, ic, TRUE);
8448 freeAsmop (result, NULL, ic, TRUE);
8451 #ifdef BETTER_LITERAL_SHIFT
8452 /*-----------------------------------------------------------------*/
8453 /* genrshOne - right shift a one byte quantity by known count */
8454 /*-----------------------------------------------------------------*/
8456 genrshOne (operand * result, operand * left,
8457 int shCount, int sign)
8459 D (emitcode (";", "genrshOne"););
8460 shiftR1Left2Result (left, LSB, result, LSB, shCount, sign);
8464 #ifdef BETTER_LITERAL_SHIFT
8465 /*-----------------------------------------------------------------*/
8466 /* genrshTwo - right shift two bytes by known amount != 0 */
8467 /*-----------------------------------------------------------------*/
8469 genrshTwo (operand * result, operand * left,
8470 int shCount, int sign)
8472 D (emitcode (";", "genrshTwo"););
8474 /* if shCount >= 8 */
8478 _startLazyDPSEvaluation();
8481 shiftR1Left2Result (left, MSB16, result, LSB,
8486 movLeft2Result (left, MSB16, result, LSB, sign);
8488 addSign (result, MSB16, sign);
8489 _endLazyDPSEvaluation();
8492 /* 1 <= shCount <= 7 */
8495 shiftR2Left2Result (left, LSB, result, LSB, shCount, sign);
8500 /*-----------------------------------------------------------------*/
8501 /* shiftRLong - shift right one long from left to result */
8502 /* offl = LSB or MSB16 */
8503 /*-----------------------------------------------------------------*/
8505 shiftRLong (operand * left, int offl,
8506 operand * result, int sign)
8508 int isSameRegs=sameRegs(AOP(left),AOP(result));
8510 if (isSameRegs && offl>1) {
8511 // we are in big trouble, but this shouldn't happen
8512 werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
8515 MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE, NULL));
8520 emitcode ("rlc", "a");
8521 emitcode ("subb", "a,acc");
8522 emitcode ("xch", "a,%s",
8523 aopGet(AOP(left), MSB32, FALSE, FALSE, DP2_RESULT_REG));
8525 aopPut (AOP(result), zero, MSB32);
8530 emitcode ("clr", "c");
8532 emitcode ("mov", "c,acc.7");
8535 emitcode ("rrc", "a");
8537 if (isSameRegs && offl==MSB16) {
8539 "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE, DP2_RESULT_REG));
8541 aopPut (AOP (result), "a", MSB32);
8542 MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE, NULL));
8545 emitcode ("rrc", "a");
8546 if (isSameRegs && offl==1) {
8547 emitcode ("xch", "a,%s",
8548 aopGet (AOP (left), MSB16, FALSE, FALSE, DP2_RESULT_REG));
8550 aopPut (AOP (result), "a", MSB24);
8551 MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE, NULL));
8553 emitcode ("rrc", "a");
8554 aopPut (AOP (result), "a", MSB16 - offl);
8558 MOVA (aopGet (AOP (left), LSB, FALSE, FALSE, NULL));
8559 emitcode ("rrc", "a");
8560 aopPut (AOP (result), "a", LSB);
8564 /*-----------------------------------------------------------------*/
8565 /* genrshFour - shift four byte by a known amount != 0 */
8566 /*-----------------------------------------------------------------*/
8568 genrshFour (operand * result, operand * left,
8569 int shCount, int sign)
8571 D (emitcode (";", "genrshFour"););
8573 /* if shifting more that 3 bytes */
8577 _startLazyDPSEvaluation();
8579 shiftR1Left2Result (left, MSB32, result, LSB, shCount, sign);
8581 movLeft2Result (left, MSB32, result, LSB, sign);
8582 addSign (result, MSB16, sign);
8583 _endLazyDPSEvaluation();
8585 else if (shCount >= 16)
8588 _startLazyDPSEvaluation();
8590 shiftR2Left2Result (left, MSB24, result, LSB, shCount, sign);
8593 movLeft2Result (left, MSB24, result, LSB, 0);
8594 movLeft2Result (left, MSB32, result, MSB16, sign);
8596 addSign (result, MSB24, sign);
8597 _endLazyDPSEvaluation();
8599 else if (shCount >= 8)
8602 _startLazyDPSEvaluation();
8605 shiftRLong (left, MSB16, result, sign);
8607 else if (shCount == 0)
8609 movLeft2Result (left, MSB16, result, LSB, 0);
8610 movLeft2Result (left, MSB24, result, MSB16, 0);
8611 movLeft2Result (left, MSB32, result, MSB24, sign);
8612 addSign (result, MSB32, sign);
8616 shiftR2Left2Result (left, MSB16, result, LSB, shCount, 0);
8617 shiftLLeftOrResult (left, MSB32, result, MSB16, 8 - shCount);
8618 /* the last shift is signed */
8619 shiftR1Left2Result (left, MSB32, result, MSB24, shCount, sign);
8620 addSign (result, MSB32, sign);
8622 _endLazyDPSEvaluation();
8626 /* 1 <= shCount <= 7 */
8629 shiftRLong (left, LSB, result, sign);
8631 shiftRLong (result, LSB, result, sign);
8635 shiftR2Left2Result (left, LSB, result, LSB, shCount, 0);
8636 shiftLLeftOrResult (left, MSB24, result, MSB16, 8 - shCount);
8637 shiftR2Left2Result (left, MSB24, result, MSB24, shCount, sign);
8642 #ifdef BETTER_LITERAL_SHIFT
8643 /*-----------------------------------------------------------------*/
8644 /* genRightShiftLiteral - right shifting by known count */
8645 /*-----------------------------------------------------------------*/
8647 genRightShiftLiteral (operand * left,
8653 int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
8656 size = getSize (operandType (result));
8658 D(emitcode (";", "genRightShiftLiteral (%d), size %d", shCount, size););
8660 /* We only handle certain easy cases so far. */
8662 && (shCount < (size * 8))
8667 D(emitcode (";", "genRightShiftLiteral wimping out"););
8671 freeAsmop (right, NULL, ic, TRUE);
8673 aopOp (left, ic, FALSE, FALSE);
8674 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8677 emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
8681 /* test the LEFT size !!! */
8683 /* I suppose that the left size >= result size */
8686 size = getDataSize (result);
8687 _startLazyDPSEvaluation();
8690 movLeft2Result (left, size, result, size, 0);
8692 _endLazyDPSEvaluation();
8694 else if (shCount >= (size * 8))
8698 /* get sign in acc.7 */
8699 MOVA (aopGet (AOP (left), size - 1, FALSE, FALSE, NULL));
8701 addSign (result, LSB, sign);
8708 genrshOne (result, left, shCount, sign);
8712 genrshTwo (result, left, shCount, sign);
8716 genrshFour (result, left, shCount, sign);
8723 freeAsmop (left, NULL, ic, TRUE);
8724 freeAsmop (result, NULL, ic, TRUE);
8730 /*-----------------------------------------------------------------*/
8731 /* genSignedRightShift - right shift of signed number */
8732 /*-----------------------------------------------------------------*/
8734 genSignedRightShift (iCode * ic)
8736 operand *right, *left, *result;
8739 symbol *tlbl, *tlbl1;
8741 D (emitcode (";", "genSignedRightShift "););
8743 /* we do it the hard way put the shift count in b
8744 and loop thru preserving the sign */
8746 right = IC_RIGHT (ic);
8747 left = IC_LEFT (ic);
8748 result = IC_RESULT (ic);
8750 aopOp (right, ic, FALSE, FALSE);
8752 #ifdef BETTER_LITERAL_SHIFT
8753 if (AOP_TYPE (right) == AOP_LIT)
8755 if (genRightShiftLiteral (left, right, result, ic, 1))
8761 /* shift count is unknown then we have to form
8762 a loop get the loop count in B : Note: we take
8763 only the lower order byte since shifting
8764 more that 32 bits make no sense anyway, ( the
8765 largest size of an object can be only 32 bits ) */
8767 if (AOP_TYPE (right) == AOP_LIT)
8769 /* Really should be handled by genRightShiftLiteral,
8770 * but since I'm too lazy to fix that today, at least we can make
8771 * some small improvement.
8773 emitcode("mov", "b,#!constbyte",
8774 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8778 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8779 emitcode ("inc", "b");
8781 freeAsmop (right, NULL, ic, TRUE);
8782 aopOp (left, ic, FALSE, FALSE);
8783 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8785 /* now move the left to the result if they are not the
8787 if (!sameRegs (AOP (left), AOP (result)) &&
8788 AOP_SIZE (result) > 1)
8791 size = AOP_SIZE (result);
8793 _startLazyDPSEvaluation ();
8796 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8797 if (*l == '@' && IS_AOP_PREG (result))
8800 emitcode ("mov", "a,%s", l);
8801 aopPut (AOP (result), "a", offset);
8804 aopPut (AOP (result), l, offset);
8807 _endLazyDPSEvaluation ();
8810 /* mov the highest order bit to OVR */
8811 tlbl = newiTempLabel (NULL);
8812 tlbl1 = newiTempLabel (NULL);
8814 size = AOP_SIZE (result);
8816 MOVA (aopGet (AOP (left), offset, FALSE, FALSE, NULL));
8817 emitcode ("rlc", "a");
8818 emitcode ("mov", "ov,c");
8819 /* if it is only one byte then */
8822 MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8823 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8824 emitcode ("", "!tlabeldef", tlbl->key + 100);
8825 emitcode ("mov", "c,ov");
8826 emitcode ("rrc", "a");
8827 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8828 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8829 aopPut (AOP (result), "a", 0);
8833 reAdjustPreg (AOP (result));
8834 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8835 emitcode ("", "!tlabeldef", tlbl->key + 100);
8836 emitcode ("mov", "c,ov");
8837 _startLazyDPSEvaluation ();
8840 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8841 emitcode ("rrc", "a");
8842 aopPut (AOP (result), "a", offset--);
8844 _endLazyDPSEvaluation ();
8845 reAdjustPreg (AOP (result));
8846 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8847 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8850 freeAsmop (left, NULL, ic, TRUE);
8851 freeAsmop (result, NULL, ic, TRUE);
8854 /*-----------------------------------------------------------------*/
8855 /* genRightShift - generate code for right shifting */
8856 /*-----------------------------------------------------------------*/
8858 genRightShift (iCode * ic)
8860 operand *right, *left, *result;
8864 symbol *tlbl, *tlbl1;
8866 D (emitcode (";", "genRightShift "););
8868 /* if signed then we do it the hard way preserve the
8869 sign bit moving it inwards */
8870 retype = getSpec (operandType (IC_RESULT (ic)));
8872 if (!SPEC_USIGN (retype))
8874 genSignedRightShift (ic);
8878 /* signed & unsigned types are treated the same : i.e. the
8879 signed is NOT propagated inwards : quoting from the
8880 ANSI - standard : "for E1 >> E2, is equivalent to division
8881 by 2**E2 if unsigned or if it has a non-negative value,
8882 otherwise the result is implementation defined ", MY definition
8883 is that the sign does not get propagated */
8885 right = IC_RIGHT (ic);
8886 left = IC_LEFT (ic);
8887 result = IC_RESULT (ic);
8889 aopOp (right, ic, FALSE, FALSE);
8891 #ifdef BETTER_LITERAL_SHIFT
8892 /* if the shift count is known then do it
8893 as efficiently as possible */
8894 if (AOP_TYPE (right) == AOP_LIT)
8896 if (genRightShiftLiteral (left, right, result, ic, 0))
8903 /* shift count is unknown then we have to form
8904 a loop get the loop count in B : Note: we take
8905 only the lower order byte since shifting
8906 more that 32 bits make no sense anyway, ( the
8907 largest size of an object can be only 32 bits ) */
8909 if (AOP_TYPE (right) == AOP_LIT)
8911 /* Really should be handled by genRightShiftLiteral,
8912 * but since I'm too lazy to fix that today, at least we can make
8913 * some small improvement.
8915 emitcode("mov", "b,#!constbyte",
8916 ((int) floatFromVal (AOP (right)->aopu.aop_lit)) + 1);
8920 MOVB(aopGet (AOP (right), 0, FALSE, FALSE, "b"));
8921 emitcode ("inc", "b");
8923 freeAsmop (right, NULL, ic, TRUE);
8924 aopOp (left, ic, FALSE, FALSE);
8925 aopOp (result, ic, FALSE, AOP_USESDPTR(left));
8927 /* now move the left to the result if they are not the
8929 if (!sameRegs (AOP (left), AOP (result)) &&
8930 AOP_SIZE (result) > 1)
8933 size = AOP_SIZE (result);
8935 _startLazyDPSEvaluation ();
8938 l = aopGet (AOP (left), offset, FALSE, TRUE, NULL);
8939 if (*l == '@' && IS_AOP_PREG (result))
8942 emitcode ("mov", "a,%s", l);
8943 aopPut (AOP (result), "a", offset);
8946 aopPut (AOP (result), l, offset);
8949 _endLazyDPSEvaluation ();
8952 tlbl = newiTempLabel (NULL);
8953 tlbl1 = newiTempLabel (NULL);
8954 size = AOP_SIZE (result);
8957 /* if it is only one byte then */
8960 MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
8961 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8962 emitcode ("", "!tlabeldef", tlbl->key + 100);
8964 emitcode ("rrc", "a");
8965 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8966 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8967 aopPut (AOP (result), "a", 0);
8971 reAdjustPreg (AOP (result));
8972 emitcode ("sjmp", "!tlabel", tlbl1->key + 100);
8973 emitcode ("", "!tlabeldef", tlbl->key + 100);
8975 _startLazyDPSEvaluation ();
8978 MOVA (aopGet (AOP (result), offset, FALSE, FALSE, NULL));
8979 emitcode ("rrc", "a");
8980 aopPut (AOP (result), "a", offset--);
8982 _endLazyDPSEvaluation ();
8983 reAdjustPreg (AOP (result));
8985 emitcode ("", "!tlabeldef", tlbl1->key + 100);
8986 emitcode ("djnz", "b,!tlabel", tlbl->key + 100);
8989 freeAsmop (left, NULL, ic, TRUE);
8990 freeAsmop (result, NULL, ic, TRUE);
8994 /*-----------------------------------------------------------------*/
8995 /* emitPtrByteGet - emits code to get a byte into A through a */
8996 /* pointer register (R0, R1, or DPTR). The */
8997 /* original value of A can be preserved in B. */
8998 /*-----------------------------------------------------------------*/
9000 emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
9007 emitcode ("mov", "b,a");
9008 emitcode ("mov", "a,@%s", rname);
9013 emitcode ("mov", "b,a");
9014 emitcode ("movx", "a,@%s", rname);
9019 emitcode ("mov", "b,a");
9020 emitcode ("movx", "a,@dptr");
9025 emitcode ("mov", "b,a");
9026 emitcode ("clr", "a");
9027 emitcode ("movc", "a,@a+dptr");
9033 emitcode ("push", "b");
9034 emitcode ("push", "acc");
9036 emitcode ("lcall", "__gptrget");
9038 emitcode ("pop", "b");
9043 /*-----------------------------------------------------------------*/
9044 /* emitPtrByteSet - emits code to set a byte from src through a */
9045 /* pointer register (R0, R1, or DPTR). */
9046 /*-----------------------------------------------------------------*/
9048 emitPtrByteSet (char *rname, int p_type, char *src)
9057 emitcode ("mov", "@%s,a", rname);
9060 emitcode ("mov", "@%s,%s", rname, src);
9065 emitcode ("movx", "@%s,a", rname);
9070 emitcode ("movx", "@dptr,a");
9075 emitcode ("lcall", "__gptrput");
9080 /*-----------------------------------------------------------------*/
9081 /* genUnpackBits - generates code for unpacking bits */
9082 /*-----------------------------------------------------------------*/
9084 genUnpackBits (operand * result, char *rname, int ptype)
9086 int offset = 0; /* result byte offset */
9087 int rsize; /* result size */
9088 int rlen = 0; /* remaining bitfield length */
9089 sym_link *etype; /* bitfield type information */
9090 int blen; /* bitfield length */
9091 int bstr; /* bitfield starting bit within byte */
9093 D(emitcode ("; genUnpackBits",""));
9095 etype = getSpec (operandType (result));
9096 rsize = getSize (operandType (result));
9097 blen = SPEC_BLEN (etype);
9098 bstr = SPEC_BSTR (etype);
9100 /* If the bitfield length is less than a byte */
9103 emitPtrByteGet (rname, ptype, FALSE);
9105 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8 - blen));
9106 aopPut (AOP (result), "a", offset++);
9110 /* Bit field did not fit in a byte. Copy all
9111 but the partial byte at the end. */
9112 for (rlen=blen;rlen>=8;rlen-=8)
9114 emitPtrByteGet (rname, ptype, FALSE);
9115 aopPut (AOP (result), "a", offset++);
9117 emitcode ("inc", "%s", rname);
9120 /* Handle the partial byte at the end */
9123 emitPtrByteGet (rname, ptype, FALSE);
9124 emitcode ("anl", "a,#!constbyte", ((unsigned char) -1) >> (8-rlen));
9125 aopPut (AOP (result), "a", offset++);
9133 aopPut (AOP (result), zero, offset++);
9138 /*-----------------------------------------------------------------*/
9139 /* genDataPointerGet - generates code when ptr offset is known */
9140 /*-----------------------------------------------------------------*/
9142 genDataPointerGet (operand * left,
9148 int size, offset = 0;
9149 aopOp (result, ic, TRUE, FALSE);
9151 /* get the string representation of the name */
9152 l = aopGet (AOP (left), 0, FALSE, TRUE, NULL);
9153 size = AOP_SIZE (result);
9154 _startLazyDPSEvaluation ();
9159 SNPRINTF (buff, sizeof(buff),
9160 "(%s + %d)", l + 1, offset);
9164 SNPRINTF (buff, sizeof(buff),
9167 aopPut (AOP (result), buff, offset++);
9169 _endLazyDPSEvaluation ();
9171 freeAsmop (left, NULL, ic, TRUE);
9172 freeAsmop (result, NULL, ic, TRUE);
9175 /*-----------------------------------------------------------------*/
9176 /* genNearPointerGet - emitcode for near pointer fetch */
9177 /*-----------------------------------------------------------------*/
9179 genNearPointerGet (operand * left,
9187 sym_link *rtype, *retype, *letype;
9188 sym_link *ltype = operandType (left);
9191 rtype = operandType (result);
9192 retype = getSpec (rtype);
9193 letype = getSpec (ltype);
9195 aopOp (left, ic, FALSE, FALSE);
9197 /* if left is rematerialisable and
9198 result is not bit variable type and
9199 the left is pointer to data space i.e
9200 lower 128 bytes of space */
9201 if (AOP_TYPE (left) == AOP_IMMD &&
9202 !IS_BITVAR (retype) &&
9203 !IS_BITVAR (letype) &&
9204 DCL_TYPE (ltype) == POINTER)
9206 genDataPointerGet (left, result, ic);
9210 /* if the value is already in a pointer register
9211 then don't need anything more */
9212 if (!AOP_INPREG (AOP (left)))
9214 /* otherwise get a free pointer register */
9216 preg = getFreePtr (ic, &aop, FALSE);
9217 emitcode ("mov", "%s,%s",
9219 aopGet (AOP (left), 0, FALSE, TRUE, DP2_RESULT_REG));
9223 rname = aopGet (AOP (left), 0, FALSE, FALSE, DP2_RESULT_REG);
9225 freeAsmop (left, NULL, ic, TRUE);
9226 aopOp (result, ic, FALSE, FALSE);
9228 /* if bitfield then unpack the bits */
9229 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9230 genUnpackBits (result, rname, POINTER);
9233 /* we have can just get the values */
9234 int size = AOP_SIZE (result);
9239 if (IS_AOP_PREG (result) || AOP_TYPE (result) == AOP_STK)
9242 emitcode ("mov", "a,@%s", rname);
9243 aopPut (AOP (result), "a", offset);
9247 SNPRINTF (buff, sizeof(buff), "@%s", rname);
9248 aopPut (AOP (result), buff, offset);
9253 emitcode ("inc", "%s", rname);
9258 /* now some housekeeping stuff */
9261 /* we had to allocate for this iCode */
9262 if (pi) { /* post increment present */
9263 aopPut(AOP ( left ),rname,0);
9265 freeAsmop (NULL, aop, ic, TRUE);
9269 /* we did not allocate which means left
9270 already in a pointer register, then
9271 if size > 0 && this could be used again
9272 we have to point it back to where it
9274 if (AOP_SIZE (result) > 1 &&
9275 !OP_SYMBOL (left)->remat &&
9276 (OP_SYMBOL (left)->liveTo > ic->seq ||
9280 int size = AOP_SIZE (result) - 1;
9282 emitcode ("dec", "%s", rname);
9287 freeAsmop (result, NULL, ic, TRUE);
9288 if (pi) pi->generated = 1;
9291 /*-----------------------------------------------------------------*/
9292 /* genPagedPointerGet - emitcode for paged pointer fetch */
9293 /*-----------------------------------------------------------------*/
9295 genPagedPointerGet (operand * left,
9303 sym_link *rtype, *retype, *letype;
9305 rtype = operandType (result);
9306 retype = getSpec (rtype);
9307 letype = getSpec (operandType (left));
9308 aopOp (left, ic, FALSE, FALSE);
9310 /* if the value is already in a pointer register
9311 then don't need anything more */
9312 if (!AOP_INPREG (AOP (left)))
9314 /* otherwise get a free pointer register */
9316 preg = getFreePtr (ic, &aop, FALSE);
9317 emitcode ("mov", "%s,%s",
9319 aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9323 rname = aopGet (AOP (left), 0, FALSE, FALSE, NULL);
9325 freeAsmop (left, NULL, ic, TRUE);
9326 aopOp (result, ic, FALSE, FALSE);
9328 /* if bitfield then unpack the bits */
9329 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9330 genUnpackBits (result, rname, PPOINTER);
9333 /* we have can just get the values */
9334 int size = AOP_SIZE (result);
9340 emitcode ("movx", "a,@%s", rname);
9341 aopPut (AOP (result), "a", offset);
9346 emitcode ("inc", "%s", rname);
9350 /* now some housekeeping stuff */
9353 /* we had to allocate for this iCode */
9354 if (pi) aopPut ( AOP (left), rname, 0);
9355 freeAsmop (NULL, aop, ic, TRUE);
9359 /* we did not allocate which means left
9360 already in a pointer register, then
9361 if size > 0 && this could be used again
9362 we have to point it back to where it
9364 if (AOP_SIZE (result) > 1 &&
9365 !OP_SYMBOL (left)->remat &&
9366 (OP_SYMBOL (left)->liveTo > ic->seq ||
9370 int size = AOP_SIZE (result) - 1;
9372 emitcode ("dec", "%s", rname);
9377 freeAsmop (result, NULL, ic, TRUE);
9378 if (pi) pi->generated = 1;
9381 /*-----------------------------------------------------------------*/
9382 /* genFarPointerGet - gget value from far space */
9383 /*-----------------------------------------------------------------*/
9385 genFarPointerGet (operand * left,
9386 operand * result, iCode * ic, iCode *pi)
9388 int size, offset, dopi=1;
9389 sym_link *retype = getSpec (operandType (result));
9390 sym_link *letype = getSpec (operandType (left));
9391 D (emitcode (";", "genFarPointerGet"););
9393 aopOp (left, ic, FALSE, FALSE);
9395 /* if the operand is already in dptr
9396 then we do nothing else we move the value to dptr */
9397 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left) )
9399 /* if this is remateriazable */
9400 if (AOP_TYPE (left) == AOP_IMMD)
9402 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9406 /* we need to get it byte by byte */
9407 _startLazyDPSEvaluation ();
9408 if (AOP_TYPE (left) != AOP_DPTR)
9410 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9411 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9412 if (options.model == MODEL_FLAT24)
9413 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9417 /* We need to generate a load to DPTR indirect through DPTR. */
9418 D (emitcode (";", "genFarPointerGet -- indirection special case."););
9419 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9420 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9421 if (options.model == MODEL_FLAT24)
9422 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9423 emitcode ("pop", "dph");
9424 emitcode ("pop", "dpl");
9427 _endLazyDPSEvaluation ();
9430 /* so dptr know contains the address */
9431 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9433 /* if bit then unpack */
9434 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
9435 if (AOP_INDPTRn(left)) {
9436 genSetDPTR(AOP(left)->aopu.dptr);
9438 genUnpackBits (result, "dptr", FPOINTER);
9439 if (AOP_INDPTRn(left)) {
9444 size = AOP_SIZE (result);
9447 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9449 genSetDPTR(AOP(left)->aopu.dptr);
9450 emitcode ("movx", "a,@dptr");
9451 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9452 emitcode ("inc", "dptr");
9454 aopPut (AOP (result), "a", offset++);
9457 _startLazyDPSEvaluation ();
9459 if (AOP_INDPTRn(left)) {
9460 genSetDPTR(AOP(left)->aopu.dptr);
9466 emitcode ("movx", "a,@dptr");
9467 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9468 emitcode ("inc", "dptr");
9470 aopPut (AOP (result), "a", offset++);
9472 _endLazyDPSEvaluation ();
9475 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9476 if (!AOP_INDPTRn(left)) {
9477 _startLazyDPSEvaluation ();
9478 aopPut ( AOP (left), "dpl", 0);
9479 aopPut ( AOP (left), "dph", 1);
9480 if (options.model == MODEL_FLAT24)
9481 aopPut ( AOP (left), "dpx", 2);
9482 _endLazyDPSEvaluation ();
9485 } else if ((AOP_IS_STR(left) || AOP_INDPTRn(left)) &&
9486 AOP_SIZE(result) > 1 &&
9488 (OP_SYMBOL(left)->liveTo > ic->seq || ic->depth)) {
9490 size = AOP_SIZE (result) - 1;
9491 if (AOP_INDPTRn(left)) {
9492 genSetDPTR(AOP(left)->aopu.dptr);
9494 while (size--) emitcode ("lcall","__decdptr");
9495 if (AOP_INDPTRn(left)) {
9500 freeAsmop (left, NULL, ic, TRUE);
9501 freeAsmop (result, NULL, ic, TRUE);
9504 /*-----------------------------------------------------------------*/
9505 /* genCodePointerGet - get value from code space */
9506 /*-----------------------------------------------------------------*/
9508 genCodePointerGet (operand * left,
9509 operand * result, iCode * ic, iCode *pi)
9511 int size, offset, dopi=1;
9512 sym_link *retype = getSpec (operandType (result));
9514 aopOp (left, ic, FALSE, FALSE);
9516 /* if the operand is already in dptr
9517 then we do nothing else we move the value to dptr */
9518 if (AOP_TYPE (left) != AOP_STR && !AOP_INDPTRn(left))
9520 /* if this is remateriazable */
9521 if (AOP_TYPE (left) == AOP_IMMD)
9523 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9526 { /* we need to get it byte by byte */
9527 _startLazyDPSEvaluation ();
9528 if (AOP_TYPE (left) != AOP_DPTR)
9530 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
9531 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
9532 if (options.model == MODEL_FLAT24)
9533 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9537 /* We need to generate a load to DPTR indirect through DPTR. */
9538 D (emitcode (";", "gencodePointerGet -- indirection special case."););
9539 emitcode ("push", "%s", aopGet (AOP (left), 0, FALSE, TRUE, NULL));
9540 emitcode ("push", "%s", aopGet (AOP (left), 1, FALSE, TRUE, NULL));
9541 if (options.model == MODEL_FLAT24)
9542 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
9543 emitcode ("pop", "dph");
9544 emitcode ("pop", "dpl");
9547 _endLazyDPSEvaluation ();
9550 /* so dptr know contains the address */
9551 aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
9553 /* if bit then unpack */
9554 if (IS_BITVAR (retype)) {
9555 if (AOP_INDPTRn(left)) {
9556 genSetDPTR(AOP(left)->aopu.dptr);
9558 genUnpackBits (result, "dptr", CPOINTER);
9559 if (AOP_INDPTRn(left)) {
9564 size = AOP_SIZE (result);
9566 if (AOP_INDPTRn(left) && AOP_USESDPTR(result)) {
9568 genSetDPTR(AOP(left)->aopu.dptr);
9569 emitcode ("clr", "a");
9570 emitcode ("movc", "a,@a+dptr");
9571 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9572 emitcode ("inc", "dptr");
9574 aopPut (AOP (result), "a", offset++);
9577 _startLazyDPSEvaluation ();
9580 if (AOP_INDPTRn(left)) {
9581 genSetDPTR(AOP(left)->aopu.dptr);
9587 emitcode ("clr", "a");
9588 emitcode ("movc", "a,@a+dptr");
9589 if (size || (dopi && pi && AOP_TYPE (left) != AOP_IMMD))
9590 emitcode ("inc", "dptr");
9591 aopPut (AOP (result), "a", offset++);
9593 _endLazyDPSEvaluation ();
9596 if (dopi && pi && AOP_TYPE (left) != AOP_IMMD) {
9597 if (!AOP_INDPTRn(left)) {
9598 _startLazyDPSEvaluation ();
9600 aopPut ( AOP (left), "dpl", 0);
9601 aopPut ( AOP (left), "dph", 1);
9602 if (options.model == MODEL_FLAT24)
9603 aopPut ( AOP (left), "dpx", 2);
9605 _endLazyDPSEvaluation ();
9608 } else if ((OP_SYMBOL(left)->ruonly || AOP_INDPTRn(left)) &&
9609 AOP_SIZE(result) > 1 &&
9610 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9612 size = AOP_SIZE (result) - 1;
9613 if (AOP_INDPTRn(left)) {
9614 genSetDPTR(AOP(left)->aopu.dptr);
9616 while (size--) emitcode ("lcall","__decdptr");
9617 if (AOP_INDPTRn(left)) {
9622 freeAsmop (left, NULL, ic, TRUE);
9623 freeAsmop (result, NULL, ic, TRUE);
9626 /*-----------------------------------------------------------------*/
9627 /* genGenPointerGet - gget value from generic pointer space */
9628 /*-----------------------------------------------------------------*/
9630 genGenPointerGet (operand * left,
9631 operand * result, iCode * ic, iCode * pi)
9634 sym_link *retype = getSpec (operandType (result));
9635 sym_link *letype = getSpec (operandType (left));
9637 D (emitcode (";", "genGenPointerGet "); );
9639 aopOp (left, ic, FALSE, (AOP_IS_STR(left) ? FALSE : TRUE));
9641 /* if the operand is already in dptr
9642 then we do nothing else we move the value to dptr */
9643 if (AOP_TYPE (left) != AOP_STR)
9645 /* if this is remateriazable */
9646 if (AOP_TYPE (left) == AOP_IMMD)
9648 emitcode ("mov", "dptr,%s", aopGet (AOP (left), 0, TRUE, FALSE, NULL));
9649 if (AOP(left)->aopu.aop_immd.from_cast_remat)
9651 MOVB(aopGet(AOP (left), AOP_SIZE(left)-1, FALSE, FALSE, NULL));
9655 emitcode ("mov", "b,#%d", pointerCode (retype));
9659 { /* we need to get it byte by byte */
9660 _startLazyDPSEvaluation ();
9661 emitcode ("mov", "dpl,%s", aopGet (AOP(left),0,FALSE,FALSE,NULL));
9662 emitcode ("mov", "dph,%s", aopGet (AOP(left),1,FALSE,FALSE,NULL));
9663 if (options.model == MODEL_FLAT24) {
9664 emitcode ("mov", "dpx,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9665 emitcode ("mov", "b,%s", aopGet (AOP(left),3,FALSE,FALSE,NULL));
9667 emitcode ("mov", "b,%s", aopGet (AOP(left),2,FALSE,FALSE,NULL));
9669 _endLazyDPSEvaluation ();
9673 /* so dptr-b now contains the address */
9675 aopOp (result, ic, FALSE, TRUE);
9678 /* if bit then unpack */
9679 if (IS_BITVAR (retype) || IS_BITVAR (letype))
9681 genUnpackBits (result, "dptr", GPOINTER);
9685 size = AOP_SIZE (result);
9692 // Get two bytes at a time, results in _AP & A.
9693 // dptr will be incremented ONCE by __gptrgetWord.
9695 // Note: any change here must be coordinated
9696 // with the implementation of __gptrgetWord
9697 // in device/lib/_gptrget.c
9698 emitcode ("lcall", "__gptrgetWord");
9699 aopPut (AOP (result), DP2_RESULT_REG, offset++);
9700 aopPut (AOP (result), "a", offset++);
9705 // Only one byte to get.
9706 emitcode ("lcall", "__gptrget");
9707 aopPut (AOP (result), "a", offset++);
9710 if (size || (pi && AOP_TYPE (left) != AOP_IMMD))
9712 emitcode ("inc", "dptr");
9717 if (pi && AOP_TYPE (left) != AOP_IMMD) {
9718 _startLazyDPSEvaluation ();
9720 aopPut ( AOP (left), "dpl", 0);
9721 aopPut ( AOP (left), "dph", 1);
9722 if (options.model == MODEL_FLAT24) {
9723 aopPut ( AOP (left), "dpx", 2);
9724 aopPut ( AOP (left), "b", 3);
9725 } else aopPut ( AOP (left), "b", 2);
9727 _endLazyDPSEvaluation ();
9730 } else if (OP_SYMBOL(left)->ruonly && AOP_SIZE(result) > 1 &&
9731 (OP_SYMBOL (left)->liveTo > ic->seq || ic->depth)) {
9733 size = AOP_SIZE (result) - 1;
9734 while (size--) emitcode ("lcall","__decdptr");
9737 freeAsmop (left, NULL, ic, TRUE);
9738 freeAsmop (result, NULL, ic, TRUE);
9741 /*-----------------------------------------------------------------*/
9742 /* genPointerGet - generate code for pointer get */
9743 /*-----------------------------------------------------------------*/
9745 genPointerGet (iCode * ic, iCode *pi)
9747 operand *left, *result;
9748 sym_link *type, *etype;
9751 D (emitcode (";", "genPointerGet ");
9754 left = IC_LEFT (ic);
9755 result = IC_RESULT (ic);
9757 /* depending on the type of pointer we need to
9758 move it to the correct pointer register */
9759 type = operandType (left);
9760 etype = getSpec (type);
9761 /* if left is of type of pointer then it is simple */
9762 if (IS_PTR (type) && !IS_FUNC (type->next))
9763 p_type = DCL_TYPE (type);
9766 /* we have to go by the storage class */
9767 p_type = PTR_TYPE (SPEC_OCLS (etype));
9769 /* special case when cast remat */
9770 if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
9771 IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
9772 left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
9773 type = operandType (left);
9774 p_type = DCL_TYPE (type);
9776 /* now that we have the pointer type we assign
9777 the pointer values */
9783 genNearPointerGet (left, result, ic, pi);
9787 genPagedPointerGet (left, result, ic, pi);
9791 genFarPointerGet (left, result, ic, pi);
9795 genCodePointerGet (left, result, ic, pi);
9799 genGenPointerGet (left, result, ic, pi);
9805 /*-----------------------------------------------------------------*/
9806 /* genPackBits - generates code for packed bit storage */
9807 /*-----------------------------------------------------------------*/
9809 genPackBits (sym_link * etype,
9811 char *rname, int p_type)
9813 int offset = 0; /* source byte offset */
9814 int rlen = 0; /* remaining bitfield length */
9815 int blen; /* bitfield length */
9816 int bstr; /* bitfield starting bit within byte */
9817 int litval; /* source literal value (if AOP_LIT) */
9818 unsigned char mask; /* bitmask within current byte */
9820 D(emitcode ("; genPackBits",""));
9822 blen = SPEC_BLEN (etype);
9823 bstr = SPEC_BSTR (etype);
9825 /* If the bitfield length is less than a byte */
9828 mask = ((unsigned char) (0xFF << (blen + bstr)) |
9829 (unsigned char) (0xFF >> (8 - bstr)));
9831 if (AOP_TYPE (right) == AOP_LIT)
9833 /* Case with a bitfield length <8 and literal source
9835 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9837 litval &= (~mask) & 0xff;
9838 emitPtrByteGet (rname, p_type, FALSE);
9839 if ((mask|litval)!=0xff)
9840 emitcode ("anl","a,#!constbyte", mask);
9842 emitcode ("orl","a,#!constbyte", litval);
9846 if ((blen==1) && (p_type!=GPOINTER))
9848 /* Case with a bitfield length == 1 and no generic pointer
9850 if (AOP_TYPE (right) == AOP_CRY)
9851 emitcode ("mov", "c,%s", AOP(right)->aopu.aop_dir);
9854 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9855 emitcode ("rrc","a");
9857 emitPtrByteGet (rname, p_type, FALSE);
9858 emitcode ("mov","acc.%d,c",bstr);
9862 /* Case with a bitfield length < 8 and arbitrary source
9864 MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
9865 /* shift and mask source value */
9867 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9869 /* transfer A to B and get next byte */
9870 emitPtrByteGet (rname, p_type, TRUE);
9872 emitcode ("anl", "a,#!constbyte", mask);
9873 emitcode ("orl", "a,b");
9874 if (p_type == GPOINTER)
9875 emitcode ("pop", "b");
9879 emitPtrByteSet (rname, p_type, "a");
9883 /* Bit length is greater than 7 bits. In this case, copy */
9884 /* all except the partial byte at the end */
9885 for (rlen=blen;rlen>=8;rlen-=8)
9887 emitPtrByteSet (rname, p_type,
9888 aopGet (AOP (right), offset++, FALSE, TRUE, NULL) );
9890 emitcode ("inc", "%s", rname);
9893 /* If there was a partial byte at the end */
9896 mask = (((unsigned char) -1 << rlen) & 0xff);
9898 if (AOP_TYPE (right) == AOP_LIT)
9900 /* Case with partial byte and literal source
9902 litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
9903 litval >>= (blen-rlen);
9904 litval &= (~mask) & 0xff;
9905 emitPtrByteGet (rname, p_type, FALSE);
9906 if ((mask|litval)!=0xff)
9907 emitcode ("anl","a,#!constbyte", mask);
9909 emitcode ("orl","a,#!constbyte", litval);
9913 /* Case with partial byte and arbitrary source
9915 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9916 emitcode ("anl", "a,#!constbyte", (~mask) & 0xff);
9918 /* transfer A to B and get next byte */
9919 emitPtrByteGet (rname, p_type, TRUE);
9921 emitcode ("anl", "a,#!constbyte", mask);
9922 emitcode ("orl", "a,b");
9923 if (p_type == GPOINTER)
9924 emitcode ("pop", "b");
9926 emitPtrByteSet (rname, p_type, "a");
9932 /*-----------------------------------------------------------------*/
9933 /* genDataPointerSet - remat pointer to data space */
9934 /*-----------------------------------------------------------------*/
9936 genDataPointerSet (operand * right,
9940 int size, offset = 0;
9943 aopOp (right, ic, FALSE, FALSE);
9945 l = aopGet (AOP (result), 0, FALSE, TRUE, NULL);
9946 size = AOP_SIZE (right);
9951 SNPRINTF (buff, sizeof(buff), "(%s + %d)", l + 1, offset);
9955 SNPRINTF (buff, sizeof(buff), "%s", l + 1);
9958 emitcode ("mov", "%s,%s", buff,
9959 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
9962 freeAsmop (right, NULL, ic, TRUE);
9963 freeAsmop (result, NULL, ic, TRUE);
9966 /*-----------------------------------------------------------------*/
9967 /* genNearPointerSet - emitcode for near pointer put */
9968 /*-----------------------------------------------------------------*/
9970 genNearPointerSet (operand * right,
9977 sym_link *retype, *letype;
9978 sym_link *ptype = operandType (result);
9980 retype = getSpec (operandType (right));
9981 letype = getSpec (ptype);
9983 aopOp (result, ic, FALSE, FALSE);
9985 /* if the result is rematerializable &
9986 in data space & not a bit variable */
9987 if (AOP_TYPE (result) == AOP_IMMD &&
9988 DCL_TYPE (ptype) == POINTER &&
9989 !IS_BITVAR (retype) &&
9990 !IS_BITVAR (letype))
9992 genDataPointerSet (right, result, ic);
9996 /* if the value is already in a pointer register
9997 then don't need anything more */
9998 if (!AOP_INPREG (AOP (result)))
10000 /* otherwise get a free pointer register */
10003 aop = newAsmop (0);
10004 preg = getFreePtr (ic, &aop, FALSE);
10005 emitcode ("mov", "%s,%s",
10007 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10008 rname = preg->name;
10011 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10013 aopOp (right, ic, FALSE, FALSE);
10015 /* if bitfield then unpack the bits */
10016 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10017 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
10020 /* we have can just get the values */
10021 int size = AOP_SIZE (right);
10026 l = aopGet (AOP (right), offset, FALSE, TRUE, NULL);
10030 emitcode ("mov", "@%s,a", rname);
10033 emitcode ("mov", "@%s,%s", rname, l);
10035 emitcode ("inc", "%s", rname);
10040 /* now some housekeeping stuff */
10043 /* we had to allocate for this iCode */
10044 if (pi) aopPut (AOP (result),rname,0);
10045 freeAsmop (NULL, aop, ic, TRUE);
10049 /* we did not allocate which means left
10050 already in a pointer register, then
10051 if size > 0 && this could be used again
10052 we have to point it back to where it
10054 if (AOP_SIZE (right) > 1 &&
10055 !OP_SYMBOL (result)->remat &&
10056 (OP_SYMBOL (result)->liveTo > ic->seq ||
10060 int size = AOP_SIZE (right) - 1;
10062 emitcode ("dec", "%s", rname);
10067 if (pi) pi->generated = 1;
10068 freeAsmop (result, NULL, ic, TRUE);
10069 freeAsmop (right, NULL, ic, TRUE);
10074 /*-----------------------------------------------------------------*/
10075 /* genPagedPointerSet - emitcode for Paged pointer put */
10076 /*-----------------------------------------------------------------*/
10078 genPagedPointerSet (operand * right,
10085 sym_link *retype, *letype;
10087 retype = getSpec (operandType (right));
10088 letype = getSpec (operandType (result));
10090 aopOp (result, ic, FALSE, FALSE);
10092 /* if the value is already in a pointer register
10093 then don't need anything more */
10094 if (!AOP_INPREG (AOP (result)))
10096 /* otherwise get a free pointer register */
10099 aop = newAsmop (0);
10100 preg = getFreePtr (ic, &aop, FALSE);
10101 emitcode ("mov", "%s,%s",
10103 aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10104 rname = preg->name;
10107 rname = aopGet (AOP (result), 0, FALSE, FALSE, NULL);
10109 aopOp (right, ic, FALSE, FALSE);
10111 /* if bitfield then unpack the bits */
10112 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10113 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
10116 /* we have can just get the values */
10117 int size = AOP_SIZE (right);
10122 MOVA (aopGet (AOP (right), offset, FALSE, TRUE, NULL));
10124 emitcode ("movx", "@%s,a", rname);
10127 emitcode ("inc", "%s", rname);
10133 /* now some housekeeping stuff */
10136 if (pi) aopPut (AOP (result),rname,0);
10137 /* we had to allocate for this iCode */
10138 freeAsmop (NULL, aop, ic, TRUE);
10142 /* we did not allocate which means left
10143 already in a pointer register, then
10144 if size > 0 && this could be used again
10145 we have to point it back to where it
10147 if (AOP_SIZE (right) > 1 &&
10148 !OP_SYMBOL (result)->remat &&
10149 (OP_SYMBOL (result)->liveTo > ic->seq ||
10153 int size = AOP_SIZE (right) - 1;
10155 emitcode ("dec", "%s", rname);
10160 if (pi) pi->generated = 1;
10161 freeAsmop (result, NULL, ic, TRUE);
10162 freeAsmop (right, NULL, ic, TRUE);
10167 /*-----------------------------------------------------------------*/
10168 /* genFarPointerSet - set value from far space */
10169 /*-----------------------------------------------------------------*/
10171 genFarPointerSet (operand * right,
10172 operand * result, iCode * ic, iCode *pi)
10174 int size, offset, dopi=1;
10175 sym_link *retype = getSpec (operandType (right));
10176 sym_link *letype = getSpec (operandType (result));
10178 aopOp (result, ic, FALSE, FALSE);
10180 /* if the operand is already in dptr
10181 then we do nothing else we move the value to dptr */
10182 if (AOP_TYPE (result) != AOP_STR && !AOP_INDPTRn(result))
10184 /* if this is remateriazable */
10185 if (AOP_TYPE (result) == AOP_IMMD)
10186 emitcode ("mov", "dptr,%s",
10187 aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10190 /* we need to get it byte by byte */
10191 _startLazyDPSEvaluation ();
10192 if (AOP_TYPE (result) != AOP_DPTR)
10194 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10195 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10196 if (options.model == MODEL_FLAT24)
10197 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10201 /* We need to generate a load to DPTR indirect through DPTR. */
10202 D (emitcode (";", "genFarPointerSet -- indirection special case."););
10204 emitcode ("push", "%s", aopGet (AOP (result), 0, FALSE, TRUE, NULL));
10205 emitcode ("push", "%s", aopGet (AOP (result), 1, FALSE, TRUE, NULL));
10206 if (options.model == MODEL_FLAT24)
10207 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10208 emitcode ("pop", "dph");
10209 emitcode ("pop", "dpl");
10212 _endLazyDPSEvaluation ();
10215 /* so dptr know contains the address */
10216 aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
10218 /* if bit then unpack */
10219 if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
10220 if (AOP_INDPTRn(result)) {
10221 genSetDPTR(AOP(result)->aopu.dptr);
10223 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
10224 if (AOP_INDPTRn(result)) {
10228 size = AOP_SIZE (right);
10230 if (AOP_INDPTRn(result) && AOP_USESDPTR(right)) {
10232 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10234 genSetDPTR(AOP(result)->aopu.dptr);
10235 emitcode ("movx", "@dptr,a");
10236 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10237 emitcode ("inc", "dptr");
10241 _startLazyDPSEvaluation ();
10243 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10245 if (AOP_INDPTRn(result)) {
10246 genSetDPTR(AOP(result)->aopu.dptr);
10252 emitcode ("movx", "@dptr,a");
10253 if (size || (dopi && pi && AOP_TYPE (result) != AOP_IMMD))
10254 emitcode ("inc", "dptr");
10256 _endLazyDPSEvaluation ();
10260 if (dopi && pi && AOP_TYPE (result) != AOP_IMMD) {
10261 if (!AOP_INDPTRn(result)) {
10262 _startLazyDPSEvaluation ();
10264 aopPut (AOP(result),"dpl",0);
10265 aopPut (AOP(result),"dph",1);
10266 if (options.model == MODEL_FLAT24)
10267 aopPut (AOP(result),"dpx",2);
10269 _endLazyDPSEvaluation ();
10272 } else if ((OP_SYMBOL(result)->ruonly || AOP_INDPTRn(result)) &&
10273 AOP_SIZE(right) > 1 &&
10274 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10276 size = AOP_SIZE (right) - 1;
10277 if (AOP_INDPTRn(result)) {
10278 genSetDPTR(AOP(result)->aopu.dptr);
10280 while (size--) emitcode ("lcall","__decdptr");
10281 if (AOP_INDPTRn(result)) {
10285 freeAsmop (result, NULL, ic, TRUE);
10286 freeAsmop (right, NULL, ic, TRUE);
10289 /*-----------------------------------------------------------------*/
10290 /* genGenPointerSet - set value from generic pointer space */
10291 /*-----------------------------------------------------------------*/
10293 genGenPointerSet (operand * right,
10294 operand * result, iCode * ic, iCode *pi)
10297 sym_link *retype = getSpec (operandType (right));
10298 sym_link *letype = getSpec (operandType (result));
10300 aopOp (result, ic, FALSE, AOP_IS_STR(result) ? FALSE : TRUE);
10302 /* if the operand is already in dptr
10303 then we do nothing else we move the value to dptr */
10304 if (AOP_TYPE (result) != AOP_STR)
10306 _startLazyDPSEvaluation ();
10307 /* if this is remateriazable */
10308 if (AOP_TYPE (result) == AOP_IMMD)
10310 emitcode ("mov", "dptr,%s", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10311 if (AOP(result)->aopu.aop_immd.from_cast_remat)
10313 MOVB(aopGet(AOP (result), AOP_SIZE(result)-1, FALSE, FALSE, NULL));
10318 "b,%s + 1", aopGet (AOP (result), 0, TRUE, FALSE, NULL));
10322 { /* we need to get it byte by byte */
10323 emitcode ("mov", "dpl,%s", aopGet (AOP (result), 0, FALSE, FALSE, NULL));
10324 emitcode ("mov", "dph,%s", aopGet (AOP (result), 1, FALSE, FALSE, NULL));
10325 if (options.model == MODEL_FLAT24) {
10326 emitcode ("mov", "dpx,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10327 emitcode ("mov", "b,%s", aopGet (AOP (result), 3, FALSE, FALSE, NULL));
10329 emitcode ("mov", "b,%s", aopGet (AOP (result), 2, FALSE, FALSE, NULL));
10332 _endLazyDPSEvaluation ();
10334 /* so dptr + b now contains the address */
10336 aopOp (right, ic, FALSE, TRUE);
10340 /* if bit then unpack */
10341 if (IS_BITVAR (retype) || IS_BITVAR (letype))
10343 genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
10347 size = AOP_SIZE (right);
10350 _startLazyDPSEvaluation ();
10355 // Set two bytes at a time, passed in _AP & A.
10356 // dptr will be incremented ONCE by __gptrputWord.
10358 // Note: any change here must be coordinated
10359 // with the implementation of __gptrputWord
10360 // in device/lib/_gptrput.c
10361 emitcode("mov", "_ap, %s",
10362 aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10363 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10367 emitcode ("lcall", "__gptrputWord");
10372 // Only one byte to put.
10373 MOVA (aopGet (AOP (right), offset++, FALSE, FALSE, NULL));
10377 emitcode ("lcall", "__gptrput");
10380 if (size || (pi && AOP_TYPE (result) != AOP_IMMD))
10382 emitcode ("inc", "dptr");
10385 _endLazyDPSEvaluation ();
10388 if (pi && AOP_TYPE (result) != AOP_IMMD) {
10389 _startLazyDPSEvaluation ();
10391 aopPut (AOP(result),"dpl",0);
10392 aopPut (AOP(result),"dph",1);
10393 if (options.model == MODEL_FLAT24) {
10394 aopPut (AOP(result),"dpx",2);
10395 aopPut (AOP(result),"b",3);
10397 aopPut (AOP(result),"b",2);
10399 _endLazyDPSEvaluation ();
10402 } else if (OP_SYMBOL(result)->ruonly && AOP_SIZE(right) > 1 &&
10403 (OP_SYMBOL (result)->liveTo > ic->seq || ic->depth)) {
10405 size = AOP_SIZE (right) - 1;
10406 while (size--) emitcode ("lcall","__decdptr");
10408 freeAsmop (result, NULL, ic, TRUE);
10409 freeAsmop (right, NULL, ic, TRUE);
10412 /*-----------------------------------------------------------------*/
10413 /* genPointerSet - stores the value into a pointer location */
10414 /*-----------------------------------------------------------------*/
10416 genPointerSet (iCode * ic, iCode *pi)
10418 operand *right, *result;
10419 sym_link *type, *etype;
10422 D (emitcode (";", "genPointerSet "););
10424 right = IC_RIGHT (ic);
10425 result = IC_RESULT (ic);
10427 /* depending on the type of pointer we need to
10428 move it to the correct pointer register */
10429 type = operandType (result);
10430 etype = getSpec (type);
10431 /* if left is of type of pointer then it is simple */
10432 if (IS_PTR (type) && !IS_FUNC (type->next))
10434 p_type = DCL_TYPE (type);
10438 /* we have to go by the storage class */
10439 p_type = PTR_TYPE (SPEC_OCLS (etype));
10441 /* special case when cast remat */
10442 if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
10443 IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
10444 result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
10445 type = operandType (result);
10446 p_type = DCL_TYPE (type);
10449 /* now that we have the pointer type we assign
10450 the pointer values */
10456 genNearPointerSet (right, result, ic, pi);
10460 genPagedPointerSet (right, result, ic, pi);
10464 genFarPointerSet (right, result, ic, pi);
10468 genGenPointerSet (right, result, ic, pi);
10472 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10473 "genPointerSet: illegal pointer type");
10478 /*-----------------------------------------------------------------*/
10479 /* genIfx - generate code for Ifx statement */
10480 /*-----------------------------------------------------------------*/
10482 genIfx (iCode * ic, iCode * popIc)
10484 operand *cond = IC_COND (ic);
10487 D (emitcode (";", "genIfx "););
10489 aopOp (cond, ic, FALSE, FALSE);
10491 /* get the value into acc */
10492 if (AOP_TYPE (cond) != AOP_CRY)
10501 /* the result is now in the accumulator */
10502 freeAsmop (cond, NULL, ic, TRUE);
10504 /* if there was something to be popped then do it */
10508 /* if the condition is a bit variable */
10509 if (isbit && IS_ITEMP (cond) &&
10512 genIfxJump (ic, SPIL_LOC (cond)->rname);
10514 else if (isbit && !IS_ITEMP (cond))
10516 genIfxJump (ic, OP_SYMBOL (cond)->rname);
10520 genIfxJump (ic, "a");
10526 /*-----------------------------------------------------------------*/
10527 /* genAddrOf - generates code for address of */
10528 /*-----------------------------------------------------------------*/
10530 genAddrOf (iCode * ic)
10532 symbol *sym = OP_SYMBOL (IC_LEFT (ic));
10535 D (emitcode (";", "genAddrOf ");
10538 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
10540 /* if the operand is on the stack then we
10541 need to get the stack offset of this
10543 if (sym->onStack) {
10545 /* if 10 bit stack */
10546 if (options.stack10bit) {
10550 tsprintf(buff, sizeof(buff),
10551 "#!constbyte",(options.stack_loc >> 16) & 0xff);
10552 /* if it has an offset then we need to compute it */
10553 /* emitcode ("subb", "a,#!constbyte", */
10554 /* -((sym->stack < 0) ? */
10555 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10556 /* ((short) sym->stack)) & 0xff); */
10557 /* emitcode ("mov","b,a"); */
10558 /* emitcode ("mov","a,#!constbyte",(-((sym->stack < 0) ? */
10559 /* ((short) (sym->stack - _G.nRegsSaved)) : */
10560 /* ((short) sym->stack)) >> 8) & 0xff); */
10562 emitcode ("mov", "a,_bpx");
10563 emitcode ("add", "a,#!constbyte", ((sym->stack < 0) ?
10564 ((char) (sym->stack - _G.nRegsSaved)) :
10565 ((char) sym->stack )) & 0xff);
10566 emitcode ("mov", "b,a");
10567 emitcode ("mov", "a,_bpx+1");
10569 offset = (((sym->stack < 0) ?
10570 ((short) (sym->stack - _G.nRegsSaved)) :
10571 ((short) sym->stack )) >> 8) & 0xff;
10573 emitcode ("addc","a,#!constbyte", offset);
10575 aopPut (AOP (IC_RESULT (ic)), "b", 0);
10576 aopPut (AOP (IC_RESULT (ic)), "a", 1);
10577 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10579 /* we can just move _bp */
10580 aopPut (AOP (IC_RESULT (ic)), "_bpx", 0);
10581 aopPut (AOP (IC_RESULT (ic)), "_bpx+1", 1);
10582 aopPut (AOP (IC_RESULT (ic)), buff, 2);
10585 /* if it has an offset then we need to compute it */
10587 emitcode ("mov", "a,_bp");
10588 emitcode ("add", "a,#!constbyte", ((char) sym->stack & 0xff));
10589 aopPut (AOP (IC_RESULT (ic)), "a", 0);
10591 /* we can just move _bp */
10592 aopPut (AOP (IC_RESULT (ic)), "_bp", 0);
10594 /* fill the result with zero */
10595 size = AOP_SIZE (IC_RESULT (ic)) - 1;
10598 if (options.stack10bit && size < (FPTRSIZE - 1)) {
10600 "*** warning: pointer to stack var truncated.\n");
10605 aopPut (AOP (IC_RESULT (ic)), zero, offset++);
10611 /* object not on stack then we need the name */
10612 size = AOP_SIZE (IC_RESULT (ic));
10617 char s[SDCC_NAME_MAX];
10621 tsprintf(s, sizeof(s), "#!his",sym->rname);
10624 tsprintf(s, sizeof(s), "#!hihis",sym->rname);
10627 tsprintf(s, sizeof(s), "#!hihihis",sym->rname);
10629 default: /* should not need this (just in case) */
10630 SNPRINTF (s, sizeof(s), "#(%s >> %d)",
10637 SNPRINTF (s, sizeof(s), "#%s", sym->rname);
10640 aopPut (AOP (IC_RESULT (ic)), s, offset++);
10644 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
10648 #if 0 // obsolete, and buggy for != xdata
10649 /*-----------------------------------------------------------------*/
10650 /* genArrayInit - generates code for address of */
10651 /*-----------------------------------------------------------------*/
10653 genArrayInit (iCode * ic)
10655 literalList *iLoop;
10657 int elementSize = 0, eIndex;
10658 unsigned val, lastVal;
10660 operand *left=IC_LEFT(ic);
10662 D (emitcode (";", "genArrayInit "););
10664 aopOp (IC_LEFT(ic), ic, FALSE, FALSE);
10666 if (AOP_TYPE(IC_LEFT(ic)) == AOP_IMMD)
10668 // Load immediate value into DPTR.
10669 emitcode("mov", "dptr, %s",
10670 aopGet(AOP(IC_LEFT(ic)), 0, TRUE, FALSE, NULL));
10672 else if (AOP_TYPE(IC_LEFT(ic)) != AOP_DPTR)
10675 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10676 "Unexpected operand to genArrayInit.\n");
10679 // a regression because of SDCCcse.c:1.52
10680 emitcode ("mov", "dpl,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
10681 emitcode ("mov", "dph,%s", aopGet (AOP (left), 1, FALSE, FALSE, NULL));
10682 if (options.model == MODEL_FLAT24)
10683 emitcode ("mov", "dpx,%s", aopGet (AOP (left), 2, FALSE, FALSE, NULL));
10687 type = operandType(IC_LEFT(ic));
10689 if (type && type->next)
10691 elementSize = getSize(type->next);
10695 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
10696 "can't determine element size in genArrayInit.\n");
10700 iLoop = IC_ARRAYILIST(ic);
10705 bool firstpass = TRUE;
10707 emitcode(";", "store %d x 0x%x to DPTR (element size %d)",
10708 iLoop->count, (int)iLoop->literalValue, elementSize);
10714 symbol *tlbl = NULL;
10716 count = ix > 256 ? 256 : ix;
10720 tlbl = newiTempLabel (NULL);
10721 if (firstpass || (count & 0xff))
10723 emitcode("mov", "b, #!constbyte", count & 0xff);
10726 emitcode ("", "!tlabeldef", tlbl->key + 100);
10731 for (eIndex = 0; eIndex < elementSize; eIndex++)
10733 val = (((int)iLoop->literalValue) >> (eIndex * 8)) & 0xff;
10734 if (val != lastVal)
10736 emitcode("mov", "a, #!constbyte", val);
10740 emitcode("movx", "@dptr, a");
10741 emitcode("inc", "dptr");
10746 emitcode("djnz", "b, !tlabel", tlbl->key + 100);
10752 iLoop = iLoop->next;
10755 freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
10759 /*-----------------------------------------------------------------*/
10760 /* genFarFarAssign - assignment when both are in far space */
10761 /*-----------------------------------------------------------------*/
10763 genFarFarAssign (operand * result, operand * right, iCode * ic)
10765 int size = AOP_SIZE (right);
10767 symbol *rSym = NULL;
10771 /* quick & easy case. */
10772 D(emitcode(";","genFarFarAssign (1 byte case)"););
10773 MOVA(aopGet(AOP(right), 0, FALSE, FALSE, NULL));
10774 freeAsmop (right, NULL, ic, FALSE);
10775 /* now assign DPTR to result */
10777 aopOp(result, ic, FALSE, FALSE);
10779 aopPut(AOP(result), "a", 0);
10780 freeAsmop(result, NULL, ic, FALSE);
10784 /* See if we've got an underlying symbol to abuse. */
10785 if (IS_SYMOP(result) && OP_SYMBOL(result))
10787 if (IS_TRUE_SYMOP(result))
10789 rSym = OP_SYMBOL(result);
10791 else if (IS_ITEMP(result) && OP_SYMBOL(result)->isspilt && OP_SYMBOL(result)->usl.spillLoc)
10793 rSym = OP_SYMBOL(result)->usl.spillLoc;
10797 if (size > 1 && rSym && rSym->rname && !rSym->onStack)
10799 /* We can use the '390 auto-toggle feature to good effect here. */
10801 D(emitcode(";","genFarFarAssign (390 auto-toggle fun)"););
10802 emitcode("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
10803 emitcode ("mov", "dptr,#%s", rSym->rname);
10804 /* DP2 = result, DP1 = right, DP1 is current. */
10807 emitcode("movx", "a,@dptr");
10808 emitcode("movx", "@dptr,a");
10811 emitcode("inc", "dptr");
10812 emitcode("inc", "dptr");
10815 emitcode("mov", "dps,#0");
10816 freeAsmop (right, NULL, ic, FALSE);
10818 some alternative code for processors without auto-toggle
10819 no time to test now, so later well put in...kpb
10820 D(emitcode(";","genFarFarAssign (dual-dptr fun)"););
10821 emitcode("mov", "dps,#1"); /* Select DPTR2. */
10822 emitcode ("mov", "dptr,#%s", rSym->rname);
10823 /* DP2 = result, DP1 = right, DP1 is current. */
10827 emitcode("movx", "a,@dptr");
10829 emitcode("inc", "dptr");
10830 emitcode("inc", "dps");
10831 emitcode("movx", "@dptr,a");
10833 emitcode("inc", "dptr");
10834 emitcode("inc", "dps");
10836 emitcode("mov", "dps,#0");
10837 freeAsmop (right, NULL, ic, FALSE);
10842 D (emitcode (";", "genFarFarAssign"););
10843 aopOp (result, ic, TRUE, TRUE);
10845 _startLazyDPSEvaluation ();
10849 aopPut (AOP (result),
10850 aopGet (AOP (right), offset, FALSE, FALSE, NULL), offset);
10853 _endLazyDPSEvaluation ();
10854 freeAsmop (result, NULL, ic, FALSE);
10855 freeAsmop (right, NULL, ic, FALSE);
10859 /*-----------------------------------------------------------------*/
10860 /* genAssign - generate code for assignment */
10861 /*-----------------------------------------------------------------*/
10863 genAssign (iCode * ic)
10865 operand *result, *right;
10867 unsigned long lit = 0L;
10869 D (emitcode (";", "genAssign ");
10872 result = IC_RESULT (ic);
10873 right = IC_RIGHT (ic);
10875 /* if they are the same */
10876 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
10879 aopOp (right, ic, FALSE, FALSE);
10881 emitcode (";", "genAssign: resultIsFar = %s",
10882 isOperandInFarSpace (result) ?
10885 /* special case both in far space */
10886 if ((AOP_TYPE (right) == AOP_DPTR ||
10887 AOP_TYPE (right) == AOP_DPTR2) &&
10888 /* IS_TRUE_SYMOP(result) && */
10889 isOperandInFarSpace (result))
10891 genFarFarAssign (result, right, ic);
10895 aopOp (result, ic, TRUE, FALSE);
10897 /* if they are the same registers */
10898 if (sameRegs (AOP (right), AOP (result)))
10901 /* if the result is a bit */
10902 if (AOP_TYPE (result) == AOP_CRY) /* works only for true symbols */
10904 /* if the right size is a literal then
10905 we know what the value is */
10906 if (AOP_TYPE (right) == AOP_LIT)
10908 if (((int) operandLitValue (right)))
10909 aopPut (AOP (result), one, 0);
10911 aopPut (AOP (result), zero, 0);
10915 /* the right is also a bit variable */
10916 if (AOP_TYPE (right) == AOP_CRY)
10918 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
10919 aopPut (AOP (result), "c", 0);
10923 /* we need to or */
10925 aopPut (AOP (result), "a", 0);
10929 /* bit variables done */
10931 size = AOP_SIZE (result);
10933 if (AOP_TYPE (right) == AOP_LIT)
10934 lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
10937 (AOP_TYPE (result) != AOP_REG) &&
10938 (AOP_TYPE (right) == AOP_LIT) &&
10939 !IS_FLOAT (operandType (right)))
10941 _startLazyDPSEvaluation ();
10942 while (size && ((unsigned int) (lit >> (offset * 8)) != 0))
10944 aopPut (AOP (result),
10945 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10950 /* And now fill the rest with zeros. */
10953 emitcode ("clr", "a");
10957 aopPut (AOP (result), "a", offset++);
10959 _endLazyDPSEvaluation ();
10963 _startLazyDPSEvaluation ();
10966 aopPut (AOP (result),
10967 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
10971 _endLazyDPSEvaluation ();
10975 freeAsmop (right, NULL, ic, FALSE);
10976 freeAsmop (result, NULL, ic, TRUE);
10979 /*-----------------------------------------------------------------*/
10980 /* genJumpTab - generates code for jump table */
10981 /*-----------------------------------------------------------------*/
10983 genJumpTab (iCode * ic)
10988 D (emitcode (";", "genJumpTab ");
10991 aopOp (IC_JTCOND (ic), ic, FALSE, FALSE);
10992 /* get the condition into accumulator */
10993 l = aopGet (AOP (IC_JTCOND (ic)), 0, FALSE, FALSE, NULL);
10995 /* multiply by four! */
10996 emitcode ("add", "a,acc");
10997 emitcode ("add", "a,acc");
10998 freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
11000 jtab = newiTempLabel (NULL);
11001 emitcode ("mov", "dptr,#!tlabel", jtab->key + 100);
11002 emitcode ("jmp", "@a+dptr");
11003 emitcode ("", "!tlabeldef", jtab->key + 100);
11004 /* now generate the jump labels */
11005 for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
11006 jtab = setNextItem (IC_JTLABELS (ic)))
11007 emitcode ("ljmp", "!tlabel", jtab->key + 100);
11011 /*-----------------------------------------------------------------*/
11012 /* genCast - gen code for casting */
11013 /*-----------------------------------------------------------------*/
11015 genCast (iCode * ic)
11017 operand *result = IC_RESULT (ic);
11018 sym_link *ctype = operandType (IC_LEFT (ic));
11019 sym_link *rtype = operandType (IC_RIGHT (ic));
11020 operand *right = IC_RIGHT (ic);
11023 D (emitcode (";", "genCast "););
11025 /* if they are equivalent then do nothing */
11026 if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
11029 aopOp (right, ic, FALSE, FALSE);
11030 aopOp (result, ic, FALSE, AOP_USESDPTR(right));
11032 /* if the result is a bit */
11033 if (IS_BITVAR (OP_SYMBOL (result)->type)
11034 && !IS_BITFIELD (OP_SYMBOL (result)->type) )
11036 /* if the right size is a literal then
11037 we know what the value is */
11038 if (AOP_TYPE (right) == AOP_LIT)
11040 if (((int) operandLitValue (right)))
11041 aopPut (AOP (result), one, 0);
11043 aopPut (AOP (result), zero, 0);
11048 /* the right is also a bit variable */
11049 if (AOP_TYPE (right) == AOP_CRY)
11051 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
11052 aopPut (AOP (result), "c", 0);
11056 /* we need to or */
11058 aopPut (AOP (result), "a", 0);
11062 /* if they are the same size : or less */
11063 if (AOP_SIZE (result) <= AOP_SIZE (right))
11066 /* if they are in the same place */
11067 if (sameRegs (AOP (right), AOP (result)))
11070 /* if they in different places then copy */
11071 size = AOP_SIZE (result);
11073 _startLazyDPSEvaluation ();
11076 aopPut (AOP (result),
11077 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11081 _endLazyDPSEvaluation ();
11086 /* if the result is of type pointer */
11087 if (IS_PTR (ctype))
11091 sym_link *type = operandType (right);
11093 /* pointer to generic pointer */
11094 if (IS_GENPTR (ctype))
11098 p_type = DCL_TYPE (type);
11102 #if OLD_CAST_BEHAVIOR
11103 /* KV: we are converting a non-pointer type to
11104 * a generic pointer. This (ifdef'd out) code
11105 * says that the resulting generic pointer
11106 * should have the same class as the storage
11107 * location of the non-pointer variable.
11109 * For example, converting an int (which happens
11110 * to be stored in DATA space) to a pointer results
11111 * in a DATA generic pointer; if the original int
11112 * in XDATA space, so will be the resulting pointer.
11114 * I don't like that behavior, and thus this change:
11115 * all such conversions will be forced to XDATA and
11116 * throw a warning. If you want some non-XDATA
11117 * type, or you want to suppress the warning, you
11118 * must go through an intermediate cast, like so:
11120 * char _generic *gp = (char _xdata *)(intVar);
11122 sym_link *etype = getSpec (type);
11124 /* we have to go by the storage class */
11125 if (SPEC_OCLS (etype) != generic)
11127 p_type = PTR_TYPE (SPEC_OCLS (etype));
11132 /* Converting unknown class (i.e. register variable)
11133 * to generic pointer. This is not good, but
11134 * we'll make a guess (and throw a warning).
11137 werror (W_INT_TO_GEN_PTR_CAST);
11141 /* the first two bytes are known */
11142 size = GPTRSIZE - 1;
11144 _startLazyDPSEvaluation ();
11147 aopPut (AOP (result),
11148 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11152 _endLazyDPSEvaluation ();
11154 /* the last byte depending on type */
11156 int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
11161 // pointerTypeToGPByte will have bitched.
11165 SNPRINTF(gpValStr, sizeof(gpValStr), "#0x%d", gpVal);
11166 aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
11171 /* just copy the pointers */
11172 size = AOP_SIZE (result);
11174 _startLazyDPSEvaluation ();
11177 aopPut (AOP (result),
11178 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11182 _endLazyDPSEvaluation ();
11186 /* so we now know that the size of destination is greater
11187 than the size of the source */
11188 /* we move to result for the size of source */
11189 size = AOP_SIZE (right);
11191 _startLazyDPSEvaluation ();
11194 aopPut (AOP (result),
11195 aopGet (AOP (right), offset, FALSE, FALSE, NULL),
11199 _endLazyDPSEvaluation ();
11201 /* now depending on the sign of the source && destination */
11202 size = AOP_SIZE (result) - AOP_SIZE (right);
11203 /* if unsigned or not an integral type */
11204 /* also, if the source is a bit, we don't need to sign extend, because
11205 * it can't possibly have set the sign bit.
11207 if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE (right) == AOP_CRY)
11211 aopPut (AOP (result), zero, offset++);
11216 /* we need to extend the sign :{ */
11217 MOVA (aopGet (AOP (right), AOP_SIZE (right) - 1,
11218 FALSE, FALSE, NULL));
11219 emitcode ("rlc", "a");
11220 emitcode ("subb", "a,acc");
11222 aopPut (AOP (result), "a", offset++);
11225 /* we are done hurray !!!! */
11228 freeAsmop (right, NULL, ic, TRUE);
11229 freeAsmop (result, NULL, ic, TRUE);
11233 /*-----------------------------------------------------------------*/
11234 /* genDjnz - generate decrement & jump if not zero instrucion */
11235 /*-----------------------------------------------------------------*/
11237 genDjnz (iCode * ic, iCode * ifx)
11239 symbol *lbl, *lbl1;
11243 /* if the if condition has a false label
11244 then we cannot save */
11245 if (IC_FALSE (ifx))
11248 /* if the minus is not of the form
11250 if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
11251 !IS_OP_LITERAL (IC_RIGHT (ic)))
11254 if (operandLitValue (IC_RIGHT (ic)) != 1)
11257 /* if the size of this greater than one then no
11259 if (getSize (operandType (IC_RESULT (ic))) > 1)
11262 /* otherwise we can save BIG */
11263 D(emitcode(";", "genDjnz"););
11265 lbl = newiTempLabel (NULL);
11266 lbl1 = newiTempLabel (NULL);
11268 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11270 if (AOP_NEEDSACC(IC_RESULT(ic)))
11272 /* If the result is accessed indirectly via
11273 * the accumulator, we must explicitly write
11274 * it back after the decrement.
11276 char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE, NULL);
11278 if (strcmp(rByte, "a"))
11280 /* Something is hopelessly wrong */
11281 fprintf(stderr, "*** warning: internal error at %s:%d\n",
11282 __FILE__, __LINE__);
11283 /* We can just give up; the generated code will be inefficient,
11284 * but what the hey.
11286 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11289 emitcode ("dec", "%s", rByte);
11290 aopPut(AOP(IC_RESULT(ic)), rByte, 0);
11291 emitcode ("jnz", "!tlabel", lbl->key + 100);
11293 else if (IS_AOP_PREG (IC_RESULT (ic)))
11295 emitcode ("dec", "%s",
11296 aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11297 emitcode ("mov", "a,%s", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE, NULL));
11298 emitcode ("jnz", "!tlabel", lbl->key + 100);
11302 emitcode ("djnz", "%s,!tlabel", aopGet (AOP (IC_RESULT (ic)), 0, FALSE, TRUE, NULL),
11305 emitcode ("sjmp", "!tlabel", lbl1->key + 100);
11306 emitcode ("", "!tlabeldef", lbl->key + 100);
11307 emitcode ("ljmp", "!tlabel", IC_TRUE (ifx)->key + 100);
11308 emitcode ("", "!tlabeldef", lbl1->key + 100);
11310 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11311 ifx->generated = 1;
11315 /*-----------------------------------------------------------------*/
11316 /* genReceive - generate code for a receive iCode */
11317 /*-----------------------------------------------------------------*/
11319 genReceive (iCode * ic)
11321 int size = getSize (operandType (IC_RESULT (ic)));
11325 D (emitcode (";", "genReceive "););
11327 if (ic->argreg == 1)
11329 /* first parameter */
11330 if (AOP_IS_STR(IC_RESULT(ic)))
11332 /* Nothing to do: it's already in the proper place. */
11339 useDp2 = isOperandInFarSpace (IC_RESULT (ic)) &&
11340 (OP_SYMBOL (IC_RESULT (ic))->isspilt ||
11341 IS_TRUE_SYMOP (IC_RESULT (ic)));
11344 aopOp (IC_RESULT (ic), ic, FALSE, useDp2);
11347 /* Sanity checking... */
11348 if (AOP_USESDPTR(IC_RESULT(ic)))
11350 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
11351 "genReceive got unexpected DPTR.");
11353 assignResultValue (IC_RESULT (ic));
11358 /* second receive onwards */
11359 /* this gets a little tricky since unused recevies will be
11360 eliminated, we have saved the reg in the type field . and
11361 we use that to figure out which register to use */
11362 aopOp (IC_RESULT (ic), ic, FALSE, FALSE);
11363 rb1off = ic->argreg;
11366 aopPut (AOP (IC_RESULT (ic)), rb1regs[rb1off++ -5], offset++);
11369 freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
11372 /*-----------------------------------------------------------------*/
11373 /* genMemcpyX2X - gen code for memcpy xdata to xdata */
11374 /*-----------------------------------------------------------------*/
11375 static void genMemcpyX2X( iCode *ic, int nparms, operand **parms, int fromc)
11377 operand *from , *to , *count;
11382 /* we know it has to be 3 parameters */
11383 assert (nparms == 3);
11385 rsave = newBitVect(16);
11386 /* save DPTR if it needs to be saved */
11387 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11388 if (bitVectBitValue(ic->rMask,i))
11389 rsave = bitVectSetBit(rsave,i);
11391 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11392 ds390_rUmaskForOp (IC_RESULT(ic))));
11399 aopOp (from, ic->next, FALSE, FALSE);
11401 /* get from into DPTR1 */
11402 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11403 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11404 if (options.model == MODEL_FLAT24) {
11405 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11408 freeAsmop (from, NULL, ic, FALSE);
11409 aopOp (to, ic, FALSE, FALSE);
11410 /* get "to" into DPTR */
11411 /* if the operand is already in dptr
11412 then we do nothing else we move the value to dptr */
11413 if (AOP_TYPE (to) != AOP_STR) {
11414 /* if already in DPTR then we need to push */
11415 if (AOP_TYPE(to) == AOP_DPTR) {
11416 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11417 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11418 if (options.model == MODEL_FLAT24)
11419 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11420 emitcode ("pop", "dph");
11421 emitcode ("pop", "dpl");
11423 _startLazyDPSEvaluation ();
11424 /* if this is remateriazable */
11425 if (AOP_TYPE (to) == AOP_IMMD) {
11426 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11427 } else { /* we need to get it byte by byte */
11428 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11429 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11430 if (options.model == MODEL_FLAT24) {
11431 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11434 _endLazyDPSEvaluation ();
11437 freeAsmop (to, NULL, ic, FALSE);
11438 _G.dptrInUse = _G.dptr1InUse = 1;
11439 aopOp (count, ic->next->next, FALSE,FALSE);
11440 lbl =newiTempLabel(NULL);
11442 /* now for the actual copy */
11443 if (AOP_TYPE(count) == AOP_LIT &&
11444 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11445 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11447 emitcode ("lcall","__bi_memcpyc2x_s");
11449 emitcode ("lcall","__bi_memcpyx2x_s");
11451 freeAsmop (count, NULL, ic, FALSE);
11453 symbol *lbl1 = newiTempLabel(NULL);
11455 emitcode (";"," Auto increment but no djnz");
11456 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11457 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11458 freeAsmop (count, NULL, ic, FALSE);
11459 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11460 emitcode ("","!tlabeldef",lbl->key+100);
11462 emitcode ("clr","a");
11463 emitcode ("movc", "a,@a+dptr");
11465 emitcode ("movx", "a,@dptr");
11466 emitcode ("movx", "@dptr,a");
11467 emitcode ("inc", "dptr");
11468 emitcode ("inc", "dptr");
11469 emitcode ("mov","a,b");
11470 emitcode ("orl","a,_ap");
11471 emitcode ("jz","!tlabel",lbl1->key+100);
11472 emitcode ("mov","a,_ap");
11473 emitcode ("add","a,#!constbyte",0xFF);
11474 emitcode ("mov","_ap,a");
11475 emitcode ("mov","a,b");
11476 emitcode ("addc","a,#!constbyte",0xFF);
11477 emitcode ("mov","b,a");
11478 emitcode ("sjmp","!tlabel",lbl->key+100);
11479 emitcode ("","!tlabeldef",lbl1->key+100);
11481 emitcode ("mov", "dps,#0");
11482 _G.dptrInUse = _G.dptr1InUse = 0;
11483 unsavermask(rsave);
11487 /*-----------------------------------------------------------------*/
11488 /* genMemcmpX2X - gen code for memcmp xdata to xdata */
11489 /*-----------------------------------------------------------------*/
11490 static void genMemcmpX2X( iCode *ic, int nparms, operand **parms, int fromc)
11492 operand *from , *to , *count;
11497 /* we know it has to be 3 parameters */
11498 assert (nparms == 3);
11500 rsave = newBitVect(16);
11501 /* save DPTR if it needs to be saved */
11502 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11503 if (bitVectBitValue(ic->rMask,i))
11504 rsave = bitVectSetBit(rsave,i);
11506 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11507 ds390_rUmaskForOp (IC_RESULT(ic))));
11514 aopOp (from, ic->next, FALSE, FALSE);
11516 /* get from into DPTR1 */
11517 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11518 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11519 if (options.model == MODEL_FLAT24) {
11520 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11523 freeAsmop (from, NULL, ic, FALSE);
11524 aopOp (to, ic, FALSE, FALSE);
11525 /* get "to" into DPTR */
11526 /* if the operand is already in dptr
11527 then we do nothing else we move the value to dptr */
11528 if (AOP_TYPE (to) != AOP_STR) {
11529 /* if already in DPTR then we need to push */
11530 if (AOP_TYPE(to) == AOP_DPTR) {
11531 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11532 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11533 if (options.model == MODEL_FLAT24)
11534 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11535 emitcode ("pop", "dph");
11536 emitcode ("pop", "dpl");
11538 _startLazyDPSEvaluation ();
11539 /* if this is remateriazable */
11540 if (AOP_TYPE (to) == AOP_IMMD) {
11541 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11542 } else { /* we need to get it byte by byte */
11543 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11544 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11545 if (options.model == MODEL_FLAT24) {
11546 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11549 _endLazyDPSEvaluation ();
11552 freeAsmop (to, NULL, ic, FALSE);
11553 _G.dptrInUse = _G.dptr1InUse = 1;
11554 aopOp (count, ic->next->next, FALSE,FALSE);
11555 lbl =newiTempLabel(NULL);
11556 lbl2 =newiTempLabel(NULL);
11558 /* now for the actual compare */
11559 if (AOP_TYPE(count) == AOP_LIT &&
11560 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11561 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11563 emitcode("lcall","__bi_memcmpc2x_s");
11565 emitcode("lcall","__bi_memcmpx2x_s");
11566 freeAsmop (count, NULL, ic, FALSE);
11567 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11568 aopPut(AOP(IC_RESULT(ic)),"a",0);
11569 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11571 symbol *lbl1 = newiTempLabel(NULL);
11573 emitcode("push","ar0");
11574 emitcode (";"," Auto increment but no djnz");
11575 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11576 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11577 freeAsmop (count, NULL, ic, FALSE);
11578 emitcode ("mov", "dps,#!constbyte",0x21); /* Select DPTR2 & auto-toggle. */
11579 emitcode ("","!tlabeldef",lbl->key+100);
11581 emitcode ("clr","a");
11582 emitcode ("movc", "a,@a+dptr");
11584 emitcode ("movx", "a,@dptr");
11585 emitcode ("mov","r0,a");
11586 emitcode ("movx", "a,@dptr");
11587 emitcode ("clr","c");
11588 emitcode ("subb","a,r0");
11589 emitcode ("jnz","!tlabel",lbl2->key+100);
11590 emitcode ("inc", "dptr");
11591 emitcode ("inc", "dptr");
11592 emitcode ("mov","a,b");
11593 emitcode ("orl","a,_ap");
11594 emitcode ("jz","!tlabel",lbl1->key+100);
11595 emitcode ("mov","a,_ap");
11596 emitcode ("add","a,#!constbyte",0xFF);
11597 emitcode ("mov","_ap,a");
11598 emitcode ("mov","a,b");
11599 emitcode ("addc","a,#!constbyte",0xFF);
11600 emitcode ("mov","b,a");
11601 emitcode ("sjmp","!tlabel",lbl->key+100);
11602 emitcode ("","!tlabeldef",lbl1->key+100);
11603 emitcode ("clr","a");
11604 emitcode ("","!tlabeldef",lbl2->key+100);
11605 aopOp (IC_RESULT(ic), ic, FALSE,FALSE);
11606 aopPut(AOP(IC_RESULT(ic)),"a",0);
11607 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
11608 emitcode("pop","ar0");
11609 emitcode ("mov", "dps,#0");
11611 _G.dptrInUse = _G.dptr1InUse = 0;
11612 unsavermask(rsave);
11616 /*-----------------------------------------------------------------*/
11617 /* genInp - gen code for __builtin_inp read data from a mem mapped */
11618 /* port, first parameter output area second parameter pointer to */
11619 /* port third parameter count */
11620 /*-----------------------------------------------------------------*/
11621 static void genInp( iCode *ic, int nparms, operand **parms)
11623 operand *from , *to , *count;
11628 /* we know it has to be 3 parameters */
11629 assert (nparms == 3);
11631 rsave = newBitVect(16);
11632 /* save DPTR if it needs to be saved */
11633 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11634 if (bitVectBitValue(ic->rMask,i))
11635 rsave = bitVectSetBit(rsave,i);
11637 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11638 ds390_rUmaskForOp (IC_RESULT(ic))));
11645 aopOp (from, ic->next, FALSE, FALSE);
11647 /* get from into DPTR1 */
11648 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11649 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11650 if (options.model == MODEL_FLAT24) {
11651 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11654 freeAsmop (from, NULL, ic, FALSE);
11655 aopOp (to, ic, FALSE, FALSE);
11656 /* get "to" into DPTR */
11657 /* if the operand is already in dptr
11658 then we do nothing else we move the value to dptr */
11659 if (AOP_TYPE (to) != AOP_STR) {
11660 /* if already in DPTR then we need to push */
11661 if (AOP_TYPE(to) == AOP_DPTR) {
11662 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11663 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11664 if (options.model == MODEL_FLAT24)
11665 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11666 emitcode ("pop", "dph");
11667 emitcode ("pop", "dpl");
11669 _startLazyDPSEvaluation ();
11670 /* if this is remateriazable */
11671 if (AOP_TYPE (to) == AOP_IMMD) {
11672 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11673 } else { /* we need to get it byte by byte */
11674 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11675 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11676 if (options.model == MODEL_FLAT24) {
11677 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11680 _endLazyDPSEvaluation ();
11683 freeAsmop (to, NULL, ic, FALSE);
11685 _G.dptrInUse = _G.dptr1InUse = 1;
11686 aopOp (count, ic->next->next, FALSE,FALSE);
11687 lbl =newiTempLabel(NULL);
11689 /* now for the actual copy */
11690 if (AOP_TYPE(count) == AOP_LIT &&
11691 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11692 emitcode (";","OH JOY auto increment with djnz (very fast)");
11693 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11694 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11695 freeAsmop (count, NULL, ic, FALSE);
11696 emitcode ("","!tlabeldef",lbl->key+100);
11697 emitcode ("movx", "a,@dptr"); /* read data from port */
11698 emitcode ("dec","dps"); /* switch to DPTR */
11699 emitcode ("movx", "@dptr,a"); /* save into location */
11700 emitcode ("inc", "dptr"); /* point to next area */
11701 emitcode ("inc","dps"); /* switch to DPTR2 */
11702 emitcode ("djnz","b,!tlabel",lbl->key+100);
11704 symbol *lbl1 = newiTempLabel(NULL);
11706 emitcode (";"," Auto increment but no djnz");
11707 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11708 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11709 freeAsmop (count, NULL, ic, FALSE);
11710 emitcode ("mov", "dps,#!constbyte",0x1); /* Select DPTR2 */
11711 emitcode ("","!tlabeldef",lbl->key+100);
11712 emitcode ("movx", "a,@dptr");
11713 emitcode ("dec","dps"); /* switch to DPTR */
11714 emitcode ("movx", "@dptr,a");
11715 emitcode ("inc", "dptr");
11716 emitcode ("inc","dps"); /* switch to DPTR2 */
11717 /* emitcode ("djnz","b,!tlabel",lbl->key+100); */
11718 /* emitcode ("djnz","_ap,!tlabel",lbl->key+100); */
11719 emitcode ("mov","a,b");
11720 emitcode ("orl","a,_ap");
11721 emitcode ("jz","!tlabel",lbl1->key+100);
11722 emitcode ("mov","a,_ap");
11723 emitcode ("add","a,#!constbyte",0xFF);
11724 emitcode ("mov","_ap,a");
11725 emitcode ("mov","a,b");
11726 emitcode ("addc","a,#!constbyte",0xFF);
11727 emitcode ("mov","b,a");
11728 emitcode ("sjmp","!tlabel",lbl->key+100);
11729 emitcode ("","!tlabeldef",lbl1->key+100);
11731 emitcode ("mov", "dps,#0");
11732 _G.dptrInUse = _G.dptr1InUse = 0;
11733 unsavermask(rsave);
11737 /*-----------------------------------------------------------------*/
11738 /* genOutp - gen code for __builtin_inp write data to a mem mapped */
11739 /* port, first parameter output area second parameter pointer to */
11740 /* port third parameter count */
11741 /*-----------------------------------------------------------------*/
11742 static void genOutp( iCode *ic, int nparms, operand **parms)
11744 operand *from , *to , *count;
11749 /* we know it has to be 3 parameters */
11750 assert (nparms == 3);
11752 rsave = newBitVect(16);
11753 /* save DPTR if it needs to be saved */
11754 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11755 if (bitVectBitValue(ic->rMask,i))
11756 rsave = bitVectSetBit(rsave,i);
11758 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11759 ds390_rUmaskForOp (IC_RESULT(ic))));
11766 aopOp (from, ic->next, FALSE, FALSE);
11768 /* get from into DPTR1 */
11769 emitcode ("mov", "dpl1,%s", aopGet (AOP (from), 0, FALSE, FALSE, NULL));
11770 emitcode ("mov", "dph1,%s", aopGet (AOP (from), 1, FALSE, FALSE, NULL));
11771 if (options.model == MODEL_FLAT24) {
11772 emitcode ("mov", "dpx1,%s", aopGet (AOP (from), 2, FALSE, FALSE, NULL));
11775 freeAsmop (from, NULL, ic, FALSE);
11776 aopOp (to, ic, FALSE, FALSE);
11777 /* get "to" into DPTR */
11778 /* if the operand is already in dptr
11779 then we do nothing else we move the value to dptr */
11780 if (AOP_TYPE (to) != AOP_STR) {
11781 /* if already in DPTR then we need to push */
11782 if (AOP_TYPE(to) == AOP_DPTR) {
11783 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11784 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11785 if (options.model == MODEL_FLAT24)
11786 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11787 emitcode ("pop", "dph");
11788 emitcode ("pop", "dpl");
11790 _startLazyDPSEvaluation ();
11791 /* if this is remateriazable */
11792 if (AOP_TYPE (to) == AOP_IMMD) {
11793 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11794 } else { /* we need to get it byte by byte */
11795 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11796 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11797 if (options.model == MODEL_FLAT24) {
11798 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11801 _endLazyDPSEvaluation ();
11804 freeAsmop (to, NULL, ic, FALSE);
11806 _G.dptrInUse = _G.dptr1InUse = 1;
11807 aopOp (count, ic->next->next, FALSE,FALSE);
11808 lbl =newiTempLabel(NULL);
11810 /* now for the actual copy */
11811 if (AOP_TYPE(count) == AOP_LIT &&
11812 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11813 emitcode (";","OH JOY auto increment with djnz (very fast)");
11814 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11815 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11816 emitcode ("","!tlabeldef",lbl->key+100);
11817 emitcode ("movx", "a,@dptr"); /* read data from port */
11818 emitcode ("inc","dps"); /* switch to DPTR2 */
11819 emitcode ("movx", "@dptr,a"); /* save into location */
11820 emitcode ("inc", "dptr"); /* point to next area */
11821 emitcode ("dec","dps"); /* switch to DPTR */
11822 emitcode ("djnz","b,!tlabel",lbl->key+100);
11823 freeAsmop (count, NULL, ic, FALSE);
11825 symbol *lbl1 = newiTempLabel(NULL);
11827 emitcode (";"," Auto increment but no djnz");
11828 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11829 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11830 freeAsmop (count, NULL, ic, FALSE);
11831 emitcode ("mov", "dps,#!constbyte",0x0); /* Select DPTR */
11832 emitcode ("","!tlabeldef",lbl->key+100);
11833 emitcode ("movx", "a,@dptr");
11834 emitcode ("inc", "dptr");
11835 emitcode ("inc","dps"); /* switch to DPTR2 */
11836 emitcode ("movx", "@dptr,a");
11837 emitcode ("dec","dps"); /* switch to DPTR */
11838 emitcode ("mov","a,b");
11839 emitcode ("orl","a,_ap");
11840 emitcode ("jz","!tlabel",lbl1->key+100);
11841 emitcode ("mov","a,_ap");
11842 emitcode ("add","a,#!constbyte",0xFF);
11843 emitcode ("mov","_ap,a");
11844 emitcode ("mov","a,b");
11845 emitcode ("addc","a,#!constbyte",0xFF);
11846 emitcode ("mov","b,a");
11847 emitcode ("sjmp","!tlabel",lbl->key+100);
11848 emitcode ("","!tlabeldef",lbl1->key+100);
11850 emitcode ("mov", "dps,#0");
11851 _G.dptrInUse = _G.dptr1InUse = 0;
11852 unsavermask(rsave);
11856 /*-----------------------------------------------------------------*/
11857 /* genSwapW - swap lower & high order bytes */
11858 /*-----------------------------------------------------------------*/
11859 static void genSwapW(iCode *ic, int nparms, operand **parms)
11863 assert (nparms==1);
11866 dest=IC_RESULT(ic);
11868 assert(getSize(operandType(src))==2);
11870 aopOp (src, ic, FALSE, FALSE);
11871 emitcode ("mov","a,%s",aopGet(AOP(src),0,FALSE,FALSE,NULL));
11873 MOVB(aopGet(AOP(src),1,FALSE,FALSE,"b"));
11875 freeAsmop (src, NULL, ic, FALSE);
11877 aopOp (dest,ic, FALSE, FALSE);
11878 aopPut(AOP(dest),"b",0);
11879 aopPut(AOP(dest),"a",1);
11880 freeAsmop (dest, NULL, ic, FALSE);
11883 /*-----------------------------------------------------------------*/
11884 /* genMemsetX - gencode for memSetX data */
11885 /*-----------------------------------------------------------------*/
11886 static void genMemsetX(iCode *ic, int nparms, operand **parms)
11888 operand *to , *val , *count;
11894 /* we know it has to be 3 parameters */
11895 assert (nparms == 3);
11901 /* save DPTR if it needs to be saved */
11902 rsave = newBitVect(16);
11903 for (i = DPL_IDX ; i <= B_IDX ; i++ ) {
11904 if (bitVectBitValue(ic->rMask,i))
11905 rsave = bitVectSetBit(rsave,i);
11907 rsave = bitVectIntersect(rsave,bitVectCplAnd (bitVectCopy (ic->rMask),
11908 ds390_rUmaskForOp (IC_RESULT(ic))));
11911 aopOp (to, ic, FALSE, FALSE);
11912 /* get "to" into DPTR */
11913 /* if the operand is already in dptr
11914 then we do nothing else we move the value to dptr */
11915 if (AOP_TYPE (to) != AOP_STR) {
11916 /* if already in DPTR then we need to push */
11917 if (AOP_TYPE(to) == AOP_DPTR) {
11918 emitcode ("push", "%s", aopGet (AOP (to), 0, FALSE, TRUE, NULL));
11919 emitcode ("push", "%s", aopGet (AOP (to), 1, FALSE, TRUE, NULL));
11920 if (options.model == MODEL_FLAT24)
11921 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11922 emitcode ("pop", "dph");
11923 emitcode ("pop", "dpl");
11925 _startLazyDPSEvaluation ();
11926 /* if this is remateriazable */
11927 if (AOP_TYPE (to) == AOP_IMMD) {
11928 emitcode ("mov", "dptr,%s", aopGet (AOP (to), 0, TRUE, FALSE, NULL));
11929 } else { /* we need to get it byte by byte */
11930 emitcode ("mov", "dpl,%s", aopGet (AOP (to), 0, FALSE, FALSE, NULL));
11931 emitcode ("mov", "dph,%s", aopGet (AOP (to), 1, FALSE, FALSE, NULL));
11932 if (options.model == MODEL_FLAT24) {
11933 emitcode ("mov", "dpx,%s", aopGet (AOP (to), 2, FALSE, FALSE, NULL));
11936 _endLazyDPSEvaluation ();
11939 freeAsmop (to, NULL, ic, FALSE);
11941 aopOp (val, ic->next->next, FALSE,FALSE);
11942 aopOp (count, ic->next->next, FALSE,FALSE);
11943 lbl =newiTempLabel(NULL);
11944 /* now for the actual copy */
11945 if (AOP_TYPE(count) == AOP_LIT &&
11946 (int)floatFromVal (AOP(count)->aopu.aop_lit) <= 256) {
11947 l = aopGet(AOP (val), 0, FALSE, FALSE, NULL);
11948 emitcode ("mov", "b,%s",aopGet(AOP(count),0,FALSE,FALSE,NULL));
11950 emitcode ("","!tlabeldef",lbl->key+100);
11951 emitcode ("movx", "@dptr,a");
11952 emitcode ("inc", "dptr");
11953 emitcode ("djnz","b,!tlabel",lbl->key+100);
11955 symbol *lbl1 = newiTempLabel(NULL);
11957 emitcode ("mov","_ap,%s",aopGet (AOP (count), 0, FALSE, TRUE, NULL));
11958 emitcode ("mov","b,%s",aopGet (AOP (count), 1, FALSE, TRUE, NULL));
11959 emitcode ("","!tlabeldef",lbl->key+100);
11960 MOVA (aopGet(AOP (val), 0, FALSE, FALSE, NULL));
11961 emitcode ("movx", "@dptr,a");
11962 emitcode ("inc", "dptr");
11963 emitcode ("mov","a,b");
11964 emitcode ("orl","a,_ap");
11965 emitcode ("jz","!tlabel",lbl1->key+100);
11966 emitcode ("mov","a,_ap");
11967 emitcode ("add","a,#!constbyte",0xFF);
11968 emitcode ("mov","_ap,a");
11969 emitcode ("mov","a,b");
11970 emitcode ("addc","a,#!constbyte",0xFF);
11971 emitcode ("mov","b,a");
11972 emitcode ("sjmp","!tlabel",lbl->key+100);
11973 emitcode ("","!tlabeldef",lbl1->key+100);
11975 freeAsmop (count, NULL, ic, FALSE);
11976 unsavermask(rsave);
11979 /*-----------------------------------------------------------------*/
11980 /* genNatLibLoadPrimitive - calls TINI api function to load primitive */
11981 /*-----------------------------------------------------------------*/
11982 static void genNatLibLoadPrimitive(iCode *ic, int nparms, operand **parms,int size)
11985 operand *pnum, *result;
11988 assert (nparms==1);
11989 /* save registers that need to be saved */
11990 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
11991 ds390_rUmaskForOp (IC_RESULT(ic))));
11994 aopOp (pnum, ic, FALSE, FALSE);
11995 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
11996 freeAsmop (pnum, NULL, ic, FALSE);
11997 emitcode ("lcall","NatLib_LoadPrimitive");
11998 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
11999 if (aopHasRegs(AOP(result),R0_IDX,R1_IDX) ||
12000 aopHasRegs(AOP(result),R2_IDX,R3_IDX) ) {
12001 for (i = (size-1) ; i >= 0 ; i-- ) {
12002 emitcode ("push","a%s",javaRet[i]);
12004 for (i=0; i < size ; i++ ) {
12005 emitcode ("pop","a%s",
12006 aopGet(AOP(result),i,FALSE,FALSE,DP2_RESULT_REG));
12009 for (i = 0 ; i < size ; i++ ) {
12010 aopPut(AOP(result),javaRet[i],i);
12013 freeAsmop (result, NULL, ic, FALSE);
12014 unsavermask(rsave);
12017 /*-----------------------------------------------------------------*/
12018 /* genNatLibLoadPointer - calls TINI api function to load pointer */
12019 /*-----------------------------------------------------------------*/
12020 static void genNatLibLoadPointer(iCode *ic, int nparms, operand **parms)
12023 operand *pnum, *result;
12027 assert (nparms==1);
12028 /* save registers that need to be saved */
12029 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12030 ds390_rUmaskForOp (IC_RESULT(ic))));
12033 aopOp (pnum, ic, FALSE, FALSE);
12034 emitcode ("mov","a,%s",aopGet(AOP(pnum),0,FALSE,FALSE,DP2_RESULT_REG));
12035 freeAsmop (pnum, NULL, ic, FALSE);
12036 emitcode ("lcall","NatLib_LoadPointer");
12037 aopOp (result=IC_RESULT(ic), ic, FALSE, FALSE);
12038 if (AOP_TYPE(result)!=AOP_STR) {
12039 for (i = 0 ; i < size ; i++ ) {
12040 aopPut(AOP(result),fReturn[i],i);
12043 freeAsmop (result, NULL, ic, FALSE);
12044 unsavermask(rsave);
12047 /*-----------------------------------------------------------------*/
12048 /* genNatLibInstallStateBlock - */
12049 /*-----------------------------------------------------------------*/
12050 static void genNatLibInstallStateBlock(iCode *ic, int nparms,
12051 operand **parms, const char *name)
12054 operand *psb, *handle;
12055 assert (nparms==2);
12057 /* save registers that need to be saved */
12058 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12059 ds390_rUmaskForOp (IC_RESULT(ic))));
12063 /* put pointer to state block into DPTR1 */
12064 aopOp (psb, ic, FALSE, FALSE);
12065 if (AOP_TYPE (psb) == AOP_IMMD) {
12066 emitcode ("mov","dps,#1");
12067 emitcode ("mov", "dptr,%s",
12068 aopGet (AOP (psb), 0, TRUE, FALSE, DP2_RESULT_REG));
12069 emitcode ("mov","dps,#0");
12071 emitcode ("mov","dpl1,%s",aopGet(AOP(psb),0,FALSE,FALSE,DP2_RESULT_REG));
12072 emitcode ("mov","dph1,%s",aopGet(AOP(psb),1,FALSE,FALSE,DP2_RESULT_REG));
12073 emitcode ("mov","dpx1,%s",aopGet(AOP(psb),2,FALSE,FALSE,DP2_RESULT_REG));
12075 freeAsmop (psb, NULL, ic, FALSE);
12077 /* put libraryID into DPTR */
12078 emitcode ("mov","dptr,#LibraryID");
12080 /* put handle into r3:r2 */
12081 aopOp (handle, ic, FALSE, FALSE);
12082 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12083 emitcode ("push","%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12084 emitcode ("push","%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12085 emitcode ("pop","ar3");
12086 emitcode ("pop","ar2");
12088 emitcode ("mov","r2,%s",aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12089 emitcode ("mov","r3,%s",aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12091 freeAsmop (psb, NULL, ic, FALSE);
12093 /* make the call */
12094 emitcode ("lcall","NatLib_Install%sStateBlock",name);
12096 /* put return value into place*/
12098 aopOp (IC_RESULT(ic), ic, FALSE, FALSE);
12100 aopPut(AOP(IC_RESULT(ic)),"a",0);
12101 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12102 unsavermask(rsave);
12105 /*-----------------------------------------------------------------*/
12106 /* genNatLibRemoveStateBlock - */
12107 /*-----------------------------------------------------------------*/
12108 static void genNatLibRemoveStateBlock(iCode *ic,int nparms,const char *name)
12114 /* save registers that need to be saved */
12115 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12116 ds390_rUmaskForOp (IC_RESULT(ic))));
12118 /* put libraryID into DPTR */
12119 emitcode ("mov","dptr,#LibraryID");
12120 /* make the call */
12121 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12122 unsavermask(rsave);
12125 /*-----------------------------------------------------------------*/
12126 /* genNatLibGetStateBlock - */
12127 /*-----------------------------------------------------------------*/
12128 static void genNatLibGetStateBlock(iCode *ic,int nparms,
12129 operand **parms,const char *name)
12132 symbol *lbl = newiTempLabel(NULL);
12135 /* save registers that need to be saved */
12136 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12137 ds390_rUmaskForOp (IC_RESULT(ic))));
12139 /* put libraryID into DPTR */
12140 emitcode ("mov","dptr,#LibraryID");
12141 /* make the call */
12142 emitcode ("lcall","NatLib_Remove%sStateBlock",name);
12143 emitcode ("jnz","!tlabel",lbl->key+100);
12145 /* put return value into place */
12146 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12147 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12148 emitcode ("push","ar3");
12149 emitcode ("push","ar2");
12150 emitcode ("pop","%s",
12151 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12152 emitcode ("pop","%s",
12153 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12155 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12156 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12158 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12159 emitcode ("","!tlabeldef",lbl->key+100);
12160 unsavermask(rsave);
12163 /*-----------------------------------------------------------------*/
12164 /* genMMMalloc - */
12165 /*-----------------------------------------------------------------*/
12166 static void genMMMalloc (iCode *ic,int nparms, operand **parms,
12167 int size, const char *name)
12172 symbol *lbl = newiTempLabel(NULL);
12174 assert (nparms == 1);
12175 /* save registers that need to be saved */
12176 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12177 ds390_rUmaskForOp (IC_RESULT(ic))));
12180 aopOp (bsize,ic,FALSE,FALSE);
12182 /* put the size in R4-R2 */
12183 if (aopHasRegs(AOP(bsize),R2_IDX, (size==3 ? R4_IDX: R3_IDX))) {
12184 emitcode("push","%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12185 emitcode("push","%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12187 emitcode("push","%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12188 emitcode("pop","ar4");
12190 emitcode("pop","ar3");
12191 emitcode("pop","ar2");
12193 emitcode ("mov","r2,%s",aopGet(AOP(bsize),0,FALSE,TRUE,DP2_RESULT_REG));
12194 emitcode ("mov","r3,%s",aopGet(AOP(bsize),1,FALSE,TRUE,DP2_RESULT_REG));
12196 emitcode("mov","r4,%s",aopGet(AOP(bsize),2,FALSE,TRUE,DP2_RESULT_REG));
12199 freeAsmop (bsize, NULL, ic, FALSE);
12201 /* make the call */
12202 emitcode ("lcall","MM_%s",name);
12203 emitcode ("jz","!tlabel",lbl->key+100);
12204 emitcode ("mov","r2,#!constbyte",0xff);
12205 emitcode ("mov","r3,#!constbyte",0xff);
12206 emitcode ("","!tlabeldef",lbl->key+100);
12207 /* we don't care about the pointer : we just save the handle */
12208 rsym = OP_SYMBOL(IC_RESULT(ic));
12209 if (rsym->liveFrom != rsym->liveTo) {
12210 aopOp(IC_RESULT(ic),ic,FALSE,FALSE);
12211 if (aopHasRegs(AOP(IC_RESULT(ic)),R2_IDX,R3_IDX)) {
12212 emitcode ("push","ar3");
12213 emitcode ("push","ar2");
12214 emitcode ("pop","%s",
12215 aopGet(AOP(IC_RESULT(ic)),0,FALSE,TRUE,DP2_RESULT_REG));
12216 emitcode ("pop","%s",
12217 aopGet(AOP(IC_RESULT(ic)),1,FALSE,TRUE,DP2_RESULT_REG));
12219 aopPut(AOP(IC_RESULT(ic)),"r2",0);
12220 aopPut(AOP(IC_RESULT(ic)),"r3",1);
12222 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12224 unsavermask(rsave);
12227 /*-----------------------------------------------------------------*/
12229 /*-----------------------------------------------------------------*/
12230 static void genMMDeref (iCode *ic,int nparms, operand **parms)
12235 assert (nparms == 1);
12236 /* save registers that need to be saved */
12237 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12238 ds390_rUmaskForOp (IC_RESULT(ic))));
12241 aopOp (handle,ic,FALSE,FALSE);
12243 /* put the size in R4-R2 */
12244 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12245 emitcode("push","%s",
12246 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12247 emitcode("push","%s",
12248 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12249 emitcode("pop","ar3");
12250 emitcode("pop","ar2");
12252 emitcode ("mov","r2,%s",
12253 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12254 emitcode ("mov","r3,%s",
12255 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12257 freeAsmop (handle, NULL, ic, FALSE);
12259 /* make the call */
12260 emitcode ("lcall","MM_Deref");
12263 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12264 if (rsym->liveFrom != rsym->liveTo) {
12265 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12266 if (AOP_TYPE(IC_RESULT(ic)) != AOP_STR) {
12267 _startLazyDPSEvaluation ();
12269 aopPut(AOP(IC_RESULT(ic)),"dpl",0);
12270 aopPut(AOP(IC_RESULT(ic)),"dph",1);
12271 aopPut(AOP(IC_RESULT(ic)),"dpx",2);
12273 _endLazyDPSEvaluation ();
12278 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12279 unsavermask(rsave);
12282 /*-----------------------------------------------------------------*/
12283 /* genMMUnrestrictedPersist - */
12284 /*-----------------------------------------------------------------*/
12285 static void genMMUnrestrictedPersist(iCode *ic,int nparms, operand **parms)
12290 assert (nparms == 1);
12291 /* save registers that need to be saved */
12292 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12293 ds390_rUmaskForOp (IC_RESULT(ic))));
12296 aopOp (handle,ic,FALSE,FALSE);
12298 /* put the size in R3-R2 */
12299 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12300 emitcode("push","%s",
12301 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12302 emitcode("push","%s",
12303 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12304 emitcode("pop","ar3");
12305 emitcode("pop","ar2");
12307 emitcode ("mov","r2,%s",
12308 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12309 emitcode ("mov","r3,%s",
12310 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12312 freeAsmop (handle, NULL, ic, FALSE);
12314 /* make the call */
12315 emitcode ("lcall","MM_UnrestrictedPersist");
12318 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12319 if (rsym->liveFrom != rsym->liveTo) {
12320 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12321 aopPut(AOP(IC_RESULT(ic)),"a",0);
12322 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12325 unsavermask(rsave);
12328 /*-----------------------------------------------------------------*/
12329 /* genSystemExecJavaProcess - */
12330 /*-----------------------------------------------------------------*/
12331 static void genSystemExecJavaProcess(iCode *ic,int nparms, operand **parms)
12334 operand *handle, *pp;
12336 assert (nparms==2);
12337 /* save registers that need to be saved */
12338 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12339 ds390_rUmaskForOp (IC_RESULT(ic))));
12344 /* put the handle in R3-R2 */
12345 aopOp (handle,ic,FALSE,FALSE);
12346 if (aopHasRegs(AOP(handle),R2_IDX,R3_IDX)) {
12347 emitcode("push","%s",
12348 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12349 emitcode("push","%s",
12350 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12351 emitcode("pop","ar3");
12352 emitcode("pop","ar2");
12354 emitcode ("mov","r2,%s",
12355 aopGet(AOP(handle),0,FALSE,TRUE,DP2_RESULT_REG));
12356 emitcode ("mov","r3,%s",
12357 aopGet(AOP(handle),1,FALSE,TRUE,DP2_RESULT_REG));
12359 freeAsmop (handle, NULL, ic, FALSE);
12361 /* put pointer in DPTR */
12362 aopOp (pp,ic,FALSE,FALSE);
12363 if (AOP_TYPE(pp) == AOP_IMMD) {
12364 emitcode ("mov", "dptr,%s",
12365 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12366 } else if (AOP_TYPE(pp) != AOP_STR) { /* not already in dptr */
12367 emitcode ("mov","dpl,%s",aopGet(AOP(pp),0,FALSE,FALSE,NULL));
12368 emitcode ("mov","dph,%s",aopGet(AOP(pp),1,FALSE,FALSE,NULL));
12369 emitcode ("mov","dpx,%s",aopGet(AOP(pp),2,FALSE,FALSE,NULL));
12371 freeAsmop (handle, NULL, ic, FALSE);
12373 /* make the call */
12374 emitcode ("lcall","System_ExecJavaProcess");
12376 /* put result in place */
12378 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12379 if (rsym->liveFrom != rsym->liveTo) {
12380 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12381 aopPut(AOP(IC_RESULT(ic)),"a",0);
12382 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12386 unsavermask(rsave);
12389 /*-----------------------------------------------------------------*/
12390 /* genSystemRTCRegisters - */
12391 /*-----------------------------------------------------------------*/
12392 static void genSystemRTCRegisters(iCode *ic,int nparms, operand **parms,
12398 assert (nparms==1);
12399 /* save registers that need to be saved */
12400 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12401 ds390_rUmaskForOp (IC_RESULT(ic))));
12404 /* put pointer in DPTR */
12405 aopOp (pp,ic,FALSE,FALSE);
12406 if (AOP_TYPE (pp) == AOP_IMMD) {
12407 emitcode ("mov","dps,#1");
12408 emitcode ("mov", "dptr,%s",
12409 aopGet (AOP (pp), 0, TRUE, FALSE, NULL));
12410 emitcode ("mov","dps,#0");
12412 emitcode ("mov","dpl1,%s",
12413 aopGet(AOP(pp),0,FALSE,FALSE,DP2_RESULT_REG));
12414 emitcode ("mov","dph1,%s",
12415 aopGet(AOP(pp),1,FALSE,FALSE,DP2_RESULT_REG));
12416 emitcode ("mov","dpx1,%s",
12417 aopGet(AOP(pp),2,FALSE,FALSE,DP2_RESULT_REG));
12419 freeAsmop (pp, NULL, ic, FALSE);
12421 /* make the call */
12422 emitcode ("lcall","System_%sRTCRegisters",name);
12424 unsavermask(rsave);
12427 /*-----------------------------------------------------------------*/
12428 /* genSystemThreadSleep - */
12429 /*-----------------------------------------------------------------*/
12430 static void genSystemThreadSleep(iCode *ic,int nparms, operand **parms, char *name)
12435 assert (nparms==1);
12436 /* save registers that need to be saved */
12437 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12438 ds390_rUmaskForOp (IC_RESULT(ic))));
12441 aopOp(to,ic,FALSE,FALSE);
12442 if (aopHasRegs(AOP(to),R2_IDX,R3_IDX) ||
12443 aopHasRegs(AOP(to),R0_IDX,R1_IDX) ) {
12444 emitcode ("push","%s",
12445 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12446 emitcode ("push","%s",
12447 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12448 emitcode ("push","%s",
12449 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12450 emitcode ("push","%s",
12451 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12452 emitcode ("pop","ar3");
12453 emitcode ("pop","ar2");
12454 emitcode ("pop","ar1");
12455 emitcode ("pop","ar0");
12457 emitcode ("mov","r0,%s",
12458 aopGet(AOP(to),0,FALSE,TRUE,DP2_RESULT_REG));
12459 emitcode ("mov","r1,%s",
12460 aopGet(AOP(to),1,FALSE,TRUE,DP2_RESULT_REG));
12461 emitcode ("mov","r2,%s",
12462 aopGet(AOP(to),2,FALSE,TRUE,DP2_RESULT_REG));
12463 emitcode ("mov","r3,%s",
12464 aopGet(AOP(to),3,FALSE,TRUE,DP2_RESULT_REG));
12466 freeAsmop (to, NULL, ic, FALSE);
12468 /* suspend in acc */
12470 aopOp(s,ic,FALSE,FALSE);
12471 emitcode ("mov","a,%s",
12472 aopGet(AOP(s),0,FALSE,TRUE,NULL));
12473 freeAsmop (s, NULL, ic, FALSE);
12475 /* make the call */
12476 emitcode ("lcall","System_%s",name);
12478 unsavermask(rsave);
12481 /*-----------------------------------------------------------------*/
12482 /* genSystemThreadResume - */
12483 /*-----------------------------------------------------------------*/
12484 static void genSystemThreadResume(iCode *ic,int nparms, operand **parms)
12489 assert (nparms==2);
12490 /* save registers that need to be saved */
12491 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12492 ds390_rUmaskForOp (IC_RESULT(ic))));
12498 aopOp(pid,ic,FALSE,FALSE);
12499 emitcode ("mov","r0,%s",
12500 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12501 freeAsmop (pid, NULL, ic, FALSE);
12504 aopOp(tid,ic,FALSE,FALSE);
12505 emitcode ("mov","a,%s",
12506 aopGet(AOP(tid),0,FALSE,TRUE,DP2_RESULT_REG));
12507 freeAsmop (tid, NULL, ic, FALSE);
12509 emitcode ("lcall","System_ThreadResume");
12511 /* put result into place */
12513 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12514 if (rsym->liveFrom != rsym->liveTo) {
12515 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12516 aopPut(AOP(IC_RESULT(ic)),"a",0);
12517 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12520 unsavermask(rsave);
12523 /*-----------------------------------------------------------------*/
12524 /* genSystemProcessResume - */
12525 /*-----------------------------------------------------------------*/
12526 static void genSystemProcessResume(iCode *ic,int nparms, operand **parms)
12531 assert (nparms==1);
12532 /* save registers that need to be saved */
12533 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12534 ds390_rUmaskForOp (IC_RESULT(ic))));
12539 aopOp(pid,ic,FALSE,FALSE);
12540 emitcode ("mov","a,%s",
12541 aopGet(AOP(pid),0,FALSE,TRUE,DP2_RESULT_REG));
12542 freeAsmop (pid, NULL, ic, FALSE);
12544 emitcode ("lcall","System_ProcessResume");
12546 unsavermask(rsave);
12549 /*-----------------------------------------------------------------*/
12551 /*-----------------------------------------------------------------*/
12552 static void genSystem (iCode *ic,int nparms,char *name)
12554 assert(nparms == 0);
12556 emitcode ("lcall","System_%s",name);
12559 /*-----------------------------------------------------------------*/
12560 /* genSystemPoll - */
12561 /*-----------------------------------------------------------------*/
12562 static void genSystemPoll(iCode *ic,int nparms, operand **parms,char *name)
12567 assert (nparms==1);
12568 /* save registers that need to be saved */
12569 savermask(rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
12570 ds390_rUmaskForOp (IC_RESULT(ic))));
12573 aopOp (fp,ic,FALSE,FALSE);
12574 if (AOP_TYPE (fp) == AOP_IMMD) {
12575 emitcode ("mov", "dptr,%s",
12576 aopGet (AOP (fp), 0, TRUE, FALSE, DP2_RESULT_REG));
12577 } else if (AOP_TYPE(fp) != AOP_STR) { /* not already in dptr */
12578 emitcode ("mov","dpl,%s",
12579 aopGet(AOP(fp),0,FALSE,FALSE,DP2_RESULT_REG));
12580 emitcode ("mov","dph,%s",
12581 aopGet(AOP(fp),1,FALSE,FALSE,DP2_RESULT_REG));
12582 emitcode ("mov","dpx,%s",
12583 aopGet(AOP(fp),2,FALSE,FALSE,DP2_RESULT_REG));
12585 freeAsmop (fp, NULL, ic, FALSE);
12587 emitcode ("lcall","System_%sPoll",name);
12589 /* put result into place */
12591 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12592 if (rsym->liveFrom != rsym->liveTo) {
12593 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12594 aopPut(AOP(IC_RESULT(ic)),"a",0);
12595 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12598 unsavermask(rsave);
12601 /*-----------------------------------------------------------------*/
12602 /* genSystemGetCurrentID - */
12603 /*-----------------------------------------------------------------*/
12604 static void genSystemGetCurrentID(iCode *ic,int nparms, operand **parms,char *name)
12606 assert (nparms==0);
12608 emitcode ("lcall","System_GetCurrent%sId",name);
12609 /* put result into place */
12611 symbol *rsym = OP_SYMBOL(IC_RESULT(ic));
12612 if (rsym->liveFrom != rsym->liveTo) {
12613 aopOp (IC_RESULT(ic),ic,FALSE,FALSE);
12614 aopPut(AOP(IC_RESULT(ic)),"a",0);
12615 freeAsmop (IC_RESULT(ic), NULL, ic, FALSE);
12620 /*-----------------------------------------------------------------*/
12621 /* genDummyRead - generate code for dummy read of volatiles */
12622 /*-----------------------------------------------------------------*/
12624 genDummyRead (iCode * ic)
12629 D(emitcode("; genDummyRead",""));
12631 right = IC_RIGHT (ic);
12633 aopOp (right, ic, FALSE, FALSE);
12635 /* if the result is a bit */
12636 if (AOP_TYPE (right) == AOP_CRY)
12638 emitcode ("mov", "c,%s", AOP (right)->aopu.aop_dir);
12642 /* bit variables done */
12644 size = AOP_SIZE (right);
12648 emitcode ("mov", "a,%s", aopGet (AOP (right), offset, FALSE, FALSE, FALSE));
12653 freeAsmop (right, NULL, ic, TRUE);
12656 /*-----------------------------------------------------------------*/
12657 /* genBuiltIn - calls the appropriate function to generating code */
12658 /* for a built in function */
12659 /*-----------------------------------------------------------------*/
12660 static void genBuiltIn (iCode *ic)
12662 operand *bi_parms[MAX_BUILTIN_ARGS];
12667 /* get all the arguments for a built in function */
12668 bi_iCode = getBuiltinParms(ic,&nbi_parms,bi_parms);
12670 /* which function is it */
12671 bif = OP_SYMBOL(IC_LEFT(bi_iCode));
12672 if (strcmp(bif->name,"__builtin_memcpy_x2x")==0) {
12673 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,0);
12674 } else if (strcmp(bif->name,"__builtin_memcpy_c2x")==0) {
12675 genMemcpyX2X(bi_iCode,nbi_parms,bi_parms,1);
12676 } else if (strcmp(bif->name,"__builtin_memcmp_x2x")==0) {
12677 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,0);
12678 } else if (strcmp(bif->name,"__builtin_memcmp_c2x")==0) {
12679 genMemcmpX2X(bi_iCode,nbi_parms,bi_parms,1);
12680 } else if (strcmp(bif->name,"__builtin_memset_x")==0) {
12681 genMemsetX(bi_iCode,nbi_parms,bi_parms);
12682 } else if (strcmp(bif->name,"__builtin_inp")==0) {
12683 genInp(bi_iCode,nbi_parms,bi_parms);
12684 } else if (strcmp(bif->name,"__builtin_outp")==0) {
12685 genOutp(bi_iCode,nbi_parms,bi_parms);
12686 } else if (strcmp(bif->name,"__builtin_swapw")==0) {
12687 genSwapW(bi_iCode,nbi_parms,bi_parms);
12688 /* JavaNative builtIns */
12689 } else if (strcmp(bif->name,"NatLib_LoadByte")==0) {
12690 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,1);
12691 } else if (strcmp(bif->name,"NatLib_LoadShort")==0) {
12692 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,2);
12693 } else if (strcmp(bif->name,"NatLib_LoadInt")==0) {
12694 genNatLibLoadPrimitive(bi_iCode,nbi_parms,bi_parms,4);
12695 } else if (strcmp(bif->name,"NatLib_LoadPointer")==0) {
12696 genNatLibLoadPointer(bi_iCode,nbi_parms,bi_parms);
12697 } else if (strcmp(bif->name,"NatLib_InstallImmutableStateBlock")==0) {
12698 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12699 } else if (strcmp(bif->name,"NatLib_InstallEphemeralStateBlock")==0) {
12700 genNatLibInstallStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12701 } else if (strcmp(bif->name,"NatLib_RemoveImmutableStateBlock")==0) {
12702 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Immutable");
12703 } else if (strcmp(bif->name,"NatLib_RemoveEphemeralStateBlock")==0) {
12704 genNatLibRemoveStateBlock(bi_iCode,nbi_parms,"Ephemeral");
12705 } else if (strcmp(bif->name,"NatLib_GetImmutableStateBlock")==0) {
12706 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Immutable");
12707 } else if (strcmp(bif->name,"NatLib_GetEphemeralStateBlock")==0) {
12708 genNatLibGetStateBlock(bi_iCode,nbi_parms,bi_parms,"Ephemeral");
12709 } else if (strcmp(bif->name,"MM_XMalloc")==0) {
12710 genMMMalloc(bi_iCode,nbi_parms,bi_parms,3,"XMalloc");
12711 } else if (strcmp(bif->name,"MM_Malloc")==0) {
12712 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Malloc");
12713 } else if (strcmp(bif->name,"MM_ApplicationMalloc")==0) {
12714 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"ApplicationMalloc");
12715 } else if (strcmp(bif->name,"MM_Free")==0) {
12716 genMMMalloc(bi_iCode,nbi_parms,bi_parms,2,"Free");
12717 } else if (strcmp(bif->name,"MM_Deref")==0) {
12718 genMMDeref(bi_iCode,nbi_parms,bi_parms);
12719 } else if (strcmp(bif->name,"MM_UnrestrictedPersist")==0) {
12720 genMMUnrestrictedPersist(bi_iCode,nbi_parms,bi_parms);
12721 } else if (strcmp(bif->name,"System_ExecJavaProcess")==0) {
12722 genSystemExecJavaProcess(bi_iCode,nbi_parms,bi_parms);
12723 } else if (strcmp(bif->name,"System_GetRTCRegisters")==0) {
12724 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Get");
12725 } else if (strcmp(bif->name,"System_SetRTCRegisters")==0) {
12726 genSystemRTCRegisters(bi_iCode,nbi_parms,bi_parms,"Set");
12727 } else if (strcmp(bif->name,"System_ThreadSleep")==0) {
12728 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep");
12729 } else if (strcmp(bif->name,"System_ThreadSleep_ExitCriticalSection")==0) {
12730 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ThreadSleep_ExitCriticalSection");
12731 } else if (strcmp(bif->name,"System_ProcessSleep")==0) {
12732 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep");
12733 } else if (strcmp(bif->name,"System_ProcessSleep_ExitCriticalSection")==0) {
12734 genSystemThreadSleep(bi_iCode,nbi_parms,bi_parms,"ProcessSleep_ExitCriticalSection");
12735 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12736 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12737 } else if (strcmp(bif->name,"System_SaveThread")==0) {
12738 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12739 } else if (strcmp(bif->name,"System_ThreadResume")==0) {
12740 genSystemThreadResume(bi_iCode,nbi_parms,bi_parms);
12741 } else if (strcmp(bif->name,"System_ProcessResume")==0) {
12742 genSystemProcessResume(bi_iCode,nbi_parms,bi_parms);
12743 } else if (strcmp(bif->name,"System_SaveJavaThreadState")==0) {
12744 genSystem(bi_iCode,nbi_parms,"SaveJavaThreadState");
12745 } else if (strcmp(bif->name,"System_RestoreJavaThreadState")==0) {
12746 genSystem(bi_iCode,nbi_parms,"RestoreJavaThreadState");
12747 } else if (strcmp(bif->name,"System_ProcessYield")==0) {
12748 genSystem(bi_iCode,nbi_parms,"ProcessYield");
12749 } else if (strcmp(bif->name,"System_ProcessSuspend")==0) {
12750 genSystem(bi_iCode,nbi_parms,"ProcessSuspend");
12751 } else if (strcmp(bif->name,"System_RegisterPoll")==0) {
12752 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Register");
12753 } else if (strcmp(bif->name,"System_RemovePoll")==0) {
12754 genSystemPoll(bi_iCode,nbi_parms,bi_parms,"Remove");
12755 } else if (strcmp(bif->name,"System_GetCurrentThreadId")==0) {
12756 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Thread");
12757 } else if (strcmp(bif->name,"System_GetCurrentProcessId")==0) {
12758 genSystemGetCurrentID(bi_iCode,nbi_parms,bi_parms,"Process");
12760 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,"unknown builtin function encountered\n");
12766 /*-----------------------------------------------------------------*/
12767 /* gen390Code - generate code for Dallas 390 based controllers */
12768 /*-----------------------------------------------------------------*/
12770 gen390Code (iCode * lic)
12775 lineHead = lineCurr = NULL;
12776 dptrn[1][0] = "dpl1";
12777 dptrn[1][1] = "dph1";
12778 dptrn[1][2] = "dpx1";
12780 if (options.model == MODEL_FLAT24) {
12781 fReturnSizeDS390 = 5;
12782 fReturn = fReturn24;
12784 fReturnSizeDS390 = 4;
12785 fReturn = fReturn16;
12786 options.stack10bit=0;
12789 /* print the allocation information */
12790 if (allocInfo && currFunc)
12791 printAllocInfo (currFunc, codeOutFile);
12793 /* if debug information required */
12794 if (options.debug && currFunc)
12796 debugFile->writeFunction(currFunc);
12798 if (IS_STATIC (currFunc->etype))
12799 emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
12801 emitcode ("", "G$%s$0$0 ==.", currFunc->name);
12804 /* stack pointer name */
12805 if (options.useXstack)
12811 for (ic = lic; ic; ic = ic->next)
12814 if (ic->lineno && cln != ic->lineno)
12819 emitcode ("", "C$%s$%d$%d$%d ==.",
12820 FileBaseName (ic->filename), ic->lineno,
12821 ic->level, ic->block);
12824 if (!options.noCcodeInAsm) {
12825 emitcode ("", ";\t%s:%d: %s", ic->filename, ic->lineno,
12826 printCLine(ic->filename, ic->lineno));
12830 if (options.iCodeInAsm) {
12831 emitcode("", ";ic:%d: %s", ic->key, printILine(ic));
12833 /* if the result is marked as
12834 spilt and rematerializable or code for
12835 this has already been generated then
12837 if (resultRemat (ic) || ic->generated)
12840 /* depending on the operation */
12860 /* IPOP happens only when trying to restore a
12861 spilt live range, if there is an ifx statement
12862 following this pop then the if statement might
12863 be using some of the registers being popped which
12864 would destory the contents of the register so
12865 we need to check for this condition and handle it */
12867 ic->next->op == IFX &&
12868 regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
12869 genIfx (ic->next, ic);
12887 genEndFunction (ic);
12907 if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
12924 genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
12928 genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
12935 /* note these two are xlated by algebraic equivalence
12936 during parsing SDCC.y */
12937 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
12938 "got '>=' or '<=' shouldn't have come here");
12942 genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
12954 genXor (ic, ifxForOp (IC_RESULT (ic), ic));
12958 genOr (ic, ifxForOp (IC_RESULT (ic), ic));
12962 genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
12986 genRightShift (ic);
12989 case GET_VALUE_AT_ADDRESS:
12990 genPointerGet (ic,hasInc(IC_LEFT(ic),ic, getSize(operandType(IC_RESULT(ic)))));
12994 if (POINTER_SET (ic))
12995 genPointerSet (ic,hasInc(IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
13021 if (ic->builtinSEND) genBuiltIn(ic);
13022 else addSet (&_G.sendSet, ic);
13025 case DUMMY_READ_VOLATILE:
13029 #if 0 // obsolete, and buggy for != xdata
13041 /* now we are ready to call the
13042 peep hole optimizer */
13043 if (!options.nopeep)
13044 peepHole (&lineHead);
13046 /* now do the actual printing */
13047 printLine (lineHead, codeOutFile);