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
17 Better reg packing, first peephole 20038 163 1873
18 With assign packing 19281 165 1849
20 Michael Hope <michaelh@earthling.net> 2000
21 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
22 and - Jean-Louis VERN.jlvern@writeme.com (1999)
24 This program is free software; you can redistribute it and/or modify it
25 under the terms of the GNU General Public License as published by the
26 Free Software Foundation; either version 2, or (at your option) any
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
34 You should have received a copy of the GNU General Public License
35 along with this program; if not, write to the Free Software
36 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 In other words, you are welcome to use, share and improve this program.
39 You are forbidden to forbid anyone else to use, share and improve
40 what you give them. Help stamp out software-hoarding!
42 -------------------------------------------------------------------------*/
49 #ifdef HAVE_SYS_ISA_DEFS_H
50 #include <sys/isa_defs.h>
54 #include "SDCCpeeph.h"
58 /* this is the down and dirty file with all kinds of kludgy & hacky
59 stuff. This is what it is all about CODE GENERATION for a specific MCU.
60 Some of the routines may be reusable, will have to see */
62 static char *zero = "#0x00";
63 static char *one = "#0x01";
65 static char *_z80_return[] = {"l", "h", "e", "d" };
66 static char *_gbz80_return[] = { "e", "d", "l", "h" };
67 static char **_fReturn;
70 static char *accUse[] = {"a" };
76 extern int ptrRegReq ;
78 extern FILE *codeOutFile;
80 const char *_shortJP = "jp";
94 } _pairs[NUM_PAIRS] = {
101 #define RESULTONSTACK(x) \
102 (IC_RESULT(x) && IC_RESULT(x)->aop && \
103 IC_RESULT(x)->aop->type == AOP_STK )
105 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
106 #define CLRC emitcode("xor","a,a");
108 #define LABEL_STR "%05d$"
110 lineNode *lineHead = NULL;
111 lineNode *lineCurr = NULL;
113 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
114 0xE0, 0xC0, 0x80, 0x00};
115 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
116 0x07, 0x03, 0x01, 0x00};
118 static int _lastStack = 0;
119 static int _pushed = 0;
120 static int _spoffset;
121 static int _lastHLOff = 0;
122 static asmop *_lastHL;
144 static char *aopGet(asmop *aop, int offset, bool bit16);
146 /*-----------------------------------------------------------------*/
147 /* emitcode - writes the code into a file : for now it is simple */
148 /*-----------------------------------------------------------------*/
149 void emitcode (const char *inst, const char *fmt, ...)
152 char lb[MAX_INLINEASM];
158 sprintf(lb,"%s\t",inst);
159 vsprintf(lb+(strlen(lb)),fmt,ap);
163 while (isspace(*lbp)) lbp++;
166 lineCurr = (lineCurr ?
167 connectLine(lineCurr,newLineNode(lb)) :
168 (lineHead = newLineNode(lb)));
169 lineCurr->isInline = inLine;
170 lineCurr->isDebug = debugLine;
174 const char *getPairName(asmop *aop)
176 if (aop->type == AOP_REG) {
177 switch (aop->aopu.aop_reg[0]->rIdx) {
189 else if (aop->type == AOP_STR) {
190 switch (*aop->aopu.aop_str[0]) {
206 static int getPairId(asmop *aop)
208 if (aop->size == 2) {
209 if (aop->type == AOP_REG) {
210 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
213 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
216 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
220 if (aop->type == AOP_STR) {
221 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
224 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
227 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
235 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
236 bool isPair(asmop *aop)
238 return (getPairId(aop) != PAIR_INVALID);
241 /** Push a register pair onto the stack */
242 void genPairPush(asmop *aop)
244 emitcode("push", "%s", getPairName(aop));
247 static char *_strdup(const char *s)
250 ALLOC_ATOMIC(ret, strlen(s)+1);
256 /*-----------------------------------------------------------------*/
257 /* newAsmop - creates a new asmOp */
258 /*-----------------------------------------------------------------*/
259 static asmop *newAsmop (short type)
263 ALLOC(aop,sizeof(asmop));
268 /*-----------------------------------------------------------------*/
269 /* aopForSym - for a true symbol */
270 /*-----------------------------------------------------------------*/
271 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
274 memmap *space= SPEC_OCLS(sym->etype);
276 /* if already has one */
280 /* Assign depending on the storage class */
281 if (sym->onStack || sym->iaccess) {
282 sym->aop = aop = newAsmop(AOP_STK);
283 aop->size = getSize(sym->type);
285 aop->aopu.aop_stk = sym->stack;
289 /* special case for a function */
290 if (IS_FUNC(sym->type)) {
291 sym->aop = aop = newAsmop(AOP_IMMD);
292 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
293 strcpy(aop->aopu.aop_immd,sym->rname);
300 /* if it is in direct space */
301 if (IN_DIRSPACE(space)) {
302 sym->aop = aop = newAsmop (AOP_DIR);
303 aop->aopu.aop_dir = sym->rname ;
304 aop->size = getSize(sym->type);
305 emitcode("", "; AOP_DIR for %s", sym->rname);
311 /* only remaining is far space */
312 /* in which case DPTR gets the address */
314 sym->aop = aop = newAsmop(AOP_HL);
318 sym->aop = aop = newAsmop(AOP_IY);
319 emitcode ("ld","iy,#%s ; a", sym->rname);
321 aop->size = getSize(sym->type);
322 aop->aopu.aop_dir = sym->rname;
324 /* if it is in code space */
325 if (IN_CODESPACE(space))
331 /*-----------------------------------------------------------------*/
332 /* aopForRemat - rematerialzes an object */
333 /*-----------------------------------------------------------------*/
334 static asmop *aopForRemat (symbol *sym)
337 iCode *ic = sym->rematiCode;
338 asmop *aop = newAsmop(AOP_IMMD);
341 /* if plus or minus print the right hand side */
342 if (ic->op == '+' || ic->op == '-') {
343 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
346 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
349 /* we reached the end */
350 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
354 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
355 strcpy(aop->aopu.aop_immd,buffer);
359 /*-----------------------------------------------------------------*/
360 /* regsInCommon - two operands have some registers in common */
361 /*-----------------------------------------------------------------*/
362 bool regsInCommon (operand *op1, operand *op2)
367 /* if they have registers in common */
368 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
371 sym1 = OP_SYMBOL(op1);
372 sym2 = OP_SYMBOL(op2);
374 if (sym1->nRegs == 0 || sym2->nRegs == 0)
377 for (i = 0 ; i < sym1->nRegs ; i++) {
382 for (j = 0 ; j < sym2->nRegs ;j++ ) {
386 if (sym2->regs[j] == sym1->regs[i])
394 /*-----------------------------------------------------------------*/
395 /* operandsEqu - equivalent */
396 /*-----------------------------------------------------------------*/
397 bool operandsEqu ( operand *op1, operand *op2)
401 /* if they not symbols */
402 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
405 sym1 = OP_SYMBOL(op1);
406 sym2 = OP_SYMBOL(op2);
408 /* if both are itemps & one is spilt
409 and the other is not then false */
410 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
411 sym1->isspilt != sym2->isspilt )
414 /* if they are the same */
418 if (strcmp(sym1->rname,sym2->rname) == 0)
422 /* if left is a tmp & right is not */
426 (sym1->usl.spillLoc == sym2))
433 (sym2->usl.spillLoc == sym1))
439 /*-----------------------------------------------------------------*/
440 /* sameRegs - two asmops have the same registers */
441 /*-----------------------------------------------------------------*/
442 bool sameRegs (asmop *aop1, asmop *aop2 )
449 if (aop1->type != AOP_REG ||
450 aop2->type != AOP_REG )
453 if (aop1->size != aop2->size)
456 for (i = 0 ; i < aop1->size ; i++ )
457 if (aop1->aopu.aop_reg[i] !=
458 aop2->aopu.aop_reg[i] )
464 /*-----------------------------------------------------------------*/
465 /* aopOp - allocates an asmop for an operand : */
466 /*-----------------------------------------------------------------*/
467 static void aopOp (operand *op, iCode *ic, bool result)
476 /* if this a literal */
477 if (IS_OP_LITERAL(op)) {
478 op->aop = aop = newAsmop(AOP_LIT);
479 aop->aopu.aop_lit = op->operand.valOperand;
480 aop->size = getSize(operandType(op));
484 /* if already has a asmop then continue */
488 /* if the underlying symbol has a aop */
489 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
490 op->aop = OP_SYMBOL(op)->aop;
494 /* if this is a true symbol */
495 if (IS_TRUE_SYMOP(op)) {
496 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
500 /* this is a temporary : this has
506 e) can be a return use only */
510 /* if the type is a conditional */
511 if (sym->regType == REG_CND) {
512 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
517 /* if it is spilt then two situations
519 b) has a spill location */
520 if (sym->isspilt || sym->nRegs == 0) {
521 /* rematerialize it NOW */
523 sym->aop = op->aop = aop =
525 aop->size = getSize(sym->type);
531 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
532 aop->size = getSize(sym->type);
533 for ( i = 0 ; i < 2 ; i++ )
534 aop->aopu.aop_str[i] = accUse[i];
540 aop = op->aop = sym->aop = newAsmop(AOP_STR);
541 aop->size = getSize(sym->type);
542 for ( i = 0 ; i < 4 ; i++ )
543 aop->aopu.aop_str[i] = _fReturn[i];
547 /* else spill location */
548 sym->aop = op->aop = aop =
549 aopForSym(ic,sym->usl.spillLoc,result);
550 aop->size = getSize(sym->type);
554 /* must be in a register */
555 sym->aop = op->aop = aop = newAsmop(AOP_REG);
556 aop->size = sym->nRegs;
557 for ( i = 0 ; i < sym->nRegs ;i++)
558 aop->aopu.aop_reg[i] = sym->regs[i];
561 /*-----------------------------------------------------------------*/
562 /* freeAsmop - free up the asmop given to an operand */
563 /*----------------------------------------------------------------*/
564 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
587 /* all other cases just dealloc */
591 OP_SYMBOL(op)->aop = NULL;
592 /* if the symbol has a spill */
594 SPIL_LOC(op)->aop = NULL;
599 bool isLitWord(asmop *aop)
612 char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
621 /* depending on type */
624 sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
625 ALLOC_ATOMIC(rs,strlen(s)+1);
630 value * val = aop->aopu.aop_lit;
631 /* if it is a float then it gets tricky */
632 /* otherwise it is fairly simple */
633 if (!IS_FLOAT(val->type)) {
634 unsigned long v = floatFromVal(val);
636 sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
637 ALLOC_ATOMIC(rs,strlen(buffer)+1);
638 return strcpy (rs,buffer);
647 char *aopGetWord(asmop *aop, int offset)
649 return aopGetLitWordLong(aop, offset, TRUE);
652 bool isPtr(const char *s)
654 if (!strcmp(s, "hl"))
656 if (!strcmp(s, "ix"))
658 if (!strcmp(s, "iy"))
663 static void adjustPair(const char *pair, int *pold, int new)
667 while (*pold < new) {
668 emitcode("inc", "%s", pair);
671 while (*pold > new) {
672 emitcode("dec", "%s", pair);
677 static void spillHL(void)
682 static bool requiresHL(asmop *aop)
693 static void fetchHL(asmop *aop)
696 if (IS_GB && requiresHL(aop)) {
697 aopGet(aop, 0, FALSE);
698 emitcode("ld", "a,(hl+)");
699 emitcode("ld", "h,(hl)");
700 emitcode("ld", "l,a");
703 emitcode("ld", "l,%s", aopGet(aop, 0, FALSE));
704 emitcode("ld", "h,%s", aopGet(aop, 1, FALSE));
708 static void fetchLitPair(int pairId, asmop *left, int offset)
711 const char *pair = _pairs[pairId].name;
712 l = aopGetLitWordLong(left, 0, FALSE);
716 if (_G.HL.lit && !strcmp(_G.HL.lit, l) && abs(_G.HL.offset - offset) < 3) {
717 adjustPair(pair, &_G.HL.offset, offset);
720 _G.HL.lit = _strdup(l);
721 _G.HL.offset = offset;
722 emitcode("ld", "%s,#%s + %d", pair, l, offset);
726 /* Both a lit on the right and a true symbol on the left */
727 emitcode("ld", "%s,#%s + %d", pair, l, offset);
731 static void setupHL(asmop *aop, int offset)
734 if (_lastHL != aop) {
738 fetchLitPair(PAIR_HL, aop, offset);
741 /* In some cases we can still inc or dec hl */
742 emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
751 while (offset < _lastHLOff) {
752 emitcode("dec", "hl");
755 while (offset > _lastHLOff) {
756 emitcode("inc", "hl");
762 /*-----------------------------------------------------------------*/
763 /* aopGet - for fetching value of the aop */
764 /*-----------------------------------------------------------------*/
765 static char *aopGet(asmop *aop, int offset, bool bit16)
770 /* offset is greater than size then zero */
771 /* PENDING: this seems a bit screwed in some pointer cases. */
772 if (offset > (aop->size - 1) &&
773 aop->type != AOP_LIT)
776 /* depending on type */
780 sprintf (s,"#%s ; 5",aop->aopu.aop_immd);
790 ALLOC_ATOMIC(rs,strlen(s)+1);
796 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
798 ALLOC_ATOMIC(rs,strlen(s)+1);
803 return aop->aopu.aop_reg[offset]->name;
808 setupHL(aop, offset);
810 return _strdup("(hl)");
813 sprintf(s,"%d(iy)", offset);
814 ALLOC_ATOMIC(rs,strlen(s)+1);
820 setupHL(aop, offset);
824 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
826 ALLOC_ATOMIC(rs,strlen(s)+1);
840 return aopLiteral (aop->aopu.aop_lit,offset);
844 return aop->aopu.aop_str[offset];
847 fprintf(stderr, "Type %u\n", aop->type);
849 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
850 "aopget got unsupported aop->type");
854 bool isRegString(char *s)
856 if (!strcmp(s, "b") ||
867 bool isConstant(const char *s)
872 bool canAssignToPtr(char *s)
881 /*-----------------------------------------------------------------*/
882 /* aopPut - puts a string for a aop */
883 /*-----------------------------------------------------------------*/
884 static void aopPut (asmop *aop, char *s, int offset)
886 if (aop->size && offset > ( aop->size - 1)) {
887 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
888 "aopPut got offset > aop->size");
892 /* will assign value to value */
893 /* depending on where it is ofcourse */
898 emitcode("ld", "a,%s", s);
899 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
903 /* Dont bother if it's a ld x,x */
904 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
905 emitcode("ld","%s,%s",
906 aop->aopu.aop_reg[offset]->name,s);
912 if (!canAssignToPtr(s)) {
913 emitcode("ld", "a,%s", s);
914 emitcode("ld", "%d(iy),a", offset);
917 emitcode("ld", "%d(iy),%s", offset, s);
922 if (!strcmp(s, "(hl)")) {
923 emitcode("ld", "a,(hl)");
927 setupHL(aop, offset);
928 emitcode("ld", "(hl),%s", s);
933 if (!strcmp("(hl)", s)) {
934 emitcode("ld", "a,(hl)");
937 setupHL(aop, offset);
938 if (!canAssignToPtr(s)) {
939 emitcode("ld", "a,%s", s);
940 emitcode("ld", "(hl),a");
943 emitcode("ld", "(hl),%s", s);
946 if (!canAssignToPtr(s)) {
947 emitcode("ld", "a,%s", s);
948 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
951 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
956 /* if bit variable */
957 if (!aop->aopu.aop_dir) {
958 emitcode("ld", "a,#0");
961 /* In bit space but not in C - cant happen */
968 if (strcmp(aop->aopu.aop_str[offset],s)) {
969 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
975 if (!offset && (strcmp(s,"acc") == 0))
979 emitcode("", "; Error aopPut AOP_ACC");
982 if (strcmp(aop->aopu.aop_str[offset],s))
983 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
988 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
989 "aopPut got unsupported aop->type");
994 #define AOP(op) op->aop
995 #define AOP_TYPE(op) AOP(op)->type
996 #define AOP_SIZE(op) AOP(op)->size
997 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
999 /*-----------------------------------------------------------------*/
1000 /* getDataSize - get the operand data size */
1001 /*-----------------------------------------------------------------*/
1002 int getDataSize(operand *op)
1005 size = AOP_SIZE(op);
1013 /*-----------------------------------------------------------------*/
1014 /* movLeft2Result - move byte from left to result */
1015 /*-----------------------------------------------------------------*/
1016 static void movLeft2Result (operand *left, int offl,
1017 operand *result, int offr, int sign)
1020 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1021 l = aopGet(AOP(left),offl,FALSE);
1024 aopPut(AOP(result),l,offr);
1033 /** Put Acc into a register set
1035 void outAcc(operand *result)
1038 size = getDataSize(result);
1040 aopPut(AOP(result),"a",0);
1043 /* unsigned or positive */
1045 aopPut(AOP(result),zero,offset++);
1050 /** Take the value in carry and put it into a register
1052 void outBitC(operand *result)
1054 /* if the result is bit */
1055 if (AOP_TYPE(result) == AOP_CRY) {
1056 emitcode("", "; Note: outBitC form 1");
1057 aopPut(AOP(result),"blah",0);
1060 emitcode("ld", "a,#0");
1061 emitcode("rla", "");
1066 /*-----------------------------------------------------------------*/
1067 /* toBoolean - emit code for orl a,operator(sizeop) */
1068 /*-----------------------------------------------------------------*/
1069 void toBoolean(operand *oper)
1071 int size = AOP_SIZE(oper);
1074 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1077 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1080 if (AOP(oper)->type != AOP_ACC) {
1082 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1087 /*-----------------------------------------------------------------*/
1088 /* genNot - generate code for ! operation */
1089 /*-----------------------------------------------------------------*/
1090 static void genNot (iCode *ic)
1092 link *optype = operandType(IC_LEFT(ic));
1094 /* assign asmOps to operand & result */
1095 aopOp (IC_LEFT(ic),ic,FALSE);
1096 aopOp (IC_RESULT(ic),ic,TRUE);
1098 /* if in bit space then a special case */
1099 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1103 /* if type float then do float */
1104 if (IS_FLOAT(optype)) {
1108 toBoolean(IC_LEFT(ic));
1113 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1114 emitcode("sub", "a,#0x01");
1115 outBitC(IC_RESULT(ic));
1117 /* release the aops */
1118 freeAsmop(IC_LEFT(ic),NULL,ic);
1119 freeAsmop(IC_RESULT(ic),NULL,ic);
1122 /*-----------------------------------------------------------------*/
1123 /* genCpl - generate code for complement */
1124 /*-----------------------------------------------------------------*/
1125 static void genCpl (iCode *ic)
1131 /* assign asmOps to operand & result */
1132 aopOp (IC_LEFT(ic),ic,FALSE);
1133 aopOp (IC_RESULT(ic),ic,TRUE);
1135 /* if both are in bit space then
1137 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1138 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1142 size = AOP_SIZE(IC_RESULT(ic));
1144 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1147 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1150 /* release the aops */
1151 freeAsmop(IC_LEFT(ic),NULL,ic);
1152 freeAsmop(IC_RESULT(ic),NULL,ic);
1155 /*-----------------------------------------------------------------*/
1156 /* genUminus - unary minus code generation */
1157 /*-----------------------------------------------------------------*/
1158 static void genUminus (iCode *ic)
1161 link *optype, *rtype;
1164 aopOp(IC_LEFT(ic),ic,FALSE);
1165 aopOp(IC_RESULT(ic),ic,TRUE);
1167 /* if both in bit space then special
1169 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1170 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1175 optype = operandType(IC_LEFT(ic));
1176 rtype = operandType(IC_RESULT(ic));
1178 /* if float then do float stuff */
1179 if (IS_FLOAT(optype)) {
1184 /* otherwise subtract from zero */
1185 size = AOP_SIZE(IC_LEFT(ic));
1189 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1190 emitcode("ld", "a,#0");
1191 emitcode("sbc","a,%s",l);
1192 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1195 /* if any remaining bytes in the result */
1196 /* we just need to propagate the sign */
1197 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1198 emitcode("rlc","a");
1199 emitcode("sbc","a,a");
1201 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1205 /* release the aops */
1206 freeAsmop(IC_LEFT(ic),NULL,ic);
1207 freeAsmop(IC_RESULT(ic),NULL,ic);
1210 /*-----------------------------------------------------------------*/
1211 /* assignResultValue - */
1212 /*-----------------------------------------------------------------*/
1213 void assignResultValue(operand * oper)
1216 int size = AOP_SIZE(oper);
1221 aopPut(AOP(oper),_fReturn[offset],offset);
1226 /*-----------------------------------------------------------------*/
1227 /* genIpush - genrate code for pushing this gets a little complex */
1228 /*-----------------------------------------------------------------*/
1229 static void genIpush (iCode *ic)
1231 int size, offset = 0 ;
1235 /* if this is not a parm push : ie. it is spill push
1236 and spill push is always done on the local stack */
1237 if (!ic->parmPush) {
1238 /* and the item is spilt then do nothing */
1239 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1242 aopOp(IC_LEFT(ic),ic,FALSE);
1243 size = AOP_SIZE(IC_LEFT(ic));
1244 /* push it on the stack */
1245 if (isPair(AOP(IC_LEFT(ic)))) {
1246 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1252 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1253 /* Simple for now - load into A and PUSH AF */
1254 emitcode("ld", "a,%s", l);
1255 emitcode("push", "af");
1256 emitcode("inc", "sp");
1263 /* Hmmm... what about saving the currently used registers
1266 /* then do the push */
1267 aopOp(IC_LEFT(ic),ic,FALSE);
1269 size = AOP_SIZE(IC_LEFT(ic));
1271 if (isPair(AOP(IC_LEFT(ic)))) {
1273 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1277 char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
1279 emitcode("ld", "hl,%s", s);
1280 emitcode("push", "hl");
1284 /* Optimise here - load into HL then push HL */
1285 fetchHL(AOP(IC_LEFT(ic)));
1286 emitcode("push", "hl");
1293 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1294 emitcode("ld", "a,%s", l);
1295 emitcode("push", "af");
1296 emitcode("inc", "sp");
1301 freeAsmop(IC_LEFT(ic),NULL,ic);
1304 /*-----------------------------------------------------------------*/
1305 /* genIpop - recover the registers: can happen only for spilling */
1306 /*-----------------------------------------------------------------*/
1307 static void genIpop (iCode *ic)
1312 /* if the temp was not pushed then */
1313 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1316 aopOp(IC_LEFT(ic),ic,FALSE);
1317 size = AOP_SIZE(IC_LEFT(ic));
1319 if (isPair(AOP(IC_LEFT(ic)))) {
1320 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1324 emitcode("dec", "sp");
1325 emitcode("pop", "hl");
1326 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1330 freeAsmop(IC_LEFT(ic),NULL,ic);
1333 /** Emit the code for a call statement
1335 static void emitCall (iCode *ic, bool ispcall)
1337 /* if caller saves & we have not saved then */
1338 if (!ic->regsSaved) {
1342 /* if send set is not empty then assign */
1345 for (sic = setFirstItem(sendSet) ; sic ;
1346 sic = setNextItem(sendSet)) {
1347 int size, offset = 0;
1348 aopOp(IC_LEFT(sic),sic,FALSE);
1349 size = AOP_SIZE(IC_LEFT(sic));
1351 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1353 if (strcmp(l, _fReturn[offset]))
1354 emitcode("ld","%s,%s",
1359 freeAsmop (IC_LEFT(sic),NULL,sic);
1365 symbol *rlbl = newiTempLabel(NULL);
1367 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1368 emitcode("push", "hl");
1371 aopOp(IC_LEFT(ic),ic,FALSE);
1372 fetchHL(AOP(IC_LEFT(ic)));
1373 freeAsmop(IC_LEFT(ic),NULL,ic);
1375 emitcode("jp", "(hl)");
1376 emitcode("","%05d$:",(rlbl->key+100));
1381 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1382 OP_SYMBOL(IC_LEFT(ic))->rname :
1383 OP_SYMBOL(IC_LEFT(ic))->name;
1384 emitcode("call", "%s", name);
1387 /* if we need assign a result value */
1388 if ((IS_ITEMP(IC_RESULT(ic)) &&
1389 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1390 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1391 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1394 aopOp(IC_RESULT(ic),ic,FALSE);
1397 assignResultValue(IC_RESULT(ic));
1399 freeAsmop(IC_RESULT(ic),NULL, ic);
1402 /* adjust the stack for parameters if required */
1403 if (IC_LEFT(ic)->parmBytes) {
1404 int i = IC_LEFT(ic)->parmBytes;
1407 emitcode("lda", "sp,%d(sp)", i);
1411 emitcode("ld", "hl,#%d", i);
1412 emitcode("add", "hl,sp");
1413 emitcode("ld", "sp,hl");
1417 emitcode("pop", "hl");
1421 emitcode("inc", "sp");
1428 /*-----------------------------------------------------------------*/
1429 /* genCall - generates a call statement */
1430 /*-----------------------------------------------------------------*/
1431 static void genCall (iCode *ic)
1433 emitCall(ic, FALSE);
1436 /*-----------------------------------------------------------------*/
1437 /* genPcall - generates a call by pointer statement */
1438 /*-----------------------------------------------------------------*/
1439 static void genPcall (iCode *ic)
1444 /*-----------------------------------------------------------------*/
1445 /* resultRemat - result is rematerializable */
1446 /*-----------------------------------------------------------------*/
1447 static int resultRemat (iCode *ic)
1449 if (SKIP_IC(ic) || ic->op == IFX)
1452 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1453 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1454 if (sym->remat && !POINTER_SET(ic))
1461 /*-----------------------------------------------------------------*/
1462 /* genFunction - generated code for function entry */
1463 /*-----------------------------------------------------------------*/
1464 static void genFunction (iCode *ic)
1470 /* create the function header */
1471 emitcode(";","-----------------------------------------");
1472 emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
1473 emitcode(";","-----------------------------------------");
1475 emitcode("","%s:",sym->rname);
1476 emitcode("", "__%s_start:", sym->rname);
1477 fetype = getSpec(operandType(IC_LEFT(ic)));
1479 /* if critical function then turn interrupts off */
1480 if (SPEC_CRTCL(fetype))
1483 /* if this is an interrupt service routine then
1484 save acc, b, dpl, dph */
1485 if (IS_ISR(sym->etype)) {
1486 emitcode("push", "af");
1487 emitcode("push", "bc");
1488 emitcode("push", "de");
1489 emitcode("push", "hl");
1491 /* PENDING: callee-save etc */
1493 /* adjust the stack for the function */
1494 emitcode("push", "bc");
1496 emitcode("push", "de");
1497 emitcode("push", "ix");
1498 emitcode("ld", "ix,#0");
1499 emitcode("add", "ix,sp");
1502 _lastStack = sym->stack;
1506 emitcode("lda", "sp,-%d(sp)", sym->stack);
1509 emitcode("ld", "hl,#-%d", sym->stack);
1510 emitcode("add", "hl,sp");
1511 emitcode("ld", "sp,hl");
1514 _spoffset = sym->stack;
1517 /*-----------------------------------------------------------------*/
1518 /* genEndFunction - generates epilogue for functions */
1519 /*-----------------------------------------------------------------*/
1520 static void genEndFunction (iCode *ic)
1522 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1524 if (IS_ISR(sym->etype)) {
1528 if (SPEC_CRTCL(sym->etype))
1531 /* PENDING: calleeSave */
1533 /* if debug then send end of function */
1534 if (options.debug && currFunc) {
1536 emitcode("","C$%s$%d$%d$%d ==.",
1537 ic->filename,currFunc->lastLine,
1538 ic->level,ic->block);
1539 if (IS_STATIC(currFunc->etype))
1540 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1542 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1546 emitcode("ld", "sp,ix");
1547 emitcode("pop", "ix");
1548 emitcode("pop", "de");
1552 emitcode("ld", "hl,#%d", _spoffset);
1553 emitcode("add", "hl,sp");
1554 emitcode("ld", "sp,hl");
1557 emitcode("pop", "bc");
1558 emitcode("ret", "");
1559 emitcode("", "__%s_end:", sym->rname);
1565 /*-----------------------------------------------------------------*/
1566 /* genRet - generate code for return statement */
1567 /*-----------------------------------------------------------------*/
1568 static void genRet (iCode *ic)
1571 /* Errk. This is a hack until I can figure out how
1572 to cause dehl to spill on a call */
1573 int size,offset = 0;
1575 /* if we have no return value then
1576 just generate the "ret" */
1580 /* we have something to return then
1581 move the return value into place */
1582 aopOp(IC_LEFT(ic),ic,FALSE);
1583 size = AOP_SIZE(IC_LEFT(ic));
1585 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1587 emitcode("ld", "de,%s", l);
1590 emitcode("ld", "hl,%s", l);
1595 l = aopGet(AOP(IC_LEFT(ic)),offset,
1597 if (strcmp(_fReturn[offset],l))
1598 emitcode("ld","%s,%s", _fReturn[offset++],l);
1601 freeAsmop (IC_LEFT(ic),NULL,ic);
1604 /* generate a jump to the return label
1605 if the next is not the return statement */
1606 if (!(ic->next && ic->next->op == LABEL &&
1607 IC_LABEL(ic->next) == returnLabel))
1609 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1612 /*-----------------------------------------------------------------*/
1613 /* genLabel - generates a label */
1614 /*-----------------------------------------------------------------*/
1615 static void genLabel (iCode *ic)
1617 /* special case never generate */
1618 if (IC_LABEL(ic) == entryLabel)
1621 emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
1624 /*-----------------------------------------------------------------*/
1625 /* genGoto - generates a ljmp */
1626 /*-----------------------------------------------------------------*/
1627 static void genGoto (iCode *ic)
1629 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1632 /*-----------------------------------------------------------------*/
1633 /* genPlusIncr :- does addition with increment if possible */
1634 /*-----------------------------------------------------------------*/
1635 static bool genPlusIncr (iCode *ic)
1637 unsigned int icount ;
1638 unsigned int size = getDataSize(IC_RESULT(ic));
1640 /* will try to generate an increment */
1641 /* if the right side is not a literal
1643 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1646 emitcode("", "; genPlusIncr");
1648 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1651 /* If result is a pair */
1652 if (isPair(AOP(IC_RESULT(ic))) && isLitWord(AOP(IC_LEFT(ic)))) {
1653 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
1657 /* if the literal value of the right hand side
1658 is greater than 4 then it is not worth it */
1663 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1664 isPair(AOP(IC_RESULT(ic)))) {
1666 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1670 /* if increment 16 bits in register */
1671 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1674 symbol *tlbl = newiTempLabel(NULL);
1675 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1676 emitcode(_shortJP, "nz," LABEL_STR ,tlbl->key+100);
1678 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1682 emitcode("", LABEL_STR ":",tlbl->key+100);
1686 /* If result is a pair */
1687 if (isPair(AOP(IC_RESULT(ic)))) {
1688 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1689 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1691 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1695 /* if the sizes are greater than 1 then we cannot */
1696 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1697 AOP_SIZE(IC_LEFT(ic)) > 1 )
1700 /* we can if the aops of the left & result match or
1701 if they are in registers and the registers are the
1703 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1705 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1713 /*-----------------------------------------------------------------*/
1714 /* outBitAcc - output a bit in acc */
1715 /*-----------------------------------------------------------------*/
1716 void outBitAcc(operand *result)
1718 symbol *tlbl = newiTempLabel(NULL);
1719 /* if the result is a bit */
1720 if (AOP_TYPE(result) == AOP_CRY){
1724 emitcode(_shortJP,"z," LABEL_STR ,tlbl->key+100);
1725 emitcode("ld","a,%s",one);
1726 emitcode("", LABEL_STR ":",tlbl->key+100);
1731 /*-----------------------------------------------------------------*/
1732 /* genPlus - generates code for addition */
1733 /*-----------------------------------------------------------------*/
1734 static void genPlus (iCode *ic)
1736 int size, offset = 0;
1738 /* special cases :- */
1740 aopOp (IC_LEFT(ic),ic,FALSE);
1741 aopOp (IC_RIGHT(ic),ic,FALSE);
1742 aopOp (IC_RESULT(ic),ic,TRUE);
1744 /* Swap the left and right operands if:
1746 if literal, literal on the right or
1747 if left requires ACC or right is already
1750 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1751 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1752 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1753 operand *t = IC_RIGHT(ic);
1754 IC_RIGHT(ic) = IC_LEFT(ic);
1758 /* if both left & right are in bit
1760 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1761 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1766 /* if left in bit space & right literal */
1767 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1768 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1769 /* Can happen I guess */
1773 /* if I can do an increment instead
1774 of add then GOOD for ME */
1775 if (genPlusIncr (ic) == TRUE)
1778 size = getDataSize(IC_RESULT(ic));
1780 /* Special case when left and right are constant */
1781 if (isPair(AOP(IC_RESULT(ic)))) {
1784 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1785 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1786 if (left && right) {
1790 sprintf(buffer, "#(%s + %s)", left, right);
1791 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1797 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1798 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1800 emitcode("add","a,%s",
1801 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1803 emitcode("adc","a,%s",
1804 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1806 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1808 emitcode("add","a,%s",
1809 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1811 emitcode("adc","a,%s",
1812 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1814 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1817 /* Some kind of pointer arith. */
1818 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1819 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1820 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1823 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1824 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1825 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1830 freeAsmop(IC_LEFT(ic),NULL,ic);
1831 freeAsmop(IC_RIGHT(ic),NULL,ic);
1832 freeAsmop(IC_RESULT(ic),NULL,ic);
1836 /*-----------------------------------------------------------------*/
1837 /* genMinusDec :- does subtraction with deccrement if possible */
1838 /*-----------------------------------------------------------------*/
1839 static bool genMinusDec (iCode *ic)
1841 unsigned int icount ;
1842 unsigned int size = getDataSize(IC_RESULT(ic));
1844 /* will try to generate an increment */
1845 /* if the right side is not a literal we cannot */
1846 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1849 /* if the literal value of the right hand side
1850 is greater than 4 then it is not worth it */
1851 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1854 size = getDataSize(IC_RESULT(ic));
1857 /* if increment 16 bits in register */
1858 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1861 symbol *tlbl = newiTempLabel(NULL);
1862 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1863 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1865 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1869 emitcode("", LABEL_STR ":",tlbl->key+100);
1874 /* if decrement 16 bits in register */
1875 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1876 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1878 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1882 /* If result is a pair */
1883 if (isPair(AOP(IC_RESULT(ic)))) {
1884 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1885 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1887 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1891 /* if the sizes are greater than 1 then we cannot */
1892 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1893 AOP_SIZE(IC_LEFT(ic)) > 1 )
1896 /* we can if the aops of the left & result match or if they are in
1897 registers and the registers are the same */
1898 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1900 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1907 /*-----------------------------------------------------------------*/
1908 /* genMinus - generates code for subtraction */
1909 /*-----------------------------------------------------------------*/
1910 static void genMinus (iCode *ic)
1912 int size, offset = 0;
1913 unsigned long lit = 0L;
1915 aopOp (IC_LEFT(ic),ic,FALSE);
1916 aopOp (IC_RIGHT(ic),ic,FALSE);
1917 aopOp (IC_RESULT(ic),ic,TRUE);
1919 /* special cases :- */
1920 /* if both left & right are in bit space */
1921 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1922 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1927 /* if I can do an decrement instead of subtract then GOOD for ME */
1928 if (genMinusDec (ic) == TRUE)
1931 size = getDataSize(IC_RESULT(ic));
1933 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1936 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1941 /* if literal, add a,#-lit, else normal subb */
1943 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1944 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1946 emitcode("sub","a,%s",
1947 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1949 emitcode("sbc","a,%s",
1950 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1953 /* first add without previous c */
1955 emitcode("add","a,#0x%02x",
1956 (unsigned int)(lit & 0x0FFL));
1958 emitcode("adc","a,#0x%02x",
1959 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1961 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1964 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1965 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1966 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1970 freeAsmop(IC_LEFT(ic),NULL,ic);
1971 freeAsmop(IC_RIGHT(ic),NULL,ic);
1972 freeAsmop(IC_RESULT(ic),NULL,ic);
1975 /*-----------------------------------------------------------------*/
1976 /* genMult - generates code for multiplication */
1977 /*-----------------------------------------------------------------*/
1978 static void genMult (iCode *ic)
1980 /* Shouldn't occur - all done through function calls */
1984 /*-----------------------------------------------------------------*/
1985 /* genDiv - generates code for division */
1986 /*-----------------------------------------------------------------*/
1987 static void genDiv (iCode *ic)
1989 /* Shouldn't occur - all done through function calls */
1993 /*-----------------------------------------------------------------*/
1994 /* genMod - generates code for division */
1995 /*-----------------------------------------------------------------*/
1996 static void genMod (iCode *ic)
1998 /* Shouldn't occur - all done through function calls */
2002 /*-----------------------------------------------------------------*/
2003 /* genIfxJump :- will create a jump depending on the ifx */
2004 /*-----------------------------------------------------------------*/
2005 static void genIfxJump (iCode *ic, char *jval)
2010 /* if true label then we jump if condition
2012 if ( IC_TRUE(ic) ) {
2014 if (!strcmp(jval, "a")) {
2017 else if (!strcmp(jval, "c")) {
2021 /* The buffer contains the bit on A that we should test */
2026 /* false label is present */
2027 jlbl = IC_FALSE(ic) ;
2028 if (!strcmp(jval, "a")) {
2031 else if (!strcmp(jval, "c")) {
2035 /* The buffer contains the bit on A that we should test */
2039 /* Z80 can do a conditional long jump */
2040 if (!strcmp(jval, "a")) {
2041 emitcode("or", "a,a");
2043 else if (!strcmp(jval, "c")) {
2046 emitcode("bit", "%s,a", jval);
2048 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
2050 /* mark the icode as generated */
2054 /** Generic compare for > or <
2056 static void genCmp (operand *left,operand *right,
2057 operand *result, iCode *ifx, int sign)
2059 int size, offset = 0 ;
2060 unsigned long lit = 0L;
2062 /* if left & right are bit variables */
2063 if (AOP_TYPE(left) == AOP_CRY &&
2064 AOP_TYPE(right) == AOP_CRY ) {
2065 /* Cant happen on the Z80 */
2068 /* subtract right from left if at the
2069 end the carry flag is set then we know that
2070 left is greater than right */
2071 size = max(AOP_SIZE(left),AOP_SIZE(right));
2073 /* if unsigned char cmp with lit, just compare */
2075 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2076 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2078 emitcode("xor", "a,#0x80");
2079 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
2082 emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
2085 if(AOP_TYPE(right) == AOP_LIT) {
2086 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2087 /* optimize if(x < 0) or if(x >= 0) */
2090 /* No sign so it's always false */
2094 /* Just load in the top most bit */
2095 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2096 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2097 genIfxJump (ifx,"7");
2101 emitcode("rlc","a");
2107 /* First setup h and l contaning the top most bytes XORed */
2108 bool fDidXor = FALSE;
2109 if (AOP_TYPE(left) == AOP_LIT){
2110 unsigned long lit = (unsigned long)
2111 floatFromVal(AOP(left)->aopu.aop_lit);
2112 emitcode("ld", "%s,#0x%02x", _fTmp[0],
2113 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2116 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2117 emitcode("xor", "a,#0x80");
2118 emitcode("ld", "%s,a", _fTmp[0]);
2121 if (AOP_TYPE(right) == AOP_LIT) {
2122 unsigned long lit = (unsigned long)
2123 floatFromVal(AOP(right)->aopu.aop_lit);
2124 emitcode("ld", "%s,#0x%02x", _fTmp[1],
2125 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2128 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2129 emitcode("xor", "a,#0x80");
2130 emitcode("ld", "%s,a", _fTmp[1]);
2140 /* Do a long subtract */
2141 if (!sign || size ) {
2142 MOVA(aopGet(AOP(left),offset,FALSE));
2144 if (sign && size == 0) {
2145 emitcode("ld", "a,%s", _fTmp[0]);
2146 emitcode("sbc", "a,%s", _fTmp[1]);
2149 /* Subtract through, propagating the carry */
2150 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2157 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2160 /* if the result is used in the next
2161 ifx conditional branch then generate
2162 code a little differently */
2164 genIfxJump (ifx,"c");
2167 /* leave the result in acc */
2171 /*-----------------------------------------------------------------*/
2172 /* genCmpGt :- greater than comparison */
2173 /*-----------------------------------------------------------------*/
2174 static void genCmpGt (iCode *ic, iCode *ifx)
2176 operand *left, *right, *result;
2177 link *letype , *retype;
2181 right= IC_RIGHT(ic);
2182 result = IC_RESULT(ic);
2184 letype = getSpec(operandType(left));
2185 retype =getSpec(operandType(right));
2186 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2187 /* assign the amsops */
2188 aopOp (left,ic,FALSE);
2189 aopOp (right,ic,FALSE);
2190 aopOp (result,ic,TRUE);
2192 genCmp(right, left, result, ifx, sign);
2194 freeAsmop(left,NULL,ic);
2195 freeAsmop(right,NULL,ic);
2196 freeAsmop(result,NULL,ic);
2199 /*-----------------------------------------------------------------*/
2200 /* genCmpLt - less than comparisons */
2201 /*-----------------------------------------------------------------*/
2202 static void genCmpLt (iCode *ic, iCode *ifx)
2204 operand *left, *right, *result;
2205 link *letype , *retype;
2209 right= IC_RIGHT(ic);
2210 result = IC_RESULT(ic);
2212 letype = getSpec(operandType(left));
2213 retype =getSpec(operandType(right));
2214 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2216 /* assign the amsops */
2217 aopOp (left,ic,FALSE);
2218 aopOp (right,ic,FALSE);
2219 aopOp (result,ic,TRUE);
2221 genCmp(left, right, result, ifx, sign);
2223 freeAsmop(left,NULL,ic);
2224 freeAsmop(right,NULL,ic);
2225 freeAsmop(result,NULL,ic);
2228 /*-----------------------------------------------------------------*/
2229 /* gencjneshort - compare and jump if not equal */
2230 /*-----------------------------------------------------------------*/
2231 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2233 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2235 unsigned long lit = 0L;
2237 /* Swap the left and right if it makes the computation easier */
2238 if (AOP_TYPE(left) == AOP_LIT) {
2244 if(AOP_TYPE(right) == AOP_LIT)
2245 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2247 /* if the right side is a literal then anything goes */
2248 if (AOP_TYPE(right) == AOP_LIT &&
2249 AOP_TYPE(left) != AOP_DIR ) {
2251 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2256 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2260 emitcode("or", "a,a");
2262 emitcode("jp", "nz," LABEL_STR, lbl->key+100);
2266 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2267 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2268 emitcode("or", "a,a");
2270 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2271 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2276 /* if the right side is in a register or in direct space or
2277 if the left is a pointer register & right is not */
2278 else if (AOP_TYPE(right) == AOP_REG ||
2279 AOP_TYPE(right) == AOP_DIR ||
2280 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2282 MOVA(aopGet(AOP(left),offset,FALSE));
2283 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2284 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2286 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
2288 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2289 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2294 /* right is a pointer reg need both a & b */
2295 /* PENDING: is this required? */
2297 MOVA(aopGet(AOP(right),offset,FALSE));
2298 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2299 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2305 /*-----------------------------------------------------------------*/
2306 /* gencjne - compare and jump if not equal */
2307 /*-----------------------------------------------------------------*/
2308 static void gencjne(operand *left, operand *right, symbol *lbl)
2310 symbol *tlbl = newiTempLabel(NULL);
2312 gencjneshort(left, right, lbl);
2315 emitcode("ld","a,%s",one);
2316 emitcode(_shortJP, LABEL_STR ,tlbl->key+100);
2317 emitcode("", LABEL_STR ":",lbl->key+100);
2318 emitcode("xor","a,a");
2319 emitcode("", LABEL_STR ":",tlbl->key+100);
2322 /*-----------------------------------------------------------------*/
2323 /* genCmpEq - generates code for equal to */
2324 /*-----------------------------------------------------------------*/
2325 static void genCmpEq (iCode *ic, iCode *ifx)
2327 operand *left, *right, *result;
2329 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2330 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2331 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2333 /* Swap operands if it makes the operation easier. ie if:
2334 1. Left is a literal.
2336 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2337 operand *t = IC_RIGHT(ic);
2338 IC_RIGHT(ic) = IC_LEFT(ic);
2342 if (ifx && !AOP_SIZE(result)){
2344 /* if they are both bit variables */
2345 if (AOP_TYPE(left) == AOP_CRY &&
2346 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2349 tlbl = newiTempLabel(NULL);
2350 gencjneshort(left, right, tlbl);
2351 if ( IC_TRUE(ifx) ) {
2352 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2353 emitcode("", LABEL_STR ":",tlbl->key+100);
2355 /* PENDING: do this better */
2356 symbol *lbl = newiTempLabel(NULL);
2357 emitcode(_shortJP, LABEL_STR ,lbl->key+100);
2358 emitcode("", LABEL_STR ":",tlbl->key+100);
2359 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2360 emitcode("", LABEL_STR ":",lbl->key+100);
2363 /* mark the icode as generated */
2368 /* if they are both bit variables */
2369 if (AOP_TYPE(left) == AOP_CRY &&
2370 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2373 gencjne(left,right,newiTempLabel(NULL));
2374 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2378 genIfxJump(ifx,"a");
2381 /* if the result is used in an arithmetic operation
2382 then put the result in place */
2383 if (AOP_TYPE(result) != AOP_CRY) {
2386 /* leave the result in acc */
2390 freeAsmop(left,NULL,ic);
2391 freeAsmop(right,NULL,ic);
2392 freeAsmop(result,NULL,ic);
2395 /*-----------------------------------------------------------------*/
2396 /* ifxForOp - returns the icode containing the ifx for operand */
2397 /*-----------------------------------------------------------------*/
2398 static iCode *ifxForOp ( operand *op, iCode *ic )
2400 /* if true symbol then needs to be assigned */
2401 if (IS_TRUE_SYMOP(op))
2404 /* if this has register type condition and
2405 the next instruction is ifx with the same operand
2406 and live to of the operand is upto the ifx only then */
2408 ic->next->op == IFX &&
2409 IC_COND(ic->next)->key == op->key &&
2410 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2416 /*-----------------------------------------------------------------*/
2417 /* genAndOp - for && operation */
2418 /*-----------------------------------------------------------------*/
2419 static void genAndOp (iCode *ic)
2421 operand *left,*right, *result;
2424 /* note here that && operations that are in an if statement are
2425 taken away by backPatchLabels only those used in arthmetic
2426 operations remain */
2427 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2428 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2429 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2431 /* if both are bit variables */
2432 if (AOP_TYPE(left) == AOP_CRY &&
2433 AOP_TYPE(right) == AOP_CRY ) {
2436 tlbl = newiTempLabel(NULL);
2438 emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100);
2440 emitcode("", LABEL_STR ":",tlbl->key+100);
2444 freeAsmop(left,NULL,ic);
2445 freeAsmop(right,NULL,ic);
2446 freeAsmop(result,NULL,ic);
2449 /*-----------------------------------------------------------------*/
2450 /* genOrOp - for || operation */
2451 /*-----------------------------------------------------------------*/
2452 static void genOrOp (iCode *ic)
2454 operand *left,*right, *result;
2457 /* note here that || operations that are in an
2458 if statement are taken away by backPatchLabels
2459 only those used in arthmetic operations remain */
2460 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2461 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2462 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2464 /* if both are bit variables */
2465 if (AOP_TYPE(left) == AOP_CRY &&
2466 AOP_TYPE(right) == AOP_CRY ) {
2469 tlbl = newiTempLabel(NULL);
2471 emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100);
2473 emitcode("", LABEL_STR ":",tlbl->key+100);
2477 freeAsmop(left,NULL,ic);
2478 freeAsmop(right,NULL,ic);
2479 freeAsmop(result,NULL,ic);
2482 /*-----------------------------------------------------------------*/
2483 /* isLiteralBit - test if lit == 2^n */
2484 /*-----------------------------------------------------------------*/
2485 int isLiteralBit(unsigned long lit)
2487 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2488 0x100L,0x200L,0x400L,0x800L,
2489 0x1000L,0x2000L,0x4000L,0x8000L,
2490 0x10000L,0x20000L,0x40000L,0x80000L,
2491 0x100000L,0x200000L,0x400000L,0x800000L,
2492 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2493 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2496 for(idx = 0; idx < 32; idx++)
2502 /*-----------------------------------------------------------------*/
2503 /* jmpTrueOrFalse - */
2504 /*-----------------------------------------------------------------*/
2505 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2507 // ugly but optimized by peephole
2509 symbol *nlbl = newiTempLabel(NULL);
2510 emitcode("jp", LABEL_STR, nlbl->key+100);
2511 emitcode("", LABEL_STR ":",tlbl->key+100);
2512 emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100);
2513 emitcode("", LABEL_STR ":",nlbl->key+100);
2516 emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100);
2517 emitcode("", LABEL_STR ":",tlbl->key+100);
2522 /*-----------------------------------------------------------------*/
2523 /* genAnd - code for and */
2524 /*-----------------------------------------------------------------*/
2525 static void genAnd (iCode *ic, iCode *ifx)
2527 operand *left, *right, *result;
2529 unsigned long lit = 0L;
2532 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2533 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2534 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2537 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2539 AOP_TYPE(left), AOP_TYPE(right));
2540 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2542 AOP_SIZE(left), AOP_SIZE(right));
2545 /* if left is a literal & right is not then exchange them */
2546 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2547 AOP_NEEDSACC(left)) {
2548 operand *tmp = right ;
2553 /* if result = right then exchange them */
2554 if(sameRegs(AOP(result),AOP(right))){
2555 operand *tmp = right ;
2560 /* if right is bit then exchange them */
2561 if (AOP_TYPE(right) == AOP_CRY &&
2562 AOP_TYPE(left) != AOP_CRY){
2563 operand *tmp = right ;
2567 if(AOP_TYPE(right) == AOP_LIT)
2568 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2570 size = AOP_SIZE(result);
2572 if (AOP_TYPE(left) == AOP_CRY){
2577 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2578 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2579 if((AOP_TYPE(right) == AOP_LIT) &&
2580 (AOP_TYPE(result) == AOP_CRY) &&
2581 (AOP_TYPE(left) != AOP_CRY)) {
2582 int posbit = isLiteralBit(lit);
2586 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2590 emitcode("mov","c,acc.%d",posbit&0x07);
2595 sprintf(buffer, "%d", posbit&0x07);
2596 genIfxJump(ifx, buffer);
2604 symbol *tlbl = newiTempLabel(NULL);
2605 int sizel = AOP_SIZE(left);
2608 emitcode("setb","c");
2611 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2612 MOVA( aopGet(AOP(left),offset,FALSE));
2614 if((posbit = isLiteralBit(bytelit)) != 0) {
2616 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2619 if(bytelit != 0x0FFL)
2620 emitcode("and","a,%s",
2621 aopGet(AOP(right),offset,FALSE));
2622 emitcode("jr","nz, %05d$",tlbl->key+100);
2627 // bit = left & literal
2629 emitcode("clr","c");
2630 emitcode("","%05d$:",tlbl->key+100);
2632 // if(left & literal)
2635 jmpTrueOrFalse(ifx, tlbl);
2643 /* if left is same as result */
2644 if(sameRegs(AOP(result),AOP(left))){
2645 for(;size--; offset++) {
2646 if(AOP_TYPE(right) == AOP_LIT){
2647 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2651 aopPut(AOP(result),zero,offset);
2653 MOVA(aopGet(AOP(left),offset,FALSE));
2654 emitcode("and","a,%s",
2655 aopGet(AOP(right),offset,FALSE));
2656 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2661 if (AOP_TYPE(left) == AOP_ACC) {
2665 MOVA(aopGet(AOP(right),offset,FALSE));
2666 emitcode("and","%s,a",
2667 aopGet(AOP(left),offset,FALSE));
2672 // left & result in different registers
2673 if(AOP_TYPE(result) == AOP_CRY){
2676 for(;(size--);offset++) {
2678 // result = left & right
2679 if(AOP_TYPE(right) == AOP_LIT){
2680 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2682 aopGet(AOP(left),offset,FALSE),
2685 } else if(bytelit == 0){
2686 aopPut(AOP(result),zero,offset);
2690 // faster than result <- left, anl result,right
2691 // and better if result is SFR
2692 if (AOP_TYPE(left) == AOP_ACC)
2693 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2695 MOVA(aopGet(AOP(right),offset,FALSE));
2696 emitcode("and","a,%s",
2697 aopGet(AOP(left),offset,FALSE));
2699 aopPut(AOP(result),"a",offset);
2706 freeAsmop(left,NULL,ic);
2707 freeAsmop(right,NULL,ic);
2708 freeAsmop(result,NULL,ic);
2711 /*-----------------------------------------------------------------*/
2712 /* genOr - code for or */
2713 /*-----------------------------------------------------------------*/
2714 static void genOr (iCode *ic, iCode *ifx)
2716 operand *left, *right, *result;
2718 unsigned long lit = 0L;
2720 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2721 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2722 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2725 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2727 AOP_TYPE(left), AOP_TYPE(right));
2728 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2730 AOP_SIZE(left), AOP_SIZE(right));
2733 /* if left is a literal & right is not then exchange them */
2734 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2735 AOP_NEEDSACC(left)) {
2736 operand *tmp = right ;
2741 /* if result = right then exchange them */
2742 if(sameRegs(AOP(result),AOP(right))){
2743 operand *tmp = right ;
2748 /* if right is bit then exchange them */
2749 if (AOP_TYPE(right) == AOP_CRY &&
2750 AOP_TYPE(left) != AOP_CRY){
2751 operand *tmp = right ;
2755 if(AOP_TYPE(right) == AOP_LIT)
2756 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2758 size = AOP_SIZE(result);
2760 if (AOP_TYPE(left) == AOP_CRY){
2765 if((AOP_TYPE(right) == AOP_LIT) &&
2766 (AOP_TYPE(result) == AOP_CRY) &&
2767 (AOP_TYPE(left) != AOP_CRY)){
2772 /* if left is same as result */
2773 if(sameRegs(AOP(result),AOP(left))){
2774 for(;size--; offset++) {
2775 if(AOP_TYPE(right) == AOP_LIT){
2776 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2779 MOVA(aopGet(AOP(right),offset,FALSE));
2780 emitcode("or","a,%s; 5",
2781 aopGet(AOP(left),offset,FALSE));
2782 aopPut(AOP(result),"a ; 8", offset);
2785 if (AOP_TYPE(left) == AOP_ACC)
2786 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2788 MOVA(aopGet(AOP(right),offset,FALSE));
2789 emitcode("or","a,%s ; 7",
2790 aopGet(AOP(left),offset,FALSE));
2791 aopPut(AOP(result),"a ; 8", offset);
2796 // left & result in different registers
2797 if(AOP_TYPE(result) == AOP_CRY){
2799 } else for(;(size--);offset++){
2801 // result = left & right
2802 if(AOP_TYPE(right) == AOP_LIT){
2803 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2805 aopGet(AOP(left),offset,FALSE),
2810 // faster than result <- left, anl result,right
2811 // and better if result is SFR
2812 if (AOP_TYPE(left) == AOP_ACC)
2813 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2815 MOVA(aopGet(AOP(right),offset,FALSE));
2816 emitcode("or","a,%s",
2817 aopGet(AOP(left),offset,FALSE));
2819 aopPut(AOP(result),"a",offset);
2820 /* PENDING: something weird is going on here. Add exception. */
2821 if (AOP_TYPE(result) == AOP_ACC)
2827 freeAsmop(left,NULL,ic);
2828 freeAsmop(right,NULL,ic);
2829 freeAsmop(result,NULL,ic);
2832 /*-----------------------------------------------------------------*/
2833 /* genXor - code for xclusive or */
2834 /*-----------------------------------------------------------------*/
2835 static void genXor (iCode *ic, iCode *ifx)
2837 operand *left, *right, *result;
2839 unsigned long lit = 0L;
2841 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2842 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2843 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2845 /* if left is a literal & right is not then exchange them */
2846 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2847 AOP_NEEDSACC(left)) {
2848 operand *tmp = right ;
2853 /* if result = right then exchange them */
2854 if(sameRegs(AOP(result),AOP(right))){
2855 operand *tmp = right ;
2860 /* if right is bit then exchange them */
2861 if (AOP_TYPE(right) == AOP_CRY &&
2862 AOP_TYPE(left) != AOP_CRY){
2863 operand *tmp = right ;
2867 if(AOP_TYPE(right) == AOP_LIT)
2868 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2870 size = AOP_SIZE(result);
2872 if (AOP_TYPE(left) == AOP_CRY){
2877 if((AOP_TYPE(right) == AOP_LIT) &&
2878 (AOP_TYPE(result) == AOP_CRY) &&
2879 (AOP_TYPE(left) != AOP_CRY)){
2884 /* if left is same as result */
2885 if(sameRegs(AOP(result),AOP(left))){
2886 for(;size--; offset++) {
2887 if(AOP_TYPE(right) == AOP_LIT){
2888 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2891 MOVA(aopGet(AOP(right),offset,FALSE));
2892 emitcode("xor","a,%s",
2893 aopGet(AOP(left),offset,FALSE));
2894 aopPut(AOP(result),"a",0);
2897 if (AOP_TYPE(left) == AOP_ACC)
2898 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2900 MOVA(aopGet(AOP(right),offset,FALSE));
2901 emitcode("xor","a,%s",
2902 aopGet(AOP(left),offset,FALSE));
2903 aopPut(AOP(result),"a",0);
2908 // left & result in different registers
2909 if(AOP_TYPE(result) == AOP_CRY){
2911 } else for(;(size--);offset++){
2913 // result = left & right
2914 if(AOP_TYPE(right) == AOP_LIT){
2915 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2917 aopGet(AOP(left),offset,FALSE),
2922 // faster than result <- left, anl result,right
2923 // and better if result is SFR
2924 if (AOP_TYPE(left) == AOP_ACC)
2925 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2927 MOVA(aopGet(AOP(right),offset,FALSE));
2928 emitcode("xor","a,%s",
2929 aopGet(AOP(left),offset,FALSE));
2930 aopPut(AOP(result),"a",0);
2932 aopPut(AOP(result),"a",offset);
2937 freeAsmop(left,NULL,ic);
2938 freeAsmop(right,NULL,ic);
2939 freeAsmop(result,NULL,ic);
2942 /*-----------------------------------------------------------------*/
2943 /* genInline - write the inline code out */
2944 /*-----------------------------------------------------------------*/
2945 static void genInline (iCode *ic)
2947 char buffer[MAX_INLINEASM];
2951 inLine += (!options.asmpeep);
2952 strcpy(buffer,IC_INLINE(ic));
2954 /* emit each line as a code */
2973 /* emitcode("",buffer); */
2974 inLine -= (!options.asmpeep);
2977 /*-----------------------------------------------------------------*/
2978 /* genRRC - rotate right with carry */
2979 /*-----------------------------------------------------------------*/
2980 static void genRRC (iCode *ic)
2985 /*-----------------------------------------------------------------*/
2986 /* genRLC - generate code for rotate left with carry */
2987 /*-----------------------------------------------------------------*/
2988 static void genRLC (iCode *ic)
2993 /*-----------------------------------------------------------------*/
2994 /* shiftR2Left2Result - shift right two bytes from left to result */
2995 /*-----------------------------------------------------------------*/
2996 static void shiftR2Left2Result (operand *left, int offl,
2997 operand *result, int offr,
2998 int shCount, int sign)
3000 if(sameRegs(AOP(result), AOP(left)) &&
3001 ((offl + MSB16) == offr)){
3004 movLeft2Result(left, offl, result, offr, 0);
3005 movLeft2Result(left, offl+1, result, offr+1, 0);
3012 /* if (AOP(result)->type == AOP_REG) {*/
3015 symbol *tlbl , *tlbl1;
3018 /* Left is already in result - so now do the shift */
3020 emitcode("ld","a,#%u+1", shCount);
3021 tlbl = newiTempLabel(NULL);
3022 tlbl1 = newiTempLabel(NULL);
3023 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3024 emitcode("", LABEL_STR ":",tlbl->key+100);
3027 emitcode("or", "a,a");
3030 l = aopGet(AOP(result), --offset, FALSE);
3031 emitcode("rr","%s", l);
3034 emitcode("", LABEL_STR ":",tlbl1->key+100);
3035 emitcode("dec", "a");
3036 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3041 /*-----------------------------------------------------------------*/
3042 /* shiftL2Left2Result - shift left two bytes from left to result */
3043 /*-----------------------------------------------------------------*/
3044 static void shiftL2Left2Result (operand *left, int offl,
3045 operand *result, int offr, int shCount)
3047 if(sameRegs(AOP(result), AOP(left)) &&
3048 ((offl + MSB16) == offr)){
3051 /* Copy left into result */
3052 movLeft2Result(left, offl, result, offr, 0);
3053 movLeft2Result(left, offl+1, result, offr+1, 0);
3055 /* PENDING: for now just see if it'll work. */
3056 /*if (AOP(result)->type == AOP_REG) { */
3060 symbol *tlbl , *tlbl1;
3063 /* Left is already in result - so now do the shift */
3065 emitcode("ld","a,#%u+1", shCount);
3066 tlbl = newiTempLabel(NULL);
3067 tlbl1 = newiTempLabel(NULL);
3068 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3069 emitcode("", LABEL_STR ":",tlbl->key+100);
3072 emitcode("or", "a,a");
3074 l = aopGet(AOP(result),offset++,FALSE);
3075 emitcode("rl","%s", l);
3078 emitcode("", LABEL_STR ":",tlbl1->key+100);
3079 emitcode("dec", "a");
3080 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3085 /*-----------------------------------------------------------------*/
3086 /* AccRol - rotate left accumulator by known count */
3087 /*-----------------------------------------------------------------*/
3088 static void AccRol (int shCount)
3090 shCount &= 0x0007; // shCount : 0..7
3127 /*-----------------------------------------------------------------*/
3128 /* AccLsh - left shift accumulator by known count */
3129 /*-----------------------------------------------------------------*/
3130 static void AccLsh (int shCount)
3134 emitcode("add","a,a");
3137 emitcode("add","a,a");
3138 emitcode("add","a,a");
3140 /* rotate left accumulator */
3142 /* and kill the lower order bits */
3143 emitcode("and","a,#0x%02x", SLMask[shCount]);
3148 /*-----------------------------------------------------------------*/
3149 /* shiftL1Left2Result - shift left one byte from left to result */
3150 /*-----------------------------------------------------------------*/
3151 static void shiftL1Left2Result (operand *left, int offl,
3152 operand *result, int offr, int shCount)
3155 l = aopGet(AOP(left),offl,FALSE);
3157 /* shift left accumulator */
3159 aopPut(AOP(result),"a",offr);
3163 /*-----------------------------------------------------------------*/
3164 /* genlshTwo - left shift two bytes by known amount != 0 */
3165 /*-----------------------------------------------------------------*/
3166 static void genlshTwo (operand *result,operand *left, int shCount)
3168 int size = AOP_SIZE(result);
3172 /* if shCount >= 8 */
3178 movLeft2Result(left, LSB, result, MSB16, 0);
3179 aopPut(AOP(result),zero, 0);
3180 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
3183 movLeft2Result(left, LSB, result, MSB16, 0);
3184 aopPut(AOP(result),zero, 0);
3187 aopPut(AOP(result),zero,LSB);
3189 /* 1 <= shCount <= 7 */
3195 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3200 /*-----------------------------------------------------------------*/
3201 /* genlshOne - left shift a one byte quantity by known count */
3202 /*-----------------------------------------------------------------*/
3203 static void genlshOne (operand *result, operand *left, int shCount)
3205 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3208 /*-----------------------------------------------------------------*/
3209 /* genLeftShiftLiteral - left shifting by known count */
3210 /*-----------------------------------------------------------------*/
3211 static void genLeftShiftLiteral (operand *left,
3216 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3219 freeAsmop(right,NULL,ic);
3221 aopOp(left,ic,FALSE);
3222 aopOp(result,ic,FALSE);
3224 size = getSize(operandType(result));
3227 emitcode("; shift left ","result %d, left %d",size,
3231 /* I suppose that the left size >= result size */
3236 else if(shCount >= (size * 8))
3238 aopPut(AOP(result),zero,size);
3242 genlshOne (result,left,shCount);
3245 genlshTwo (result,left,shCount);
3254 freeAsmop(left,NULL,ic);
3255 freeAsmop(result,NULL,ic);
3258 /*-----------------------------------------------------------------*/
3259 /* genLeftShift - generates code for left shifting */
3260 /*-----------------------------------------------------------------*/
3261 static void genLeftShift (iCode *ic)
3265 symbol *tlbl , *tlbl1;
3266 operand *left,*right, *result;
3268 right = IC_RIGHT(ic);
3270 result = IC_RESULT(ic);
3272 aopOp(right,ic,FALSE);
3274 /* if the shift count is known then do it
3275 as efficiently as possible */
3276 if (AOP_TYPE(right) == AOP_LIT) {
3277 genLeftShiftLiteral (left,right,result,ic);
3281 /* shift count is unknown then we have to form a loop get the loop
3282 count in B : Note: we take only the lower order byte since
3283 shifting more that 32 bits make no sense anyway, ( the largest
3284 size of an object can be only 32 bits ) */
3285 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3286 emitcode("inc","a");
3287 freeAsmop (right,NULL,ic);
3288 aopOp(left,ic,FALSE);
3289 aopOp(result,ic,FALSE);
3291 /* now move the left to the result if they are not the
3294 if (!sameRegs(AOP(left),AOP(result))) {
3296 size = AOP_SIZE(result);
3299 l = aopGet(AOP(left),offset,FALSE);
3300 aopPut(AOP(result),l,offset);
3305 size = AOP_SIZE(result);
3308 l = aopGet(AOP(left),offset,FALSE);
3309 aopPut(AOP(result),l,offset);
3315 tlbl = newiTempLabel(NULL);
3316 size = AOP_SIZE(result);
3318 tlbl1 = newiTempLabel(NULL);
3320 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3321 emitcode("", LABEL_STR ":",tlbl->key+100);
3322 l = aopGet(AOP(result),offset,FALSE);
3323 emitcode("or", "a,a");
3325 l = aopGet(AOP(result),offset++,FALSE);
3326 emitcode("rl","%s", l);
3328 emitcode("", LABEL_STR ":",tlbl1->key+100);
3329 emitcode("dec", "a");
3330 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3332 freeAsmop(left,NULL,ic);
3333 freeAsmop(result,NULL,ic);
3336 /* genlshTwo - left shift two bytes by known amount != 0 */
3337 /*-----------------------------------------------------------------*/
3338 static void genrshOne (operand *result,operand *left, int shCount)
3341 int size = AOP_SIZE(result);
3347 l = aopGet(AOP(left),0,FALSE);
3348 if (AOP(result)->type == AOP_REG) {
3349 aopPut(AOP(result), l, 0);
3350 l = aopGet(AOP(result), 0, FALSE);
3352 emitcode("srl", "%s", l);
3357 emitcode("srl", "a");
3359 aopPut(AOP(result),"a",0);
3363 /*-----------------------------------------------------------------*/
3364 /* AccRsh - right shift accumulator by known count */
3365 /*-----------------------------------------------------------------*/
3366 static void AccRsh (int shCount)
3373 /* rotate right accumulator */
3374 AccRol(8 - shCount);
3375 /* and kill the higher order bits */
3376 emitcode("and","a,#0x%02x", SRMask[shCount]);
3381 /*-----------------------------------------------------------------*/
3382 /* shiftR1Left2Result - shift right one byte from left to result */
3383 /*-----------------------------------------------------------------*/
3384 static void shiftR1Left2Result (operand *left, int offl,
3385 operand *result, int offr,
3386 int shCount, int sign)
3388 MOVA(aopGet(AOP(left),offl,FALSE));
3395 aopPut(AOP(result),"a",offr);
3398 /*-----------------------------------------------------------------*/
3399 /* genrshTwo - right shift two bytes by known amount != 0 */
3400 /*-----------------------------------------------------------------*/
3401 static void genrshTwo (operand *result,operand *left,
3402 int shCount, int sign)
3404 /* if shCount >= 8 */
3409 shiftR1Left2Result(left, MSB16, result, LSB,
3413 movLeft2Result(left, MSB16, result, LSB, sign);
3414 aopPut(AOP(result),zero,1);
3417 /* 1 <= shCount <= 7 */
3419 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3423 /*-----------------------------------------------------------------*/
3424 /* genRightShiftLiteral - left shifting by known count */
3425 /*-----------------------------------------------------------------*/
3426 static void genRightShiftLiteral (operand *left,
3431 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3434 freeAsmop(right,NULL,ic);
3436 aopOp(left,ic,FALSE);
3437 aopOp(result,ic,FALSE);
3439 size = getSize(operandType(result));
3441 emitcode("; shift right ","result %d, left %d",size,
3444 /* I suppose that the left size >= result size */
3449 else if(shCount >= (size * 8))
3451 aopPut(AOP(result),zero,size);
3455 genrshOne(result, left, shCount);
3458 /* PENDING: sign support */
3459 genrshTwo(result, left, shCount, FALSE);
3468 freeAsmop(left,NULL,ic);
3469 freeAsmop(result,NULL,ic);
3472 /*-----------------------------------------------------------------*/
3473 /* genRightShift - generate code for right shifting */
3474 /*-----------------------------------------------------------------*/
3475 static void genRightShift (iCode *ic)
3477 operand *left,*right, *result;
3479 right = IC_RIGHT(ic);
3481 result = IC_RESULT(ic);
3483 aopOp(right,ic,FALSE);
3485 /* if the shift count is known then do it
3486 as efficiently as possible */
3487 if (AOP_TYPE(right) == AOP_LIT) {
3488 genRightShiftLiteral (left,right,result,ic);
3496 /*-----------------------------------------------------------------*/
3497 /* genGenPointerGet - gget value from generic pointer space */
3498 /*-----------------------------------------------------------------*/
3499 static void genGenPointerGet (operand *left,
3500 operand *result, iCode *ic)
3503 link *retype = getSpec(operandType(result));
3504 const char *ptr = "hl";
3509 aopOp(left,ic,FALSE);
3510 aopOp(result,ic,FALSE);
3512 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3514 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3515 aopPut(AOP(result),"a", 0);
3516 freeAsmop(left,NULL,ic);
3520 /* For now we always load into IY */
3521 /* if this is remateriazable */
3522 if (AOP_TYPE(left) == AOP_IMMD)
3523 emitcode("ld","%s,%s", ptr, aopGet(AOP(left),0,TRUE));
3524 else { /* we need to get it byte by byte */
3526 emitcode("ld", "e,%s ; 1", aopGet(AOP(left), 0, FALSE));
3527 emitcode("ld", "d,%s ; 2", aopGet(AOP(left), 1, FALSE));
3532 /* so iy now contains the address */
3533 freeAsmop(left,NULL,ic);
3535 /* if bit then unpack */
3536 if (IS_BITVAR(retype)) {
3540 size = AOP_SIZE(result);
3544 /* PENDING: make this better */
3545 if (!IS_GB && AOP(result)->type == AOP_REG) {
3546 aopPut(AOP(result),"(hl)",offset++);
3549 emitcode("ld", "a,(%s)", ptr, offset);
3550 aopPut(AOP(result),"a",offset++);
3553 emitcode("inc", "%s", ptr);
3559 freeAsmop(result,NULL,ic);
3562 /*-----------------------------------------------------------------*/
3563 /* genPointerGet - generate code for pointer get */
3564 /*-----------------------------------------------------------------*/
3565 static void genPointerGet (iCode *ic)
3567 operand *left, *result ;
3571 result = IC_RESULT(ic) ;
3573 /* depending on the type of pointer we need to
3574 move it to the correct pointer register */
3575 type = operandType(left);
3576 etype = getSpec(type);
3578 genGenPointerGet (left,result,ic);
3581 bool isRegOrLit(asmop *aop)
3583 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3588 static void fetchPair(int pairId, asmop *aop)
3590 /* if this is remateriazable */
3591 if (aop->type == AOP_IMMD) {
3592 fetchLitPair(pairId, aop, 0);
3594 else { /* we need to get it byte by byte */
3595 if (pairId == PAIR_HL) {
3599 emitcode("ld", "%s,%s", _pairs[pairId].l, 0, TRUE);
3600 emitcode("ld", "%s,%s", _pairs[pairId].h, 1, TRUE);
3605 /*-----------------------------------------------------------------*/
3606 /* genGenPointerSet - stores the value into a pointer location */
3607 /*-----------------------------------------------------------------*/
3608 static void genGenPointerSet (operand *right,
3609 operand *result, iCode *ic)
3612 link *retype = getSpec(operandType(right));
3613 int pairId = PAIR_HL;
3615 aopOp(result,ic,FALSE);
3616 aopOp(right,ic,FALSE);
3621 /* Handle the exceptions first */
3622 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3624 char *l = aopGet(AOP(right), 0, FALSE);
3625 const char *pair = getPairName(AOP(result));
3626 if (canAssignToPtr(l) && isPtr(pair)) {
3627 emitcode("ld", "(%s),%s", pair, l);
3631 emitcode("ld", "(%s),a ; 1", pair);
3636 /* if the operand is already in dptr
3637 then we do nothing else we move the value to dptr */
3638 if (AOP_TYPE(result) != AOP_STR) {
3639 fetchPair(pairId, AOP(result));
3641 /* so hl know contains the address */
3642 freeAsmop(result,NULL,ic);
3644 /* if bit then unpack */
3645 if (IS_BITVAR(retype)) {
3649 size = AOP_SIZE(right);
3653 char *l = aopGet(AOP(right),offset,FALSE);
3654 if (isRegOrLit(AOP(right)) && !IS_GB) {
3655 emitcode("ld", "(%s),%s ; 2", _pairs[pairId].name, l);
3659 emitcode("ld", "(%s),a ; 3", _pairs[pairId].name, offset);
3662 emitcode("inc", _pairs[pairId].name);
3668 freeAsmop(right,NULL,ic);
3671 /*-----------------------------------------------------------------*/
3672 /* genPointerSet - stores the value into a pointer location */
3673 /*-----------------------------------------------------------------*/
3674 static void genPointerSet (iCode *ic)
3676 operand *right, *result ;
3679 right = IC_RIGHT(ic);
3680 result = IC_RESULT(ic) ;
3682 /* depending on the type of pointer we need to
3683 move it to the correct pointer register */
3684 type = operandType(result);
3685 etype = getSpec(type);
3687 genGenPointerSet (right,result,ic);
3690 /*-----------------------------------------------------------------*/
3691 /* genIfx - generate code for Ifx statement */
3692 /*-----------------------------------------------------------------*/
3693 static void genIfx (iCode *ic, iCode *popIc)
3695 operand *cond = IC_COND(ic);
3698 aopOp(cond,ic,FALSE);
3700 /* get the value into acc */
3701 if (AOP_TYPE(cond) != AOP_CRY)
3705 /* the result is now in the accumulator */
3706 freeAsmop(cond,NULL,ic);
3708 /* if there was something to be popped then do it */
3712 /* if the condition is a bit variable */
3713 if (isbit && IS_ITEMP(cond) &&
3715 genIfxJump(ic,SPIL_LOC(cond)->rname);
3717 if (isbit && !IS_ITEMP(cond))
3718 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3725 /*-----------------------------------------------------------------*/
3726 /* genAddrOf - generates code for address of */
3727 /*-----------------------------------------------------------------*/
3728 static void genAddrOf (iCode *ic)
3730 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3732 aopOp(IC_RESULT(ic),ic,FALSE);
3734 /* if the operand is on the stack then we
3735 need to get the stack offset of this
3739 emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _pushed, _spoffset);
3740 emitcode("ld", "d,h");
3741 emitcode("ld", "e,l");
3744 emitcode("ld", "de,#%s", sym->rname);
3746 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3747 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3751 /* if it has an offset then we need to compute it */
3752 emitcode("push", "de");
3753 emitcode("push", "ix");
3754 emitcode("pop", "hl");
3755 emitcode("ld", "de,#%d", sym->stack);
3756 emitcode("add", "hl,de");
3757 emitcode("pop", "de");
3760 emitcode("ld", "hl,#%s", sym->rname);
3762 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3763 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3765 freeAsmop(IC_RESULT(ic),NULL,ic);
3768 /*-----------------------------------------------------------------*/
3769 /* genAssign - generate code for assignment */
3770 /*-----------------------------------------------------------------*/
3771 static void genAssign (iCode *ic)
3773 operand *result, *right;
3775 unsigned long lit = 0L;
3777 result = IC_RESULT(ic);
3778 right = IC_RIGHT(ic) ;
3781 /* Dont bother assigning if they are the same */
3782 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3783 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3788 aopOp(right,ic,FALSE);
3789 aopOp(result,ic,TRUE);
3791 /* if they are the same registers */
3792 if (sameRegs(AOP(right),AOP(result))) {
3793 emitcode("", "; (registers are the same)");
3797 /* if the result is a bit */
3798 if (AOP_TYPE(result) == AOP_CRY) {
3803 size = AOP_SIZE(result);
3806 if(AOP_TYPE(right) == AOP_LIT)
3807 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3808 if (isPair(AOP(result)) && AOP_TYPE(right) == AOP_LIT) {
3809 emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
3811 else if((size > 1) &&
3812 (AOP_TYPE(result) != AOP_REG) &&
3813 (AOP_TYPE(right) == AOP_LIT) &&
3814 !IS_FLOAT(operandType(right)) &&
3816 bool fXored = FALSE;
3818 /* Work from the top down.
3819 Done this way so that we can use the cached copy of 0
3820 in A for a fast clear */
3822 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3823 if (!fXored && size>1) {
3824 emitcode("xor", "a,a");
3828 aopPut(AOP(result),"a",offset);
3831 aopPut(AOP(result), "#0", offset);
3836 aopGet(AOP(right),offset,FALSE),
3841 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
3842 /* Special case. Load into a and d, then load out. */
3843 MOVA(aopGet(AOP(right), 0, FALSE));
3844 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
3845 aopPut(AOP(result), "a", 0);
3846 aopPut(AOP(result), "e", 1);
3850 aopGet(AOP(right),offset,FALSE),
3857 freeAsmop(right,NULL,ic);
3858 freeAsmop(result,NULL,ic);
3861 /*-----------------------------------------------------------------*/
3862 /* genJumpTab - genrates code for jump table */
3863 /*-----------------------------------------------------------------*/
3864 static void genJumpTab (iCode *ic)
3869 aopOp(IC_JTCOND(ic),ic,FALSE);
3870 /* get the condition into accumulator */
3871 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3874 emitcode("push", "de");
3875 emitcode("ld", "e,%s", l);
3876 emitcode("ld", "d,#0");
3877 jtab = newiTempLabel(NULL);
3878 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3879 emitcode("add", "hl,de");
3880 emitcode("add", "hl,de");
3881 emitcode("add", "hl,de");
3882 freeAsmop(IC_JTCOND(ic),NULL,ic);
3884 emitcode("pop", "de");
3885 emitcode("jp", "(hl)");
3886 emitcode("","%05d$:",jtab->key+100);
3887 /* now generate the jump labels */
3888 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3889 jtab = setNextItem(IC_JTLABELS(ic)))
3890 emitcode("jp", LABEL_STR, jtab->key+100);
3893 /*-----------------------------------------------------------------*/
3894 /* genCast - gen code for casting */
3895 /*-----------------------------------------------------------------*/
3896 static void genCast (iCode *ic)
3898 operand *result = IC_RESULT(ic);
3899 link *ctype = operandType(IC_LEFT(ic));
3900 operand *right = IC_RIGHT(ic);
3903 /* if they are equivalent then do nothing */
3904 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3907 aopOp(right,ic,FALSE) ;
3908 aopOp(result,ic,FALSE);
3910 /* if the result is a bit */
3911 if (AOP_TYPE(result) == AOP_CRY) {
3915 /* if they are the same size : or less */
3916 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3918 /* if they are in the same place */
3919 if (sameRegs(AOP(right),AOP(result)))
3922 /* if they in different places then copy */
3923 size = AOP_SIZE(result);
3927 aopGet(AOP(right),offset,FALSE),
3934 /* PENDING: should be OK. */
3936 /* if the result is of type pointer */
3937 if (IS_PTR(ctype)) {
3942 /* so we now know that the size of destination is greater
3943 than the size of the source */
3944 /* we move to result for the size of source */
3945 size = AOP_SIZE(right);
3949 aopGet(AOP(right),offset,FALSE),
3954 /* now depending on the sign of the destination */
3955 size = AOP_SIZE(result) - AOP_SIZE(right);
3956 /* Unsigned or not an integral type - right fill with zeros */
3957 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3959 aopPut(AOP(result),zero,offset++);
3961 /* we need to extend the sign :{ */
3962 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3965 emitcode("", "; genCast: sign extend untested.");
3966 emitcode("rla", "");
3967 emitcode("sbc", "a,a");
3969 aopPut(AOP(result),"a",offset++);
3973 freeAsmop(right, NULL, ic);
3974 freeAsmop(result, NULL, ic);
3977 /*-----------------------------------------------------------------*/
3978 /* genReceive - generate code for a receive iCode */
3979 /*-----------------------------------------------------------------*/
3980 static void genReceive (iCode *ic)
3982 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3983 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3984 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3988 aopOp(IC_RESULT(ic),ic,FALSE);
3990 assignResultValue(IC_RESULT(ic));
3993 freeAsmop(IC_RESULT(ic),NULL,ic);
3996 /*-----------------------------------------------------------------*/
3997 /* genZ80Code - generate code for Z80 based controllers */
3998 /*-----------------------------------------------------------------*/
3999 void genZ80Code (iCode *lic)
4006 _fReturn = _gbz80_return;
4007 _fTmp = _gbz80_return;
4011 _fReturn = _z80_return;
4012 _fTmp = _z80_return;
4016 lineHead = lineCurr = NULL;
4018 /* if debug information required */
4019 if (options.debug && currFunc) {
4020 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4022 if (IS_STATIC(currFunc->etype))
4023 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4025 emitcode("","G$%s$0$0 ==.",currFunc->name);
4028 /* stack pointer name */
4032 for (ic = lic ; ic ; ic = ic->next ) {
4034 if ( cln != ic->lineno ) {
4035 if ( options.debug ) {
4037 emitcode("","C$%s$%d$%d$%d ==.",
4038 ic->filename,ic->lineno,
4039 ic->level,ic->block);
4042 emitcode(";","%s %d",ic->filename,ic->lineno);
4045 /* if the result is marked as
4046 spilt and rematerializable or code for
4047 this has already been generated then
4049 if (resultRemat(ic) || ic->generated )
4052 /* depending on the operation */
4055 emitcode("", "; genNot");
4060 emitcode("", "; genCpl");
4065 emitcode("", "; genUminus");
4070 emitcode("", "; genIpush");
4075 /* IPOP happens only when trying to restore a
4076 spilt live range, if there is an ifx statement
4077 following this pop then the if statement might
4078 be using some of the registers being popped which
4079 would destory the contents of the register so
4080 we need to check for this condition and handle it */
4082 ic->next->op == IFX &&
4083 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4084 emitcode("", "; genIfx");
4085 genIfx (ic->next,ic);
4088 emitcode("", "; genIpop");
4094 emitcode("", "; genCall");
4099 emitcode("", "; genPcall");
4104 emitcode("", "; genFunction");
4109 emitcode("", "; genEndFunction");
4110 genEndFunction (ic);
4114 emitcode("", "; genRet");
4119 emitcode("", "; genLabel");
4124 emitcode("", "; genGoto");
4129 emitcode("", "; genPlus");
4134 emitcode("", "; genMinus");
4139 emitcode("", "; genMult");
4144 emitcode("", "; genDiv");
4149 emitcode("", "; genMod");
4154 emitcode("", "; genCmpGt");
4155 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4159 emitcode("", "; genCmpLt");
4160 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4167 /* note these two are xlated by algebraic equivalence
4168 during parsing SDCC.y */
4169 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4170 "got '>=' or '<=' shouldn't have come here");
4174 emitcode("", "; genCmpEq");
4175 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4179 emitcode("", "; genAndOp");
4184 emitcode("", "; genOrOp");
4189 emitcode("", "; genXor");
4190 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4194 emitcode("", "; genOr");
4195 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4199 emitcode("", "; genAnd");
4200 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4204 emitcode("", "; genInline");
4209 emitcode("", "; genRRC");
4214 emitcode("", "; genRLC");
4219 emitcode("", "; genHBIT");
4223 emitcode("", "; genLeftShift");
4228 emitcode("", "; genRightShift");
4232 case GET_VALUE_AT_ADDRESS:
4233 emitcode("", "; genPointerGet");
4239 if (POINTER_SET(ic)) {
4240 emitcode("", "; genAssign (pointer)");
4244 emitcode("", "; genAssign");
4250 emitcode("", "; genIfx");
4255 emitcode("", "; genAddrOf");
4260 emitcode("", "; genJumpTab");
4265 emitcode("", "; genCast");
4270 emitcode("", "; genReceive");
4275 emitcode("", "; addSet");
4276 addSet(&sendSet,ic);
4281 /* piCode(ic,stdout); */
4287 /* now we are ready to call the
4288 peep hole optimizer */
4289 if (!options.nopeep)
4290 peepHole (&lineHead);
4292 /* now do the actual printing */
4293 printLine (lineHead,codeOutFile);