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
21 Michael Hope <michaelh@earthling.net> 2000
22 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
23 and - Jean-Louis VERN.jlvern@writeme.com (1999)
25 This program is free software; you can redistribute it and/or modify it
26 under the terms of the GNU General Public License as published by the
27 Free Software Foundation; either version 2, or (at your option) any
30 This program is distributed in the hope that it will be useful,
31 but WITHOUT ANY WARRANTY; without even the implied warranty of
32 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
33 GNU General Public License for more details.
36 You should have received a copy of the GNU General Public License
37 along with this program; if not, write to the Free Software
38 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
40 In other words, you are welcome to use, share and improve this program.
41 You are forbidden to forbid anyone else to use, share and improve
42 what you give them. Help stamp out software-hoarding!
44 -------------------------------------------------------------------------*/
51 #ifdef HAVE_SYS_ISA_DEFS_H
52 #include <sys/isa_defs.h>
56 #include "SDCCpeeph.h"
60 /* this is the down and dirty file with all kinds of kludgy & hacky
61 stuff. This is what it is all about CODE GENERATION for a specific MCU.
62 Some of the routines may be reusable, will have to see */
65 static char *_z80_return[] = {"l", "h", "e", "d" };
66 static char *_gbz80_return[] = { "e", "d", "l", "h" };
67 static char **_fReturn;
73 static char *accUse[] = {"a" };
79 extern int ptrRegReq ;
81 extern FILE *codeOutFile;
98 } _pairs[NUM_PAIRS] = {
103 { "iy", "iy.l?", "iy.h?" },
104 { "ix", "ix.l?", "ix.h?" }
107 #define RESULTONSTACK(x) \
108 (IC_RESULT(x) && IC_RESULT(x)->aop && \
109 IC_RESULT(x)->aop->type == AOP_STK )
111 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
112 #define CLRC emitcode("xor","a,a");
114 lineNode *lineHead = NULL;
115 lineNode *lineCurr = NULL;
117 static const unsigned char SLMask[] =
118 {0xFF ,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
119 static const unsigned char SRMask[] =
120 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
148 static char *aopGet(asmop *aop, int offset, bool bit16);
150 static void _tidyUp(char *buf)
152 /* Clean up the line so that it is 'prettier' */
153 if (strchr(buf, ':')) {
154 /* Is a label - cant do anything */
157 /* Change the first (and probably only) ' ' to a tab so
169 static void emit2(const char *szFormat, ...)
174 va_start(ap, szFormat);
176 tvsprintf(buffer, szFormat, ap);
179 lineCurr = (lineCurr ?
180 connectLine(lineCurr,newLineNode(buffer)) :
181 (lineHead = newLineNode(buffer)));
183 lineCurr->isInline = inLine;
184 lineCurr->isDebug = debugLine;
187 /*-----------------------------------------------------------------*/
188 /* emitcode - writes the code into a file : for now it is simple */
189 /*-----------------------------------------------------------------*/
190 void emitcode (const char *inst, const char *fmt, ...)
193 char lb[MAX_INLINEASM];
199 sprintf(lb,"%s\t",inst);
200 vsprintf(lb+(strlen(lb)),fmt,ap);
204 while (isspace(*lbp)) lbp++;
207 lineCurr = (lineCurr ?
208 connectLine(lineCurr,newLineNode(lb)) :
209 (lineHead = newLineNode(lb)));
210 lineCurr->isInline = inLine;
211 lineCurr->isDebug = debugLine;
228 emitcode("ld", "sp,ix");
229 emitcode("pop", "ix");
230 emitcode("pop", "de");
235 const char *getPairName(asmop *aop)
237 if (aop->type == AOP_REG) {
238 switch (aop->aopu.aop_reg[0]->rIdx) {
250 else if (aop->type == AOP_STR) {
251 switch (*aop->aopu.aop_str[0]) {
267 static PAIR_ID getPairId(asmop *aop)
269 if (aop->size == 2) {
270 if (aop->type == AOP_REG) {
271 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
274 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
277 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
281 if (aop->type == AOP_STR) {
282 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
285 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
288 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
296 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
297 bool isPair(asmop *aop)
299 return (getPairId(aop) != PAIR_INVALID);
302 bool isPtrPair(asmop *aop)
304 PAIR_ID pairId = getPairId(aop);
314 /** Push a register pair onto the stack */
315 void genPairPush(asmop *aop)
317 emitcode("push", "%s", getPairName(aop));
321 /*-----------------------------------------------------------------*/
322 /* newAsmop - creates a new asmOp */
323 /*-----------------------------------------------------------------*/
324 static asmop *newAsmop (short type)
328 ALLOC(aop,sizeof(asmop));
333 /*-----------------------------------------------------------------*/
334 /* aopForSym - for a true symbol */
335 /*-----------------------------------------------------------------*/
336 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
339 memmap *space= SPEC_OCLS(sym->etype);
341 /* if already has one */
345 /* Assign depending on the storage class */
346 if (sym->onStack || sym->iaccess) {
347 sym->aop = aop = newAsmop(AOP_STK);
348 aop->size = getSize(sym->type);
349 aop->aopu.aop_stk = sym->stack;
353 /* special case for a function */
354 if (IS_FUNC(sym->type)) {
355 sym->aop = aop = newAsmop(AOP_IMMD);
356 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
357 strcpy(aop->aopu.aop_immd,sym->rname);
364 /* if it is in direct space */
365 if (IN_DIRSPACE(space)) {
366 sym->aop = aop = newAsmop (AOP_DIR);
367 aop->aopu.aop_dir = sym->rname ;
368 aop->size = getSize(sym->type);
369 emitcode("", "; AOP_DIR for %s", sym->rname);
375 /* only remaining is far space */
376 /* in which case DPTR gets the address */
378 sym->aop = aop = newAsmop(AOP_HL);
381 sym->aop = aop = newAsmop(AOP_IY);
383 aop->size = getSize(sym->type);
384 aop->aopu.aop_dir = sym->rname;
386 /* if it is in code space */
387 if (IN_CODESPACE(space))
393 /*-----------------------------------------------------------------*/
394 /* aopForRemat - rematerialzes an object */
395 /*-----------------------------------------------------------------*/
396 static asmop *aopForRemat (symbol *sym)
399 iCode *ic = sym->rematiCode;
400 asmop *aop = newAsmop(AOP_IMMD);
403 /* if plus or minus print the right hand side */
404 if (ic->op == '+' || ic->op == '-') {
405 /* PENDING: for re-target */
406 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
409 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
412 /* we reached the end */
413 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
417 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
418 strcpy(aop->aopu.aop_immd,buffer);
422 /*-----------------------------------------------------------------*/
423 /* regsInCommon - two operands have some registers in common */
424 /*-----------------------------------------------------------------*/
425 bool regsInCommon (operand *op1, operand *op2)
430 /* if they have registers in common */
431 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
434 sym1 = OP_SYMBOL(op1);
435 sym2 = OP_SYMBOL(op2);
437 if (sym1->nRegs == 0 || sym2->nRegs == 0)
440 for (i = 0 ; i < sym1->nRegs ; i++) {
445 for (j = 0 ; j < sym2->nRegs ;j++ ) {
449 if (sym2->regs[j] == sym1->regs[i])
457 /*-----------------------------------------------------------------*/
458 /* operandsEqu - equivalent */
459 /*-----------------------------------------------------------------*/
460 bool operandsEqu ( operand *op1, operand *op2)
464 /* if they not symbols */
465 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
468 sym1 = OP_SYMBOL(op1);
469 sym2 = OP_SYMBOL(op2);
471 /* if both are itemps & one is spilt
472 and the other is not then false */
473 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
474 sym1->isspilt != sym2->isspilt )
477 /* if they are the same */
481 if (strcmp(sym1->rname,sym2->rname) == 0)
485 /* if left is a tmp & right is not */
489 (sym1->usl.spillLoc == sym2))
496 (sym2->usl.spillLoc == sym1))
502 /*-----------------------------------------------------------------*/
503 /* sameRegs - two asmops have the same registers */
504 /*-----------------------------------------------------------------*/
505 bool sameRegs (asmop *aop1, asmop *aop2 )
512 if (aop1->type != AOP_REG ||
513 aop2->type != AOP_REG )
516 if (aop1->size != aop2->size)
519 for (i = 0 ; i < aop1->size ; i++ )
520 if (aop1->aopu.aop_reg[i] !=
521 aop2->aopu.aop_reg[i] )
527 /*-----------------------------------------------------------------*/
528 /* aopOp - allocates an asmop for an operand : */
529 /*-----------------------------------------------------------------*/
530 static void aopOp (operand *op, iCode *ic, bool result)
539 /* if this a literal */
540 if (IS_OP_LITERAL(op)) {
541 op->aop = aop = newAsmop(AOP_LIT);
542 aop->aopu.aop_lit = op->operand.valOperand;
543 aop->size = getSize(operandType(op));
547 /* if already has a asmop then continue */
551 /* if the underlying symbol has a aop */
552 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
553 op->aop = OP_SYMBOL(op)->aop;
557 /* if this is a true symbol */
558 if (IS_TRUE_SYMOP(op)) {
559 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
563 /* this is a temporary : this has
569 e) can be a return use only */
573 /* if the type is a conditional */
574 if (sym->regType == REG_CND) {
575 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
580 /* if it is spilt then two situations
582 b) has a spill location */
583 if (sym->isspilt || sym->nRegs == 0) {
584 /* rematerialize it NOW */
586 sym->aop = op->aop = aop =
588 aop->size = getSize(sym->type);
594 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
595 aop->size = getSize(sym->type);
596 for ( i = 0 ; i < 2 ; i++ )
597 aop->aopu.aop_str[i] = accUse[i];
603 aop = op->aop = sym->aop = newAsmop(AOP_STR);
604 aop->size = getSize(sym->type);
605 for ( i = 0 ; i < 4 ; i++ )
606 aop->aopu.aop_str[i] = _fReturn[i];
610 /* else spill location */
611 sym->aop = op->aop = aop =
612 aopForSym(ic,sym->usl.spillLoc,result);
613 aop->size = getSize(sym->type);
617 /* must be in a register */
618 sym->aop = op->aop = aop = newAsmop(AOP_REG);
619 aop->size = sym->nRegs;
620 for ( i = 0 ; i < sym->nRegs ;i++)
621 aop->aopu.aop_reg[i] = sym->regs[i];
624 /*-----------------------------------------------------------------*/
625 /* freeAsmop - free up the asmop given to an operand */
626 /*----------------------------------------------------------------*/
627 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
645 /* all other cases just dealloc */
649 OP_SYMBOL(op)->aop = NULL;
650 /* if the symbol has a spill */
652 SPIL_LOC(op)->aop = NULL;
657 bool isLitWord(asmop *aop)
659 /* if (aop->size != 2)
670 char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
676 if (aop->size != 2 && aop->type != AOP_HL)
679 wassert(offset == 0);
681 /* depending on type */
686 /* PENDING: for re-target */
688 tsprintf(s, "!hashed", aop->aopu.aop_immd);
690 strcpy(s, aop->aopu.aop_immd);
691 ALLOC_ATOMIC(rs,strlen(s)+1);
695 value * val = aop->aopu.aop_lit;
696 /* if it is a float then it gets tricky */
697 /* otherwise it is fairly simple */
698 if (!IS_FLOAT(val->type)) {
699 unsigned long v = floatFromVal(val);
701 tsprintf(buffer, "!immedword", v);
703 tsprintf(buffer, "!constword", v);
704 ALLOC_ATOMIC(rs,strlen(buffer)+1);
705 return strcpy (rs,buffer);
715 char *aopGetWord(asmop *aop, int offset)
717 return aopGetLitWordLong(aop, offset, TRUE);
720 bool isPtr(const char *s)
722 if (!strcmp(s, "hl"))
724 if (!strcmp(s, "ix"))
726 if (!strcmp(s, "iy"))
731 static void adjustPair(const char *pair, int *pold, int new)
735 while (*pold < new) {
736 emitcode("inc", "%s", pair);
739 while (*pold > new) {
740 emitcode("dec", "%s", pair);
745 static void spillPair(PAIR_ID pairId)
747 _G.pairs[pairId].last_type = AOP_INVALID;
748 _G.pairs[pairId].lit = NULL;
751 static void spillCached(void)
757 static bool requiresHL(asmop *aop)
768 static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
771 const char *pair = _pairs[pairId].name;
772 l = aopGetLitWordLong(left, 0, FALSE);
776 if (pairId == PAIR_HL || pairId == PAIR_IY) {
777 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
778 if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
779 adjustPair(pair, &_G.pairs[pairId].offset, offset);
782 if (pairId == PAIR_IY && abs(offset)<127) {
787 _G.pairs[pairId].last_type = left->type;
788 _G.pairs[pairId].lit = gc_strdup(l);
789 _G.pairs[pairId].offset = offset;
791 /* Both a lit on the right and a true symbol on the left */
792 /* PENDING: for re-target */
794 emit2("ld %s,!hashedstr + %d", pair, l, offset);
796 emit2("ld %s,!hashedstr", pair, l);
799 static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
801 /* if this is remateriazable */
802 if (isLitWord(aop)) {
803 fetchLitPair(pairId, aop, offset);
805 else { /* we need to get it byte by byte */
806 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
807 aopGet(aop, offset, FALSE);
813 emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE));
814 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, offset+1, FALSE));
816 /* PENDING: check? */
817 if (pairId == PAIR_HL)
822 static void fetchPair(PAIR_ID pairId, asmop *aop)
824 fetchPairLong(pairId, aop, 0);
827 static void fetchHL(asmop *aop)
829 fetchPair(PAIR_HL, aop);
832 static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
834 assert(pairId == PAIR_HL || pairId == PAIR_IY);
839 fetchLitPair(pairId, aop, offset);
840 _G.pairs[pairId].offset = offset;
843 /* Doesnt include _G.stack.pushed */
844 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
845 assert(pairId == PAIR_HL);
846 /* In some cases we can still inc or dec hl */
847 if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
848 adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
851 emit2("!ldahlsp", aop->aopu.aop_stk+offset + _G.stack.pushed + _G.stack.offset);
853 _G.pairs[pairId].offset = abso;
859 _G.pairs[pairId].last_type = aop->type;
862 static void emitLabel(int key)
864 emit2("!tlabeldef", key);
868 /*-----------------------------------------------------------------*/
869 /* aopGet - for fetching value of the aop */
870 /*-----------------------------------------------------------------*/
871 static char *aopGet(asmop *aop, int offset, bool bit16)
876 /* offset is greater than size then zero */
877 /* PENDING: this seems a bit screwed in some pointer cases. */
878 if (offset > (aop->size - 1) &&
879 aop->type != AOP_LIT)
882 /* depending on type */
885 /* PENDING: re-target */
887 tsprintf (s,"!immedwords", aop->aopu.aop_immd);
890 wassert(offset == 1);
891 tsprintf(s, "!lsbimmeds", aop->aopu.aop_immd);
894 tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
895 ALLOC_ATOMIC(rs,strlen(s)+1);
901 /* PENDING: for re-target: currently unsupported. */
903 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
905 ALLOC_ATOMIC(rs,strlen(s)+1);
910 return aop->aopu.aop_reg[offset]->name;
914 setupPair(PAIR_HL, aop, offset);
920 setupPair(PAIR_IY, aop, offset);
921 tsprintf(s,"!*iyx", offset);
922 ALLOC_ATOMIC(rs,strlen(s)+1);
928 setupPair(PAIR_HL, aop, offset);
932 tsprintf(s,"!*ixx", aop->aopu.aop_stk+offset);
934 ALLOC_ATOMIC(rs,strlen(s)+1);
948 return aopLiteral (aop->aopu.aop_lit,offset);
952 return aop->aopu.aop_str[offset];
956 wassertl(0, "aopget got unsupported aop->type");
960 bool isRegString(char *s)
962 if (!strcmp(s, "b") ||
973 bool isConstant(const char *s)
975 /* This is a bit of a hack... */
976 return (*s == '#' || *s == '$');
979 bool canAssignToPtr(char *s)
988 /*-----------------------------------------------------------------*/
989 /* aopPut - puts a string for a aop */
990 /*-----------------------------------------------------------------*/
991 static void aopPut (asmop *aop, char *s, int offset)
993 if (aop->size && offset > ( aop->size - 1)) {
994 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
995 "aopPut got offset > aop->size");
999 /* will assign value to value */
1000 /* depending on where it is ofcourse */
1001 switch (aop->type) {
1005 /* Currently unsupported */
1007 emitcode("ld", "a,%s", s);
1008 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1012 emitcode("ld","%s,%s",
1013 aop->aopu.aop_reg[offset]->name,s);
1018 setupPair(PAIR_IY, aop, offset);
1019 if (!canAssignToPtr(s)) {
1020 emit2("ld a,%s", s);
1021 emit2("ld !*iyx,a", offset);
1024 emit2("ld !*iyx,%s", offset, s);
1029 /* PENDING: for re-target */
1030 if (!strcmp(s, "!*hl")) {
1034 setupPair(PAIR_HL, aop, offset);
1036 emit2("ld !*hl,%s", s);
1041 /* PENDING: re-target */
1042 if (!strcmp("!*hl", s)) {
1046 setupPair(PAIR_HL, aop, offset);
1047 if (!canAssignToPtr(s)) {
1048 emit2("ld a,%s", s);
1052 emit2("ld !*hl,%s ; 3", s);
1055 if (!canAssignToPtr(s)) {
1056 emit2("ld a,%s", s);
1057 emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
1060 emit2("ld !*ixx,%s", aop->aopu.aop_stk+offset, s);
1065 /* if bit variable */
1066 if (!aop->aopu.aop_dir) {
1070 /* In bit space but not in C - cant happen */
1077 if (strcmp(aop->aopu.aop_str[offset],s)) {
1078 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1084 if (!offset && (strcmp(s,"acc") == 0))
1088 emitcode("", "; Error aopPut AOP_ACC");
1091 if (strcmp(aop->aopu.aop_str[offset],s))
1092 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1097 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1098 "aopPut got unsupported aop->type");
1103 #define AOP(op) op->aop
1104 #define AOP_TYPE(op) AOP(op)->type
1105 #define AOP_SIZE(op) AOP(op)->size
1106 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1108 /*-----------------------------------------------------------------*/
1109 /* getDataSize - get the operand data size */
1110 /*-----------------------------------------------------------------*/
1111 int getDataSize(operand *op)
1114 size = AOP_SIZE(op);
1122 /*-----------------------------------------------------------------*/
1123 /* movLeft2Result - move byte from left to result */
1124 /*-----------------------------------------------------------------*/
1125 static void movLeft2Result (operand *left, int offl,
1126 operand *result, int offr, int sign)
1129 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1130 l = aopGet(AOP(left),offl,FALSE);
1133 aopPut(AOP(result),l,offr);
1142 /** Put Acc into a register set
1144 void outAcc(operand *result)
1147 size = getDataSize(result);
1149 aopPut(AOP(result),"a",0);
1152 /* unsigned or positive */
1154 aopPut(AOP(result), zero, offset++);
1159 /** Take the value in carry and put it into a register
1161 void outBitC(operand *result)
1163 /* if the result is bit */
1164 if (AOP_TYPE(result) == AOP_CRY) {
1165 emitcode("", "; Note: outBitC form 1");
1166 aopPut(AOP(result),"blah",0);
1169 emit2("ld a,!zero");
1175 /*-----------------------------------------------------------------*/
1176 /* toBoolean - emit code for orl a,operator(sizeop) */
1177 /*-----------------------------------------------------------------*/
1178 void toBoolean(operand *oper)
1180 int size = AOP_SIZE(oper);
1183 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1186 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1189 if (AOP(oper)->type != AOP_ACC) {
1191 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1196 /*-----------------------------------------------------------------*/
1197 /* genNot - generate code for ! operation */
1198 /*-----------------------------------------------------------------*/
1199 static void genNot (iCode *ic)
1201 link *optype = operandType(IC_LEFT(ic));
1203 /* assign asmOps to operand & result */
1204 aopOp (IC_LEFT(ic),ic,FALSE);
1205 aopOp (IC_RESULT(ic),ic,TRUE);
1207 /* if in bit space then a special case */
1208 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1212 /* if type float then do float */
1213 if (IS_FLOAT(optype)) {
1217 toBoolean(IC_LEFT(ic));
1222 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1223 emit2("sub a,!one");
1224 outBitC(IC_RESULT(ic));
1226 /* release the aops */
1227 freeAsmop(IC_LEFT(ic),NULL,ic);
1228 freeAsmop(IC_RESULT(ic),NULL,ic);
1231 /*-----------------------------------------------------------------*/
1232 /* genCpl - generate code for complement */
1233 /*-----------------------------------------------------------------*/
1234 static void genCpl (iCode *ic)
1240 /* assign asmOps to operand & result */
1241 aopOp (IC_LEFT(ic),ic,FALSE);
1242 aopOp (IC_RESULT(ic),ic,TRUE);
1244 /* if both are in bit space then
1246 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1247 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1251 size = AOP_SIZE(IC_RESULT(ic));
1253 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1256 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1259 /* release the aops */
1260 freeAsmop(IC_LEFT(ic),NULL,ic);
1261 freeAsmop(IC_RESULT(ic),NULL,ic);
1264 /*-----------------------------------------------------------------*/
1265 /* genUminus - unary minus code generation */
1266 /*-----------------------------------------------------------------*/
1267 static void genUminus (iCode *ic)
1270 link *optype, *rtype;
1273 aopOp(IC_LEFT(ic),ic,FALSE);
1274 aopOp(IC_RESULT(ic),ic,TRUE);
1276 /* if both in bit space then special
1278 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1279 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1284 optype = operandType(IC_LEFT(ic));
1285 rtype = operandType(IC_RESULT(ic));
1287 /* if float then do float stuff */
1288 if (IS_FLOAT(optype)) {
1293 /* otherwise subtract from zero */
1294 size = AOP_SIZE(IC_LEFT(ic));
1298 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1299 emit2("ld a,!zero");
1300 emit2("sbc a,%s",l);
1301 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1304 /* if any remaining bytes in the result */
1305 /* we just need to propagate the sign */
1306 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1310 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1314 /* release the aops */
1315 freeAsmop(IC_LEFT(ic),NULL,ic);
1316 freeAsmop(IC_RESULT(ic),NULL,ic);
1319 /*-----------------------------------------------------------------*/
1320 /* assignResultValue - */
1321 /*-----------------------------------------------------------------*/
1322 void assignResultValue(operand * oper)
1324 int size = AOP_SIZE(oper);
1328 topInA = requiresHL(AOP(oper));
1332 if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
1333 /* We do it the hard way here. */
1334 emitcode("push", "hl");
1335 _G.stack.pushed += 2;
1336 aopPut(AOP(oper), _fReturn[0], 0);
1337 aopPut(AOP(oper), _fReturn[1], 1);
1338 emitcode("pop", "de");
1339 _G.stack.pushed -= 2;
1340 aopPut(AOP(oper), _fReturn[0], 2);
1341 aopPut(AOP(oper), _fReturn[1], 3);
1345 aopPut(AOP(oper), _fReturn[size], size);
1350 /*-----------------------------------------------------------------*/
1351 /* genIpush - genrate code for pushing this gets a little complex */
1352 /*-----------------------------------------------------------------*/
1353 static void genIpush (iCode *ic)
1355 int size, offset = 0 ;
1359 /* if this is not a parm push : ie. it is spill push
1360 and spill push is always done on the local stack */
1361 if (!ic->parmPush) {
1362 /* and the item is spilt then do nothing */
1363 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1366 aopOp(IC_LEFT(ic),ic,FALSE);
1367 size = AOP_SIZE(IC_LEFT(ic));
1368 /* push it on the stack */
1369 if (isPair(AOP(IC_LEFT(ic)))) {
1370 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1371 _G.stack.pushed += 2;
1376 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1377 /* Simple for now - load into A and PUSH AF */
1378 emitcode("ld", "a,%s", l);
1379 emitcode("push", "af");
1380 emitcode("inc", "sp");
1387 /* Hmmm... what about saving the currently used registers
1390 /* then do the push */
1391 aopOp(IC_LEFT(ic),ic,FALSE);
1393 size = AOP_SIZE(IC_LEFT(ic));
1395 if (isPair(AOP(IC_LEFT(ic)))) {
1397 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1401 fetchHL(AOP(IC_LEFT(ic)));
1402 emitcode("push", "hl");
1404 _G.stack.pushed += 2;
1409 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1410 emitcode("ld", "a,%s", l);
1411 emitcode("push", "af");
1412 emitcode("inc", "sp");
1417 freeAsmop(IC_LEFT(ic),NULL,ic);
1420 /*-----------------------------------------------------------------*/
1421 /* genIpop - recover the registers: can happen only for spilling */
1422 /*-----------------------------------------------------------------*/
1423 static void genIpop (iCode *ic)
1428 /* if the temp was not pushed then */
1429 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1432 aopOp(IC_LEFT(ic),ic,FALSE);
1433 size = AOP_SIZE(IC_LEFT(ic));
1435 if (isPair(AOP(IC_LEFT(ic)))) {
1436 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1440 emitcode("dec", "sp");
1441 emitcode("pop", "hl");
1443 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1447 freeAsmop(IC_LEFT(ic),NULL,ic);
1450 /** Emit the code for a call statement
1452 static void emitCall (iCode *ic, bool ispcall)
1454 /* if caller saves & we have not saved then */
1455 if (!ic->regsSaved) {
1459 /* if send set is not empty then assign */
1462 for (sic = setFirstItem(sendSet) ; sic ;
1463 sic = setNextItem(sendSet)) {
1464 int size, offset = 0;
1465 aopOp(IC_LEFT(sic),sic,FALSE);
1466 size = AOP_SIZE(IC_LEFT(sic));
1468 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1470 if (strcmp(l, _fReturn[offset]))
1471 emitcode("ld","%s,%s",
1476 freeAsmop (IC_LEFT(sic),NULL,sic);
1482 aopOp(IC_LEFT(ic),ic,FALSE);
1484 if (isLitWord(AOP(IC_LEFT(ic)))) {
1485 emitcode("", "; Special case where the pCall is to a constant");
1486 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1489 symbol *rlbl = newiTempLabel(NULL);
1491 emit2("ld hl,#!tlabel", (rlbl->key+100));
1492 emitcode("push", "hl");
1493 _G.stack.pushed += 2;
1495 fetchHL(AOP(IC_LEFT(ic)));
1496 emit2("jp", "!*hl");
1497 emit2("!tlabeldef", (rlbl->key+100));
1498 _G.stack.pushed -= 2;
1500 freeAsmop(IC_LEFT(ic),NULL,ic);
1504 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1505 OP_SYMBOL(IC_LEFT(ic))->rname :
1506 OP_SYMBOL(IC_LEFT(ic))->name;
1507 emitcode("call", "%s", name);
1511 /* if we need assign a result value */
1512 if ((IS_ITEMP(IC_RESULT(ic)) &&
1513 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1514 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1515 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1518 aopOp(IC_RESULT(ic),ic,FALSE);
1521 assignResultValue(IC_RESULT(ic));
1523 freeAsmop(IC_RESULT(ic),NULL, ic);
1526 /* adjust the stack for parameters if required */
1527 if (IC_LEFT(ic)->parmBytes) {
1528 int i = IC_LEFT(ic)->parmBytes;
1529 _G.stack.pushed -= i;
1531 emit2("!ldaspsp", i);
1536 emitcode("ld", "hl,#%d", i);
1537 emitcode("add", "hl,sp");
1538 emitcode("ld", "sp,hl");
1542 emitcode("pop", "hl");
1546 emitcode("inc", "sp");
1554 /*-----------------------------------------------------------------*/
1555 /* genCall - generates a call statement */
1556 /*-----------------------------------------------------------------*/
1557 static void genCall (iCode *ic)
1559 emitCall(ic, FALSE);
1562 /*-----------------------------------------------------------------*/
1563 /* genPcall - generates a call by pointer statement */
1564 /*-----------------------------------------------------------------*/
1565 static void genPcall (iCode *ic)
1570 /*-----------------------------------------------------------------*/
1571 /* resultRemat - result is rematerializable */
1572 /*-----------------------------------------------------------------*/
1573 static int resultRemat (iCode *ic)
1575 if (SKIP_IC(ic) || ic->op == IFX)
1578 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1579 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1580 if (sym->remat && !POINTER_SET(ic))
1587 /*-----------------------------------------------------------------*/
1588 /* genFunction - generated code for function entry */
1589 /*-----------------------------------------------------------------*/
1590 static void genFunction (iCode *ic)
1592 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1596 /* create the function header */
1597 emit2("!functionheader", sym->name);
1598 emit2("!functionlabeldef", sym->rname);
1600 fetype = getSpec(operandType(IC_LEFT(ic)));
1602 /* if critical function then turn interrupts off */
1603 if (SPEC_CRTCL(fetype))
1606 /* if this is an interrupt service routine then
1607 save acc, b, dpl, dph */
1608 if (IS_ISR(sym->etype)) {
1611 /* PENDING: callee-save etc */
1613 /* adjust the stack for the function */
1614 _G.stack.last = sym->stack;
1617 emit2("!enterx", sym->stack);
1620 _G.stack.offset = sym->stack;
1623 /*-----------------------------------------------------------------*/
1624 /* genEndFunction - generates epilogue for functions */
1625 /*-----------------------------------------------------------------*/
1626 static void genEndFunction (iCode *ic)
1628 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1630 if (IS_ISR(sym->etype)) {
1634 if (SPEC_CRTCL(sym->etype))
1637 /* PENDING: calleeSave */
1639 /* if debug then send end of function */
1640 if (options.debug && currFunc) {
1642 emitcode("","C$%s$%d$%d$%d ==.",
1643 ic->filename,currFunc->lastLine,
1644 ic->level,ic->block);
1645 if (IS_STATIC(currFunc->etype))
1646 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1648 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1651 if (_G.stack.offset)
1652 emit2("!leavex", _G.stack.offset);
1656 _G.stack.pushed = 0;
1657 _G.stack.offset = 0;
1660 /*-----------------------------------------------------------------*/
1661 /* genRet - generate code for return statement */
1662 /*-----------------------------------------------------------------*/
1663 static void genRet (iCode *ic)
1666 /* Errk. This is a hack until I can figure out how
1667 to cause dehl to spill on a call */
1668 int size,offset = 0;
1670 /* if we have no return value then
1671 just generate the "ret" */
1675 /* we have something to return then
1676 move the return value into place */
1677 aopOp(IC_LEFT(ic),ic,FALSE);
1678 size = AOP_SIZE(IC_LEFT(ic));
1680 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1682 emitcode("ld", "de,%s", l);
1685 emitcode("ld", "hl,%s", l);
1689 if (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
1690 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
1691 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
1695 l = aopGet(AOP(IC_LEFT(ic)),offset,
1697 if (strcmp(_fReturn[offset],l))
1698 emitcode("ld","%s,%s", _fReturn[offset++],l);
1702 freeAsmop (IC_LEFT(ic),NULL,ic);
1705 /* generate a jump to the return label
1706 if the next is not the return statement */
1707 if (!(ic->next && ic->next->op == LABEL &&
1708 IC_LABEL(ic->next) == returnLabel))
1710 emit2("jp !tlabel", returnLabel->key+100);
1713 /*-----------------------------------------------------------------*/
1714 /* genLabel - generates a label */
1715 /*-----------------------------------------------------------------*/
1716 static void genLabel (iCode *ic)
1718 /* special case never generate */
1719 if (IC_LABEL(ic) == entryLabel)
1722 emitLabel(IC_LABEL(ic)->key+100);
1725 /*-----------------------------------------------------------------*/
1726 /* genGoto - generates a ljmp */
1727 /*-----------------------------------------------------------------*/
1728 static void genGoto (iCode *ic)
1730 emit2("jp !tlabel", IC_LABEL(ic)->key+100);
1733 /*-----------------------------------------------------------------*/
1734 /* genPlusIncr :- does addition with increment if possible */
1735 /*-----------------------------------------------------------------*/
1736 static bool genPlusIncr (iCode *ic)
1738 unsigned int icount ;
1739 unsigned int size = getDataSize(IC_RESULT(ic));
1740 PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
1742 /* will try to generate an increment */
1743 /* if the right side is not a literal
1745 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1748 emitcode("", "; genPlusIncr");
1750 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1752 /* If result is a pair */
1753 if (resultId != PAIR_INVALID) {
1754 if (isLitWord(AOP(IC_LEFT(ic)))) {
1755 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
1758 if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
1759 fetchPair(resultId, AOP(IC_RIGHT(ic)));
1760 emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
1766 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1769 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1770 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1773 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1778 /* if the literal value of the right hand side
1779 is greater than 4 then it is not worth it */
1783 /* if increment 16 bits in register */
1784 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1787 symbol *tlbl = newiTempLabel(NULL);
1788 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1789 emit2("!shortjp nz,!tlabel", tlbl->key+100);
1791 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1795 emitLabel(tlbl->key+100);
1799 /* if the sizes are greater than 1 then we cannot */
1800 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1801 AOP_SIZE(IC_LEFT(ic)) > 1 )
1804 /* we can if the aops of the left & result match or
1805 if they are in registers and the registers are the
1807 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1809 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1817 /*-----------------------------------------------------------------*/
1818 /* outBitAcc - output a bit in acc */
1819 /*-----------------------------------------------------------------*/
1820 void outBitAcc(operand *result)
1822 symbol *tlbl = newiTempLabel(NULL);
1823 /* if the result is a bit */
1824 if (AOP_TYPE(result) == AOP_CRY){
1828 emit2("!shortjp z,!tlabel", tlbl->key+100);
1830 emitLabel(tlbl->key+100);
1835 /*-----------------------------------------------------------------*/
1836 /* genPlus - generates code for addition */
1837 /*-----------------------------------------------------------------*/
1838 static void genPlus (iCode *ic)
1840 int size, offset = 0;
1842 /* special cases :- */
1844 aopOp (IC_LEFT(ic),ic,FALSE);
1845 aopOp (IC_RIGHT(ic),ic,FALSE);
1846 aopOp (IC_RESULT(ic),ic,TRUE);
1848 /* Swap the left and right operands if:
1850 if literal, literal on the right or
1851 if left requires ACC or right is already
1854 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1855 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1856 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1857 operand *t = IC_RIGHT(ic);
1858 IC_RIGHT(ic) = IC_LEFT(ic);
1862 /* if both left & right are in bit
1864 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1865 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1870 /* if left in bit space & right literal */
1871 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1872 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1873 /* Can happen I guess */
1877 /* if I can do an increment instead
1878 of add then GOOD for ME */
1879 if (genPlusIncr (ic) == TRUE)
1882 size = getDataSize(IC_RESULT(ic));
1884 /* Special case when left and right are constant */
1885 if (isPair(AOP(IC_RESULT(ic)))) {
1888 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1889 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1890 if (left && right) {
1894 sprintf(buffer, "#(%s + %s)", left, right);
1895 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1900 if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
1901 /* Fetch into HL then do the add */
1903 fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
1904 emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
1909 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1910 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1912 emitcode("add","a,%s",
1913 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1915 emitcode("adc","a,%s",
1916 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1918 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1920 emitcode("add","a,%s",
1921 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1923 emitcode("adc","a,%s",
1924 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1926 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1929 /* Some kind of pointer arith. */
1930 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1931 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1932 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1935 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1936 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1937 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1942 freeAsmop(IC_LEFT(ic),NULL,ic);
1943 freeAsmop(IC_RIGHT(ic),NULL,ic);
1944 freeAsmop(IC_RESULT(ic),NULL,ic);
1948 /*-----------------------------------------------------------------*/
1949 /* genMinusDec :- does subtraction with deccrement if possible */
1950 /*-----------------------------------------------------------------*/
1951 static bool genMinusDec (iCode *ic)
1953 unsigned int icount ;
1954 unsigned int size = getDataSize(IC_RESULT(ic));
1956 /* will try to generate an increment */
1957 /* if the right side is not a literal we cannot */
1958 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1961 /* if the literal value of the right hand side
1962 is greater than 4 then it is not worth it */
1963 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1966 size = getDataSize(IC_RESULT(ic));
1969 /* if increment 16 bits in register */
1970 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1973 symbol *tlbl = newiTempLabel(NULL);
1974 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1975 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1977 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1981 emitLabel(tlbl->key+100);
1986 /* if decrement 16 bits in register */
1987 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1988 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1990 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1994 /* If result is a pair */
1995 if (isPair(AOP(IC_RESULT(ic)))) {
1996 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1997 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1999 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2003 /* if the sizes are greater than 1 then we cannot */
2004 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2005 AOP_SIZE(IC_LEFT(ic)) > 1 )
2008 /* we can if the aops of the left & result match or if they are in
2009 registers and the registers are the same */
2010 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2012 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
2019 /*-----------------------------------------------------------------*/
2020 /* genMinus - generates code for subtraction */
2021 /*-----------------------------------------------------------------*/
2022 static void genMinus (iCode *ic)
2024 int size, offset = 0;
2025 unsigned long lit = 0L;
2027 aopOp (IC_LEFT(ic),ic,FALSE);
2028 aopOp (IC_RIGHT(ic),ic,FALSE);
2029 aopOp (IC_RESULT(ic),ic,TRUE);
2031 /* special cases :- */
2032 /* if both left & right are in bit space */
2033 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2034 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2039 /* if I can do an decrement instead of subtract then GOOD for ME */
2040 if (genMinusDec (ic) == TRUE)
2043 size = getDataSize(IC_RESULT(ic));
2045 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2048 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2053 /* if literal, add a,#-lit, else normal subb */
2055 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2056 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2058 emitcode("sub","a,%s",
2059 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2061 emitcode("sbc","a,%s",
2062 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2065 /* first add without previous c */
2067 emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL));
2069 emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2071 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2074 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2075 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2076 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2080 freeAsmop(IC_LEFT(ic),NULL,ic);
2081 freeAsmop(IC_RIGHT(ic),NULL,ic);
2082 freeAsmop(IC_RESULT(ic),NULL,ic);
2085 /*-----------------------------------------------------------------*/
2086 /* genMult - generates code for multiplication */
2087 /*-----------------------------------------------------------------*/
2088 static void genMult (iCode *ic)
2090 /* Shouldn't occur - all done through function calls */
2094 /*-----------------------------------------------------------------*/
2095 /* genDiv - generates code for division */
2096 /*-----------------------------------------------------------------*/
2097 static void genDiv (iCode *ic)
2099 /* Shouldn't occur - all done through function calls */
2103 /*-----------------------------------------------------------------*/
2104 /* genMod - generates code for division */
2105 /*-----------------------------------------------------------------*/
2106 static void genMod (iCode *ic)
2108 /* Shouldn't occur - all done through function calls */
2112 /*-----------------------------------------------------------------*/
2113 /* genIfxJump :- will create a jump depending on the ifx */
2114 /*-----------------------------------------------------------------*/
2115 static void genIfxJump (iCode *ic, char *jval)
2120 /* if true label then we jump if condition
2122 if ( IC_TRUE(ic) ) {
2124 if (!strcmp(jval, "a")) {
2127 else if (!strcmp(jval, "c")) {
2131 /* The buffer contains the bit on A that we should test */
2136 /* false label is present */
2137 jlbl = IC_FALSE(ic) ;
2138 if (!strcmp(jval, "a")) {
2141 else if (!strcmp(jval, "c")) {
2145 /* The buffer contains the bit on A that we should test */
2149 /* Z80 can do a conditional long jump */
2150 if (!strcmp(jval, "a")) {
2151 emitcode("or", "a,a");
2153 else if (!strcmp(jval, "c")) {
2156 emitcode("bit", "%s,a", jval);
2158 emit2("jp %s,!tlabel", inst, jlbl->key+100);
2160 /* mark the icode as generated */
2164 /** Generic compare for > or <
2166 static void genCmp (operand *left,operand *right,
2167 operand *result, iCode *ifx, int sign)
2169 int size, offset = 0 ;
2170 unsigned long lit = 0L;
2172 /* if left & right are bit variables */
2173 if (AOP_TYPE(left) == AOP_CRY &&
2174 AOP_TYPE(right) == AOP_CRY ) {
2175 /* Cant happen on the Z80 */
2178 /* subtract right from left if at the
2179 end the carry flag is set then we know that
2180 left is greater than right */
2181 size = max(AOP_SIZE(left),AOP_SIZE(right));
2183 /* if unsigned char cmp with lit, just compare */
2185 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2186 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2188 emit2("xor a,!immedbyte", 0x80);
2189 emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80);
2192 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
2195 if(AOP_TYPE(right) == AOP_LIT) {
2196 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2197 /* optimize if(x < 0) or if(x >= 0) */
2200 /* No sign so it's always false */
2204 /* Just load in the top most bit */
2205 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2206 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2207 genIfxJump (ifx,"7");
2211 emitcode("rlc","a");
2217 /* First setup h and l contaning the top most bytes XORed */
2218 bool fDidXor = FALSE;
2219 if (AOP_TYPE(left) == AOP_LIT){
2220 unsigned long lit = (unsigned long)
2221 floatFromVal(AOP(left)->aopu.aop_lit);
2222 emit2("ld %s,!immedbyte", _fTmp[0],
2223 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2226 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2227 emit2("xor a,!immedbyte", 0x80);
2228 emitcode("ld", "%s,a", _fTmp[0]);
2231 if (AOP_TYPE(right) == AOP_LIT) {
2232 unsigned long lit = (unsigned long)
2233 floatFromVal(AOP(right)->aopu.aop_lit);
2234 emit2("ld %s,!immedbyte", _fTmp[1],
2235 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2238 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2239 emit2("xor a,!immedbyte", 0x80);
2240 emitcode("ld", "%s,a", _fTmp[1]);
2250 /* Do a long subtract */
2251 if (!sign || size ) {
2252 MOVA(aopGet(AOP(left),offset,FALSE));
2254 if (sign && size == 0) {
2255 emitcode("ld", "a,%s", _fTmp[0]);
2256 emitcode("sbc", "a,%s", _fTmp[1]);
2259 /* Subtract through, propagating the carry */
2260 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2267 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2270 /* if the result is used in the next
2271 ifx conditional branch then generate
2272 code a little differently */
2274 genIfxJump (ifx,"c");
2277 /* leave the result in acc */
2281 /*-----------------------------------------------------------------*/
2282 /* genCmpGt :- greater than comparison */
2283 /*-----------------------------------------------------------------*/
2284 static void genCmpGt (iCode *ic, iCode *ifx)
2286 operand *left, *right, *result;
2287 link *letype , *retype;
2291 right= IC_RIGHT(ic);
2292 result = IC_RESULT(ic);
2294 letype = getSpec(operandType(left));
2295 retype =getSpec(operandType(right));
2296 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2297 /* assign the amsops */
2298 aopOp (left,ic,FALSE);
2299 aopOp (right,ic,FALSE);
2300 aopOp (result,ic,TRUE);
2302 genCmp(right, left, result, ifx, sign);
2304 freeAsmop(left,NULL,ic);
2305 freeAsmop(right,NULL,ic);
2306 freeAsmop(result,NULL,ic);
2309 /*-----------------------------------------------------------------*/
2310 /* genCmpLt - less than comparisons */
2311 /*-----------------------------------------------------------------*/
2312 static void genCmpLt (iCode *ic, iCode *ifx)
2314 operand *left, *right, *result;
2315 link *letype , *retype;
2319 right= IC_RIGHT(ic);
2320 result = IC_RESULT(ic);
2322 letype = getSpec(operandType(left));
2323 retype =getSpec(operandType(right));
2324 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2326 /* assign the amsops */
2327 aopOp (left,ic,FALSE);
2328 aopOp (right,ic,FALSE);
2329 aopOp (result,ic,TRUE);
2331 genCmp(left, right, result, ifx, sign);
2333 freeAsmop(left,NULL,ic);
2334 freeAsmop(right,NULL,ic);
2335 freeAsmop(result,NULL,ic);
2338 /*-----------------------------------------------------------------*/
2339 /* gencjneshort - compare and jump if not equal */
2340 /*-----------------------------------------------------------------*/
2341 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2343 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2345 unsigned long lit = 0L;
2347 /* Swap the left and right if it makes the computation easier */
2348 if (AOP_TYPE(left) == AOP_LIT) {
2354 if(AOP_TYPE(right) == AOP_LIT)
2355 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2357 /* if the right side is a literal then anything goes */
2358 if (AOP_TYPE(right) == AOP_LIT &&
2359 AOP_TYPE(left) != AOP_DIR ) {
2361 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2366 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2370 emitcode("or", "a,a");
2372 emit2("jp nz,!tlabel", lbl->key+100);
2376 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2377 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2378 emitcode("or", "a,a");
2380 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2381 emit2("jp nz,!tlabel", lbl->key+100);
2386 /* if the right side is in a register or in direct space or
2387 if the left is a pointer register & right is not */
2388 else if (AOP_TYPE(right) == AOP_REG ||
2389 AOP_TYPE(right) == AOP_DIR ||
2390 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2392 MOVA(aopGet(AOP(left),offset,FALSE));
2393 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2394 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2396 emit2("jp nz,!tlabel", lbl->key+100);
2398 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2399 emit2("jp nz,!tlabel", lbl->key+100);
2404 /* right is a pointer reg need both a & b */
2405 /* PENDING: is this required? */
2407 MOVA(aopGet(AOP(right),offset,FALSE));
2408 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2409 emit2("!shortjp nz,!tlabel", lbl->key+100);
2415 /*-----------------------------------------------------------------*/
2416 /* gencjne - compare and jump if not equal */
2417 /*-----------------------------------------------------------------*/
2418 static void gencjne(operand *left, operand *right, symbol *lbl)
2420 symbol *tlbl = newiTempLabel(NULL);
2422 gencjneshort(left, right, lbl);
2426 emit2("!shortjp !tlabel", tlbl->key+100);
2427 emitLabel(lbl->key+100);
2428 emitcode("xor","a,a");
2429 emitLabel(tlbl->key+100);
2432 /*-----------------------------------------------------------------*/
2433 /* genCmpEq - generates code for equal to */
2434 /*-----------------------------------------------------------------*/
2435 static void genCmpEq (iCode *ic, iCode *ifx)
2437 operand *left, *right, *result;
2439 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2440 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2441 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2443 /* Swap operands if it makes the operation easier. ie if:
2444 1. Left is a literal.
2446 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2447 operand *t = IC_RIGHT(ic);
2448 IC_RIGHT(ic) = IC_LEFT(ic);
2452 if (ifx && !AOP_SIZE(result)){
2454 /* if they are both bit variables */
2455 if (AOP_TYPE(left) == AOP_CRY &&
2456 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2459 tlbl = newiTempLabel(NULL);
2460 gencjneshort(left, right, tlbl);
2461 if ( IC_TRUE(ifx) ) {
2462 emit2("jp !tlabel", IC_TRUE(ifx)->key+100);
2463 emitLabel(tlbl->key+100);
2465 /* PENDING: do this better */
2466 symbol *lbl = newiTempLabel(NULL);
2467 emit2("!shortjp !tlabel", lbl->key+100);
2468 emitLabel(tlbl->key+100);
2469 emit2("jp !tlabel", IC_FALSE(ifx)->key+100);
2470 emitLabel(lbl->key+100);
2473 /* mark the icode as generated */
2478 /* if they are both bit variables */
2479 if (AOP_TYPE(left) == AOP_CRY &&
2480 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2483 gencjne(left,right,newiTempLabel(NULL));
2484 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2488 genIfxJump(ifx,"a");
2491 /* if the result is used in an arithmetic operation
2492 then put the result in place */
2493 if (AOP_TYPE(result) != AOP_CRY) {
2496 /* leave the result in acc */
2500 freeAsmop(left,NULL,ic);
2501 freeAsmop(right,NULL,ic);
2502 freeAsmop(result,NULL,ic);
2505 /*-----------------------------------------------------------------*/
2506 /* ifxForOp - returns the icode containing the ifx for operand */
2507 /*-----------------------------------------------------------------*/
2508 static iCode *ifxForOp ( operand *op, iCode *ic )
2510 /* if true symbol then needs to be assigned */
2511 if (IS_TRUE_SYMOP(op))
2514 /* if this has register type condition and
2515 the next instruction is ifx with the same operand
2516 and live to of the operand is upto the ifx only then */
2518 ic->next->op == IFX &&
2519 IC_COND(ic->next)->key == op->key &&
2520 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2526 /*-----------------------------------------------------------------*/
2527 /* genAndOp - for && operation */
2528 /*-----------------------------------------------------------------*/
2529 static void genAndOp (iCode *ic)
2531 operand *left,*right, *result;
2534 /* note here that && operations that are in an if statement are
2535 taken away by backPatchLabels only those used in arthmetic
2536 operations remain */
2537 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2538 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2539 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2541 /* if both are bit variables */
2542 if (AOP_TYPE(left) == AOP_CRY &&
2543 AOP_TYPE(right) == AOP_CRY ) {
2546 tlbl = newiTempLabel(NULL);
2548 emit2("!shortjp z,!tlabel", tlbl->key+100);
2550 emitLabel(tlbl->key+100);
2554 freeAsmop(left,NULL,ic);
2555 freeAsmop(right,NULL,ic);
2556 freeAsmop(result,NULL,ic);
2559 /*-----------------------------------------------------------------*/
2560 /* genOrOp - for || operation */
2561 /*-----------------------------------------------------------------*/
2562 static void genOrOp (iCode *ic)
2564 operand *left,*right, *result;
2567 /* note here that || operations that are in an
2568 if statement are taken away by backPatchLabels
2569 only those used in arthmetic operations remain */
2570 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2571 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2572 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2574 /* if both are bit variables */
2575 if (AOP_TYPE(left) == AOP_CRY &&
2576 AOP_TYPE(right) == AOP_CRY ) {
2579 tlbl = newiTempLabel(NULL);
2581 emit2("!shortjp nz,!tlabel", tlbl->key+100);
2583 emitLabel(tlbl->key+100);
2587 freeAsmop(left,NULL,ic);
2588 freeAsmop(right,NULL,ic);
2589 freeAsmop(result,NULL,ic);
2592 /*-----------------------------------------------------------------*/
2593 /* isLiteralBit - test if lit == 2^n */
2594 /*-----------------------------------------------------------------*/
2595 int isLiteralBit(unsigned long lit)
2597 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2598 0x100L,0x200L,0x400L,0x800L,
2599 0x1000L,0x2000L,0x4000L,0x8000L,
2600 0x10000L,0x20000L,0x40000L,0x80000L,
2601 0x100000L,0x200000L,0x400000L,0x800000L,
2602 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2603 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2606 for(idx = 0; idx < 32; idx++)
2612 /*-----------------------------------------------------------------*/
2613 /* jmpTrueOrFalse - */
2614 /*-----------------------------------------------------------------*/
2615 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2617 // ugly but optimized by peephole
2619 symbol *nlbl = newiTempLabel(NULL);
2620 emit2("jp !tlabel", nlbl->key+100);
2621 emitLabel(tlbl->key+100);
2622 emit2("jp !tlabel", IC_TRUE(ic)->key+100);
2623 emitLabel(nlbl->key+100);
2626 emit2("jp !tlabel", IC_FALSE(ic)->key+100);
2627 emitLabel(tlbl->key+100);
2632 /*-----------------------------------------------------------------*/
2633 /* genAnd - code for and */
2634 /*-----------------------------------------------------------------*/
2635 static void genAnd (iCode *ic, iCode *ifx)
2637 operand *left, *right, *result;
2639 unsigned long lit = 0L;
2642 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2643 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2644 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2647 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2649 AOP_TYPE(left), AOP_TYPE(right));
2650 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2652 AOP_SIZE(left), AOP_SIZE(right));
2655 /* if left is a literal & right is not then exchange them */
2656 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2657 AOP_NEEDSACC(left)) {
2658 operand *tmp = right ;
2663 /* if result = right then exchange them */
2664 if(sameRegs(AOP(result),AOP(right))){
2665 operand *tmp = right ;
2670 /* if right is bit then exchange them */
2671 if (AOP_TYPE(right) == AOP_CRY &&
2672 AOP_TYPE(left) != AOP_CRY){
2673 operand *tmp = right ;
2677 if(AOP_TYPE(right) == AOP_LIT)
2678 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2680 size = AOP_SIZE(result);
2682 if (AOP_TYPE(left) == AOP_CRY){
2687 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2688 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2689 if((AOP_TYPE(right) == AOP_LIT) &&
2690 (AOP_TYPE(result) == AOP_CRY) &&
2691 (AOP_TYPE(left) != AOP_CRY)) {
2692 int posbit = isLiteralBit(lit);
2696 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2700 emitcode("mov","c,acc.%d",posbit&0x07);
2705 sprintf(buffer, "%d", posbit&0x07);
2706 genIfxJump(ifx, buffer);
2714 symbol *tlbl = newiTempLabel(NULL);
2715 int sizel = AOP_SIZE(left);
2718 emitcode("setb","c");
2721 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2722 MOVA( aopGet(AOP(left),offset,FALSE));
2724 if((posbit = isLiteralBit(bytelit)) != 0) {
2726 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2729 if(bytelit != 0x0FFL)
2730 emitcode("and","a,%s",
2731 aopGet(AOP(right),offset,FALSE));
2732 emit2("!shortjp nz,!tlabel", tlbl->key+100);
2737 // bit = left & literal
2739 emitcode("clr","c");
2740 emit2("!tlabeldef", tlbl->key+100);
2742 // if(left & literal)
2745 jmpTrueOrFalse(ifx, tlbl);
2753 /* if left is same as result */
2754 if(sameRegs(AOP(result),AOP(left))){
2755 for(;size--; offset++) {
2756 if(AOP_TYPE(right) == AOP_LIT){
2757 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2761 aopPut(AOP(result),zero,offset);
2763 MOVA(aopGet(AOP(left),offset,FALSE));
2764 emitcode("and","a,%s",
2765 aopGet(AOP(right),offset,FALSE));
2766 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2771 if (AOP_TYPE(left) == AOP_ACC) {
2775 MOVA(aopGet(AOP(right),offset,FALSE));
2776 emitcode("and","%s,a",
2777 aopGet(AOP(left),offset,FALSE));
2782 // left & result in different registers
2783 if(AOP_TYPE(result) == AOP_CRY){
2786 for(;(size--);offset++) {
2788 // result = left & right
2789 if(AOP_TYPE(right) == AOP_LIT){
2790 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2792 aopGet(AOP(left),offset,FALSE),
2795 } else if(bytelit == 0){
2796 aopPut(AOP(result),zero,offset);
2800 // faster than result <- left, anl result,right
2801 // and better if result is SFR
2802 if (AOP_TYPE(left) == AOP_ACC)
2803 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2805 MOVA(aopGet(AOP(right),offset,FALSE));
2806 emitcode("and","a,%s",
2807 aopGet(AOP(left),offset,FALSE));
2809 aopPut(AOP(result),"a",offset);
2816 freeAsmop(left,NULL,ic);
2817 freeAsmop(right,NULL,ic);
2818 freeAsmop(result,NULL,ic);
2821 /*-----------------------------------------------------------------*/
2822 /* genOr - code for or */
2823 /*-----------------------------------------------------------------*/
2824 static void genOr (iCode *ic, iCode *ifx)
2826 operand *left, *right, *result;
2828 unsigned long lit = 0L;
2830 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2831 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2832 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2835 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2837 AOP_TYPE(left), AOP_TYPE(right));
2838 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2840 AOP_SIZE(left), AOP_SIZE(right));
2843 /* if left is a literal & right is not then exchange them */
2844 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2845 AOP_NEEDSACC(left)) {
2846 operand *tmp = right ;
2851 /* if result = right then exchange them */
2852 if(sameRegs(AOP(result),AOP(right))){
2853 operand *tmp = right ;
2858 /* if right is bit then exchange them */
2859 if (AOP_TYPE(right) == AOP_CRY &&
2860 AOP_TYPE(left) != AOP_CRY){
2861 operand *tmp = right ;
2865 if(AOP_TYPE(right) == AOP_LIT)
2866 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2868 size = AOP_SIZE(result);
2870 if (AOP_TYPE(left) == AOP_CRY){
2875 if((AOP_TYPE(right) == AOP_LIT) &&
2876 (AOP_TYPE(result) == AOP_CRY) &&
2877 (AOP_TYPE(left) != AOP_CRY)){
2882 /* if left is same as result */
2883 if(sameRegs(AOP(result),AOP(left))){
2884 for(;size--; offset++) {
2885 if(AOP_TYPE(right) == AOP_LIT){
2886 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2889 MOVA(aopGet(AOP(right),offset,FALSE));
2890 emitcode("or","a,%s; 5",
2891 aopGet(AOP(left),offset,FALSE));
2892 aopPut(AOP(result),"a ; 8", offset);
2895 if (AOP_TYPE(left) == AOP_ACC)
2896 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2898 MOVA(aopGet(AOP(right),offset,FALSE));
2899 emitcode("or","a,%s ; 7",
2900 aopGet(AOP(left),offset,FALSE));
2901 aopPut(AOP(result),"a ; 8", offset);
2906 // left & result in different registers
2907 if(AOP_TYPE(result) == AOP_CRY){
2909 } else for(;(size--);offset++){
2911 // result = left & right
2912 if(AOP_TYPE(right) == AOP_LIT){
2913 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2915 aopGet(AOP(left),offset,FALSE),
2920 // faster than result <- left, anl result,right
2921 // and better if result is SFR
2922 if (AOP_TYPE(left) == AOP_ACC)
2923 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2925 MOVA(aopGet(AOP(right),offset,FALSE));
2926 emitcode("or","a,%s",
2927 aopGet(AOP(left),offset,FALSE));
2929 aopPut(AOP(result),"a",offset);
2930 /* PENDING: something weird is going on here. Add exception. */
2931 if (AOP_TYPE(result) == AOP_ACC)
2937 freeAsmop(left,NULL,ic);
2938 freeAsmop(right,NULL,ic);
2939 freeAsmop(result,NULL,ic);
2942 /*-----------------------------------------------------------------*/
2943 /* genXor - code for xclusive or */
2944 /*-----------------------------------------------------------------*/
2945 static void genXor (iCode *ic, iCode *ifx)
2947 operand *left, *right, *result;
2949 unsigned long lit = 0L;
2951 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2952 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2953 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2955 /* if left is a literal & right is not then exchange them */
2956 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2957 AOP_NEEDSACC(left)) {
2958 operand *tmp = right ;
2963 /* if result = right then exchange them */
2964 if(sameRegs(AOP(result),AOP(right))){
2965 operand *tmp = right ;
2970 /* if right is bit then exchange them */
2971 if (AOP_TYPE(right) == AOP_CRY &&
2972 AOP_TYPE(left) != AOP_CRY){
2973 operand *tmp = right ;
2977 if(AOP_TYPE(right) == AOP_LIT)
2978 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2980 size = AOP_SIZE(result);
2982 if (AOP_TYPE(left) == AOP_CRY){
2987 if((AOP_TYPE(right) == AOP_LIT) &&
2988 (AOP_TYPE(result) == AOP_CRY) &&
2989 (AOP_TYPE(left) != AOP_CRY)){
2994 /* if left is same as result */
2995 if(sameRegs(AOP(result),AOP(left))){
2996 for(;size--; offset++) {
2997 if(AOP_TYPE(right) == AOP_LIT){
2998 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3001 MOVA(aopGet(AOP(right),offset,FALSE));
3002 emitcode("xor","a,%s",
3003 aopGet(AOP(left),offset,FALSE));
3004 aopPut(AOP(result),"a",0);
3007 if (AOP_TYPE(left) == AOP_ACC)
3008 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3010 MOVA(aopGet(AOP(right),offset,FALSE));
3011 emitcode("xor","a,%s",
3012 aopGet(AOP(left),offset,FALSE));
3013 aopPut(AOP(result),"a",0);
3018 // left & result in different registers
3019 if(AOP_TYPE(result) == AOP_CRY){
3021 } else for(;(size--);offset++){
3023 // result = left & right
3024 if(AOP_TYPE(right) == AOP_LIT){
3025 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3027 aopGet(AOP(left),offset,FALSE),
3032 // faster than result <- left, anl result,right
3033 // and better if result is SFR
3034 if (AOP_TYPE(left) == AOP_ACC)
3035 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3037 MOVA(aopGet(AOP(right),offset,FALSE));
3038 emitcode("xor","a,%s",
3039 aopGet(AOP(left),offset,FALSE));
3040 aopPut(AOP(result),"a",0);
3042 aopPut(AOP(result),"a",offset);
3047 freeAsmop(left,NULL,ic);
3048 freeAsmop(right,NULL,ic);
3049 freeAsmop(result,NULL,ic);
3052 /*-----------------------------------------------------------------*/
3053 /* genInline - write the inline code out */
3054 /*-----------------------------------------------------------------*/
3055 static void genInline (iCode *ic)
3057 char buffer[MAX_INLINEASM];
3061 inLine += (!options.asmpeep);
3062 strcpy(buffer,IC_INLINE(ic));
3064 /* emit each line as a code */
3083 /* emitcode("",buffer); */
3084 inLine -= (!options.asmpeep);
3087 /*-----------------------------------------------------------------*/
3088 /* genRRC - rotate right with carry */
3089 /*-----------------------------------------------------------------*/
3090 static void genRRC (iCode *ic)
3095 /*-----------------------------------------------------------------*/
3096 /* genRLC - generate code for rotate left with carry */
3097 /*-----------------------------------------------------------------*/
3098 static void genRLC (iCode *ic)
3103 /*-----------------------------------------------------------------*/
3104 /* shiftR2Left2Result - shift right two bytes from left to result */
3105 /*-----------------------------------------------------------------*/
3106 static void shiftR2Left2Result (operand *left, int offl,
3107 operand *result, int offr,
3108 int shCount, int sign)
3110 if(sameRegs(AOP(result), AOP(left)) &&
3111 ((offl + MSB16) == offr)){
3114 movLeft2Result(left, offl, result, offr, 0);
3115 movLeft2Result(left, offl+1, result, offr+1, 0);
3122 /* if (AOP(result)->type == AOP_REG) {*/
3125 symbol *tlbl , *tlbl1;
3128 /* Left is already in result - so now do the shift */
3130 emit2("ld a,!immedbyte+1", shCount);
3131 tlbl = newiTempLabel(NULL);
3132 tlbl1 = newiTempLabel(NULL);
3133 emit2("!shortjp !tlabel", tlbl1->key+100);
3134 emitLabel(tlbl->key+100);
3137 emitcode("or", "a,a");
3140 l = aopGet(AOP(result), --offset, FALSE);
3141 emitcode("rr","%s", l);
3144 emitLabel(tlbl1->key+100);
3145 emitcode("dec", "a");
3146 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3151 /*-----------------------------------------------------------------*/
3152 /* shiftL2Left2Result - shift left two bytes from left to result */
3153 /*-----------------------------------------------------------------*/
3154 static void shiftL2Left2Result (operand *left, int offl,
3155 operand *result, int offr, int shCount)
3157 if(sameRegs(AOP(result), AOP(left)) &&
3158 ((offl + MSB16) == offr)){
3161 /* Copy left into result */
3162 movLeft2Result(left, offl, result, offr, 0);
3163 movLeft2Result(left, offl+1, result, offr+1, 0);
3165 /* PENDING: for now just see if it'll work. */
3166 /*if (AOP(result)->type == AOP_REG) { */
3170 symbol *tlbl , *tlbl1;
3173 /* Left is already in result - so now do the shift */
3175 emit2("ld a,!immedbyte+1", shCount);
3176 tlbl = newiTempLabel(NULL);
3177 tlbl1 = newiTempLabel(NULL);
3178 emit2("!shortjp !tlabel", tlbl1->key+100);
3179 emitLabel(tlbl->key+100);
3182 emitcode("or", "a,a");
3184 l = aopGet(AOP(result),offset++,FALSE);
3185 emitcode("rl","%s", l);
3188 emitLabel(tlbl1->key+100);
3189 emitcode("dec", "a");
3190 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3195 /*-----------------------------------------------------------------*/
3196 /* AccRol - rotate left accumulator by known count */
3197 /*-----------------------------------------------------------------*/
3198 static void AccRol (int shCount)
3200 shCount &= 0x0007; // shCount : 0..7
3237 /*-----------------------------------------------------------------*/
3238 /* AccLsh - left shift accumulator by known count */
3239 /*-----------------------------------------------------------------*/
3240 static void AccLsh (int shCount)
3244 emitcode("add","a,a");
3247 emitcode("add","a,a");
3248 emitcode("add","a,a");
3250 /* rotate left accumulator */
3252 /* and kill the lower order bits */
3253 emit2("and a,!immedbyte", SLMask[shCount]);
3258 /*-----------------------------------------------------------------*/
3259 /* shiftL1Left2Result - shift left one byte from left to result */
3260 /*-----------------------------------------------------------------*/
3261 static void shiftL1Left2Result (operand *left, int offl,
3262 operand *result, int offr, int shCount)
3265 l = aopGet(AOP(left),offl,FALSE);
3267 /* shift left accumulator */
3269 aopPut(AOP(result),"a",offr);
3273 /*-----------------------------------------------------------------*/
3274 /* genlshTwo - left shift two bytes by known amount != 0 */
3275 /*-----------------------------------------------------------------*/
3276 static void genlshTwo (operand *result,operand *left, int shCount)
3278 int size = AOP_SIZE(result);
3282 /* if shCount >= 8 */
3288 movLeft2Result(left, LSB, result, MSB16, 0);
3289 aopPut(AOP(result),zero, 0);
3290 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
3293 movLeft2Result(left, LSB, result, MSB16, 0);
3294 aopPut(AOP(result),zero, 0);
3297 aopPut(AOP(result),zero,LSB);
3299 /* 1 <= shCount <= 7 */
3305 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3310 /*-----------------------------------------------------------------*/
3311 /* genlshOne - left shift a one byte quantity by known count */
3312 /*-----------------------------------------------------------------*/
3313 static void genlshOne (operand *result, operand *left, int shCount)
3315 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3318 /*-----------------------------------------------------------------*/
3319 /* genLeftShiftLiteral - left shifting by known count */
3320 /*-----------------------------------------------------------------*/
3321 static void genLeftShiftLiteral (operand *left,
3326 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3329 freeAsmop(right,NULL,ic);
3331 aopOp(left,ic,FALSE);
3332 aopOp(result,ic,FALSE);
3334 size = getSize(operandType(result));
3337 emitcode("; shift left ","result %d, left %d",size,
3341 /* I suppose that the left size >= result size */
3346 else if(shCount >= (size * 8))
3348 aopPut(AOP(result),zero,size);
3352 genlshOne (result,left,shCount);
3355 genlshTwo (result,left,shCount);
3364 freeAsmop(left,NULL,ic);
3365 freeAsmop(result,NULL,ic);
3368 /*-----------------------------------------------------------------*/
3369 /* genLeftShift - generates code for left shifting */
3370 /*-----------------------------------------------------------------*/
3371 static void genLeftShift (iCode *ic)
3375 symbol *tlbl , *tlbl1;
3376 operand *left,*right, *result;
3378 right = IC_RIGHT(ic);
3380 result = IC_RESULT(ic);
3382 aopOp(right,ic,FALSE);
3384 /* if the shift count is known then do it
3385 as efficiently as possible */
3386 if (AOP_TYPE(right) == AOP_LIT) {
3387 genLeftShiftLiteral (left,right,result,ic);
3391 /* shift count is unknown then we have to form a loop get the loop
3392 count in B : Note: we take only the lower order byte since
3393 shifting more that 32 bits make no sense anyway, ( the largest
3394 size of an object can be only 32 bits ) */
3395 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3396 emitcode("inc","a");
3397 freeAsmop (right,NULL,ic);
3398 aopOp(left,ic,FALSE);
3399 aopOp(result,ic,FALSE);
3401 /* now move the left to the result if they are not the
3404 if (!sameRegs(AOP(left),AOP(result))) {
3406 size = AOP_SIZE(result);
3409 l = aopGet(AOP(left),offset,FALSE);
3410 aopPut(AOP(result),l,offset);
3415 size = AOP_SIZE(result);
3418 l = aopGet(AOP(left),offset,FALSE);
3419 aopPut(AOP(result),l,offset);
3425 tlbl = newiTempLabel(NULL);
3426 size = AOP_SIZE(result);
3428 tlbl1 = newiTempLabel(NULL);
3430 emit2("!shortjp !tlabel", tlbl1->key+100);
3431 emitLabel(tlbl->key+100);
3432 l = aopGet(AOP(result),offset,FALSE);
3433 emitcode("or", "a,a");
3435 l = aopGet(AOP(result),offset++,FALSE);
3436 emitcode("rl","%s", l);
3438 emitLabel(tlbl1->key+100);
3439 emitcode("dec", "a");
3440 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3442 freeAsmop(left,NULL,ic);
3443 freeAsmop(result,NULL,ic);
3446 /*-----------------------------------------------------------------*/
3447 /* genlshTwo - left shift two bytes by known amount != 0 */
3448 /*-----------------------------------------------------------------*/
3449 static void genrshOne (operand *result,operand *left, int shCount)
3452 int size = AOP_SIZE(result);
3458 l = aopGet(AOP(left),0,FALSE);
3459 if (AOP(result)->type == AOP_REG) {
3460 aopPut(AOP(result), l, 0);
3461 l = aopGet(AOP(result), 0, FALSE);
3463 emitcode("srl", "%s", l);
3468 emitcode("srl", "a");
3470 aopPut(AOP(result),"a",0);
3474 /*-----------------------------------------------------------------*/
3475 /* AccRsh - right shift accumulator by known count */
3476 /*-----------------------------------------------------------------*/
3477 static void AccRsh (int shCount)
3484 /* rotate right accumulator */
3485 AccRol(8 - shCount);
3486 /* and kill the higher order bits */
3487 emit2("and a,!immedbyte", SRMask[shCount]);
3492 /*-----------------------------------------------------------------*/
3493 /* shiftR1Left2Result - shift right one byte from left to result */
3494 /*-----------------------------------------------------------------*/
3495 static void shiftR1Left2Result (operand *left, int offl,
3496 operand *result, int offr,
3497 int shCount, int sign)
3499 MOVA(aopGet(AOP(left),offl,FALSE));
3506 aopPut(AOP(result),"a",offr);
3509 /*-----------------------------------------------------------------*/
3510 /* genrshTwo - right shift two bytes by known amount != 0 */
3511 /*-----------------------------------------------------------------*/
3512 static void genrshTwo (operand *result,operand *left,
3513 int shCount, int sign)
3515 /* if shCount >= 8 */
3520 shiftR1Left2Result(left, MSB16, result, LSB,
3524 movLeft2Result(left, MSB16, result, LSB, sign);
3525 aopPut(AOP(result),zero,1);
3528 /* 1 <= shCount <= 7 */
3530 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3534 /*-----------------------------------------------------------------*/
3535 /* genRightShiftLiteral - left shifting by known count */
3536 /*-----------------------------------------------------------------*/
3537 static void genRightShiftLiteral (operand *left,
3542 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3545 freeAsmop(right,NULL,ic);
3547 aopOp(left,ic,FALSE);
3548 aopOp(result,ic,FALSE);
3550 size = getSize(operandType(result));
3552 emitcode("; shift right ","result %d, left %d",size,
3555 /* I suppose that the left size >= result size */
3560 else if(shCount >= (size * 8))
3562 aopPut(AOP(result),zero,size);
3566 genrshOne(result, left, shCount);
3569 /* PENDING: sign support */
3570 genrshTwo(result, left, shCount, FALSE);
3579 freeAsmop(left,NULL,ic);
3580 freeAsmop(result,NULL,ic);
3583 /*-----------------------------------------------------------------*/
3584 /* genRightShift - generate code for right shifting */
3585 /*-----------------------------------------------------------------*/
3586 static void genRightShift (iCode *ic)
3588 operand *right, *left, *result;
3590 int size, offset, first = 1;
3594 symbol *tlbl, *tlbl1 ;
3596 /* if signed then we do it the hard way preserve the
3597 sign bit moving it inwards */
3598 retype = getSpec(operandType(IC_RESULT(ic)));
3600 is_signed = !SPEC_USIGN(retype);
3602 /* signed & unsigned types are treated the same : i.e. the
3603 signed is NOT propagated inwards : quoting from the
3604 ANSI - standard : "for E1 >> E2, is equivalent to division
3605 by 2**E2 if unsigned or if it has a non-negative value,
3606 otherwise the result is implementation defined ", MY definition
3607 is that the sign does not get propagated */
3609 right = IC_RIGHT(ic);
3611 result = IC_RESULT(ic);
3613 aopOp(right,ic,FALSE);
3615 /* if the shift count is known then do it
3616 as efficiently as possible */
3617 if (AOP_TYPE(right) == AOP_LIT) {
3618 genRightShiftLiteral(left,right,result,ic);
3622 aopOp(left,ic,FALSE);
3623 aopOp(result,ic,FALSE);
3625 /* now move the left to the result if they are not the
3627 if (!sameRegs(AOP(left),AOP(result)) &&
3628 AOP_SIZE(result) > 1) {
3630 size = AOP_SIZE(result);
3633 l = aopGet(AOP(left),offset,FALSE);
3634 aopPut(AOP(result),l,offset);
3639 emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
3640 emitcode("inc","a");
3641 freeAsmop (right, NULL, ic);
3643 tlbl = newiTempLabel(NULL);
3644 tlbl1= newiTempLabel(NULL);
3645 size = AOP_SIZE(result);
3648 emit2("!shortjp !tlabel", tlbl1->key+100);
3649 emitLabel(tlbl->key+100);
3651 l = aopGet(AOP(result),offset--,FALSE);
3654 emitcode("sra", "%s", l);
3656 emitcode("srl", "%s", l);
3660 emitcode("rr", "%s", l);
3662 emitLabel(tlbl1->key+100);
3663 emitcode("dec", "a");
3664 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3666 freeAsmop(left,NULL,ic);
3667 freeAsmop(result,NULL,ic);
3670 /*-----------------------------------------------------------------*/
3671 /* genGenPointerGet - gget value from generic pointer space */
3672 /*-----------------------------------------------------------------*/
3673 static void genGenPointerGet (operand *left,
3674 operand *result, iCode *ic)
3677 link *retype = getSpec(operandType(result));
3683 aopOp(left,ic,FALSE);
3684 aopOp(result,ic,FALSE);
3686 if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
3688 if (isPtrPair(AOP(left)))
3690 tsprintf(buffer, "!*pair", getPairName(AOP(left)));
3691 aopPut(AOP(result), buffer, 0);
3694 emit2("ld a,!*pair", getPairName(AOP(left)));
3695 aopPut(AOP(result),"a", 0);
3697 freeAsmop(left,NULL,ic);
3701 /* For now we always load into IY */
3702 /* if this is remateriazable */
3703 fetchPair(pair, AOP(left));
3705 /* so iy now contains the address */
3706 freeAsmop(left,NULL,ic);
3708 /* if bit then unpack */
3709 if (IS_BITVAR(retype)) {
3713 size = AOP_SIZE(result);
3717 /* PENDING: make this better */
3718 if (!IS_GB && AOP(result)->type == AOP_REG) {
3719 aopPut(AOP(result), "!*hl", offset++);
3722 emit2("ld a,!*pair", _pairs[pair].name);
3723 aopPut(AOP(result),"a",offset++);
3726 emit2("inc %s", _pairs[pair].name);
3732 freeAsmop(result,NULL,ic);
3735 /*-----------------------------------------------------------------*/
3736 /* genPointerGet - generate code for pointer get */
3737 /*-----------------------------------------------------------------*/
3738 static void genPointerGet (iCode *ic)
3740 operand *left, *result ;
3744 result = IC_RESULT(ic) ;
3746 /* depending on the type of pointer we need to
3747 move it to the correct pointer register */
3748 type = operandType(left);
3749 etype = getSpec(type);
3751 genGenPointerGet (left,result,ic);
3754 bool isRegOrLit(asmop *aop)
3756 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3761 /*-----------------------------------------------------------------*/
3762 /* genGenPointerSet - stores the value into a pointer location */
3763 /*-----------------------------------------------------------------*/
3764 static void genGenPointerSet (operand *right,
3765 operand *result, iCode *ic)
3768 link *retype = getSpec(operandType(right));
3769 PAIR_ID pairId = PAIR_HL;
3771 aopOp(result,ic,FALSE);
3772 aopOp(right,ic,FALSE);
3777 /* Handle the exceptions first */
3778 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3780 char *l = aopGet(AOP(right), 0, FALSE);
3781 const char *pair = getPairName(AOP(result));
3782 if (canAssignToPtr(l) && isPtr(pair)) {
3783 emit2("ld !*pair,%s", pair, l);
3787 emit2("ld !*pair,a", pair);
3792 /* if the operand is already in dptr
3793 then we do nothing else we move the value to dptr */
3794 if (AOP_TYPE(result) != AOP_STR) {
3795 fetchPair(pairId, AOP(result));
3797 /* so hl know contains the address */
3798 freeAsmop(result,NULL,ic);
3800 /* if bit then unpack */
3801 if (IS_BITVAR(retype)) {
3805 size = AOP_SIZE(right);
3809 char *l = aopGet(AOP(right),offset,FALSE);
3810 if (isRegOrLit(AOP(right)) && !IS_GB) {
3811 emit2("ld !*pair,%s", _pairs[pairId].name, l);
3815 emit2("ld !*pair,a", _pairs[pairId].name);
3818 emitcode("inc", _pairs[pairId].name);
3824 freeAsmop(right,NULL,ic);
3827 /*-----------------------------------------------------------------*/
3828 /* genPointerSet - stores the value into a pointer location */
3829 /*-----------------------------------------------------------------*/
3830 static void genPointerSet (iCode *ic)
3832 operand *right, *result ;
3835 right = IC_RIGHT(ic);
3836 result = IC_RESULT(ic) ;
3838 /* depending on the type of pointer we need to
3839 move it to the correct pointer register */
3840 type = operandType(result);
3841 etype = getSpec(type);
3843 genGenPointerSet (right,result,ic);
3846 /*-----------------------------------------------------------------*/
3847 /* genIfx - generate code for Ifx statement */
3848 /*-----------------------------------------------------------------*/
3849 static void genIfx (iCode *ic, iCode *popIc)
3851 operand *cond = IC_COND(ic);
3854 aopOp(cond,ic,FALSE);
3856 /* get the value into acc */
3857 if (AOP_TYPE(cond) != AOP_CRY)
3861 /* the result is now in the accumulator */
3862 freeAsmop(cond,NULL,ic);
3864 /* if there was something to be popped then do it */
3868 /* if the condition is a bit variable */
3869 if (isbit && IS_ITEMP(cond) &&
3871 genIfxJump(ic,SPIL_LOC(cond)->rname);
3873 if (isbit && !IS_ITEMP(cond))
3874 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3881 /*-----------------------------------------------------------------*/
3882 /* genAddrOf - generates code for address of */
3883 /*-----------------------------------------------------------------*/
3884 static void genAddrOf (iCode *ic)
3886 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3888 aopOp(IC_RESULT(ic),ic,FALSE);
3890 /* if the operand is on the stack then we
3891 need to get the stack offset of this
3896 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
3897 emitcode("ld", "d,h");
3898 emitcode("ld", "e,l");
3901 emitcode("ld", "de,#%s", sym->rname);
3903 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3904 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3909 /* if it has an offset then we need to compute it */
3910 emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
3911 emitcode("add", "hl,sp");
3914 emitcode("ld", "hl,#%s", sym->rname);
3916 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3917 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3919 freeAsmop(IC_RESULT(ic),NULL,ic);
3922 /*-----------------------------------------------------------------*/
3923 /* genAssign - generate code for assignment */
3924 /*-----------------------------------------------------------------*/
3925 static void genAssign (iCode *ic)
3927 operand *result, *right;
3929 unsigned long lit = 0L;
3931 result = IC_RESULT(ic);
3932 right = IC_RIGHT(ic) ;
3935 /* Dont bother assigning if they are the same */
3936 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3937 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3942 aopOp(right,ic,FALSE);
3943 aopOp(result,ic,TRUE);
3945 /* if they are the same registers */
3946 if (sameRegs(AOP(right),AOP(result))) {
3947 emitcode("", "; (registers are the same)");
3951 /* if the result is a bit */
3952 if (AOP_TYPE(result) == AOP_CRY) {
3957 size = AOP_SIZE(result);
3960 if(AOP_TYPE(right) == AOP_LIT)
3961 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3962 if (isPair(AOP(result)) && isLitWord(AOP(right))) {
3963 emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
3965 else if((size > 1) &&
3966 (AOP_TYPE(result) != AOP_REG) &&
3967 (AOP_TYPE(right) == AOP_LIT) &&
3968 !IS_FLOAT(operandType(right)) &&
3970 bool fXored = FALSE;
3972 /* Work from the top down.
3973 Done this way so that we can use the cached copy of 0
3974 in A for a fast clear */
3976 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3977 if (!fXored && size>1) {
3978 emitcode("xor", "a,a");
3982 aopPut(AOP(result),"a",offset);
3985 aopPut(AOP(result), zero, offset);
3990 aopGet(AOP(right),offset,FALSE),
3995 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
3996 /* Special case. Load into a and d, then load out. */
3997 MOVA(aopGet(AOP(right), 0, FALSE));
3998 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
3999 aopPut(AOP(result), "a", 0);
4000 aopPut(AOP(result), "e", 1);
4003 /* PENDING: do this check better */
4004 if (requiresHL(AOP(right)) && requiresHL(AOP(result))) {
4005 MOVA(aopGet(AOP(right), offset, FALSE));
4006 aopPut(AOP(result), "a", offset);
4010 aopGet(AOP(right),offset,FALSE),
4017 freeAsmop(right,NULL,ic);
4018 freeAsmop(result,NULL,ic);
4021 /*-----------------------------------------------------------------*/
4022 /* genJumpTab - genrates code for jump table */
4023 /*-----------------------------------------------------------------*/
4024 static void genJumpTab (iCode *ic)
4029 aopOp(IC_JTCOND(ic),ic,FALSE);
4030 /* get the condition into accumulator */
4031 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
4033 emitcode("push", "de");
4034 emitcode("ld", "e,%s", l);
4035 emit2("ld d,!zero");
4036 jtab = newiTempLabel(NULL);
4038 emit2("ld hl,!immed!tlabel", jtab->key+100);
4039 emitcode("add", "hl,de");
4040 emitcode("add", "hl,de");
4041 emitcode("add", "hl,de");
4042 freeAsmop(IC_JTCOND(ic),NULL,ic);
4044 emitcode("pop", "de");
4046 emitLabel(jtab->key+100);
4047 /* now generate the jump labels */
4048 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4049 jtab = setNextItem(IC_JTLABELS(ic)))
4050 emit2("jp !tlabel", jtab->key+100);
4053 /*-----------------------------------------------------------------*/
4054 /* genCast - gen code for casting */
4055 /*-----------------------------------------------------------------*/
4056 static void genCast (iCode *ic)
4058 operand *result = IC_RESULT(ic);
4059 link *ctype = operandType(IC_LEFT(ic));
4060 operand *right = IC_RIGHT(ic);
4063 /* if they are equivalent then do nothing */
4064 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4067 aopOp(right,ic,FALSE) ;
4068 aopOp(result,ic,FALSE);
4070 /* if the result is a bit */
4071 if (AOP_TYPE(result) == AOP_CRY) {
4075 /* if they are the same size : or less */
4076 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4078 /* if they are in the same place */
4079 if (sameRegs(AOP(right),AOP(result)))
4082 /* if they in different places then copy */
4083 size = AOP_SIZE(result);
4087 aopGet(AOP(right),offset,FALSE),
4094 /* PENDING: should be OK. */
4096 /* if the result is of type pointer */
4097 if (IS_PTR(ctype)) {
4102 /* so we now know that the size of destination is greater
4103 than the size of the source */
4104 /* we move to result for the size of source */
4105 size = AOP_SIZE(right);
4109 aopGet(AOP(right),offset,FALSE),
4114 /* now depending on the sign of the destination */
4115 size = AOP_SIZE(result) - AOP_SIZE(right);
4116 /* Unsigned or not an integral type - right fill with zeros */
4117 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4119 aopPut(AOP(result),zero,offset++);
4121 /* we need to extend the sign :{ */
4122 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4125 emitcode("", "; genCast: sign extend untested.");
4126 emitcode("rla", "");
4127 emitcode("sbc", "a,a");
4129 aopPut(AOP(result),"a",offset++);
4133 freeAsmop(right, NULL, ic);
4134 freeAsmop(result, NULL, ic);
4137 /*-----------------------------------------------------------------*/
4138 /* genReceive - generate code for a receive iCode */
4139 /*-----------------------------------------------------------------*/
4140 static void genReceive (iCode *ic)
4142 if (isOperandInFarSpace(IC_RESULT(ic)) &&
4143 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4144 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4148 aopOp(IC_RESULT(ic),ic,FALSE);
4150 assignResultValue(IC_RESULT(ic));
4153 freeAsmop(IC_RESULT(ic),NULL,ic);
4156 /*-----------------------------------------------------------------*/
4157 /* genZ80Code - generate code for Z80 based controllers */
4158 /*-----------------------------------------------------------------*/
4159 void genZ80Code (iCode *lic)
4166 _fReturn = _gbz80_return;
4167 _fTmp = _gbz80_return;
4170 _fReturn = _z80_return;
4171 _fTmp = _z80_return;
4173 tsprintf(zero, "!zero");
4175 lineHead = lineCurr = NULL;
4177 /* if debug information required */
4178 if (options.debug && currFunc) {
4179 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4181 if (IS_STATIC(currFunc->etype))
4182 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4184 emitcode("","G$%s$0$0 ==.",currFunc->name);
4187 /* stack pointer name */
4191 for (ic = lic ; ic ; ic = ic->next ) {
4193 if ( cln != ic->lineno ) {
4194 if ( options.debug ) {
4196 emitcode("","C$%s$%d$%d$%d ==.",
4197 ic->filename,ic->lineno,
4198 ic->level,ic->block);
4201 emitcode(";","%s %d",ic->filename,ic->lineno);
4204 /* if the result is marked as
4205 spilt and rematerializable or code for
4206 this has already been generated then
4208 if (resultRemat(ic) || ic->generated )
4211 /* depending on the operation */
4214 emitcode("", "; genNot");
4219 emitcode("", "; genCpl");
4224 emitcode("", "; genUminus");
4229 emitcode("", "; genIpush");
4234 /* IPOP happens only when trying to restore a
4235 spilt live range, if there is an ifx statement
4236 following this pop then the if statement might
4237 be using some of the registers being popped which
4238 would destory the contents of the register so
4239 we need to check for this condition and handle it */
4241 ic->next->op == IFX &&
4242 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4243 emitcode("", "; genIfx");
4244 genIfx (ic->next,ic);
4247 emitcode("", "; genIpop");
4253 emitcode("", "; genCall");
4258 emitcode("", "; genPcall");
4263 emitcode("", "; genFunction");
4268 emitcode("", "; genEndFunction");
4269 genEndFunction (ic);
4273 emitcode("", "; genRet");
4278 emitcode("", "; genLabel");
4283 emitcode("", "; genGoto");
4288 emitcode("", "; genPlus");
4293 emitcode("", "; genMinus");
4298 emitcode("", "; genMult");
4303 emitcode("", "; genDiv");
4308 emitcode("", "; genMod");
4313 emitcode("", "; genCmpGt");
4314 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4318 emitcode("", "; genCmpLt");
4319 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4326 /* note these two are xlated by algebraic equivalence
4327 during parsing SDCC.y */
4328 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4329 "got '>=' or '<=' shouldn't have come here");
4333 emitcode("", "; genCmpEq");
4334 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4338 emitcode("", "; genAndOp");
4343 emitcode("", "; genOrOp");
4348 emitcode("", "; genXor");
4349 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4353 emitcode("", "; genOr");
4354 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4358 emitcode("", "; genAnd");
4359 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4363 emitcode("", "; genInline");
4368 emitcode("", "; genRRC");
4373 emitcode("", "; genRLC");
4378 emitcode("", "; genHBIT");
4382 emitcode("", "; genLeftShift");
4387 emitcode("", "; genRightShift");
4391 case GET_VALUE_AT_ADDRESS:
4392 emitcode("", "; genPointerGet");
4398 if (POINTER_SET(ic)) {
4399 emitcode("", "; genAssign (pointer)");
4403 emitcode("", "; genAssign");
4409 emitcode("", "; genIfx");
4414 emitcode("", "; genAddrOf");
4419 emitcode("", "; genJumpTab");
4424 emitcode("", "; genCast");
4429 emitcode("", "; genReceive");
4434 emitcode("", "; addSet");
4435 addSet(&sendSet,ic);
4440 /* piCode(ic,stdout); */
4446 /* now we are ready to call the
4447 peep hole optimizer */
4448 if (!options.nopeep)
4449 peepHole (&lineHead);
4451 /* now do the actual printing */
4452 printLine (lineHead,codeOutFile);