1 /*-------------------------------------------------------------------------
2 gen.c - Z80 specific code generator.
4 Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
6 Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
7 Improved WORD push 22784 144 19AE
8 With label1 on 22694 144 197E
9 With label2 on 22743 144 198A
10 With label3 on 22776 144 1999
11 With label4 on 22776 144 1999
12 With all 'label' on 22661 144 196F
13 With loopInvariant on 20919 156 19AB
14 With loopInduction on Breaks 198B
15 With all working on 20796 158 196C
16 Slightly better genCmp(signed) 20597 159 195B
18 Michael Hope <michaelh@earthling.net> 2000
19 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
20 and - Jean-Louis VERN.jlvern@writeme.com (1999)
22 This program is free software; you can redistribute it and/or modify it
23 under the terms of the GNU General Public License as published by the
24 Free Software Foundation; either version 2, or (at your option) any
27 This program is distributed in the hope that it will be useful,
28 but WITHOUT ANY WARRANTY; without even the implied warranty of
29 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 GNU General Public License for more details.
32 You should have received a copy of the GNU General Public License
33 along with this program; if not, write to the Free Software
34 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
36 In other words, you are welcome to use, share and improve this program.
37 You are forbidden to forbid anyone else to use, share and improve
38 what you give them. Help stamp out software-hoarding!
40 -------------------------------------------------------------------------*/
46 #include "SDCCglobl.h"
48 #ifdef HAVE_SYS_ISA_DEFS_H
49 #include <sys/isa_defs.h>
55 #include "SDCChasht.h"
58 #include "SDCCicode.h"
59 #include "SDCClabel.h"
60 #include "SDCCBBlock.h"
63 #include "SDCCcflow.h"
64 #include "SDCCdflow.h"
65 #include "SDCClrange.h"
68 #include "SDCCpeeph.h"
69 #include "SDCCglue.h" /* drdani Jan 30 2000 */
71 /* this is the down and dirty file with all kinds of kludgy & hacky
72 stuff. This is what it is all about CODE GENERATION for a specific MCU.
73 Some of the routines may be reusable, will have to see */
75 static char *zero = "#0x00";
76 static char *one = "#0x01";
78 static char *fReturn[] = {"l", "h", "e", "d" };
79 static char *accUse[] = {"a" };
85 extern int ptrRegReq ;
87 extern FILE *codeOutFile;
89 #define RESULTONSTACK(x) \
90 (IC_RESULT(x) && IC_RESULT(x)->aop && \
91 IC_RESULT(x)->aop->type == AOP_STK )
93 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
94 #define CLRC emitcode("xor","a,a");
96 #define LABEL_STR "%05d$"
98 lineNode *lineHead = NULL;
99 lineNode *lineCurr = NULL;
101 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
102 0xE0, 0xC0, 0x80, 0x00};
103 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
104 0x07, 0x03, 0x01, 0x00};
106 static int _lastStack = 0;
121 /*-----------------------------------------------------------------*/
122 /* emitcode - writes the code into a file : for now it is simple */
123 /*-----------------------------------------------------------------*/
124 void emitcode (const char *inst, const char *fmt, ...)
127 char lb[MAX_INLINEASM];
133 sprintf(lb,"%s\t",inst);
134 vsprintf(lb+(strlen(lb)),fmt,ap);
138 while (isspace(*lbp)) lbp++;
141 lineCurr = (lineCurr ?
142 connectLine(lineCurr,newLineNode(lb)) :
143 (lineHead = newLineNode(lb)));
144 lineCurr->isInline = inLine;
145 lineCurr->isDebug = debugLine;
149 const char *getPairName(asmop *aop)
151 if (aop->type == AOP_REG) {
152 switch (aop->aopu.aop_reg[0]->rIdx) {
164 else if (aop->type == AOP_STR) {
165 switch (*aop->aopu.aop_str[0]) {
181 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
182 bool isPair(asmop *aop)
184 if (aop->size == 2) {
185 if (aop->type == AOP_REG) {
186 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
189 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
192 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
196 if (aop->type == AOP_STR) {
197 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
200 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
203 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
211 /** Push a register pair onto the stack */
212 void genPairPush(asmop *aop)
214 emitcode("push", "%s", getPairName(aop));
217 /*-----------------------------------------------------------------*/
218 /* newAsmop - creates a new asmOp */
219 /*-----------------------------------------------------------------*/
220 static asmop *newAsmop (short type)
224 ALLOC(aop,sizeof(asmop));
229 /*-----------------------------------------------------------------*/
230 /* aopForSym - for a true symbol */
231 /*-----------------------------------------------------------------*/
232 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
235 memmap *space= SPEC_OCLS(sym->etype);
237 /* if already has one */
241 /* Assign depending on the storage class */
242 if (sym->onStack || sym->iaccess) {
243 sym->aop = aop = newAsmop(AOP_STK);
244 aop->size = getSize(sym->type);
246 aop->aopu.aop_stk = sym->stack;
250 /* special case for a function */
251 if (IS_FUNC(sym->type)) {
252 sym->aop = aop = newAsmop(AOP_IMMD);
253 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
254 strcpy(aop->aopu.aop_immd,sym->rname);
259 /* only remaining is far space */
260 /* in which case DPTR gets the address */
261 sym->aop = aop = newAsmop(AOP_IY);
262 emitcode ("ld","iy,#%s", sym->rname);
263 aop->size = getSize(sym->type);
264 aop->aopu.aop_dir = sym->rname;
266 /* if it is in code space */
267 if (IN_CODESPACE(space))
273 /*-----------------------------------------------------------------*/
274 /* aopForRemat - rematerialzes an object */
275 /*-----------------------------------------------------------------*/
276 static asmop *aopForRemat (symbol *sym)
279 iCode *ic = sym->rematiCode;
280 asmop *aop = newAsmop(AOP_IMMD);
283 /* if plus or minus print the right hand side */
284 if (ic->op == '+' || ic->op == '-') {
285 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
288 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
291 /* we reached the end */
292 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
296 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
297 strcpy(aop->aopu.aop_immd,buffer);
301 /*-----------------------------------------------------------------*/
302 /* regsInCommon - two operands have some registers in common */
303 /*-----------------------------------------------------------------*/
304 bool regsInCommon (operand *op1, operand *op2)
309 /* if they have registers in common */
310 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
313 sym1 = OP_SYMBOL(op1);
314 sym2 = OP_SYMBOL(op2);
316 if (sym1->nRegs == 0 || sym2->nRegs == 0)
319 for (i = 0 ; i < sym1->nRegs ; i++) {
324 for (j = 0 ; j < sym2->nRegs ;j++ ) {
328 if (sym2->regs[j] == sym1->regs[i])
336 /*-----------------------------------------------------------------*/
337 /* operandsEqu - equivalent */
338 /*-----------------------------------------------------------------*/
339 bool operandsEqu ( operand *op1, operand *op2)
343 /* if they not symbols */
344 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
347 sym1 = OP_SYMBOL(op1);
348 sym2 = OP_SYMBOL(op2);
350 /* if both are itemps & one is spilt
351 and the other is not then false */
352 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
353 sym1->isspilt != sym2->isspilt )
356 /* if they are the same */
360 if (strcmp(sym1->rname,sym2->rname) == 0)
364 /* if left is a tmp & right is not */
368 (sym1->usl.spillLoc == sym2))
375 (sym2->usl.spillLoc == sym1))
381 /*-----------------------------------------------------------------*/
382 /* sameRegs - two asmops have the same registers */
383 /*-----------------------------------------------------------------*/
384 bool sameRegs (asmop *aop1, asmop *aop2 )
391 if (aop1->type != AOP_REG ||
392 aop2->type != AOP_REG )
395 if (aop1->size != aop2->size)
398 for (i = 0 ; i < aop1->size ; i++ )
399 if (aop1->aopu.aop_reg[i] !=
400 aop2->aopu.aop_reg[i] )
406 /*-----------------------------------------------------------------*/
407 /* aopOp - allocates an asmop for an operand : */
408 /*-----------------------------------------------------------------*/
409 static void aopOp (operand *op, iCode *ic, bool result)
418 /* if this a literal */
419 if (IS_OP_LITERAL(op)) {
420 op->aop = aop = newAsmop(AOP_LIT);
421 aop->aopu.aop_lit = op->operand.valOperand;
422 aop->size = getSize(operandType(op));
426 /* if already has a asmop then continue */
430 /* if the underlying symbol has a aop */
431 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
432 op->aop = OP_SYMBOL(op)->aop;
436 /* if this is a true symbol */
437 if (IS_TRUE_SYMOP(op)) {
438 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
442 /* this is a temporary : this has
448 e) can be a return use only */
452 /* if the type is a conditional */
453 if (sym->regType == REG_CND) {
454 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
459 /* if it is spilt then two situations
461 b) has a spill location */
462 if (sym->isspilt || sym->nRegs == 0) {
463 /* rematerialize it NOW */
465 sym->aop = op->aop = aop =
467 aop->size = getSize(sym->type);
473 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
474 aop->size = getSize(sym->type);
475 for ( i = 0 ; i < 2 ; i++ )
476 aop->aopu.aop_str[i] = accUse[i];
482 aop = op->aop = sym->aop = newAsmop(AOP_STR);
483 aop->size = getSize(sym->type);
484 for ( i = 0 ; i < 4 ; i++ )
485 aop->aopu.aop_str[i] = fReturn[i];
489 /* else spill location */
490 sym->aop = op->aop = aop =
491 aopForSym(ic,sym->usl.spillLoc,result);
492 aop->size = getSize(sym->type);
496 /* must be in a register */
497 sym->aop = op->aop = aop = newAsmop(AOP_REG);
498 aop->size = sym->nRegs;
499 for ( i = 0 ; i < sym->nRegs ;i++)
500 aop->aopu.aop_reg[i] = sym->regs[i];
503 /*-----------------------------------------------------------------*/
504 /* freeAsmop - free up the asmop given to an operand */
505 /*----------------------------------------------------------------*/
506 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
529 /* all other cases just dealloc */
533 OP_SYMBOL(op)->aop = NULL;
534 /* if the symbol has a spill */
536 SPIL_LOC(op)->aop = NULL;
541 char *aopGetWordLong(asmop *aop, int offset, bool with_hash)
550 /* depending on type */
553 sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
554 ALLOC_ATOMIC(rs,strlen(s)+1);
559 value * val = aop->aopu.aop_lit;
560 /* if it is a float then it gets tricky */
561 /* otherwise it is fairly simple */
562 if (!IS_FLOAT(val->type)) {
563 unsigned long v = floatFromVal(val);
565 sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
566 ALLOC_ATOMIC(rs,strlen(buffer)+1);
567 return strcpy (rs,buffer);
576 char *aopGetWord(asmop *aop, int offset)
578 return aopGetWordLong(aop, offset, TRUE);
581 /*-----------------------------------------------------------------*/
582 /* aopGet - for fetching value of the aop */
583 /*-----------------------------------------------------------------*/
584 static char *aopGet (asmop *aop, int offset, bool bit16)
589 /* offset is greater than size then zero */
590 if (offset > (aop->size - 1) &&
591 aop->type != AOP_LIT)
594 /* depending on type */
598 sprintf (s,"#%s",aop->aopu.aop_immd);
608 ALLOC_ATOMIC(rs,strlen(s)+1);
614 emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
616 ALLOC_ATOMIC(rs,strlen(s)+1);
621 return aop->aopu.aop_reg[offset]->name;
624 sprintf(s,"%d(iy)", offset);
625 ALLOC_ATOMIC(rs,strlen(s)+1);
630 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
631 ALLOC_ATOMIC(rs,strlen(s)+1);
645 return aopLiteral (aop->aopu.aop_lit,offset);
649 return aop->aopu.aop_str[offset];
652 fprintf(stderr, "Type %u\n", aop->type);
654 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
655 "aopget got unsupported aop->type");
659 bool isRegString(char *s)
661 if (!strcmp(s, "b") ||
672 bool isConstant(char *s)
677 bool canAssignToPtr(char *s)
686 /*-----------------------------------------------------------------*/
687 /* aopPut - puts a string for a aop */
688 /*-----------------------------------------------------------------*/
689 static void aopPut (asmop *aop, char *s, int offset)
693 if (aop->size && offset > ( aop->size - 1)) {
694 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
695 "aopPut got offset > aop->size");
699 /* will assign value to value */
700 /* depending on where it is ofcourse */
705 emitcode("ld", "a,%s", s);
706 emitcode("ld", "(%s+%d),a", d, offset);
710 /* Dont bother if it's a ld x,x */
711 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
712 emitcode("ld","%s,%s",
713 aop->aopu.aop_reg[offset]->name,s);
718 if (!canAssignToPtr(s)) {
719 emitcode("ld", "a,%s", s);
720 emitcode("ld", "%d(iy),a", offset);
723 emitcode("ld", "%d(iy),%s", offset, s);
727 if (!canAssignToPtr(s)) {
728 emitcode("ld", "a,%s", s);
729 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
732 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
736 /* if bit variable */
737 if (!aop->aopu.aop_dir) {
738 emitcode("ld", "a,#0");
741 /* In bit space but not in C - cant happen */
748 if (strcmp(aop->aopu.aop_str[offset],s)) {
749 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
755 if (!offset && (strcmp(s,"acc") == 0))
759 emitcode("", "; Error aopPut AOP_ACC");
762 if (strcmp(aop->aopu.aop_str[offset],s))
763 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
768 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
769 "aopPut got unsupported aop->type");
774 #define AOP(op) op->aop
775 #define AOP_TYPE(op) AOP(op)->type
776 #define AOP_SIZE(op) AOP(op)->size
777 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
779 /*-----------------------------------------------------------------*/
780 /* getDataSize - get the operand data size */
781 /*-----------------------------------------------------------------*/
782 int getDataSize(operand *op)
793 /*-----------------------------------------------------------------*/
794 /* movLeft2Result - move byte from left to result */
795 /*-----------------------------------------------------------------*/
796 static void movLeft2Result (operand *left, int offl,
797 operand *result, int offr, int sign)
800 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
801 l = aopGet(AOP(left),offl,FALSE);
804 aopPut(AOP(result),l,offr);
813 /** Put Acc into a register set
815 void outAcc(operand *result)
818 size = getDataSize(result);
820 aopPut(AOP(result),"a",0);
823 /* unsigned or positive */
825 aopPut(AOP(result),zero,offset++);
830 /** Take the value in carry and put it into a register
832 void outBitC(operand *result)
834 /* if the result is bit */
835 if (AOP_TYPE(result) == AOP_CRY) {
836 emitcode("", "; Note: outBitC form 1");
837 aopPut(AOP(result),"blah",0);
840 emitcode("ld", "a,#0");
846 /*-----------------------------------------------------------------*/
847 /* toBoolean - emit code for orl a,operator(sizeop) */
848 /*-----------------------------------------------------------------*/
849 void toBoolean(operand *oper)
851 int size = AOP_SIZE(oper);
854 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
857 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
861 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
865 /*-----------------------------------------------------------------*/
866 /* genNot - generate code for ! operation */
867 /*-----------------------------------------------------------------*/
868 static void genNot (iCode *ic)
870 link *optype = operandType(IC_LEFT(ic));
872 /* assign asmOps to operand & result */
873 aopOp (IC_LEFT(ic),ic,FALSE);
874 aopOp (IC_RESULT(ic),ic,TRUE);
876 /* if in bit space then a special case */
877 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
881 /* if type float then do float */
882 if (IS_FLOAT(optype)) {
886 toBoolean(IC_LEFT(ic));
891 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
892 emitcode("sub", "a,#0x01");
893 outBitC(IC_RESULT(ic));
895 /* release the aops */
896 freeAsmop(IC_LEFT(ic),NULL,ic);
897 freeAsmop(IC_RESULT(ic),NULL,ic);
900 /*-----------------------------------------------------------------*/
901 /* genCpl - generate code for complement */
902 /*-----------------------------------------------------------------*/
903 static void genCpl (iCode *ic)
909 /* assign asmOps to operand & result */
910 aopOp (IC_LEFT(ic),ic,FALSE);
911 aopOp (IC_RESULT(ic),ic,TRUE);
913 /* if both are in bit space then
915 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
916 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
920 size = AOP_SIZE(IC_RESULT(ic));
922 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
925 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
928 /* release the aops */
929 freeAsmop(IC_LEFT(ic),NULL,ic);
930 freeAsmop(IC_RESULT(ic),NULL,ic);
933 /*-----------------------------------------------------------------*/
934 /* genUminus - unary minus code generation */
935 /*-----------------------------------------------------------------*/
936 static void genUminus (iCode *ic)
939 link *optype, *rtype;
942 aopOp(IC_LEFT(ic),ic,FALSE);
943 aopOp(IC_RESULT(ic),ic,TRUE);
945 /* if both in bit space then special
947 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
948 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
953 optype = operandType(IC_LEFT(ic));
954 rtype = operandType(IC_RESULT(ic));
956 /* if float then do float stuff */
957 if (IS_FLOAT(optype)) {
962 /* otherwise subtract from zero */
963 size = AOP_SIZE(IC_LEFT(ic));
967 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
968 emitcode("ld", "a,#0");
969 emitcode("sbc","a,%s",l);
970 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
973 /* if any remaining bytes in the result */
974 /* we just need to propagate the sign */
975 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
977 emitcode("sbc","a,a");
979 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
983 /* release the aops */
984 freeAsmop(IC_LEFT(ic),NULL,ic);
985 freeAsmop(IC_RESULT(ic),NULL,ic);
989 /*-----------------------------------------------------------------*/
990 /* assignResultValue - */
991 /*-----------------------------------------------------------------*/
992 void assignResultValue(operand * oper)
995 int size = AOP_SIZE(oper);
997 aopPut(AOP(oper),fReturn[offset],offset);
1002 /*-----------------------------------------------------------------*/
1003 /* genIpush - genrate code for pushing this gets a little complex */
1004 /*-----------------------------------------------------------------*/
1005 static void genIpush (iCode *ic)
1007 int size, offset = 0 ;
1011 /* if this is not a parm push : ie. it is spill push
1012 and spill push is always done on the local stack */
1013 if (!ic->parmPush) {
1014 /* and the item is spilt then do nothing */
1015 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1018 aopOp(IC_LEFT(ic),ic,FALSE);
1019 size = AOP_SIZE(IC_LEFT(ic));
1020 /* push it on the stack */
1021 if (isPair(AOP(IC_LEFT(ic)))) {
1022 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1027 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1028 /* Simple for now - load into A and PUSH AF */
1029 emitcode("ld", "a,%s", l);
1030 emitcode("push", "af");
1031 emitcode("inc", "sp");
1037 /* Hmmm... what about saving the currently used registers
1040 /* then do the push */
1041 aopOp(IC_LEFT(ic),ic,FALSE);
1043 size = AOP_SIZE(IC_LEFT(ic));
1045 if (isPair(AOP(IC_LEFT(ic)))) {
1046 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1050 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1052 emitcode("ld", "hl,%s", s);
1053 emitcode("push", "hl");
1056 /* Optimise here - load into HL then push HL */
1057 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0, FALSE));
1058 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1, FALSE));
1059 emitcode("push", "hl");
1065 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1066 emitcode("ld", "a,%s", l);
1067 emitcode("push", "af");
1068 emitcode("inc", "sp");
1072 freeAsmop(IC_LEFT(ic),NULL,ic);
1075 /*-----------------------------------------------------------------*/
1076 /* genIpop - recover the registers: can happen only for spilling */
1077 /*-----------------------------------------------------------------*/
1078 static void genIpop (iCode *ic)
1083 /* if the temp was not pushed then */
1084 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1087 aopOp(IC_LEFT(ic),ic,FALSE);
1088 size = AOP_SIZE(IC_LEFT(ic));
1090 if (isPair(AOP(IC_LEFT(ic)))) {
1091 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1095 emitcode("dec", "sp");
1096 emitcode("pop", "hl");
1097 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1101 freeAsmop(IC_LEFT(ic),NULL,ic);
1104 /** Emit the code for a call statement
1106 static void emitCall (iCode *ic, bool ispcall)
1108 /* if caller saves & we have not saved then */
1109 if (!ic->regsSaved) {
1113 /* if send set is not empty then assign */
1117 for (sic = setFirstItem(sendSet) ; sic ;
1118 sic = setNextItem(sendSet)) {
1119 int size, offset = 0;
1120 aopOp(IC_LEFT(sic),sic,FALSE);
1121 size = AOP_SIZE(IC_LEFT(sic));
1123 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1125 if (strcmp(l,fReturn[offset]))
1126 emitcode("ld","%s,%s",
1131 freeAsmop (IC_LEFT(sic),NULL,sic);
1137 symbol *rlbl = newiTempLabel(NULL);
1139 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1140 emitcode("push", "hl");
1142 aopOp(IC_LEFT(ic),ic,FALSE);
1143 emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
1144 emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
1145 freeAsmop(IC_LEFT(ic),NULL,ic);
1147 emitcode("jp", "(hl)");
1148 emitcode("","%05d$:",(rlbl->key+100));
1152 emitcode("call", "%s", (OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1153 OP_SYMBOL(IC_LEFT(ic))->rname :
1154 OP_SYMBOL(IC_LEFT(ic))->name));
1157 /* if we need assign a result value */
1158 if ((IS_ITEMP(IC_RESULT(ic)) &&
1159 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1160 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1161 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1164 aopOp(IC_RESULT(ic),ic,FALSE);
1167 assignResultValue(IC_RESULT(ic));
1169 freeAsmop(IC_RESULT(ic),NULL, ic);
1172 /* adjust the stack for parameters if required */
1173 if (IC_LEFT(ic)->parmBytes) {
1174 int i = IC_LEFT(ic)->parmBytes;
1176 emitcode("ld", "hl,#%d", i);
1177 emitcode("add", "hl,sp");
1178 emitcode("ld", "sp,hl");
1182 emitcode("pop", "hl");
1186 emitcode("inc", "sp");
1192 /*-----------------------------------------------------------------*/
1193 /* genCall - generates a call statement */
1194 /*-----------------------------------------------------------------*/
1195 static void genCall (iCode *ic)
1197 emitCall(ic, FALSE);
1200 /*-----------------------------------------------------------------*/
1201 /* genPcall - generates a call by pointer statement */
1202 /*-----------------------------------------------------------------*/
1203 static void genPcall (iCode *ic)
1208 /*-----------------------------------------------------------------*/
1209 /* resultRemat - result is rematerializable */
1210 /*-----------------------------------------------------------------*/
1211 static int resultRemat (iCode *ic)
1213 if (SKIP_IC(ic) || ic->op == IFX)
1216 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1217 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1218 if (sym->remat && !POINTER_SET(ic))
1225 /*-----------------------------------------------------------------*/
1226 /* genFunction - generated code for function entry */
1227 /*-----------------------------------------------------------------*/
1228 static void genFunction (iCode *ic)
1234 /* create the function header */
1235 emitcode(";","-----------------------------------------");
1236 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1237 emitcode(";","-----------------------------------------");
1239 emitcode("","%s:",sym->rname);
1240 fetype = getSpec(operandType(IC_LEFT(ic)));
1242 /* if critical function then turn interrupts off */
1243 if (SPEC_CRTCL(fetype))
1246 /* if this is an interrupt service routine then
1247 save acc, b, dpl, dph */
1248 if (IS_ISR(sym->etype)) {
1249 emitcode("push", "af");
1250 emitcode("push", "bc");
1251 emitcode("push", "de");
1252 emitcode("push", "hl");
1254 /* PENDING: callee-save etc */
1256 /* adjust the stack for the function */
1257 emitcode("push", "de");
1258 emitcode("push", "bc");
1259 emitcode("push", "ix");
1260 emitcode("ld", "ix,#0");
1261 emitcode("add", "ix,sp");
1263 _lastStack = sym->stack;
1266 emitcode("ld", "hl,#-%d", sym->stack);
1267 emitcode("add", "hl,sp");
1268 emitcode("ld", "sp,hl");
1272 /*-----------------------------------------------------------------*/
1273 /* genEndFunction - generates epilogue for functions */
1274 /*-----------------------------------------------------------------*/
1275 static void genEndFunction (iCode *ic)
1277 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1279 if (IS_ISR(sym->etype)) {
1283 if (SPEC_CRTCL(sym->etype))
1286 /* PENDING: calleeSave */
1288 /* if debug then send end of function */
1289 if (options.debug && currFunc) {
1291 emitcode("","C$%s$%d$%d$%d ==.",
1292 ic->filename,currFunc->lastLine,
1293 ic->level,ic->block);
1294 if (IS_STATIC(currFunc->etype))
1295 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1297 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1300 emitcode("ld", "sp,ix");
1301 emitcode("pop", "ix");
1302 emitcode("pop", "bc");
1303 emitcode("pop", "de");
1304 emitcode("ret", "");
1309 /*-----------------------------------------------------------------*/
1310 /* genRet - generate code for return statement */
1311 /*-----------------------------------------------------------------*/
1312 static void genRet (iCode *ic)
1315 /* Errk. This is a hack until I can figure out how
1316 to cause dehl to spill on a call */
1317 int size,offset = 0;
1319 /* if we have no return value then
1320 just generate the "ret" */
1324 /* we have something to return then
1325 move the return value into place */
1326 aopOp(IC_LEFT(ic),ic,FALSE);
1327 size = AOP_SIZE(IC_LEFT(ic));
1329 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1330 emitcode("ld", "hl,%s", l);
1334 l = aopGet(AOP(IC_LEFT(ic)),offset,
1336 if (strcmp(fReturn[offset],l))
1337 emitcode("ld","%s,%s",fReturn[offset++],l);
1340 freeAsmop (IC_LEFT(ic),NULL,ic);
1343 /* generate a jump to the return label
1344 if the next is not the return statement */
1345 if (!(ic->next && ic->next->op == LABEL &&
1346 IC_LABEL(ic->next) == returnLabel))
1348 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1351 /*-----------------------------------------------------------------*/
1352 /* genLabel - generates a label */
1353 /*-----------------------------------------------------------------*/
1354 static void genLabel (iCode *ic)
1356 /* special case never generate */
1357 if (IC_LABEL(ic) == entryLabel)
1360 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1363 /*-----------------------------------------------------------------*/
1364 /* genGoto - generates a ljmp */
1365 /*-----------------------------------------------------------------*/
1366 static void genGoto (iCode *ic)
1368 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1371 /*-----------------------------------------------------------------*/
1372 /* genPlusIncr :- does addition with increment if possible */
1373 /*-----------------------------------------------------------------*/
1374 static bool genPlusIncr (iCode *ic)
1376 unsigned int icount ;
1377 unsigned int size = getDataSize(IC_RESULT(ic));
1379 /* will try to generate an increment */
1380 /* if the right side is not a literal
1382 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1385 emitcode("", "; genPlusIncr");
1387 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1389 /* If result is a pair */
1390 if (isPair(AOP(IC_RESULT(ic)))) {
1391 char *left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1393 /* Both a lit on the right and a true symbol on the left */
1394 emitcode("ld", "%s,#%s + %d", getPairName(AOP(IC_RESULT(ic))), left, icount);
1399 /* if the literal value of the right hand side
1400 is greater than 4 then it is not worth it */
1405 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1406 isPair(AOP(IC_RESULT(ic)))) {
1408 emitcode("inc", "%s ; 1", getPairName(AOP(IC_RESULT(ic))));
1412 /* if increment 16 bits in register */
1413 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1416 symbol *tlbl = newiTempLabel(NULL);
1417 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1418 emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
1420 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1424 emitcode("", LABEL_STR ":",tlbl->key+100);
1428 /* If result is a pair */
1429 if (isPair(AOP(IC_RESULT(ic)))) {
1430 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1431 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1433 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1437 /* if the sizes are greater than 1 then we cannot */
1438 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1439 AOP_SIZE(IC_LEFT(ic)) > 1 )
1442 /* we can if the aops of the left & result match or
1443 if they are in registers and the registers are the
1445 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1447 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1455 /*-----------------------------------------------------------------*/
1456 /* outBitAcc - output a bit in acc */
1457 /*-----------------------------------------------------------------*/
1458 void outBitAcc(operand *result)
1460 symbol *tlbl = newiTempLabel(NULL);
1461 /* if the result is a bit */
1462 if (AOP_TYPE(result) == AOP_CRY){
1466 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
1467 emitcode("ld","a,%s",one);
1468 emitcode("", LABEL_STR ":",tlbl->key+100);
1473 /*-----------------------------------------------------------------*/
1474 /* genPlus - generates code for addition */
1475 /*-----------------------------------------------------------------*/
1476 static void genPlus (iCode *ic)
1478 int size, offset = 0;
1480 /* special cases :- */
1482 aopOp (IC_LEFT(ic),ic,FALSE);
1483 aopOp (IC_RIGHT(ic),ic,FALSE);
1484 aopOp (IC_RESULT(ic),ic,TRUE);
1486 /* Swap the left and right operands if:
1488 if literal, literal on the right or
1489 if left requires ACC or right is already
1492 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1493 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1494 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1495 operand *t = IC_RIGHT(ic);
1496 IC_RIGHT(ic) = IC_LEFT(ic);
1500 /* if both left & right are in bit
1502 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1503 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1508 /* if left in bit space & right literal */
1509 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1510 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1511 /* Can happen I guess */
1515 /* if I can do an increment instead
1516 of add then GOOD for ME */
1517 if (genPlusIncr (ic) == TRUE)
1520 size = getDataSize(IC_RESULT(ic));
1522 /* Special case when left and right are constant */
1523 if (isPair(AOP(IC_RESULT(ic)))) {
1526 left = aopGetWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1527 right = aopGetWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1528 if (left && right) {
1532 sprintf(buffer, "#(%s + %s)", left, right);
1533 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1539 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1540 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1542 emitcode("add","a,%s",
1543 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1545 emitcode("adc","a,%s",
1546 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1548 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1550 emitcode("add","a,%s",
1551 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1553 emitcode("adc","a,%s",
1554 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1556 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1559 /* Some kind of pointer arith. */
1560 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1561 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1562 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1565 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1566 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1567 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1572 freeAsmop(IC_LEFT(ic),NULL,ic);
1573 freeAsmop(IC_RIGHT(ic),NULL,ic);
1574 freeAsmop(IC_RESULT(ic),NULL,ic);
1578 /*-----------------------------------------------------------------*/
1579 /* genMinusDec :- does subtraction with deccrement if possible */
1580 /*-----------------------------------------------------------------*/
1581 static bool genMinusDec (iCode *ic)
1583 unsigned int icount ;
1584 unsigned int size = getDataSize(IC_RESULT(ic));
1586 /* will try to generate an increment */
1587 /* if the right side is not a literal we cannot */
1588 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1591 /* if the literal value of the right hand side
1592 is greater than 4 then it is not worth it */
1593 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1596 size = getDataSize(IC_RESULT(ic));
1597 /* if decrement 16 bits in register */
1598 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1599 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1601 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1605 /* If result is a pair */
1606 if (isPair(AOP(IC_RESULT(ic)))) {
1607 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1608 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1610 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1614 /* if the sizes are greater than 1 then we cannot */
1615 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1616 AOP_SIZE(IC_LEFT(ic)) > 1 )
1619 /* we can if the aops of the left & result match or if they are in
1620 registers and the registers are the same */
1621 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1623 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1630 /*-----------------------------------------------------------------*/
1631 /* genMinus - generates code for subtraction */
1632 /*-----------------------------------------------------------------*/
1633 static void genMinus (iCode *ic)
1635 int size, offset = 0;
1636 unsigned long lit = 0L;
1638 aopOp (IC_LEFT(ic),ic,FALSE);
1639 aopOp (IC_RIGHT(ic),ic,FALSE);
1640 aopOp (IC_RESULT(ic),ic,TRUE);
1642 /* special cases :- */
1643 /* if both left & right are in bit space */
1644 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1645 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1650 /* if I can do an decrement instead of subtract then GOOD for ME */
1651 if (genMinusDec (ic) == TRUE)
1654 size = getDataSize(IC_RESULT(ic));
1656 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1659 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1664 /* if literal, add a,#-lit, else normal subb */
1666 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1667 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1669 emitcode("sub","a,%s",
1670 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1672 emitcode("sbc","a,%s",
1673 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1676 /* first add without previous c */
1678 emitcode("add","a,#0x%02x",
1679 (unsigned int)(lit & 0x0FFL));
1681 emitcode("adc","a,#0x%02x",
1682 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1684 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1687 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1688 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1689 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1693 freeAsmop(IC_LEFT(ic),NULL,ic);
1694 freeAsmop(IC_RIGHT(ic),NULL,ic);
1695 freeAsmop(IC_RESULT(ic),NULL,ic);
1698 /*-----------------------------------------------------------------*/
1699 /* genMult - generates code for multiplication */
1700 /*-----------------------------------------------------------------*/
1701 static void genMult (iCode *ic)
1703 /* Shouldn't occur - all done through function calls */
1707 /*-----------------------------------------------------------------*/
1708 /* genDiv - generates code for division */
1709 /*-----------------------------------------------------------------*/
1710 static void genDiv (iCode *ic)
1712 /* Shouldn't occur - all done through function calls */
1716 /*-----------------------------------------------------------------*/
1717 /* genMod - generates code for division */
1718 /*-----------------------------------------------------------------*/
1719 static void genMod (iCode *ic)
1721 /* Shouldn't occur - all done through function calls */
1725 /*-----------------------------------------------------------------*/
1726 /* genIfxJump :- will create a jump depending on the ifx */
1727 /*-----------------------------------------------------------------*/
1728 static void genIfxJump (iCode *ic, char *jval)
1733 /* if true label then we jump if condition
1735 if ( IC_TRUE(ic) ) {
1737 if (!strcmp(jval, "a")) {
1740 else if (!strcmp(jval, "c")) {
1744 /* The buffer contains the bit on A that we should test */
1749 /* false label is present */
1750 jlbl = IC_FALSE(ic) ;
1751 if (!strcmp(jval, "a")) {
1754 else if (!strcmp(jval, "c")) {
1758 /* The buffer contains the bit on A that we should test */
1762 /* Z80 can do a conditional long jump */
1763 if (!strcmp(jval, "a")) {
1764 emitcode("or", "a,a");
1766 else if (!strcmp(jval, "c")) {
1769 emitcode("bit", "%s,a", jval);
1771 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
1773 /* mark the icode as generated */
1777 /** Generic compare for > or <
1779 static void genCmp (operand *left,operand *right,
1780 operand *result, iCode *ifx, int sign)
1782 int size, offset = 0 ;
1783 unsigned long lit = 0L;
1785 /* if left & right are bit variables */
1786 if (AOP_TYPE(left) == AOP_CRY &&
1787 AOP_TYPE(right) == AOP_CRY ) {
1788 /* Cant happen on the Z80 */
1791 /* subtract right from left if at the
1792 end the carry flag is set then we know that
1793 left is greater than right */
1794 size = max(AOP_SIZE(left),AOP_SIZE(right));
1796 /* if unsigned char cmp with lit, just compare */
1798 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
1799 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
1801 emitcode("xor", "a,#0x80");
1802 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
1805 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
1808 if(AOP_TYPE(right) == AOP_LIT) {
1809 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1810 /* optimize if(x < 0) or if(x >= 0) */
1813 /* No sign so it's always false */
1817 /* Just load in the top most bit */
1818 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
1819 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
1820 genIfxJump (ifx,"7");
1824 emitcode("rlc","a");
1830 /* First setup h and l contaning the top most bytes XORed */
1831 bool fDidXor = FALSE;
1832 if (AOP_TYPE(left) == AOP_LIT){
1833 unsigned long lit = (unsigned long)
1834 floatFromVal(AOP(left)->aopu.aop_lit);
1835 emitcode("ld", "l,#0x%02x",
1836 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1839 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
1840 emitcode("xor", "a,#0x80");
1841 emitcode("ld", "l,a");
1844 if (AOP_TYPE(right) == AOP_LIT) {
1845 unsigned long lit = (unsigned long)
1846 floatFromVal(AOP(right)->aopu.aop_lit);
1847 emitcode("ld", "h,#0x%02x",
1848 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
1851 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
1852 emitcode("xor", "a,#0x80");
1853 emitcode("ld", "h,a");
1863 /* Do a long subtract */
1865 MOVA(aopGet(AOP(left),offset,FALSE));
1866 if (sign && size == 0) {
1867 emitcode("ld", "a,l");
1868 emitcode("sbc", "a,h");
1871 /* Subtract through, propagating the carry */
1872 emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
1879 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
1882 /* if the result is used in the next
1883 ifx conditional branch then generate
1884 code a little differently */
1886 genIfxJump (ifx,"c");
1889 /* leave the result in acc */
1893 /*-----------------------------------------------------------------*/
1894 /* genCmpGt :- greater than comparison */
1895 /*-----------------------------------------------------------------*/
1896 static void genCmpGt (iCode *ic, iCode *ifx)
1898 operand *left, *right, *result;
1899 link *letype , *retype;
1903 right= IC_RIGHT(ic);
1904 result = IC_RESULT(ic);
1906 letype = getSpec(operandType(left));
1907 retype =getSpec(operandType(right));
1908 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1909 /* assign the amsops */
1910 aopOp (left,ic,FALSE);
1911 aopOp (right,ic,FALSE);
1912 aopOp (result,ic,TRUE);
1914 genCmp(right, left, result, ifx, sign);
1916 freeAsmop(left,NULL,ic);
1917 freeAsmop(right,NULL,ic);
1918 freeAsmop(result,NULL,ic);
1921 /*-----------------------------------------------------------------*/
1922 /* genCmpLt - less than comparisons */
1923 /*-----------------------------------------------------------------*/
1924 static void genCmpLt (iCode *ic, iCode *ifx)
1926 operand *left, *right, *result;
1927 link *letype , *retype;
1931 right= IC_RIGHT(ic);
1932 result = IC_RESULT(ic);
1934 letype = getSpec(operandType(left));
1935 retype =getSpec(operandType(right));
1936 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
1938 /* assign the amsops */
1939 aopOp (left,ic,FALSE);
1940 aopOp (right,ic,FALSE);
1941 aopOp (result,ic,TRUE);
1943 genCmp(left, right, result, ifx, sign);
1945 freeAsmop(left,NULL,ic);
1946 freeAsmop(right,NULL,ic);
1947 freeAsmop(result,NULL,ic);
1950 /*-----------------------------------------------------------------*/
1951 /* gencjneshort - compare and jump if not equal */
1952 /*-----------------------------------------------------------------*/
1953 static void gencjneshort(operand *left, operand *right, symbol *lbl)
1955 int size = max(AOP_SIZE(left),AOP_SIZE(right));
1957 unsigned long lit = 0L;
1959 /* Swap the left and right if it makes the computation easier */
1960 if (AOP_TYPE(left) == AOP_LIT) {
1966 if(AOP_TYPE(right) == AOP_LIT)
1967 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
1969 /* if the right side is a literal then anything goes */
1970 if (AOP_TYPE(right) == AOP_LIT &&
1971 AOP_TYPE(left) != AOP_DIR ) {
1973 emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
1974 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
1975 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1979 /* if the right side is in a register or in direct space or
1980 if the left is a pointer register & right is not */
1981 else if (AOP_TYPE(right) == AOP_REG ||
1982 AOP_TYPE(right) == AOP_DIR ||
1983 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
1985 MOVA(aopGet(AOP(left),offset,FALSE));
1986 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
1987 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
1989 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
1991 emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
1992 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
1997 /* right is a pointer reg need both a & b */
1998 /* PENDING: is this required? */
2000 char *l = aopGet(AOP(left),offset,FALSE);
2001 MOVA(aopGet(AOP(right),offset,FALSE));
2002 emitcode("cp", "%s", l);
2003 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2009 /*-----------------------------------------------------------------*/
2010 /* gencjne - compare and jump if not equal */
2011 /*-----------------------------------------------------------------*/
2012 static void gencjne(operand *left, operand *right, symbol *lbl)
2014 symbol *tlbl = newiTempLabel(NULL);
2016 gencjneshort(left, right, lbl);
2019 emitcode("ld","a,%s",one);
2020 emitcode("jp", LABEL_STR ,tlbl->key+100);
2021 emitcode("", LABEL_STR ":",lbl->key+100);
2022 emitcode("xor","a,a");
2023 emitcode("", LABEL_STR ":",tlbl->key+100);
2026 /*-----------------------------------------------------------------*/
2027 /* genCmpEq - generates code for equal to */
2028 /*-----------------------------------------------------------------*/
2029 static void genCmpEq (iCode *ic, iCode *ifx)
2031 operand *left, *right, *result;
2033 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2034 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2035 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2037 /* Swap operands if it makes the operation easier. ie if:
2038 1. Left is a literal.
2040 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2041 operand *t = IC_RIGHT(ic);
2042 IC_RIGHT(ic) = IC_LEFT(ic);
2046 if (ifx && !AOP_SIZE(result)){
2048 /* if they are both bit variables */
2049 if (AOP_TYPE(left) == AOP_CRY &&
2050 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2053 tlbl = newiTempLabel(NULL);
2054 gencjneshort(left, right, tlbl);
2055 if ( IC_TRUE(ifx) ) {
2056 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2057 emitcode("", LABEL_STR ":",tlbl->key+100);
2059 /* PENDING: do this better */
2060 symbol *lbl = newiTempLabel(NULL);
2061 emitcode("jp", LABEL_STR ,lbl->key+100);
2062 emitcode("", LABEL_STR ":",tlbl->key+100);
2063 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2064 emitcode("", LABEL_STR ":",lbl->key+100);
2067 /* mark the icode as generated */
2072 /* if they are both bit variables */
2073 if (AOP_TYPE(left) == AOP_CRY &&
2074 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2077 gencjne(left,right,newiTempLabel(NULL));
2078 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2082 genIfxJump(ifx,"a");
2085 /* if the result is used in an arithmetic operation
2086 then put the result in place */
2087 if (AOP_TYPE(result) != AOP_CRY) {
2090 /* leave the result in acc */
2094 freeAsmop(left,NULL,ic);
2095 freeAsmop(right,NULL,ic);
2096 freeAsmop(result,NULL,ic);
2099 /*-----------------------------------------------------------------*/
2100 /* ifxForOp - returns the icode containing the ifx for operand */
2101 /*-----------------------------------------------------------------*/
2102 static iCode *ifxForOp ( operand *op, iCode *ic )
2104 /* if true symbol then needs to be assigned */
2105 if (IS_TRUE_SYMOP(op))
2108 /* if this has register type condition and
2109 the next instruction is ifx with the same operand
2110 and live to of the operand is upto the ifx only then */
2112 ic->next->op == IFX &&
2113 IC_COND(ic->next)->key == op->key &&
2114 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2120 /*-----------------------------------------------------------------*/
2121 /* genAndOp - for && operation */
2122 /*-----------------------------------------------------------------*/
2123 static void genAndOp (iCode *ic)
2125 operand *left,*right, *result;
2128 /* note here that && operations that are in an if statement are
2129 taken away by backPatchLabels only those used in arthmetic
2130 operations remain */
2131 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2132 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2133 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2135 /* if both are bit variables */
2136 if (AOP_TYPE(left) == AOP_CRY &&
2137 AOP_TYPE(right) == AOP_CRY ) {
2140 tlbl = newiTempLabel(NULL);
2142 emitcode("jp","z," LABEL_STR ,tlbl->key+100);
2144 emitcode("", LABEL_STR ":",tlbl->key+100);
2148 freeAsmop(left,NULL,ic);
2149 freeAsmop(right,NULL,ic);
2150 freeAsmop(result,NULL,ic);
2153 /*-----------------------------------------------------------------*/
2154 /* genOrOp - for || operation */
2155 /*-----------------------------------------------------------------*/
2156 static void genOrOp (iCode *ic)
2158 operand *left,*right, *result;
2161 /* note here that || operations that are in an
2162 if statement are taken away by backPatchLabels
2163 only those used in arthmetic operations remain */
2164 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2165 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2166 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2168 /* if both are bit variables */
2169 if (AOP_TYPE(left) == AOP_CRY &&
2170 AOP_TYPE(right) == AOP_CRY ) {
2173 tlbl = newiTempLabel(NULL);
2175 emitcode("jp","nz," LABEL_STR,tlbl->key+100);
2177 emitcode("", LABEL_STR,tlbl->key+100);
2181 freeAsmop(left,NULL,ic);
2182 freeAsmop(right,NULL,ic);
2183 freeAsmop(result,NULL,ic);
2186 /*-----------------------------------------------------------------*/
2187 /* isLiteralBit - test if lit == 2^n */
2188 /*-----------------------------------------------------------------*/
2189 int isLiteralBit(unsigned long lit)
2191 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2192 0x100L,0x200L,0x400L,0x800L,
2193 0x1000L,0x2000L,0x4000L,0x8000L,
2194 0x10000L,0x20000L,0x40000L,0x80000L,
2195 0x100000L,0x200000L,0x400000L,0x800000L,
2196 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2197 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2200 for(idx = 0; idx < 32; idx++)
2206 /*-----------------------------------------------------------------*/
2207 /* genAnd - code for and */
2208 /*-----------------------------------------------------------------*/
2209 static void genAnd (iCode *ic, iCode *ifx)
2211 operand *left, *right, *result;
2213 unsigned long lit = 0L;
2216 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2217 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2218 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2221 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2223 AOP_TYPE(left), AOP_TYPE(right));
2224 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2226 AOP_SIZE(left), AOP_SIZE(right));
2229 /* if left is a literal & right is not then exchange them */
2230 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2231 AOP_NEEDSACC(left)) {
2232 operand *tmp = right ;
2237 /* if result = right then exchange them */
2238 if(sameRegs(AOP(result),AOP(right))){
2239 operand *tmp = right ;
2244 /* if right is bit then exchange them */
2245 if (AOP_TYPE(right) == AOP_CRY &&
2246 AOP_TYPE(left) != AOP_CRY){
2247 operand *tmp = right ;
2251 if(AOP_TYPE(right) == AOP_LIT)
2252 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2254 size = AOP_SIZE(result);
2256 if (AOP_TYPE(left) == AOP_CRY){
2261 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2262 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2263 if((AOP_TYPE(right) == AOP_LIT) &&
2264 (AOP_TYPE(result) == AOP_CRY) &&
2265 (AOP_TYPE(left) != AOP_CRY)) {
2266 int posbit = isLiteralBit(lit);
2270 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2274 emitcode("mov","c,acc.%d",posbit&0x07);
2279 sprintf(buffer, "%d", posbit&0x07);
2280 genIfxJump(ifx, buffer);
2288 symbol *tlbl = newiTempLabel(NULL);
2289 int sizel = AOP_SIZE(left);
2292 emitcode("setb","c");
2295 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2296 MOVA( aopGet(AOP(left),offset,FALSE));
2298 if((posbit = isLiteralBit(bytelit)) != 0) {
2300 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2303 if(bytelit != 0x0FFL)
2304 emitcode("and","a,%s",
2305 aopGet(AOP(right),offset,FALSE));
2306 emitcode("jr","nz, %05d$",tlbl->key+100);
2311 // bit = left & literal
2313 emitcode("clr","c");
2314 emitcode("","%05d$:",tlbl->key+100);
2316 // if(left & literal)
2320 jmpTrueOrFalse(ifx, tlbl);
2331 /* if left is same as result */
2332 if(sameRegs(AOP(result),AOP(left))){
2333 for(;size--; offset++) {
2334 if(AOP_TYPE(right) == AOP_LIT){
2335 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2339 aopPut(AOP(result),zero,offset);
2341 MOVA(aopGet(AOP(left),offset,FALSE));
2342 emitcode("and","a,%s",
2343 aopGet(AOP(right),offset,FALSE));
2344 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2349 if (AOP_TYPE(left) == AOP_ACC) {
2353 MOVA(aopGet(AOP(right),offset,FALSE));
2354 emitcode("and","%s,a",
2355 aopGet(AOP(left),offset,FALSE));
2360 // left & result in different registers
2361 if(AOP_TYPE(result) == AOP_CRY){
2364 for(;(size--);offset++) {
2366 // result = left & right
2367 if(AOP_TYPE(right) == AOP_LIT){
2368 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2370 aopGet(AOP(left),offset,FALSE),
2373 } else if(bytelit == 0){
2374 aopPut(AOP(result),zero,offset);
2378 // faster than result <- left, anl result,right
2379 // and better if result is SFR
2380 if (AOP_TYPE(left) == AOP_ACC)
2381 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2383 MOVA(aopGet(AOP(right),offset,FALSE));
2384 emitcode("and","a,%s",
2385 aopGet(AOP(left),offset,FALSE));
2387 aopPut(AOP(result),"a",offset);
2394 freeAsmop(left,NULL,ic);
2395 freeAsmop(right,NULL,ic);
2396 freeAsmop(result,NULL,ic);
2399 /*-----------------------------------------------------------------*/
2400 /* genOr - code for or */
2401 /*-----------------------------------------------------------------*/
2402 static void genOr (iCode *ic, iCode *ifx)
2404 operand *left, *right, *result;
2406 unsigned long lit = 0L;
2408 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2409 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2410 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2413 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2415 AOP_TYPE(left), AOP_TYPE(right));
2416 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2418 AOP_SIZE(left), AOP_SIZE(right));
2421 /* if left is a literal & right is not then exchange them */
2422 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2423 AOP_NEEDSACC(left)) {
2424 operand *tmp = right ;
2429 /* if result = right then exchange them */
2430 if(sameRegs(AOP(result),AOP(right))){
2431 operand *tmp = right ;
2436 /* if right is bit then exchange them */
2437 if (AOP_TYPE(right) == AOP_CRY &&
2438 AOP_TYPE(left) != AOP_CRY){
2439 operand *tmp = right ;
2443 if(AOP_TYPE(right) == AOP_LIT)
2444 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2446 size = AOP_SIZE(result);
2448 if (AOP_TYPE(left) == AOP_CRY){
2453 if((AOP_TYPE(right) == AOP_LIT) &&
2454 (AOP_TYPE(result) == AOP_CRY) &&
2455 (AOP_TYPE(left) != AOP_CRY)){
2460 /* if left is same as result */
2461 if(sameRegs(AOP(result),AOP(left))){
2462 for(;size--; offset++) {
2463 if(AOP_TYPE(right) == AOP_LIT){
2464 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2467 emitcode("or","%s,%s; 5",
2468 aopGet(AOP(left),offset,FALSE),
2469 aopGet(AOP(right),offset,FALSE));
2471 if (AOP_TYPE(left) == AOP_ACC)
2472 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2474 MOVA(aopGet(AOP(right),offset,FALSE));
2475 emitcode("or","a,%s ; 7",
2476 aopGet(AOP(left),offset,FALSE));
2477 aopPut(AOP(result),"a ; 8",0);
2482 // left & result in different registers
2483 if(AOP_TYPE(result) == AOP_CRY){
2485 } else for(;(size--);offset++){
2487 // result = left & right
2488 if(AOP_TYPE(right) == AOP_LIT){
2489 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2491 aopGet(AOP(left),offset,FALSE),
2496 // faster than result <- left, anl result,right
2497 // and better if result is SFR
2498 if (AOP_TYPE(left) == AOP_ACC)
2499 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2501 MOVA(aopGet(AOP(right),offset,FALSE));
2502 emitcode("or","a,%s",
2503 aopGet(AOP(left),offset,FALSE));
2505 aopPut(AOP(result),"a",offset);
2506 /* PENDING: something weird is going on here. Add exception. */
2507 if (AOP_TYPE(result) == AOP_ACC)
2513 freeAsmop(left,NULL,ic);
2514 freeAsmop(right,NULL,ic);
2515 freeAsmop(result,NULL,ic);
2518 /*-----------------------------------------------------------------*/
2519 /* genXor - code for xclusive or */
2520 /*-----------------------------------------------------------------*/
2521 static void genXor (iCode *ic, iCode *ifx)
2523 operand *left, *right, *result;
2525 unsigned long lit = 0L;
2527 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2528 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2529 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2531 /* if left is a literal & right is not then exchange them */
2532 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2533 AOP_NEEDSACC(left)) {
2534 operand *tmp = right ;
2539 /* if result = right then exchange them */
2540 if(sameRegs(AOP(result),AOP(right))){
2541 operand *tmp = right ;
2546 /* if right is bit then exchange them */
2547 if (AOP_TYPE(right) == AOP_CRY &&
2548 AOP_TYPE(left) != AOP_CRY){
2549 operand *tmp = right ;
2553 if(AOP_TYPE(right) == AOP_LIT)
2554 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2556 size = AOP_SIZE(result);
2558 if (AOP_TYPE(left) == AOP_CRY){
2563 if((AOP_TYPE(right) == AOP_LIT) &&
2564 (AOP_TYPE(result) == AOP_CRY) &&
2565 (AOP_TYPE(left) != AOP_CRY)){
2570 /* if left is same as result */
2571 if(sameRegs(AOP(result),AOP(left))){
2572 for(;size--; offset++) {
2573 if(AOP_TYPE(right) == AOP_LIT){
2574 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2577 MOVA(aopGet(AOP(right),offset,FALSE));
2578 emitcode("xor","a,%s",
2579 aopGet(AOP(left),offset,FALSE));
2580 aopPut(AOP(result),"a",0);
2583 if (AOP_TYPE(left) == AOP_ACC)
2584 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2586 MOVA(aopGet(AOP(right),offset,FALSE));
2587 emitcode("xor","a,%s",
2588 aopGet(AOP(left),offset,FALSE));
2589 aopPut(AOP(result),"a",0);
2594 // left & result in different registers
2595 if(AOP_TYPE(result) == AOP_CRY){
2597 } else for(;(size--);offset++){
2599 // result = left & right
2600 if(AOP_TYPE(right) == AOP_LIT){
2601 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2603 aopGet(AOP(left),offset,FALSE),
2608 // faster than result <- left, anl result,right
2609 // and better if result is SFR
2610 if (AOP_TYPE(left) == AOP_ACC)
2611 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2613 MOVA(aopGet(AOP(right),offset,FALSE));
2614 emitcode("xor","a,%s",
2615 aopGet(AOP(left),offset,FALSE));
2616 aopPut(AOP(result),"a",0);
2618 aopPut(AOP(result),"a",offset);
2623 freeAsmop(left,NULL,ic);
2624 freeAsmop(right,NULL,ic);
2625 freeAsmop(result,NULL,ic);
2628 /*-----------------------------------------------------------------*/
2629 /* genInline - write the inline code out */
2630 /*-----------------------------------------------------------------*/
2631 static void genInline (iCode *ic)
2633 char buffer[MAX_INLINEASM];
2637 inLine += (!options.asmpeep);
2638 strcpy(buffer,IC_INLINE(ic));
2640 /* emit each line as a code */
2659 /* emitcode("",buffer); */
2660 inLine -= (!options.asmpeep);
2663 /*-----------------------------------------------------------------*/
2664 /* genRRC - rotate right with carry */
2665 /*-----------------------------------------------------------------*/
2666 static void genRRC (iCode *ic)
2671 /*-----------------------------------------------------------------*/
2672 /* genRLC - generate code for rotate left with carry */
2673 /*-----------------------------------------------------------------*/
2674 static void genRLC (iCode *ic)
2679 /*-----------------------------------------------------------------*/
2680 /* shiftR2Left2Result - shift right two bytes from left to result */
2681 /*-----------------------------------------------------------------*/
2682 static void shiftR2Left2Result (operand *left, int offl,
2683 operand *result, int offr,
2684 int shCount, int sign)
2686 if(sameRegs(AOP(result), AOP(left)) &&
2687 ((offl + MSB16) == offr)){
2690 movLeft2Result(left, offl, result, offr, 0);
2691 movLeft2Result(left, offl+1, result, offr+1, 0);
2698 /* if (AOP(result)->type == AOP_REG) {*/
2701 symbol *tlbl , *tlbl1;
2704 /* Left is already in result - so now do the shift */
2706 emitcode("ld","a,#%u+1", shCount);
2707 tlbl = newiTempLabel(NULL);
2708 tlbl1 = newiTempLabel(NULL);
2709 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2710 emitcode("", LABEL_STR ":",tlbl->key+100);
2713 emitcode("or", "a,a");
2716 l = aopGet(AOP(result), --offset, FALSE);
2717 emitcode("rr","%s", l);
2720 emitcode("", LABEL_STR ":",tlbl1->key+100);
2721 emitcode("dec", "a");
2722 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2727 /*-----------------------------------------------------------------*/
2728 /* shiftL2Left2Result - shift left two bytes from left to result */
2729 /*-----------------------------------------------------------------*/
2730 static void shiftL2Left2Result (operand *left, int offl,
2731 operand *result, int offr, int shCount)
2733 if(sameRegs(AOP(result), AOP(left)) &&
2734 ((offl + MSB16) == offr)){
2737 /* Copy left into result */
2738 movLeft2Result(left, offl, result, offr, 0);
2739 movLeft2Result(left, offl+1, result, offr+1, 0);
2741 /* PENDING: for now just see if it'll work. */
2742 /*if (AOP(result)->type == AOP_REG) { */
2746 symbol *tlbl , *tlbl1;
2749 /* Left is already in result - so now do the shift */
2751 emitcode("ld","a,#%u+1", shCount);
2752 tlbl = newiTempLabel(NULL);
2753 tlbl1 = newiTempLabel(NULL);
2754 emitcode("jp", LABEL_STR ,tlbl1->key+100);
2755 emitcode("", LABEL_STR ":",tlbl->key+100);
2758 emitcode("or", "a,a");
2760 l = aopGet(AOP(result),offset++,FALSE);
2761 emitcode("rl","%s", l);
2764 emitcode("", LABEL_STR ":",tlbl1->key+100);
2765 emitcode("dec", "a");
2766 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
2771 /*-----------------------------------------------------------------*/
2772 /* AccRol - rotate left accumulator by known count */
2773 /*-----------------------------------------------------------------*/
2774 static void AccRol (int shCount)
2776 shCount &= 0x0007; // shCount : 0..7
2813 /*-----------------------------------------------------------------*/
2814 /* AccLsh - left shift accumulator by known count */
2815 /*-----------------------------------------------------------------*/
2816 static void AccLsh (int shCount)
2820 emitcode("add","a,a");
2823 emitcode("add","a,a");
2824 emitcode("add","a,a");
2826 /* rotate left accumulator */
2828 /* and kill the lower order bits */
2829 emitcode("and","a,#0x%02x", SLMask[shCount]);
2834 /*-----------------------------------------------------------------*/
2835 /* shiftL1Left2Result - shift left one byte from left to result */
2836 /*-----------------------------------------------------------------*/
2837 static void shiftL1Left2Result (operand *left, int offl,
2838 operand *result, int offr, int shCount)
2841 l = aopGet(AOP(left),offl,FALSE);
2843 /* shift left accumulator */
2845 aopPut(AOP(result),"a",offr);
2849 /*-----------------------------------------------------------------*/
2850 /* genlshTwo - left shift two bytes by known amount != 0 */
2851 /*-----------------------------------------------------------------*/
2852 static void genlshTwo (operand *result,operand *left, int shCount)
2854 int size = AOP_SIZE(result);
2858 /* if shCount >= 8 */
2864 movLeft2Result(left, LSB, result, MSB16, 0);
2865 aopPut(AOP(result),zero, 0);
2866 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
2869 movLeft2Result(left, LSB, result, MSB16, 0);
2870 aopPut(AOP(result),zero, 0);
2873 aopPut(AOP(result),zero,LSB);
2875 /* 1 <= shCount <= 7 */
2881 shiftL2Left2Result(left, LSB, result, LSB, shCount);
2886 /*-----------------------------------------------------------------*/
2887 /* genlshOne - left shift a one byte quantity by known count */
2888 /*-----------------------------------------------------------------*/
2889 static void genlshOne (operand *result, operand *left, int shCount)
2891 shiftL1Left2Result(left, LSB, result, LSB, shCount);
2894 /*-----------------------------------------------------------------*/
2895 /* genLeftShiftLiteral - left shifting by known count */
2896 /*-----------------------------------------------------------------*/
2897 static void genLeftShiftLiteral (operand *left,
2902 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
2905 freeAsmop(right,NULL,ic);
2907 aopOp(left,ic,FALSE);
2908 aopOp(result,ic,FALSE);
2910 size = getSize(operandType(result));
2913 emitcode("; shift left ","result %d, left %d",size,
2917 /* I suppose that the left size >= result size */
2922 else if(shCount >= (size * 8))
2924 aopPut(AOP(result),zero,size);
2928 genlshOne (result,left,shCount);
2931 genlshTwo (result,left,shCount);
2940 freeAsmop(left,NULL,ic);
2941 freeAsmop(result,NULL,ic);
2944 /*-----------------------------------------------------------------*/
2945 /* genLeftShift - generates code for left shifting */
2946 /*-----------------------------------------------------------------*/
2947 static void genLeftShift (iCode *ic)
2951 symbol *tlbl , *tlbl1;
2952 operand *left,*right, *result;
2954 right = IC_RIGHT(ic);
2956 result = IC_RESULT(ic);
2958 aopOp(right,ic,FALSE);
2960 /* if the shift count is known then do it
2961 as efficiently as possible */
2962 if (AOP_TYPE(right) == AOP_LIT) {
2963 genLeftShiftLiteral (left,right,result,ic);
2967 /* shift count is unknown then we have to form a loop get the loop
2968 count in B : Note: we take only the lower order byte since
2969 shifting more that 32 bits make no sense anyway, ( the largest
2970 size of an object can be only 32 bits ) */
2971 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
2972 emitcode("inc","a");
2973 freeAsmop (right,NULL,ic);
2974 aopOp(left,ic,FALSE);
2975 aopOp(result,ic,FALSE);
2977 /* now move the left to the result if they are not the
2980 if (!sameRegs(AOP(left),AOP(result))) {
2982 size = AOP_SIZE(result);
2985 l = aopGet(AOP(left),offset,FALSE);
2986 aopPut(AOP(result),l,offset);
2991 size = AOP_SIZE(result);
2994 l = aopGet(AOP(left),offset,FALSE);
2995 aopPut(AOP(result),l,offset);
3001 tlbl = newiTempLabel(NULL);
3002 size = AOP_SIZE(result);
3004 tlbl1 = newiTempLabel(NULL);
3006 emitcode("jp", LABEL_STR ,tlbl1->key+100);
3007 emitcode("", LABEL_STR ":",tlbl->key+100);
3008 l = aopGet(AOP(result),offset,FALSE);
3009 emitcode("or", "a,a");
3011 l = aopGet(AOP(result),offset++,FALSE);
3012 emitcode("rl","%s", l);
3014 emitcode("", LABEL_STR ":",tlbl1->key+100);
3015 emitcode("dec", "a");
3016 emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
3018 freeAsmop(left,NULL,ic);
3019 freeAsmop(result,NULL,ic);
3022 /* genlshTwo - left shift two bytes by known amount != 0 */
3023 /*-----------------------------------------------------------------*/
3024 static void genrshOne (operand *result,operand *left, int shCount)
3027 int size = AOP_SIZE(result);
3033 l = aopGet(AOP(left),0,FALSE);
3034 if (AOP(result)->type == AOP_REG) {
3035 aopPut(AOP(result), l, 0);
3036 l = aopGet(AOP(result), 0, FALSE);
3038 emitcode("srl", "%s", l);
3043 emitcode("srl", "a");
3045 aopPut(AOP(result),"a",0);
3049 /*-----------------------------------------------------------------*/
3050 /* AccRsh - right shift accumulator by known count */
3051 /*-----------------------------------------------------------------*/
3052 static void AccRsh (int shCount)
3059 /* rotate right accumulator */
3060 AccRol(8 - shCount);
3061 /* and kill the higher order bits */
3062 emitcode("and","a,#0x%02x", SRMask[shCount]);
3067 /*-----------------------------------------------------------------*/
3068 /* shiftR1Left2Result - shift right one byte from left to result */
3069 /*-----------------------------------------------------------------*/
3070 static void shiftR1Left2Result (operand *left, int offl,
3071 operand *result, int offr,
3072 int shCount, int sign)
3074 MOVA(aopGet(AOP(left),offl,FALSE));
3081 aopPut(AOP(result),"a",offr);
3084 /*-----------------------------------------------------------------*/
3085 /* genrshTwo - right shift two bytes by known amount != 0 */
3086 /*-----------------------------------------------------------------*/
3087 static void genrshTwo (operand *result,operand *left,
3088 int shCount, int sign)
3090 /* if shCount >= 8 */
3095 shiftR1Left2Result(left, MSB16, result, LSB,
3099 movLeft2Result(left, MSB16, result, LSB, sign);
3100 aopPut(AOP(result),zero,1);
3103 /* 1 <= shCount <= 7 */
3105 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3109 /*-----------------------------------------------------------------*/
3110 /* genRightShiftLiteral - left shifting by known count */
3111 /*-----------------------------------------------------------------*/
3112 static void genRightShiftLiteral (operand *left,
3117 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3120 freeAsmop(right,NULL,ic);
3122 aopOp(left,ic,FALSE);
3123 aopOp(result,ic,FALSE);
3125 size = getSize(operandType(result));
3127 emitcode("; shift right ","result %d, left %d",size,
3130 /* I suppose that the left size >= result size */
3135 else if(shCount >= (size * 8))
3137 aopPut(AOP(result),zero,size);
3141 genrshOne(result, left, shCount);
3144 /* PENDING: sign support */
3145 genrshTwo(result, left, shCount, FALSE);
3154 freeAsmop(left,NULL,ic);
3155 freeAsmop(result,NULL,ic);
3158 /*-----------------------------------------------------------------*/
3159 /* genRightShift - generate code for right shifting */
3160 /*-----------------------------------------------------------------*/
3161 static void genRightShift (iCode *ic)
3163 operand *left,*right, *result;
3165 right = IC_RIGHT(ic);
3167 result = IC_RESULT(ic);
3169 aopOp(right,ic,FALSE);
3171 /* if the shift count is known then do it
3172 as efficiently as possible */
3173 if (AOP_TYPE(right) == AOP_LIT) {
3174 genRightShiftLiteral (left,right,result,ic);
3182 /*-----------------------------------------------------------------*/
3183 /* genGenPointerGet - gget value from generic pointer space */
3184 /*-----------------------------------------------------------------*/
3185 static void genGenPointerGet (operand *left,
3186 operand *result, iCode *ic)
3189 link *retype = getSpec(operandType(result));
3191 aopOp(left,ic,FALSE);
3192 aopOp(result,ic,FALSE);
3194 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3196 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3197 aopPut(AOP(result),"a", 0);
3198 freeAsmop(left,NULL,ic);
3202 /* For now we always load into IY */
3203 /* if this is remateriazable */
3204 if (AOP_TYPE(left) == AOP_IMMD)
3205 emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
3206 else { /* we need to get it byte by byte */
3208 emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
3209 emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
3211 /* so iy now contains the address */
3212 freeAsmop(left,NULL,ic);
3214 /* if bit then unpack */
3215 if (IS_BITVAR(retype)) {
3219 size = AOP_SIZE(result);
3223 /* PENDING: make this better */
3224 if (AOP(result)->type == AOP_REG) {
3225 aopPut(AOP(result),"(hl)",offset++);
3228 emitcode("ld", "a,(hl)", offset);
3229 aopPut(AOP(result),"a",offset++);
3232 emitcode("inc", "hl");
3238 freeAsmop(result,NULL,ic);
3241 /*-----------------------------------------------------------------*/
3242 /* genPointerGet - generate code for pointer get */
3243 /*-----------------------------------------------------------------*/
3244 static void genPointerGet (iCode *ic)
3246 operand *left, *result ;
3250 result = IC_RESULT(ic) ;
3252 /* depending on the type of pointer we need to
3253 move it to the correct pointer register */
3254 type = operandType(left);
3255 etype = getSpec(type);
3257 genGenPointerGet (left,result,ic);
3260 bool isRegOrLit(asmop *aop)
3262 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3267 /*-----------------------------------------------------------------*/
3268 /* genGenPointerSet - stores the value into a pointer location */
3269 /*-----------------------------------------------------------------*/
3270 static void genGenPointerSet (operand *right,
3271 operand *result, iCode *ic)
3274 link *retype = getSpec(operandType(right));
3276 aopOp(result,ic,FALSE);
3277 aopOp(right,ic,FALSE);
3279 /* Handle the exceptions first */
3280 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3282 char *l = aopGet(AOP(right), 0, FALSE);
3284 emitcode("ld", "(%s),a", getPairName(AOP(result)));
3285 freeAsmop(result,NULL,ic);
3289 /* if the operand is already in dptr
3290 then we do nothing else we move the value to dptr */
3291 if (AOP_TYPE(result) != AOP_STR) {
3292 /* if this is remateriazable */
3293 if (AOP_TYPE(result) == AOP_IMMD) {
3294 emitcode("", "; Error 2");
3295 emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
3297 else { /* we need to get it byte by byte */
3298 /* PENDING: do this better */
3299 emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
3300 emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
3303 /* so hl know contains the address */
3304 freeAsmop(result,NULL,ic);
3306 /* if bit then unpack */
3307 if (IS_BITVAR(retype)) {
3311 size = AOP_SIZE(right);
3315 char *l = aopGet(AOP(right),offset,FALSE);
3317 if (isRegOrLit(AOP(right))) {
3318 emitcode("ld", "(hl),%s", l);
3322 emitcode("ld", "(hl),a", offset);
3325 emitcode("inc", "hl");
3331 freeAsmop(right,NULL,ic);
3334 /*-----------------------------------------------------------------*/
3335 /* genPointerSet - stores the value into a pointer location */
3336 /*-----------------------------------------------------------------*/
3337 static void genPointerSet (iCode *ic)
3339 operand *right, *result ;
3342 right = IC_RIGHT(ic);
3343 result = IC_RESULT(ic) ;
3345 /* depending on the type of pointer we need to
3346 move it to the correct pointer register */
3347 type = operandType(result);
3348 etype = getSpec(type);
3350 genGenPointerSet (right,result,ic);
3353 /*-----------------------------------------------------------------*/
3354 /* genIfx - generate code for Ifx statement */
3355 /*-----------------------------------------------------------------*/
3356 static void genIfx (iCode *ic, iCode *popIc)
3358 operand *cond = IC_COND(ic);
3361 aopOp(cond,ic,FALSE);
3363 /* get the value into acc */
3364 if (AOP_TYPE(cond) != AOP_CRY)
3368 /* the result is now in the accumulator */
3369 freeAsmop(cond,NULL,ic);
3371 /* if there was something to be popped then do it */
3375 /* if the condition is a bit variable */
3376 if (isbit && IS_ITEMP(cond) &&
3378 genIfxJump(ic,SPIL_LOC(cond)->rname);
3380 if (isbit && !IS_ITEMP(cond))
3381 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3388 /*-----------------------------------------------------------------*/
3389 /* genAddrOf - generates code for address of */
3390 /*-----------------------------------------------------------------*/
3391 static void genAddrOf (iCode *ic)
3393 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3395 aopOp(IC_RESULT(ic),ic,FALSE);
3397 /* if the operand is on the stack then we
3398 need to get the stack offset of this
3401 /* if it has an offset then we need to compute it */
3402 emitcode("push", "de");
3403 emitcode("push", "ix");
3404 emitcode("pop", "hl");
3405 emitcode("ld", "de,#%d", sym->stack);
3406 emitcode("add", "hl,de");
3407 emitcode("pop", "de");
3410 emitcode("ld", "hl,#%s", sym->rname);
3412 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3413 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3415 freeAsmop(IC_RESULT(ic),NULL,ic);
3418 /*-----------------------------------------------------------------*/
3419 /* genAssign - generate code for assignment */
3420 /*-----------------------------------------------------------------*/
3421 static void genAssign (iCode *ic)
3423 operand *result, *right;
3425 unsigned long lit = 0L;
3427 result = IC_RESULT(ic);
3428 right = IC_RIGHT(ic) ;
3431 /* Dont bother assigning if they are the same */
3432 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3433 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3438 aopOp(right,ic,FALSE);
3439 aopOp(result,ic,TRUE);
3441 /* if they are the same registers */
3442 if (sameRegs(AOP(right),AOP(result))) {
3443 emitcode("", "; (registers are the same)");
3447 /* if the result is a bit */
3448 if (AOP_TYPE(result) == AOP_CRY) {
3453 size = AOP_SIZE(result);
3456 if(AOP_TYPE(right) == AOP_LIT)
3457 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3459 (AOP_TYPE(result) != AOP_REG) &&
3460 (AOP_TYPE(right) == AOP_LIT) &&
3461 !IS_FLOAT(operandType(right)) &&
3463 bool fXored = FALSE;
3465 /* Work from the top down.
3466 Done this way so that we can use the cached copy of 0
3467 in A for a fast clear */
3469 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3470 if (!fXored && size>1) {
3471 emitcode("xor", "a,a");
3475 aopPut(AOP(result),"a",offset);
3478 aopPut(AOP(result), "#0", offset);
3483 aopGet(AOP(right),offset,FALSE),
3490 aopGet(AOP(right),offset,FALSE),
3497 freeAsmop(right,NULL,ic);
3498 freeAsmop(result,NULL,ic);
3501 /*-----------------------------------------------------------------*/
3502 /* genJumpTab - genrates code for jump table */
3503 /*-----------------------------------------------------------------*/
3504 static void genJumpTab (iCode *ic)
3509 aopOp(IC_JTCOND(ic),ic,FALSE);
3510 /* get the condition into accumulator */
3511 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3513 emitcode("push", "de");
3514 emitcode("ld", "e,%s", l);
3515 emitcode("ld", "d,#0");
3516 jtab = newiTempLabel(NULL);
3517 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3518 emitcode("add", "hl,de");
3519 emitcode("add", "hl,de");
3520 freeAsmop(IC_JTCOND(ic),NULL,ic);
3521 emitcode("pop", "de");
3522 emitcode("jp", "(hl)");
3523 emitcode("","%05d$:",jtab->key+100);
3524 /* now generate the jump labels */
3525 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3526 jtab = setNextItem(IC_JTLABELS(ic)))
3527 emitcode("jp", LABEL_STR, jtab->key+100);
3530 /*-----------------------------------------------------------------*/
3531 /* genCast - gen code for casting */
3532 /*-----------------------------------------------------------------*/
3533 static void genCast (iCode *ic)
3535 operand *result = IC_RESULT(ic);
3536 link *ctype = operandType(IC_LEFT(ic));
3537 operand *right = IC_RIGHT(ic);
3540 /* if they are equivalent then do nothing */
3541 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3544 aopOp(right,ic,FALSE) ;
3545 aopOp(result,ic,FALSE);
3547 /* if the result is a bit */
3548 if (AOP_TYPE(result) == AOP_CRY) {
3552 /* if they are the same size : or less */
3553 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3555 /* if they are in the same place */
3556 if (sameRegs(AOP(right),AOP(result)))
3559 /* if they in different places then copy */
3560 size = AOP_SIZE(result);
3564 aopGet(AOP(right),offset,FALSE),
3571 /* if the result is of type pointer */
3572 if (IS_PTR(ctype)) {
3576 /* so we now know that the size of destination is greater
3577 than the size of the source */
3578 /* we move to result for the size of source */
3579 size = AOP_SIZE(right);
3583 aopGet(AOP(right),offset,FALSE),
3588 /* now depending on the sign of the destination */
3589 size = AOP_SIZE(result) - AOP_SIZE(right);
3590 /* Unsigned or not an integral type - right fill with zeros */
3591 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3593 aopPut(AOP(result),zero,offset++);
3595 /* we need to extend the sign :{ */
3596 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3599 emitcode("", "; genCast: sign extend untested.");
3600 emitcode("rla", "");
3601 emitcode("sbc", "a,a");
3603 aopPut(AOP(result),"a",offset++);
3607 freeAsmop(right, NULL, ic);
3608 freeAsmop(result, NULL, ic);
3611 /*-----------------------------------------------------------------*/
3612 /* genReceive - generate code for a receive iCode */
3613 /*-----------------------------------------------------------------*/
3614 static void genReceive (iCode *ic)
3616 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3617 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3618 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3622 aopOp(IC_RESULT(ic),ic,FALSE);
3624 assignResultValue(IC_RESULT(ic));
3627 freeAsmop(IC_RESULT(ic),NULL,ic);
3630 /*-----------------------------------------------------------------*/
3631 /* genZ80Code - generate code for Z80 based controllers */
3632 /*-----------------------------------------------------------------*/
3633 void genZ80Code (iCode *lic)
3638 lineHead = lineCurr = NULL;
3640 /* if debug information required */
3641 if (options.debug && currFunc) {
3642 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
3644 if (IS_STATIC(currFunc->etype))
3645 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
3647 emitcode("","G$%s$0$0 ==.",currFunc->name);
3650 /* stack pointer name */
3654 for (ic = lic ; ic ; ic = ic->next ) {
3656 if ( cln != ic->lineno ) {
3657 if ( options.debug ) {
3659 emitcode("","C$%s$%d$%d$%d ==.",
3660 ic->filename,ic->lineno,
3661 ic->level,ic->block);
3664 emitcode(";","%s %d",ic->filename,ic->lineno);
3667 /* if the result is marked as
3668 spilt and rematerializable or code for
3669 this has already been generated then
3671 if (resultRemat(ic) || ic->generated )
3674 /* depending on the operation */
3677 emitcode("", "; genNot");
3682 emitcode("", "; genCpl");
3687 emitcode("", "; genUminus");
3692 emitcode("", "; genIpush");
3697 /* IPOP happens only when trying to restore a
3698 spilt live range, if there is an ifx statement
3699 following this pop then the if statement might
3700 be using some of the registers being popped which
3701 would destory the contents of the register so
3702 we need to check for this condition and handle it */
3704 ic->next->op == IFX &&
3705 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
3706 emitcode("", "; genIfx");
3707 genIfx (ic->next,ic);
3710 emitcode("", "; genIpop");
3716 emitcode("", "; genCall");
3721 emitcode("", "; genPcall");
3726 emitcode("", "; genFunction");
3731 emitcode("", "; genEndFunction");
3732 genEndFunction (ic);
3736 emitcode("", "; genRet");
3741 emitcode("", "; genLabel");
3746 emitcode("", "; genGoto");
3751 emitcode("", "; genPlus");
3756 emitcode("", "; genMinus");
3761 emitcode("", "; genMult");
3766 emitcode("", "; genDiv");
3771 emitcode("", "; genMod");
3776 emitcode("", "; genCmpGt");
3777 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
3781 emitcode("", "; genCmpLt");
3782 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
3789 /* note these two are xlated by algebraic equivalence
3790 during parsing SDCC.y */
3791 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
3792 "got '>=' or '<=' shouldn't have come here");
3796 emitcode("", "; genCmpEq");
3797 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
3801 emitcode("", "; genAndOp");
3806 emitcode("", "; genOrOp");
3811 emitcode("", "; genXor");
3812 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
3816 emitcode("", "; genOr");
3817 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
3821 emitcode("", "; genAnd");
3822 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
3826 emitcode("", "; genInline");
3831 emitcode("", "; genRRC");
3836 emitcode("", "; genRLC");
3841 emitcode("", "; genHBIT");
3845 emitcode("", "; genLeftShift");
3850 emitcode("", "; genRightShift");
3854 case GET_VALUE_AT_ADDRESS:
3855 emitcode("", "; genPointerGet");
3861 if (POINTER_SET(ic)) {
3862 emitcode("", "; genAssign (pointer)");
3866 emitcode("", "; genAssign");
3872 emitcode("", "; genIfx");
3877 emitcode("", "; genAddrOf");
3882 emitcode("", "; genJumpTab");
3887 emitcode("", "; genCast");
3892 emitcode("", "; genReceive");
3897 emitcode("", "; addSet");
3898 addSet(&sendSet,ic);
3903 /* piCode(ic,stdout); */
3909 /* now we are ready to call the
3910 peep hole optimizer */
3911 if (!options.nopeep)
3912 peepHole (&lineHead);
3914 /* now do the actual printing */
3915 printLine (lineHead,codeOutFile);