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, bool requires_a)
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);
363 /* if it is in direct space */
364 printf("sname %s: regsp %u\n", space->sname, space->regsp);
365 if (IN_REGSP(space) && !requires_a) {
366 sym->aop = aop = newAsmop (AOP_SFR);
367 aop->aopu.aop_dir = sym->rname ;
368 aop->size = getSize(sym->type);
369 emitcode("", "; AOP_SFR for %s", sym->rname);
374 /* only remaining is far space */
375 /* in which case DPTR gets the address */
377 sym->aop = aop = newAsmop(AOP_HL);
380 sym->aop = aop = newAsmop(AOP_IY);
382 aop->size = getSize(sym->type);
383 aop->aopu.aop_dir = sym->rname;
385 /* if it is in code space */
386 if (IN_CODESPACE(space))
392 /*-----------------------------------------------------------------*/
393 /* aopForRemat - rematerialzes an object */
394 /*-----------------------------------------------------------------*/
395 static asmop *aopForRemat (symbol *sym)
398 iCode *ic = sym->rematiCode;
399 asmop *aop = newAsmop(AOP_IMMD);
402 /* if plus or minus print the right hand side */
403 if (ic->op == '+' || ic->op == '-') {
404 /* PENDING: for re-target */
405 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
408 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
411 /* we reached the end */
412 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
416 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
417 strcpy(aop->aopu.aop_immd,buffer);
421 /*-----------------------------------------------------------------*/
422 /* regsInCommon - two operands have some registers in common */
423 /*-----------------------------------------------------------------*/
424 bool regsInCommon (operand *op1, operand *op2)
429 /* if they have registers in common */
430 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
433 sym1 = OP_SYMBOL(op1);
434 sym2 = OP_SYMBOL(op2);
436 if (sym1->nRegs == 0 || sym2->nRegs == 0)
439 for (i = 0 ; i < sym1->nRegs ; i++) {
444 for (j = 0 ; j < sym2->nRegs ;j++ ) {
448 if (sym2->regs[j] == sym1->regs[i])
456 /*-----------------------------------------------------------------*/
457 /* operandsEqu - equivalent */
458 /*-----------------------------------------------------------------*/
459 bool operandsEqu ( operand *op1, operand *op2)
463 /* if they not symbols */
464 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
467 sym1 = OP_SYMBOL(op1);
468 sym2 = OP_SYMBOL(op2);
470 /* if both are itemps & one is spilt
471 and the other is not then false */
472 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
473 sym1->isspilt != sym2->isspilt )
476 /* if they are the same */
480 if (strcmp(sym1->rname,sym2->rname) == 0)
484 /* if left is a tmp & right is not */
488 (sym1->usl.spillLoc == sym2))
495 (sym2->usl.spillLoc == sym1))
501 /*-----------------------------------------------------------------*/
502 /* sameRegs - two asmops have the same registers */
503 /*-----------------------------------------------------------------*/
504 bool sameRegs (asmop *aop1, asmop *aop2 )
508 if (aop1->type == AOP_SFR ||
509 aop2->type == AOP_SFR)
515 if (aop1->type != AOP_REG ||
516 aop2->type != AOP_REG )
519 if (aop1->size != aop2->size)
522 for (i = 0 ; i < aop1->size ; i++ )
523 if (aop1->aopu.aop_reg[i] !=
524 aop2->aopu.aop_reg[i] )
530 /*-----------------------------------------------------------------*/
531 /* aopOp - allocates an asmop for an operand : */
532 /*-----------------------------------------------------------------*/
533 static void aopOp (operand *op, iCode *ic, bool result, bool requires_a)
542 /* if this a literal */
543 if (IS_OP_LITERAL(op)) {
544 op->aop = aop = newAsmop(AOP_LIT);
545 aop->aopu.aop_lit = op->operand.valOperand;
546 aop->size = getSize(operandType(op));
550 /* if already has a asmop then continue */
554 /* if the underlying symbol has a aop */
555 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
556 op->aop = OP_SYMBOL(op)->aop;
560 /* if this is a true symbol */
561 if (IS_TRUE_SYMOP(op)) {
562 op->aop = aopForSym(ic,OP_SYMBOL(op),result, requires_a);
566 /* this is a temporary : this has
572 e) can be a return use only */
576 /* if the type is a conditional */
577 if (sym->regType == REG_CND) {
578 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
583 /* if it is spilt then two situations
585 b) has a spill location */
586 if (sym->isspilt || sym->nRegs == 0) {
587 /* rematerialize it NOW */
589 sym->aop = op->aop = aop =
591 aop->size = getSize(sym->type);
597 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
598 aop->size = getSize(sym->type);
599 for ( i = 0 ; i < 2 ; i++ )
600 aop->aopu.aop_str[i] = accUse[i];
606 aop = op->aop = sym->aop = newAsmop(AOP_STR);
607 aop->size = getSize(sym->type);
608 for ( i = 0 ; i < 4 ; i++ )
609 aop->aopu.aop_str[i] = _fReturn[i];
613 /* else spill location */
614 sym->aop = op->aop = aop =
615 aopForSym(ic,sym->usl.spillLoc,result, requires_a);
616 aop->size = getSize(sym->type);
620 /* must be in a register */
621 sym->aop = op->aop = aop = newAsmop(AOP_REG);
622 aop->size = sym->nRegs;
623 for ( i = 0 ; i < sym->nRegs ;i++)
624 aop->aopu.aop_reg[i] = sym->regs[i];
627 /*-----------------------------------------------------------------*/
628 /* freeAsmop - free up the asmop given to an operand */
629 /*----------------------------------------------------------------*/
630 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
648 /* all other cases just dealloc */
652 OP_SYMBOL(op)->aop = NULL;
653 /* if the symbol has a spill */
655 SPIL_LOC(op)->aop = NULL;
660 bool isLitWord(asmop *aop)
662 /* if (aop->size != 2)
673 char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
679 if (aop->size != 2 && aop->type != AOP_HL)
682 wassert(offset == 0);
684 /* depending on type */
689 /* PENDING: for re-target */
691 tsprintf(s, "!hashedstr", aop->aopu.aop_immd);
693 strcpy(s, aop->aopu.aop_immd);
694 ALLOC_ATOMIC(rs,strlen(s)+1);
698 value * val = aop->aopu.aop_lit;
699 /* if it is a float then it gets tricky */
700 /* otherwise it is fairly simple */
701 if (!IS_FLOAT(val->type)) {
702 unsigned long v = floatFromVal(val);
704 tsprintf(buffer, "!immedword", v);
706 tsprintf(buffer, "!constword", v);
707 ALLOC_ATOMIC(rs,strlen(buffer)+1);
708 return strcpy (rs,buffer);
718 char *aopGetWord(asmop *aop, int offset)
720 return aopGetLitWordLong(aop, offset, TRUE);
723 bool isPtr(const char *s)
725 if (!strcmp(s, "hl"))
727 if (!strcmp(s, "ix"))
729 if (!strcmp(s, "iy"))
734 static void adjustPair(const char *pair, int *pold, int new)
738 while (*pold < new) {
739 emitcode("inc", "%s", pair);
742 while (*pold > new) {
743 emitcode("dec", "%s", pair);
748 static void spillPair(PAIR_ID pairId)
750 _G.pairs[pairId].last_type = AOP_INVALID;
751 _G.pairs[pairId].lit = NULL;
754 static void spillCached(void)
760 static bool requiresHL(asmop *aop)
771 static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
774 const char *pair = _pairs[pairId].name;
775 l = aopGetLitWordLong(left, 0, FALSE);
779 if (pairId == PAIR_HL || pairId == PAIR_IY) {
780 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
781 if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
782 adjustPair(pair, &_G.pairs[pairId].offset, offset);
785 if (pairId == PAIR_IY && abs(offset)<127) {
790 _G.pairs[pairId].last_type = left->type;
791 _G.pairs[pairId].lit = gc_strdup(l);
792 _G.pairs[pairId].offset = offset;
794 /* Both a lit on the right and a true symbol on the left */
795 /* PENDING: for re-target */
797 emit2("ld %s,!hashedstr + %d", pair, l, offset);
799 emit2("ld %s,!hashedstr", pair, l);
802 static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
804 /* if this is remateriazable */
805 if (isLitWord(aop)) {
806 fetchLitPair(pairId, aop, offset);
808 else { /* we need to get it byte by byte */
809 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
810 aopGet(aop, offset, FALSE);
816 emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE));
817 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, offset+1, FALSE));
819 /* PENDING: check? */
820 if (pairId == PAIR_HL)
825 static void fetchPair(PAIR_ID pairId, asmop *aop)
827 fetchPairLong(pairId, aop, 0);
830 static void fetchHL(asmop *aop)
832 fetchPair(PAIR_HL, aop);
835 static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
837 assert(pairId == PAIR_HL || pairId == PAIR_IY);
842 fetchLitPair(pairId, aop, offset);
843 _G.pairs[pairId].offset = offset;
846 /* Doesnt include _G.stack.pushed */
847 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
848 assert(pairId == PAIR_HL);
849 /* In some cases we can still inc or dec hl */
850 if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
851 adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
854 emit2("!ldahlsp", aop->aopu.aop_stk+offset + _G.stack.pushed + _G.stack.offset);
856 _G.pairs[pairId].offset = abso;
862 _G.pairs[pairId].last_type = aop->type;
865 static void emitIntLabel(int key)
867 emit2("!tlabeldef", key);
870 static void emitLabel(int key)
872 emit2("!tlabeldef", key);
876 /*-----------------------------------------------------------------*/
877 /* aopGet - for fetching value of the aop */
878 /*-----------------------------------------------------------------*/
879 static char *aopGet(asmop *aop, int offset, bool bit16)
884 /* offset is greater than size then zero */
885 /* PENDING: this seems a bit screwed in some pointer cases. */
886 if (offset > (aop->size - 1) &&
887 aop->type != AOP_LIT)
890 /* depending on type */
893 /* PENDING: re-target */
895 tsprintf (s,"!immedwords", aop->aopu.aop_immd);
898 wassert(offset == 1);
899 tsprintf(s, "!lsbimmeds", aop->aopu.aop_immd);
902 tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
903 ALLOC_ATOMIC(rs,strlen(s)+1);
909 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
911 ALLOC_ATOMIC(rs,strlen(s)+1);
917 emitcode("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
919 ALLOC_ATOMIC(rs,strlen(s)+1);
924 return aop->aopu.aop_reg[offset]->name;
928 setupPair(PAIR_HL, aop, offset);
934 setupPair(PAIR_IY, aop, offset);
935 tsprintf(s,"!*iyx", offset);
936 ALLOC_ATOMIC(rs,strlen(s)+1);
942 setupPair(PAIR_HL, aop, offset);
946 tsprintf(s,"!*ixx", aop->aopu.aop_stk+offset);
948 ALLOC_ATOMIC(rs,strlen(s)+1);
962 return aopLiteral (aop->aopu.aop_lit,offset);
966 return aop->aopu.aop_str[offset];
970 wassertl(0, "aopget got unsupported aop->type");
974 bool isRegString(char *s)
976 if (!strcmp(s, "b") ||
987 bool isConstant(const char *s)
989 /* This is a bit of a hack... */
990 return (*s == '#' || *s == '$');
993 bool canAssignToPtr(char *s)
1002 /*-----------------------------------------------------------------*/
1003 /* aopPut - puts a string for a aop */
1004 /*-----------------------------------------------------------------*/
1005 static void aopPut (asmop *aop, char *s, int offset)
1007 if (aop->size && offset > ( aop->size - 1)) {
1008 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1009 "aopPut got offset > aop->size");
1013 /* will assign value to value */
1014 /* depending on where it is ofcourse */
1015 switch (aop->type) {
1020 emitcode("ld", "a,%s", s);
1021 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1027 emitcode("ld", "a,%s", s);
1028 emitcode("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
1032 emitcode("ld","%s,%s",
1033 aop->aopu.aop_reg[offset]->name,s);
1038 setupPair(PAIR_IY, aop, offset);
1039 if (!canAssignToPtr(s)) {
1040 emit2("ld a,%s", s);
1041 emit2("ld !*iyx,a", offset);
1044 emit2("ld !*iyx,%s", offset, s);
1049 /* PENDING: for re-target */
1050 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1054 setupPair(PAIR_HL, aop, offset);
1056 emit2("ld !*hl,%s", s);
1061 /* PENDING: re-target */
1062 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1066 setupPair(PAIR_HL, aop, offset);
1067 if (!canAssignToPtr(s)) {
1068 emit2("ld a,%s", s);
1072 emit2("ld !*hl,%s ; 3", s);
1075 if (!canAssignToPtr(s)) {
1076 emit2("ld a,%s", s);
1077 emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
1080 emit2("ld !*ixx,%s", aop->aopu.aop_stk+offset, s);
1085 /* if bit variable */
1086 if (!aop->aopu.aop_dir) {
1090 /* In bit space but not in C - cant happen */
1097 if (strcmp(aop->aopu.aop_str[offset],s)) {
1098 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1104 if (!offset && (strcmp(s,"acc") == 0))
1108 emitcode("", "; Error aopPut AOP_ACC");
1111 if (strcmp(aop->aopu.aop_str[offset],s))
1112 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1117 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1118 "aopPut got unsupported aop->type");
1123 #define AOP(op) op->aop
1124 #define AOP_TYPE(op) AOP(op)->type
1125 #define AOP_SIZE(op) AOP(op)->size
1126 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1128 /*-----------------------------------------------------------------*/
1129 /* getDataSize - get the operand data size */
1130 /*-----------------------------------------------------------------*/
1131 int getDataSize(operand *op)
1134 size = AOP_SIZE(op);
1142 /*-----------------------------------------------------------------*/
1143 /* movLeft2Result - move byte from left to result */
1144 /*-----------------------------------------------------------------*/
1145 static void movLeft2Result (operand *left, int offl,
1146 operand *result, int offr, int sign)
1149 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1150 l = aopGet(AOP(left),offl,FALSE);
1153 aopPut(AOP(result),l,offr);
1162 /** Put Acc into a register set
1164 void outAcc(operand *result)
1167 size = getDataSize(result);
1169 aopPut(AOP(result),"a",0);
1172 /* unsigned or positive */
1174 aopPut(AOP(result), zero, offset++);
1179 /** Take the value in carry and put it into a register
1181 void outBitC(operand *result)
1183 /* if the result is bit */
1184 if (AOP_TYPE(result) == AOP_CRY) {
1185 emitcode("", "; Note: outBitC form 1");
1186 aopPut(AOP(result),"blah",0);
1189 emit2("ld a,!zero");
1195 /*-----------------------------------------------------------------*/
1196 /* toBoolean - emit code for orl a,operator(sizeop) */
1197 /*-----------------------------------------------------------------*/
1198 void toBoolean(operand *oper)
1200 int size = AOP_SIZE(oper);
1203 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1206 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1209 if (AOP(oper)->type != AOP_ACC) {
1211 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1216 /*-----------------------------------------------------------------*/
1217 /* genNot - generate code for ! operation */
1218 /*-----------------------------------------------------------------*/
1219 static void genNot (iCode *ic)
1221 link *optype = operandType(IC_LEFT(ic));
1223 /* assign asmOps to operand & result */
1224 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
1225 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1227 /* if in bit space then a special case */
1228 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1232 /* if type float then do float */
1233 if (IS_FLOAT(optype)) {
1237 toBoolean(IC_LEFT(ic));
1242 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1243 emit2("sub a,!one");
1244 outBitC(IC_RESULT(ic));
1246 /* release the aops */
1247 freeAsmop(IC_LEFT(ic),NULL,ic);
1248 freeAsmop(IC_RESULT(ic),NULL,ic);
1251 /*-----------------------------------------------------------------*/
1252 /* genCpl - generate code for complement */
1253 /*-----------------------------------------------------------------*/
1254 static void genCpl (iCode *ic)
1260 /* assign asmOps to operand & result */
1261 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1262 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1264 /* if both are in bit space then
1266 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1267 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1271 size = AOP_SIZE(IC_RESULT(ic));
1273 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1276 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1279 /* release the aops */
1280 freeAsmop(IC_LEFT(ic),NULL,ic);
1281 freeAsmop(IC_RESULT(ic),NULL,ic);
1284 /*-----------------------------------------------------------------*/
1285 /* genUminus - unary minus code generation */
1286 /*-----------------------------------------------------------------*/
1287 static void genUminus (iCode *ic)
1290 link *optype, *rtype;
1293 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1294 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
1296 /* if both in bit space then special
1298 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1299 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1304 optype = operandType(IC_LEFT(ic));
1305 rtype = operandType(IC_RESULT(ic));
1307 /* if float then do float stuff */
1308 if (IS_FLOAT(optype)) {
1313 /* otherwise subtract from zero */
1314 size = AOP_SIZE(IC_LEFT(ic));
1318 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1319 emit2("ld a,!zero");
1320 emit2("sbc a,%s",l);
1321 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1324 /* if any remaining bytes in the result */
1325 /* we just need to propagate the sign */
1326 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1330 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1334 /* release the aops */
1335 freeAsmop(IC_LEFT(ic),NULL,ic);
1336 freeAsmop(IC_RESULT(ic),NULL,ic);
1339 /*-----------------------------------------------------------------*/
1340 /* assignResultValue - */
1341 /*-----------------------------------------------------------------*/
1342 void assignResultValue(operand * oper)
1344 int size = AOP_SIZE(oper);
1348 topInA = requiresHL(AOP(oper));
1352 if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
1353 /* We do it the hard way here. */
1354 emitcode("push", "hl");
1355 _G.stack.pushed += 2;
1356 aopPut(AOP(oper), _fReturn[0], 0);
1357 aopPut(AOP(oper), _fReturn[1], 1);
1358 emitcode("pop", "de");
1359 _G.stack.pushed -= 2;
1360 aopPut(AOP(oper), _fReturn[0], 2);
1361 aopPut(AOP(oper), _fReturn[1], 3);
1365 aopPut(AOP(oper), _fReturn[size], size);
1370 /*-----------------------------------------------------------------*/
1371 /* genIpush - genrate code for pushing this gets a little complex */
1372 /*-----------------------------------------------------------------*/
1373 static void genIpush (iCode *ic)
1375 int size, offset = 0 ;
1379 /* if this is not a parm push : ie. it is spill push
1380 and spill push is always done on the local stack */
1381 if (!ic->parmPush) {
1382 /* and the item is spilt then do nothing */
1383 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1386 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1387 size = AOP_SIZE(IC_LEFT(ic));
1388 /* push it on the stack */
1389 if (isPair(AOP(IC_LEFT(ic)))) {
1390 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1391 _G.stack.pushed += 2;
1396 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1397 /* Simple for now - load into A and PUSH AF */
1398 emitcode("ld", "a,%s", l);
1399 emitcode("push", "af");
1400 emitcode("inc", "sp");
1407 /* Hmmm... what about saving the currently used registers
1410 /* then do the push */
1411 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1413 size = AOP_SIZE(IC_LEFT(ic));
1415 if (isPair(AOP(IC_LEFT(ic)))) {
1417 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1421 fetchHL(AOP(IC_LEFT(ic)));
1422 emitcode("push", "hl");
1424 _G.stack.pushed += 2;
1429 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1430 emitcode("ld", "a,%s", l);
1431 emitcode("push", "af");
1432 emitcode("inc", "sp");
1437 freeAsmop(IC_LEFT(ic),NULL,ic);
1440 /*-----------------------------------------------------------------*/
1441 /* genIpop - recover the registers: can happen only for spilling */
1442 /*-----------------------------------------------------------------*/
1443 static void genIpop (iCode *ic)
1448 /* if the temp was not pushed then */
1449 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1452 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1453 size = AOP_SIZE(IC_LEFT(ic));
1455 if (isPair(AOP(IC_LEFT(ic)))) {
1456 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1460 emitcode("dec", "sp");
1461 emitcode("pop", "hl");
1463 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1467 freeAsmop(IC_LEFT(ic),NULL,ic);
1470 /** Emit the code for a call statement
1472 static void emitCall (iCode *ic, bool ispcall)
1474 /* if caller saves & we have not saved then */
1475 if (!ic->regsSaved) {
1479 /* if send set is not empty then assign */
1482 for (sic = setFirstItem(sendSet) ; sic ;
1483 sic = setNextItem(sendSet)) {
1484 int size, offset = 0;
1485 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1486 size = AOP_SIZE(IC_LEFT(sic));
1488 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1490 if (strcmp(l, _fReturn[offset]))
1491 emitcode("ld","%s,%s",
1496 freeAsmop (IC_LEFT(sic),NULL,sic);
1502 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1504 if (isLitWord(AOP(IC_LEFT(ic)))) {
1505 emitcode("", "; Special case where the pCall is to a constant");
1506 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1509 symbol *rlbl = newiTempLabel(NULL);
1511 emit2("ld hl,#!tlabel", (rlbl->key+100));
1512 emitcode("push", "hl");
1513 _G.stack.pushed += 2;
1515 fetchHL(AOP(IC_LEFT(ic)));
1517 emit2("!tlabeldef", (rlbl->key+100));
1518 _G.stack.pushed -= 2;
1520 freeAsmop(IC_LEFT(ic),NULL,ic);
1524 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1525 OP_SYMBOL(IC_LEFT(ic))->rname :
1526 OP_SYMBOL(IC_LEFT(ic))->name;
1527 emitcode("call", "%s", name);
1531 /* if we need assign a result value */
1532 if ((IS_ITEMP(IC_RESULT(ic)) &&
1533 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1534 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1535 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1538 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1541 assignResultValue(IC_RESULT(ic));
1543 freeAsmop(IC_RESULT(ic),NULL, ic);
1546 /* adjust the stack for parameters if required */
1547 if (IC_LEFT(ic)->parmBytes) {
1548 int i = IC_LEFT(ic)->parmBytes;
1549 _G.stack.pushed -= i;
1551 emit2("!ldaspsp", i);
1556 emitcode("ld", "hl,#%d", i);
1557 emitcode("add", "hl,sp");
1558 emitcode("ld", "sp,hl");
1562 emitcode("pop", "hl");
1566 emitcode("inc", "sp");
1574 /*-----------------------------------------------------------------*/
1575 /* genCall - generates a call statement */
1576 /*-----------------------------------------------------------------*/
1577 static void genCall (iCode *ic)
1579 emitCall(ic, FALSE);
1582 /*-----------------------------------------------------------------*/
1583 /* genPcall - generates a call by pointer statement */
1584 /*-----------------------------------------------------------------*/
1585 static void genPcall (iCode *ic)
1590 /*-----------------------------------------------------------------*/
1591 /* resultRemat - result is rematerializable */
1592 /*-----------------------------------------------------------------*/
1593 static int resultRemat (iCode *ic)
1595 if (SKIP_IC(ic) || ic->op == IFX)
1598 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1599 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1600 if (sym->remat && !POINTER_SET(ic))
1607 /*-----------------------------------------------------------------*/
1608 /* genFunction - generated code for function entry */
1609 /*-----------------------------------------------------------------*/
1610 static void genFunction (iCode *ic)
1612 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1616 /* create the function header */
1617 emit2("!functionheader", sym->name);
1618 /* PENDING: portability. */
1619 emit2("__%s_start:", sym->rname);
1620 emit2("!functionlabeldef", sym->rname);
1622 fetype = getSpec(operandType(IC_LEFT(ic)));
1624 /* if critical function then turn interrupts off */
1625 if (SPEC_CRTCL(fetype))
1628 /* if this is an interrupt service routine then
1629 save acc, b, dpl, dph */
1630 if (IS_ISR(sym->etype)) {
1633 /* PENDING: callee-save etc */
1635 /* adjust the stack for the function */
1636 _G.stack.last = sym->stack;
1639 emit2("!enterx", sym->stack);
1642 _G.stack.offset = sym->stack;
1645 /*-----------------------------------------------------------------*/
1646 /* genEndFunction - generates epilogue for functions */
1647 /*-----------------------------------------------------------------*/
1648 static void genEndFunction (iCode *ic)
1650 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1652 if (IS_ISR(sym->etype)) {
1656 if (SPEC_CRTCL(sym->etype))
1659 /* PENDING: calleeSave */
1661 /* if debug then send end of function */
1662 if (options.debug && currFunc) {
1664 emitcode("","C$%s$%d$%d$%d ==.",
1665 ic->filename,currFunc->lastLine,
1666 ic->level,ic->block);
1667 if (IS_STATIC(currFunc->etype))
1668 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1670 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1673 if (_G.stack.offset)
1674 emit2("!leavex", _G.stack.offset);
1677 /* PENDING: portability. */
1678 emit2("__%s_end:", sym->rname);
1680 _G.stack.pushed = 0;
1681 _G.stack.offset = 0;
1684 /*-----------------------------------------------------------------*/
1685 /* genRet - generate code for return statement */
1686 /*-----------------------------------------------------------------*/
1687 static void genRet (iCode *ic)
1690 /* Errk. This is a hack until I can figure out how
1691 to cause dehl to spill on a call */
1692 int size,offset = 0;
1694 /* if we have no return value then
1695 just generate the "ret" */
1699 /* we have something to return then
1700 move the return value into place */
1701 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1702 size = AOP_SIZE(IC_LEFT(ic));
1704 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1706 emitcode("ld", "de,%s", l);
1709 emitcode("ld", "hl,%s", l);
1713 if (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
1714 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
1715 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
1719 l = aopGet(AOP(IC_LEFT(ic)),offset,
1721 if (strcmp(_fReturn[offset],l))
1722 emitcode("ld","%s,%s", _fReturn[offset++],l);
1726 freeAsmop (IC_LEFT(ic),NULL,ic);
1729 /* generate a jump to the return label
1730 if the next is not the return statement */
1731 if (!(ic->next && ic->next->op == LABEL &&
1732 IC_LABEL(ic->next) == returnLabel))
1734 emit2("jp !tlabel", returnLabel->key+100);
1737 /*-----------------------------------------------------------------*/
1738 /* genLabel - generates a label */
1739 /*-----------------------------------------------------------------*/
1740 static void genLabel (iCode *ic)
1742 /* special case never generate */
1743 if (IC_LABEL(ic) == entryLabel)
1746 emitLabel(IC_LABEL(ic)->key+100);
1749 /*-----------------------------------------------------------------*/
1750 /* genGoto - generates a ljmp */
1751 /*-----------------------------------------------------------------*/
1752 static void genGoto (iCode *ic)
1754 emit2("jp !tlabel", IC_LABEL(ic)->key+100);
1757 /*-----------------------------------------------------------------*/
1758 /* genPlusIncr :- does addition with increment if possible */
1759 /*-----------------------------------------------------------------*/
1760 static bool genPlusIncr (iCode *ic)
1762 unsigned int icount ;
1763 unsigned int size = getDataSize(IC_RESULT(ic));
1764 PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
1766 /* will try to generate an increment */
1767 /* if the right side is not a literal
1769 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1772 emitcode("", "; genPlusIncr");
1774 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1776 /* If result is a pair */
1777 if (resultId != PAIR_INVALID) {
1778 if (isLitWord(AOP(IC_LEFT(ic)))) {
1779 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
1782 if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
1783 fetchPair(resultId, AOP(IC_RIGHT(ic)));
1784 emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
1790 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1793 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1794 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1797 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1802 /* if the literal value of the right hand side
1803 is greater than 4 then it is not worth it */
1807 /* if increment 16 bits in register */
1808 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1813 symbol *tlbl = NULL;
1816 emitIntLabel(tlbl->key+100);
1818 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)), offset++, FALSE));
1820 tlbl = newiTempLabel(NULL);
1821 emit2("!shortjp nz,!tlabel", tlbl->key+100);
1827 /* if the sizes are greater than 1 then we cannot */
1828 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1829 AOP_SIZE(IC_LEFT(ic)) > 1 )
1832 /* we can if the aops of the left & result match or
1833 if they are in registers and the registers are the
1835 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1837 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1844 /*-----------------------------------------------------------------*/
1845 /* outBitAcc - output a bit in acc */
1846 /*-----------------------------------------------------------------*/
1847 void outBitAcc(operand *result)
1849 symbol *tlbl = newiTempLabel(NULL);
1850 /* if the result is a bit */
1851 if (AOP_TYPE(result) == AOP_CRY){
1855 emit2("!shortjp z,!tlabel", tlbl->key+100);
1857 emitLabel(tlbl->key+100);
1862 /*-----------------------------------------------------------------*/
1863 /* genPlus - generates code for addition */
1864 /*-----------------------------------------------------------------*/
1865 static void genPlus (iCode *ic)
1867 int size, offset = 0;
1869 /* special cases :- */
1871 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1872 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
1873 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1875 /* Swap the left and right operands if:
1877 if literal, literal on the right or
1878 if left requires ACC or right is already
1881 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1882 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1883 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1884 operand *t = IC_RIGHT(ic);
1885 IC_RIGHT(ic) = IC_LEFT(ic);
1889 /* if both left & right are in bit
1891 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1892 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1897 /* if left in bit space & right literal */
1898 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1899 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1900 /* Can happen I guess */
1904 /* if I can do an increment instead
1905 of add then GOOD for ME */
1906 if (genPlusIncr (ic) == TRUE)
1909 size = getDataSize(IC_RESULT(ic));
1911 /* Special case when left and right are constant */
1912 if (isPair(AOP(IC_RESULT(ic)))) {
1915 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1916 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1917 if (left && right) {
1921 sprintf(buffer, "#(%s + %s)", left, right);
1922 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1927 if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
1928 /* Fetch into HL then do the add */
1930 fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
1931 emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
1936 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1937 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1939 emitcode("add","a,%s",
1940 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1942 emitcode("adc","a,%s",
1943 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1945 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1947 emitcode("add","a,%s",
1948 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1950 emitcode("adc","a,%s",
1951 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1953 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1956 /* Some kind of pointer arith. */
1957 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1958 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1959 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1962 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1963 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1964 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1969 freeAsmop(IC_LEFT(ic),NULL,ic);
1970 freeAsmop(IC_RIGHT(ic),NULL,ic);
1971 freeAsmop(IC_RESULT(ic),NULL,ic);
1975 /*-----------------------------------------------------------------*/
1976 /* genMinusDec :- does subtraction with deccrement if possible */
1977 /*-----------------------------------------------------------------*/
1978 static bool genMinusDec (iCode *ic)
1980 unsigned int icount ;
1981 unsigned int size = getDataSize(IC_RESULT(ic));
1983 /* will try to generate an increment */
1984 /* if the right side is not a literal we cannot */
1985 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1988 /* if the literal value of the right hand side
1989 is greater than 4 then it is not worth it */
1990 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1993 size = getDataSize(IC_RESULT(ic));
1996 /* if increment 16 bits in register */
1997 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2000 symbol *tlbl = newiTempLabel(NULL);
2001 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
2002 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
2004 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
2008 emitLabel(tlbl->key+100);
2013 /* if decrement 16 bits in register */
2014 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2015 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
2017 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2021 /* If result is a pair */
2022 if (isPair(AOP(IC_RESULT(ic)))) {
2023 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2024 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2026 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2030 /* if the sizes are greater than 1 then we cannot */
2031 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2032 AOP_SIZE(IC_LEFT(ic)) > 1 )
2035 /* we can if the aops of the left & result match or if they are in
2036 registers and the registers are the same */
2037 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2039 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
2046 /*-----------------------------------------------------------------*/
2047 /* genMinus - generates code for subtraction */
2048 /*-----------------------------------------------------------------*/
2049 static void genMinus (iCode *ic)
2051 int size, offset = 0;
2052 unsigned long lit = 0L;
2054 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2055 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2056 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2058 /* special cases :- */
2059 /* if both left & right are in bit space */
2060 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2061 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2066 /* if I can do an decrement instead of subtract then GOOD for ME */
2067 if (genMinusDec (ic) == TRUE)
2070 size = getDataSize(IC_RESULT(ic));
2072 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2075 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2080 /* if literal, add a,#-lit, else normal subb */
2082 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2083 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2085 emitcode("sub","a,%s",
2086 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2088 emitcode("sbc","a,%s",
2089 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2092 /* first add without previous c */
2094 emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL));
2096 emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2098 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2101 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2102 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2103 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2107 freeAsmop(IC_LEFT(ic),NULL,ic);
2108 freeAsmop(IC_RIGHT(ic),NULL,ic);
2109 freeAsmop(IC_RESULT(ic),NULL,ic);
2112 /*-----------------------------------------------------------------*/
2113 /* genMult - generates code for multiplication */
2114 /*-----------------------------------------------------------------*/
2115 static void genMult (iCode *ic)
2117 /* Shouldn't occur - all done through function calls */
2121 /*-----------------------------------------------------------------*/
2122 /* genDiv - generates code for division */
2123 /*-----------------------------------------------------------------*/
2124 static void genDiv (iCode *ic)
2126 /* Shouldn't occur - all done through function calls */
2130 /*-----------------------------------------------------------------*/
2131 /* genMod - generates code for division */
2132 /*-----------------------------------------------------------------*/
2133 static void genMod (iCode *ic)
2135 /* Shouldn't occur - all done through function calls */
2139 /*-----------------------------------------------------------------*/
2140 /* genIfxJump :- will create a jump depending on the ifx */
2141 /*-----------------------------------------------------------------*/
2142 static void genIfxJump (iCode *ic, char *jval)
2147 /* if true label then we jump if condition
2149 if ( IC_TRUE(ic) ) {
2151 if (!strcmp(jval, "a")) {
2154 else if (!strcmp(jval, "c")) {
2158 /* The buffer contains the bit on A that we should test */
2163 /* false label is present */
2164 jlbl = IC_FALSE(ic) ;
2165 if (!strcmp(jval, "a")) {
2168 else if (!strcmp(jval, "c")) {
2172 /* The buffer contains the bit on A that we should test */
2176 /* Z80 can do a conditional long jump */
2177 if (!strcmp(jval, "a")) {
2178 emitcode("or", "a,a");
2180 else if (!strcmp(jval, "c")) {
2183 emitcode("bit", "%s,a", jval);
2185 emit2("jp %s,!tlabel", inst, jlbl->key+100);
2187 /* mark the icode as generated */
2191 /** Generic compare for > or <
2193 static void genCmp (operand *left,operand *right,
2194 operand *result, iCode *ifx, int sign)
2196 int size, offset = 0 ;
2197 unsigned long lit = 0L;
2199 /* if left & right are bit variables */
2200 if (AOP_TYPE(left) == AOP_CRY &&
2201 AOP_TYPE(right) == AOP_CRY ) {
2202 /* Cant happen on the Z80 */
2205 /* subtract right from left if at the
2206 end the carry flag is set then we know that
2207 left is greater than right */
2208 size = max(AOP_SIZE(left),AOP_SIZE(right));
2210 /* if unsigned char cmp with lit, just compare */
2212 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2213 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2215 emit2("xor a,!immedbyte", 0x80);
2216 emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80);
2219 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
2222 if(AOP_TYPE(right) == AOP_LIT) {
2223 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2224 /* optimize if(x < 0) or if(x >= 0) */
2227 /* No sign so it's always false */
2231 /* Just load in the top most bit */
2232 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2233 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2234 genIfxJump (ifx,"7");
2238 emitcode("rlc","a");
2244 /* First setup h and l contaning the top most bytes XORed */
2245 bool fDidXor = FALSE;
2246 if (AOP_TYPE(left) == AOP_LIT){
2247 unsigned long lit = (unsigned long)
2248 floatFromVal(AOP(left)->aopu.aop_lit);
2249 emit2("ld %s,!immedbyte", _fTmp[0],
2250 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2253 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2254 emit2("xor a,!immedbyte", 0x80);
2255 emitcode("ld", "%s,a", _fTmp[0]);
2258 if (AOP_TYPE(right) == AOP_LIT) {
2259 unsigned long lit = (unsigned long)
2260 floatFromVal(AOP(right)->aopu.aop_lit);
2261 emit2("ld %s,!immedbyte", _fTmp[1],
2262 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2265 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2266 emit2("xor a,!immedbyte", 0x80);
2267 emitcode("ld", "%s,a", _fTmp[1]);
2277 /* Do a long subtract */
2278 if (!sign || size ) {
2279 MOVA(aopGet(AOP(left),offset,FALSE));
2281 if (sign && size == 0) {
2282 emitcode("ld", "a,%s", _fTmp[0]);
2283 emitcode("sbc", "a,%s", _fTmp[1]);
2286 /* Subtract through, propagating the carry */
2287 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2294 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2297 /* if the result is used in the next
2298 ifx conditional branch then generate
2299 code a little differently */
2301 genIfxJump (ifx,"c");
2304 /* leave the result in acc */
2308 /*-----------------------------------------------------------------*/
2309 /* genCmpGt :- greater than comparison */
2310 /*-----------------------------------------------------------------*/
2311 static void genCmpGt (iCode *ic, iCode *ifx)
2313 operand *left, *right, *result;
2314 link *letype , *retype;
2318 right= IC_RIGHT(ic);
2319 result = IC_RESULT(ic);
2321 letype = getSpec(operandType(left));
2322 retype =getSpec(operandType(right));
2323 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2324 /* assign the amsops */
2325 aopOp (left,ic,FALSE, FALSE);
2326 aopOp (right,ic,FALSE, FALSE);
2327 aopOp (result,ic,TRUE, FALSE);
2329 genCmp(right, left, result, ifx, sign);
2331 freeAsmop(left,NULL,ic);
2332 freeAsmop(right,NULL,ic);
2333 freeAsmop(result,NULL,ic);
2336 /*-----------------------------------------------------------------*/
2337 /* genCmpLt - less than comparisons */
2338 /*-----------------------------------------------------------------*/
2339 static void genCmpLt (iCode *ic, iCode *ifx)
2341 operand *left, *right, *result;
2342 link *letype , *retype;
2346 right= IC_RIGHT(ic);
2347 result = IC_RESULT(ic);
2349 letype = getSpec(operandType(left));
2350 retype =getSpec(operandType(right));
2351 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2353 /* assign the amsops */
2354 aopOp (left,ic,FALSE, FALSE);
2355 aopOp (right,ic,FALSE, FALSE);
2356 aopOp (result,ic,TRUE, FALSE);
2358 genCmp(left, right, result, ifx, sign);
2360 freeAsmop(left,NULL,ic);
2361 freeAsmop(right,NULL,ic);
2362 freeAsmop(result,NULL,ic);
2365 /*-----------------------------------------------------------------*/
2366 /* gencjneshort - compare and jump if not equal */
2367 /*-----------------------------------------------------------------*/
2368 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2370 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2372 unsigned long lit = 0L;
2374 /* Swap the left and right if it makes the computation easier */
2375 if (AOP_TYPE(left) == AOP_LIT) {
2381 if(AOP_TYPE(right) == AOP_LIT)
2382 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2384 /* if the right side is a literal then anything goes */
2385 if (AOP_TYPE(right) == AOP_LIT &&
2386 AOP_TYPE(left) != AOP_DIR ) {
2388 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2393 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2397 emitcode("or", "a,a");
2399 emit2("jp nz,!tlabel", lbl->key+100);
2403 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2404 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2405 emitcode("or", "a,a");
2407 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2408 emit2("jp nz,!tlabel", lbl->key+100);
2413 /* if the right side is in a register or in direct space or
2414 if the left is a pointer register & right is not */
2415 else if (AOP_TYPE(right) == AOP_REG ||
2416 AOP_TYPE(right) == AOP_DIR ||
2417 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2419 MOVA(aopGet(AOP(left),offset,FALSE));
2420 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2421 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2423 emit2("jp nz,!tlabel", lbl->key+100);
2425 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2426 emit2("jp nz,!tlabel", lbl->key+100);
2431 /* right is a pointer reg need both a & b */
2432 /* PENDING: is this required? */
2434 MOVA(aopGet(AOP(right),offset,FALSE));
2435 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2436 emit2("!shortjp nz,!tlabel", lbl->key+100);
2442 /*-----------------------------------------------------------------*/
2443 /* gencjne - compare and jump if not equal */
2444 /*-----------------------------------------------------------------*/
2445 static void gencjne(operand *left, operand *right, symbol *lbl)
2447 symbol *tlbl = newiTempLabel(NULL);
2449 gencjneshort(left, right, lbl);
2453 emit2("!shortjp !tlabel", tlbl->key+100);
2454 emitLabel(lbl->key+100);
2455 emitcode("xor","a,a");
2456 emitLabel(tlbl->key+100);
2459 /*-----------------------------------------------------------------*/
2460 /* genCmpEq - generates code for equal to */
2461 /*-----------------------------------------------------------------*/
2462 static void genCmpEq (iCode *ic, iCode *ifx)
2464 operand *left, *right, *result;
2466 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
2467 aopOp((right=IC_RIGHT(ic)),ic,FALSE, FALSE);
2468 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
2470 /* Swap operands if it makes the operation easier. ie if:
2471 1. Left is a literal.
2473 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2474 operand *t = IC_RIGHT(ic);
2475 IC_RIGHT(ic) = IC_LEFT(ic);
2479 if (ifx && !AOP_SIZE(result)){
2481 /* if they are both bit variables */
2482 if (AOP_TYPE(left) == AOP_CRY &&
2483 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2486 tlbl = newiTempLabel(NULL);
2487 gencjneshort(left, right, tlbl);
2488 if ( IC_TRUE(ifx) ) {
2489 emit2("jp !tlabel", IC_TRUE(ifx)->key+100);
2490 emitLabel(tlbl->key+100);
2492 /* PENDING: do this better */
2493 symbol *lbl = newiTempLabel(NULL);
2494 emit2("!shortjp !tlabel", lbl->key+100);
2495 emitLabel(tlbl->key+100);
2496 emit2("jp !tlabel", IC_FALSE(ifx)->key+100);
2497 emitLabel(lbl->key+100);
2500 /* mark the icode as generated */
2505 /* if they are both bit variables */
2506 if (AOP_TYPE(left) == AOP_CRY &&
2507 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2510 gencjne(left,right,newiTempLabel(NULL));
2511 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2515 genIfxJump(ifx,"a");
2518 /* if the result is used in an arithmetic operation
2519 then put the result in place */
2520 if (AOP_TYPE(result) != AOP_CRY) {
2523 /* leave the result in acc */
2527 freeAsmop(left,NULL,ic);
2528 freeAsmop(right,NULL,ic);
2529 freeAsmop(result,NULL,ic);
2532 /*-----------------------------------------------------------------*/
2533 /* ifxForOp - returns the icode containing the ifx for operand */
2534 /*-----------------------------------------------------------------*/
2535 static iCode *ifxForOp ( operand *op, iCode *ic )
2537 /* if true symbol then needs to be assigned */
2538 if (IS_TRUE_SYMOP(op))
2541 /* if this has register type condition and
2542 the next instruction is ifx with the same operand
2543 and live to of the operand is upto the ifx only then */
2545 ic->next->op == IFX &&
2546 IC_COND(ic->next)->key == op->key &&
2547 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2553 /*-----------------------------------------------------------------*/
2554 /* genAndOp - for && operation */
2555 /*-----------------------------------------------------------------*/
2556 static void genAndOp (iCode *ic)
2558 operand *left,*right, *result;
2561 /* note here that && operations that are in an if statement are
2562 taken away by backPatchLabels only those used in arthmetic
2563 operations remain */
2564 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
2565 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
2566 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
2568 /* if both are bit variables */
2569 if (AOP_TYPE(left) == AOP_CRY &&
2570 AOP_TYPE(right) == AOP_CRY ) {
2573 tlbl = newiTempLabel(NULL);
2575 emit2("!shortjp z,!tlabel", tlbl->key+100);
2577 emitLabel(tlbl->key+100);
2581 freeAsmop(left,NULL,ic);
2582 freeAsmop(right,NULL,ic);
2583 freeAsmop(result,NULL,ic);
2586 /*-----------------------------------------------------------------*/
2587 /* genOrOp - for || operation */
2588 /*-----------------------------------------------------------------*/
2589 static void genOrOp (iCode *ic)
2591 operand *left,*right, *result;
2594 /* note here that || operations that are in an
2595 if statement are taken away by backPatchLabels
2596 only those used in arthmetic operations remain */
2597 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
2598 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
2599 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
2601 /* if both are bit variables */
2602 if (AOP_TYPE(left) == AOP_CRY &&
2603 AOP_TYPE(right) == AOP_CRY ) {
2606 tlbl = newiTempLabel(NULL);
2608 emit2("!shortjp nz,!tlabel", tlbl->key+100);
2610 emitLabel(tlbl->key+100);
2614 freeAsmop(left,NULL,ic);
2615 freeAsmop(right,NULL,ic);
2616 freeAsmop(result,NULL,ic);
2619 /*-----------------------------------------------------------------*/
2620 /* isLiteralBit - test if lit == 2^n */
2621 /*-----------------------------------------------------------------*/
2622 int isLiteralBit(unsigned long lit)
2624 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2625 0x100L,0x200L,0x400L,0x800L,
2626 0x1000L,0x2000L,0x4000L,0x8000L,
2627 0x10000L,0x20000L,0x40000L,0x80000L,
2628 0x100000L,0x200000L,0x400000L,0x800000L,
2629 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2630 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2633 for(idx = 0; idx < 32; idx++)
2639 /*-----------------------------------------------------------------*/
2640 /* jmpTrueOrFalse - */
2641 /*-----------------------------------------------------------------*/
2642 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2644 // ugly but optimized by peephole
2646 symbol *nlbl = newiTempLabel(NULL);
2647 emit2("jp !tlabel", nlbl->key+100);
2648 emitLabel(tlbl->key+100);
2649 emit2("jp !tlabel", IC_TRUE(ic)->key+100);
2650 emitLabel(nlbl->key+100);
2653 emit2("jp !tlabel", IC_FALSE(ic)->key+100);
2654 emitLabel(tlbl->key+100);
2659 /*-----------------------------------------------------------------*/
2660 /* genAnd - code for and */
2661 /*-----------------------------------------------------------------*/
2662 static void genAnd (iCode *ic, iCode *ifx)
2664 operand *left, *right, *result;
2666 unsigned long lit = 0L;
2669 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
2670 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
2671 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
2674 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2676 AOP_TYPE(left), AOP_TYPE(right));
2677 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2679 AOP_SIZE(left), AOP_SIZE(right));
2682 /* if left is a literal & right is not then exchange them */
2683 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2684 AOP_NEEDSACC(left)) {
2685 operand *tmp = right ;
2690 /* if result = right then exchange them */
2691 if(sameRegs(AOP(result),AOP(right))){
2692 operand *tmp = right ;
2697 /* if right is bit then exchange them */
2698 if (AOP_TYPE(right) == AOP_CRY &&
2699 AOP_TYPE(left) != AOP_CRY){
2700 operand *tmp = right ;
2704 if(AOP_TYPE(right) == AOP_LIT)
2705 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2707 size = AOP_SIZE(result);
2709 if (AOP_TYPE(left) == AOP_CRY){
2714 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2715 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2716 if((AOP_TYPE(right) == AOP_LIT) &&
2717 (AOP_TYPE(result) == AOP_CRY) &&
2718 (AOP_TYPE(left) != AOP_CRY)) {
2719 int posbit = isLiteralBit(lit);
2723 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2727 emitcode("mov","c,acc.%d",posbit&0x07);
2732 sprintf(buffer, "%d", posbit&0x07);
2733 genIfxJump(ifx, buffer);
2741 symbol *tlbl = newiTempLabel(NULL);
2742 int sizel = AOP_SIZE(left);
2745 emitcode("setb","c");
2748 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2749 MOVA( aopGet(AOP(left),offset,FALSE));
2751 if((posbit = isLiteralBit(bytelit)) != 0) {
2753 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2756 if(bytelit != 0x0FFL)
2757 emitcode("and","a,%s",
2758 aopGet(AOP(right),offset,FALSE));
2759 emit2("!shortjp nz,!tlabel", tlbl->key+100);
2764 // bit = left & literal
2766 emitcode("clr","c");
2767 emit2("!tlabeldef", tlbl->key+100);
2769 // if(left & literal)
2772 jmpTrueOrFalse(ifx, tlbl);
2780 /* if left is same as result */
2781 if(sameRegs(AOP(result),AOP(left))){
2782 for(;size--; offset++) {
2783 if(AOP_TYPE(right) == AOP_LIT){
2784 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2788 aopPut(AOP(result),zero,offset);
2790 MOVA(aopGet(AOP(left),offset,FALSE));
2791 emitcode("and","a,%s",
2792 aopGet(AOP(right),offset,FALSE));
2793 aopPut(AOP(left), "a", offset);
2798 if (AOP_TYPE(left) == AOP_ACC) {
2802 MOVA(aopGet(AOP(left),offset,FALSE));
2803 emitcode("and","a,%s",
2804 aopGet(AOP(right),offset,FALSE));
2805 aopPut(AOP(left), "a", offset);
2810 // left & result in different registers
2811 if(AOP_TYPE(result) == AOP_CRY){
2814 for(;(size--);offset++) {
2816 // result = left & right
2817 if(AOP_TYPE(right) == AOP_LIT){
2818 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2820 aopGet(AOP(left),offset,FALSE),
2823 } else if(bytelit == 0){
2824 aopPut(AOP(result),zero,offset);
2828 // faster than result <- left, anl result,right
2829 // and better if result is SFR
2830 if (AOP_TYPE(left) == AOP_ACC)
2831 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2833 MOVA(aopGet(AOP(right),offset,FALSE));
2834 emitcode("and","a,%s",
2835 aopGet(AOP(left),offset,FALSE));
2837 aopPut(AOP(result),"a",offset);
2844 freeAsmop(left,NULL,ic);
2845 freeAsmop(right,NULL,ic);
2846 freeAsmop(result,NULL,ic);
2849 /*-----------------------------------------------------------------*/
2850 /* genOr - code for or */
2851 /*-----------------------------------------------------------------*/
2852 static void genOr (iCode *ic, iCode *ifx)
2854 operand *left, *right, *result;
2856 unsigned long lit = 0L;
2858 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
2859 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
2860 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
2863 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2865 AOP_TYPE(left), AOP_TYPE(right));
2866 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2868 AOP_SIZE(left), AOP_SIZE(right));
2871 /* if left is a literal & right is not then exchange them */
2872 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2873 AOP_NEEDSACC(left)) {
2874 operand *tmp = right ;
2879 /* if result = right then exchange them */
2880 if(sameRegs(AOP(result),AOP(right))){
2881 operand *tmp = right ;
2886 /* if right is bit then exchange them */
2887 if (AOP_TYPE(right) == AOP_CRY &&
2888 AOP_TYPE(left) != AOP_CRY){
2889 operand *tmp = right ;
2893 if(AOP_TYPE(right) == AOP_LIT)
2894 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2896 size = AOP_SIZE(result);
2898 if (AOP_TYPE(left) == AOP_CRY){
2903 if((AOP_TYPE(right) == AOP_LIT) &&
2904 (AOP_TYPE(result) == AOP_CRY) &&
2905 (AOP_TYPE(left) != AOP_CRY)){
2910 /* if left is same as result */
2911 if(sameRegs(AOP(result),AOP(left))){
2912 for(;size--; offset++) {
2913 if(AOP_TYPE(right) == AOP_LIT){
2914 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2917 MOVA(aopGet(AOP(left),offset,FALSE));
2918 emitcode("or","a,%s",
2919 aopGet(AOP(right),offset,FALSE));
2920 aopPut(AOP(result),"a", offset);
2923 if (AOP_TYPE(left) == AOP_ACC)
2924 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2926 MOVA(aopGet(AOP(left),offset,FALSE));
2927 emitcode("or","a,%s",
2928 aopGet(AOP(right),offset,FALSE));
2929 aopPut(AOP(result),"a", offset);
2934 // left & result in different registers
2935 if(AOP_TYPE(result) == AOP_CRY){
2937 } else for(;(size--);offset++){
2939 // result = left & right
2940 if(AOP_TYPE(right) == AOP_LIT){
2941 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2943 aopGet(AOP(left),offset,FALSE),
2948 // faster than result <- left, anl result,right
2949 // and better if result is SFR
2950 if (AOP_TYPE(left) == AOP_ACC)
2951 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2953 MOVA(aopGet(AOP(right),offset,FALSE));
2954 emitcode("or","a,%s",
2955 aopGet(AOP(left),offset,FALSE));
2957 aopPut(AOP(result),"a",offset);
2958 /* PENDING: something weird is going on here. Add exception. */
2959 if (AOP_TYPE(result) == AOP_ACC)
2965 freeAsmop(left,NULL,ic);
2966 freeAsmop(right,NULL,ic);
2967 freeAsmop(result,NULL,ic);
2970 /*-----------------------------------------------------------------*/
2971 /* genXor - code for xclusive or */
2972 /*-----------------------------------------------------------------*/
2973 static void genXor (iCode *ic, iCode *ifx)
2975 operand *left, *right, *result;
2977 unsigned long lit = 0L;
2979 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
2980 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
2981 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
2983 /* if left is a literal & right is not then exchange them */
2984 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2985 AOP_NEEDSACC(left)) {
2986 operand *tmp = right ;
2991 /* if result = right then exchange them */
2992 if(sameRegs(AOP(result),AOP(right))){
2993 operand *tmp = right ;
2998 /* if right is bit then exchange them */
2999 if (AOP_TYPE(right) == AOP_CRY &&
3000 AOP_TYPE(left) != AOP_CRY){
3001 operand *tmp = right ;
3005 if(AOP_TYPE(right) == AOP_LIT)
3006 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3008 size = AOP_SIZE(result);
3010 if (AOP_TYPE(left) == AOP_CRY){
3015 if((AOP_TYPE(right) == AOP_LIT) &&
3016 (AOP_TYPE(result) == AOP_CRY) &&
3017 (AOP_TYPE(left) != AOP_CRY)){
3022 /* if left is same as result */
3023 if(sameRegs(AOP(result),AOP(left))){
3024 for(;size--; offset++) {
3025 if(AOP_TYPE(right) == AOP_LIT){
3026 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3029 MOVA(aopGet(AOP(right),offset,FALSE));
3030 emitcode("xor","a,%s",
3031 aopGet(AOP(left),offset,FALSE));
3032 aopPut(AOP(result),"a",0);
3035 if (AOP_TYPE(left) == AOP_ACC)
3036 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3038 MOVA(aopGet(AOP(right),offset,FALSE));
3039 emitcode("xor","a,%s",
3040 aopGet(AOP(left),offset,FALSE));
3041 aopPut(AOP(result),"a",0);
3046 // left & result in different registers
3047 if(AOP_TYPE(result) == AOP_CRY){
3049 } else for(;(size--);offset++){
3051 // result = left & right
3052 if(AOP_TYPE(right) == AOP_LIT){
3053 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3055 aopGet(AOP(left),offset,FALSE),
3060 // faster than result <- left, anl result,right
3061 // and better if result is SFR
3062 if (AOP_TYPE(left) == AOP_ACC)
3063 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3065 MOVA(aopGet(AOP(right),offset,FALSE));
3066 emitcode("xor","a,%s",
3067 aopGet(AOP(left),offset,FALSE));
3068 aopPut(AOP(result),"a",0);
3070 aopPut(AOP(result),"a",offset);
3075 freeAsmop(left,NULL,ic);
3076 freeAsmop(right,NULL,ic);
3077 freeAsmop(result,NULL,ic);
3080 /*-----------------------------------------------------------------*/
3081 /* genInline - write the inline code out */
3082 /*-----------------------------------------------------------------*/
3083 static void genInline (iCode *ic)
3085 char buffer[MAX_INLINEASM];
3089 inLine += (!options.asmpeep);
3090 strcpy(buffer,IC_INLINE(ic));
3092 /* emit each line as a code */
3111 /* emitcode("",buffer); */
3112 inLine -= (!options.asmpeep);
3115 /*-----------------------------------------------------------------*/
3116 /* genRRC - rotate right with carry */
3117 /*-----------------------------------------------------------------*/
3118 static void genRRC (iCode *ic)
3123 /*-----------------------------------------------------------------*/
3124 /* genRLC - generate code for rotate left with carry */
3125 /*-----------------------------------------------------------------*/
3126 static void genRLC (iCode *ic)
3131 /*-----------------------------------------------------------------*/
3132 /* shiftR2Left2Result - shift right two bytes from left to result */
3133 /*-----------------------------------------------------------------*/
3134 static void shiftR2Left2Result (operand *left, int offl,
3135 operand *result, int offr,
3136 int shCount, int sign)
3138 if(sameRegs(AOP(result), AOP(left)) &&
3139 ((offl + MSB16) == offr)){
3142 movLeft2Result(left, offl, result, offr, 0);
3143 movLeft2Result(left, offl+1, result, offr+1, 0);
3150 /* if (AOP(result)->type == AOP_REG) {*/
3153 symbol *tlbl , *tlbl1;
3156 /* Left is already in result - so now do the shift */
3158 emit2("ld a,!immedbyte+1", shCount);
3159 tlbl = newiTempLabel(NULL);
3160 tlbl1 = newiTempLabel(NULL);
3161 emit2("!shortjp !tlabel", tlbl1->key+100);
3162 emitLabel(tlbl->key+100);
3165 emitcode("or", "a,a");
3168 l = aopGet(AOP(result), --offset, FALSE);
3169 emitcode("rr","%s", l);
3172 emitLabel(tlbl1->key+100);
3173 emitcode("dec", "a");
3174 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3179 /*-----------------------------------------------------------------*/
3180 /* shiftL2Left2Result - shift left two bytes from left to result */
3181 /*-----------------------------------------------------------------*/
3182 static void shiftL2Left2Result (operand *left, int offl,
3183 operand *result, int offr, int shCount)
3185 if(sameRegs(AOP(result), AOP(left)) &&
3186 ((offl + MSB16) == offr)){
3189 /* Copy left into result */
3190 movLeft2Result(left, offl, result, offr, 0);
3191 movLeft2Result(left, offl+1, result, offr+1, 0);
3193 /* PENDING: for now just see if it'll work. */
3194 /*if (AOP(result)->type == AOP_REG) { */
3198 symbol *tlbl , *tlbl1;
3201 /* Left is already in result - so now do the shift */
3203 emit2("ld a,!immedbyte+1", shCount);
3204 tlbl = newiTempLabel(NULL);
3205 tlbl1 = newiTempLabel(NULL);
3206 emit2("!shortjp !tlabel", tlbl1->key+100);
3207 emitLabel(tlbl->key+100);
3210 emitcode("or", "a,a");
3212 l = aopGet(AOP(result),offset++,FALSE);
3213 emitcode("rl","%s", l);
3216 emitLabel(tlbl1->key+100);
3217 emitcode("dec", "a");
3218 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3223 /*-----------------------------------------------------------------*/
3224 /* AccRol - rotate left accumulator by known count */
3225 /*-----------------------------------------------------------------*/
3226 static void AccRol (int shCount)
3228 shCount &= 0x0007; // shCount : 0..7
3265 /*-----------------------------------------------------------------*/
3266 /* AccLsh - left shift accumulator by known count */
3267 /*-----------------------------------------------------------------*/
3268 static void AccLsh (int shCount)
3272 emitcode("add","a,a");
3275 emitcode("add","a,a");
3276 emitcode("add","a,a");
3278 /* rotate left accumulator */
3280 /* and kill the lower order bits */
3281 emit2("and a,!immedbyte", SLMask[shCount]);
3286 /*-----------------------------------------------------------------*/
3287 /* shiftL1Left2Result - shift left one byte from left to result */
3288 /*-----------------------------------------------------------------*/
3289 static void shiftL1Left2Result (operand *left, int offl,
3290 operand *result, int offr, int shCount)
3293 l = aopGet(AOP(left),offl,FALSE);
3295 /* shift left accumulator */
3297 aopPut(AOP(result),"a",offr);
3301 /*-----------------------------------------------------------------*/
3302 /* genlshTwo - left shift two bytes by known amount != 0 */
3303 /*-----------------------------------------------------------------*/
3304 static void genlshTwo (operand *result,operand *left, int shCount)
3306 int size = AOP_SIZE(result);
3310 /* if shCount >= 8 */
3316 movLeft2Result(left, LSB, result, MSB16, 0);
3317 aopPut(AOP(result),zero, 0);
3318 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
3321 movLeft2Result(left, LSB, result, MSB16, 0);
3322 aopPut(AOP(result),zero, 0);
3325 aopPut(AOP(result),zero,LSB);
3327 /* 1 <= shCount <= 7 */
3333 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3338 /*-----------------------------------------------------------------*/
3339 /* genlshOne - left shift a one byte quantity by known count */
3340 /*-----------------------------------------------------------------*/
3341 static void genlshOne (operand *result, operand *left, int shCount)
3343 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3346 /*-----------------------------------------------------------------*/
3347 /* genLeftShiftLiteral - left shifting by known count */
3348 /*-----------------------------------------------------------------*/
3349 static void genLeftShiftLiteral (operand *left,
3354 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3357 freeAsmop(right,NULL,ic);
3359 aopOp(left,ic,FALSE, FALSE);
3360 aopOp(result,ic,FALSE, FALSE);
3362 size = getSize(operandType(result));
3365 emitcode("; shift left ","result %d, left %d",size,
3369 /* I suppose that the left size >= result size */
3374 else if(shCount >= (size * 8))
3376 aopPut(AOP(result),zero,size);
3380 genlshOne (result,left,shCount);
3383 genlshTwo (result,left,shCount);
3392 freeAsmop(left,NULL,ic);
3393 freeAsmop(result,NULL,ic);
3396 /*-----------------------------------------------------------------*/
3397 /* genLeftShift - generates code for left shifting */
3398 /*-----------------------------------------------------------------*/
3399 static void genLeftShift (iCode *ic)
3403 symbol *tlbl , *tlbl1;
3404 operand *left,*right, *result;
3406 right = IC_RIGHT(ic);
3408 result = IC_RESULT(ic);
3410 aopOp(right,ic,FALSE, FALSE);
3412 /* if the shift count is known then do it
3413 as efficiently as possible */
3414 if (AOP_TYPE(right) == AOP_LIT) {
3415 genLeftShiftLiteral (left,right,result,ic);
3419 /* shift count is unknown then we have to form a loop get the loop
3420 count in B : Note: we take only the lower order byte since
3421 shifting more that 32 bits make no sense anyway, ( the largest
3422 size of an object can be only 32 bits ) */
3423 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3424 emitcode("inc","a");
3425 freeAsmop (right,NULL,ic);
3426 aopOp(left,ic,FALSE, FALSE);
3427 aopOp(result,ic,FALSE, FALSE);
3429 /* now move the left to the result if they are not the
3432 if (!sameRegs(AOP(left),AOP(result))) {
3434 size = AOP_SIZE(result);
3437 l = aopGet(AOP(left),offset,FALSE);
3438 aopPut(AOP(result),l,offset);
3443 size = AOP_SIZE(result);
3446 l = aopGet(AOP(left),offset,FALSE);
3447 aopPut(AOP(result),l,offset);
3453 tlbl = newiTempLabel(NULL);
3454 size = AOP_SIZE(result);
3456 tlbl1 = newiTempLabel(NULL);
3458 emit2("!shortjp !tlabel", tlbl1->key+100);
3459 emitLabel(tlbl->key+100);
3460 l = aopGet(AOP(result),offset,FALSE);
3461 emitcode("or", "a,a");
3463 l = aopGet(AOP(result),offset++,FALSE);
3464 emitcode("rl","%s", l);
3466 emitLabel(tlbl1->key+100);
3467 emitcode("dec", "a");
3468 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3470 freeAsmop(left,NULL,ic);
3471 freeAsmop(result,NULL,ic);
3474 /*-----------------------------------------------------------------*/
3475 /* genlshTwo - left shift two bytes by known amount != 0 */
3476 /*-----------------------------------------------------------------*/
3477 static void genrshOne (operand *result,operand *left, int shCount)
3480 int size = AOP_SIZE(result);
3486 l = aopGet(AOP(left),0,FALSE);
3487 if (AOP(result)->type == AOP_REG) {
3488 aopPut(AOP(result), l, 0);
3489 l = aopGet(AOP(result), 0, FALSE);
3491 emitcode("srl", "%s", l);
3496 emitcode("srl", "a");
3498 aopPut(AOP(result),"a",0);
3502 /*-----------------------------------------------------------------*/
3503 /* AccRsh - right shift accumulator by known count */
3504 /*-----------------------------------------------------------------*/
3505 static void AccRsh (int shCount)
3512 /* rotate right accumulator */
3513 AccRol(8 - shCount);
3514 /* and kill the higher order bits */
3515 emit2("and a,!immedbyte", SRMask[shCount]);
3520 /*-----------------------------------------------------------------*/
3521 /* shiftR1Left2Result - shift right one byte from left to result */
3522 /*-----------------------------------------------------------------*/
3523 static void shiftR1Left2Result (operand *left, int offl,
3524 operand *result, int offr,
3525 int shCount, int sign)
3527 MOVA(aopGet(AOP(left),offl,FALSE));
3534 aopPut(AOP(result),"a",offr);
3537 /*-----------------------------------------------------------------*/
3538 /* genrshTwo - right shift two bytes by known amount != 0 */
3539 /*-----------------------------------------------------------------*/
3540 static void genrshTwo (operand *result,operand *left,
3541 int shCount, int sign)
3543 /* if shCount >= 8 */
3548 shiftR1Left2Result(left, MSB16, result, LSB,
3552 movLeft2Result(left, MSB16, result, LSB, sign);
3553 aopPut(AOP(result),zero,1);
3556 /* 1 <= shCount <= 7 */
3558 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3562 /*-----------------------------------------------------------------*/
3563 /* genRightShiftLiteral - left shifting by known count */
3564 /*-----------------------------------------------------------------*/
3565 static void genRightShiftLiteral (operand *left,
3570 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3573 freeAsmop(right,NULL,ic);
3575 aopOp(left,ic,FALSE, FALSE);
3576 aopOp(result,ic,FALSE, FALSE);
3578 size = getSize(operandType(result));
3580 emitcode("; shift right ","result %d, left %d",size,
3583 /* I suppose that the left size >= result size */
3588 else if(shCount >= (size * 8))
3590 aopPut(AOP(result),zero,size);
3594 genrshOne(result, left, shCount);
3597 /* PENDING: sign support */
3598 genrshTwo(result, left, shCount, FALSE);
3607 freeAsmop(left,NULL,ic);
3608 freeAsmop(result,NULL,ic);
3611 /*-----------------------------------------------------------------*/
3612 /* genRightShift - generate code for right shifting */
3613 /*-----------------------------------------------------------------*/
3614 static void genRightShift (iCode *ic)
3616 operand *right, *left, *result;
3618 int size, offset, first = 1;
3622 symbol *tlbl, *tlbl1 ;
3624 /* if signed then we do it the hard way preserve the
3625 sign bit moving it inwards */
3626 retype = getSpec(operandType(IC_RESULT(ic)));
3628 is_signed = !SPEC_USIGN(retype);
3630 /* signed & unsigned types are treated the same : i.e. the
3631 signed is NOT propagated inwards : quoting from the
3632 ANSI - standard : "for E1 >> E2, is equivalent to division
3633 by 2**E2 if unsigned or if it has a non-negative value,
3634 otherwise the result is implementation defined ", MY definition
3635 is that the sign does not get propagated */
3637 right = IC_RIGHT(ic);
3639 result = IC_RESULT(ic);
3641 aopOp(right,ic,FALSE, FALSE);
3643 /* if the shift count is known then do it
3644 as efficiently as possible */
3645 if (AOP_TYPE(right) == AOP_LIT) {
3646 genRightShiftLiteral(left,right,result,ic);
3650 aopOp(left,ic,FALSE, FALSE);
3651 aopOp(result,ic,FALSE, FALSE);
3653 /* now move the left to the result if they are not the
3655 if (!sameRegs(AOP(left),AOP(result)) &&
3656 AOP_SIZE(result) > 1) {
3658 size = AOP_SIZE(result);
3661 l = aopGet(AOP(left),offset,FALSE);
3662 aopPut(AOP(result),l,offset);
3667 emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
3668 emitcode("inc","a");
3669 freeAsmop (right, NULL, ic);
3671 tlbl = newiTempLabel(NULL);
3672 tlbl1= newiTempLabel(NULL);
3673 size = AOP_SIZE(result);
3676 emit2("!shortjp !tlabel", tlbl1->key+100);
3677 emitLabel(tlbl->key+100);
3679 l = aopGet(AOP(result),offset--,FALSE);
3682 emitcode("sra", "%s", l);
3684 emitcode("srl", "%s", l);
3688 emitcode("rr", "%s", l);
3690 emitLabel(tlbl1->key+100);
3691 emitcode("dec", "a");
3692 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3694 freeAsmop(left,NULL,ic);
3695 freeAsmop(result,NULL,ic);
3698 /*-----------------------------------------------------------------*/
3699 /* genGenPointerGet - gget value from generic pointer space */
3700 /*-----------------------------------------------------------------*/
3701 static void genGenPointerGet (operand *left,
3702 operand *result, iCode *ic)
3705 link *retype = getSpec(operandType(result));
3711 aopOp(left,ic,FALSE, FALSE);
3712 aopOp(result,ic,FALSE, FALSE);
3714 if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
3716 if (isPtrPair(AOP(left)))
3718 tsprintf(buffer, "!*pair", getPairName(AOP(left)));
3719 aopPut(AOP(result), buffer, 0);
3722 emit2("ld a,!*pair", getPairName(AOP(left)));
3723 aopPut(AOP(result),"a", 0);
3725 freeAsmop(left,NULL,ic);
3729 /* For now we always load into IY */
3730 /* if this is remateriazable */
3731 fetchPair(pair, AOP(left));
3733 /* so iy now contains the address */
3734 freeAsmop(left,NULL,ic);
3736 /* if bit then unpack */
3737 if (IS_BITVAR(retype)) {
3741 size = AOP_SIZE(result);
3745 /* PENDING: make this better */
3746 if (!IS_GB && AOP(result)->type == AOP_REG) {
3747 aopPut(AOP(result), "!*hl", offset++);
3750 emit2("ld a,!*pair", _pairs[pair].name);
3751 aopPut(AOP(result),"a",offset++);
3754 emit2("inc %s", _pairs[pair].name);
3760 freeAsmop(result,NULL,ic);
3763 /*-----------------------------------------------------------------*/
3764 /* genPointerGet - generate code for pointer get */
3765 /*-----------------------------------------------------------------*/
3766 static void genPointerGet (iCode *ic)
3768 operand *left, *result ;
3772 result = IC_RESULT(ic) ;
3774 /* depending on the type of pointer we need to
3775 move it to the correct pointer register */
3776 type = operandType(left);
3777 etype = getSpec(type);
3779 genGenPointerGet (left,result,ic);
3782 bool isRegOrLit(asmop *aop)
3784 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3789 /*-----------------------------------------------------------------*/
3790 /* genGenPointerSet - stores the value into a pointer location */
3791 /*-----------------------------------------------------------------*/
3792 static void genGenPointerSet (operand *right,
3793 operand *result, iCode *ic)
3796 link *retype = getSpec(operandType(right));
3797 PAIR_ID pairId = PAIR_HL;
3799 aopOp(result,ic,FALSE, FALSE);
3800 aopOp(right,ic,FALSE, FALSE);
3805 /* Handle the exceptions first */
3806 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3808 char *l = aopGet(AOP(right), 0, FALSE);
3809 const char *pair = getPairName(AOP(result));
3810 if (canAssignToPtr(l) && isPtr(pair)) {
3811 emit2("ld !*pair,%s", pair, l);
3815 emit2("ld !*pair,a", pair);
3820 /* if the operand is already in dptr
3821 then we do nothing else we move the value to dptr */
3822 if (AOP_TYPE(result) != AOP_STR) {
3823 fetchPair(pairId, AOP(result));
3825 /* so hl know contains the address */
3826 freeAsmop(result,NULL,ic);
3828 /* if bit then unpack */
3829 if (IS_BITVAR(retype)) {
3833 size = AOP_SIZE(right);
3837 char *l = aopGet(AOP(right),offset,FALSE);
3838 if (isRegOrLit(AOP(right)) && !IS_GB) {
3839 emit2("ld !*pair,%s", _pairs[pairId].name, l);
3843 emit2("ld !*pair,a", _pairs[pairId].name);
3846 emitcode("inc", _pairs[pairId].name);
3852 freeAsmop(right,NULL,ic);
3855 /*-----------------------------------------------------------------*/
3856 /* genPointerSet - stores the value into a pointer location */
3857 /*-----------------------------------------------------------------*/
3858 static void genPointerSet (iCode *ic)
3860 operand *right, *result ;
3863 right = IC_RIGHT(ic);
3864 result = IC_RESULT(ic) ;
3866 /* depending on the type of pointer we need to
3867 move it to the correct pointer register */
3868 type = operandType(result);
3869 etype = getSpec(type);
3871 genGenPointerSet (right,result,ic);
3874 /*-----------------------------------------------------------------*/
3875 /* genIfx - generate code for Ifx statement */
3876 /*-----------------------------------------------------------------*/
3877 static void genIfx (iCode *ic, iCode *popIc)
3879 operand *cond = IC_COND(ic);
3882 aopOp(cond,ic,FALSE, TRUE);
3884 /* get the value into acc */
3885 if (AOP_TYPE(cond) != AOP_CRY)
3889 /* the result is now in the accumulator */
3890 freeAsmop(cond,NULL,ic);
3892 /* if there was something to be popped then do it */
3896 /* if the condition is a bit variable */
3897 if (isbit && IS_ITEMP(cond) &&
3899 genIfxJump(ic,SPIL_LOC(cond)->rname);
3901 if (isbit && !IS_ITEMP(cond))
3902 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3909 /*-----------------------------------------------------------------*/
3910 /* genAddrOf - generates code for address of */
3911 /*-----------------------------------------------------------------*/
3912 static void genAddrOf (iCode *ic)
3914 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3916 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
3918 /* if the operand is on the stack then we
3919 need to get the stack offset of this
3924 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
3925 emitcode("ld", "d,h");
3926 emitcode("ld", "e,l");
3929 emitcode("ld", "de,#%s", sym->rname);
3931 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3932 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3937 /* if it has an offset then we need to compute it */
3938 emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
3939 emitcode("add", "hl,sp");
3942 emitcode("ld", "hl,#%s", sym->rname);
3944 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3945 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3947 freeAsmop(IC_RESULT(ic),NULL,ic);
3950 /*-----------------------------------------------------------------*/
3951 /* genAssign - generate code for assignment */
3952 /*-----------------------------------------------------------------*/
3953 static void genAssign (iCode *ic)
3955 operand *result, *right;
3957 unsigned long lit = 0L;
3959 result = IC_RESULT(ic);
3960 right = IC_RIGHT(ic) ;
3963 /* Dont bother assigning if they are the same */
3964 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3965 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3970 aopOp(right,ic,FALSE, FALSE);
3971 aopOp(result,ic,TRUE, FALSE);
3973 /* if they are the same registers */
3974 if (sameRegs(AOP(right),AOP(result))) {
3975 emitcode("", "; (registers are the same)");
3979 /* if the result is a bit */
3980 if (AOP_TYPE(result) == AOP_CRY) {
3985 size = AOP_SIZE(result);
3988 if(AOP_TYPE(right) == AOP_LIT)
3989 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3990 if (isPair(AOP(result)) && isLitWord(AOP(right))) {
3991 emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
3993 else if((size > 1) &&
3994 (AOP_TYPE(result) != AOP_REG) &&
3995 (AOP_TYPE(right) == AOP_LIT) &&
3996 !IS_FLOAT(operandType(right)) &&
3998 bool fXored = FALSE;
4000 /* Work from the top down.
4001 Done this way so that we can use the cached copy of 0
4002 in A for a fast clear */
4004 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
4005 if (!fXored && size>1) {
4006 emitcode("xor", "a,a");
4010 aopPut(AOP(result),"a",offset);
4013 aopPut(AOP(result), zero, offset);
4018 aopGet(AOP(right),offset,FALSE),
4023 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
4024 /* Special case. Load into a and d, then load out. */
4025 MOVA(aopGet(AOP(right), 0, FALSE));
4026 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
4027 aopPut(AOP(result), "a", 0);
4028 aopPut(AOP(result), "e", 1);
4031 /* PENDING: do this check better */
4032 if (requiresHL(AOP(right)) && requiresHL(AOP(result))) {
4033 MOVA(aopGet(AOP(right), offset, FALSE));
4034 aopPut(AOP(result), "a", offset);
4038 aopGet(AOP(right),offset,FALSE),
4045 freeAsmop(right,NULL,ic);
4046 freeAsmop(result,NULL,ic);
4049 /*-----------------------------------------------------------------*/
4050 /* genJumpTab - genrates code for jump table */
4051 /*-----------------------------------------------------------------*/
4052 static void genJumpTab (iCode *ic)
4057 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
4058 /* get the condition into accumulator */
4059 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
4061 emitcode("push", "de");
4062 emitcode("ld", "e,%s", l);
4063 emit2("ld d,!zero");
4064 jtab = newiTempLabel(NULL);
4066 emit2("ld hl,!immed!tlabel", jtab->key+100);
4067 emitcode("add", "hl,de");
4068 emitcode("add", "hl,de");
4069 emitcode("add", "hl,de");
4070 freeAsmop(IC_JTCOND(ic),NULL,ic);
4072 emitcode("pop", "de");
4074 emitLabel(jtab->key+100);
4075 /* now generate the jump labels */
4076 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4077 jtab = setNextItem(IC_JTLABELS(ic)))
4078 emit2("jp !tlabel", jtab->key+100);
4081 /*-----------------------------------------------------------------*/
4082 /* genCast - gen code for casting */
4083 /*-----------------------------------------------------------------*/
4084 static void genCast (iCode *ic)
4086 operand *result = IC_RESULT(ic);
4087 link *ctype = operandType(IC_LEFT(ic));
4088 operand *right = IC_RIGHT(ic);
4091 /* if they are equivalent then do nothing */
4092 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4095 aopOp(right,ic,FALSE, FALSE);
4096 aopOp(result,ic,FALSE, FALSE);
4098 /* if the result is a bit */
4099 if (AOP_TYPE(result) == AOP_CRY) {
4103 /* if they are the same size : or less */
4104 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4106 /* if they are in the same place */
4107 if (sameRegs(AOP(right),AOP(result)))
4110 /* if they in different places then copy */
4111 size = AOP_SIZE(result);
4115 aopGet(AOP(right),offset,FALSE),
4122 /* PENDING: should be OK. */
4124 /* if the result is of type pointer */
4125 if (IS_PTR(ctype)) {
4130 /* so we now know that the size of destination is greater
4131 than the size of the source */
4132 /* we move to result for the size of source */
4133 size = AOP_SIZE(right);
4137 aopGet(AOP(right),offset,FALSE),
4142 /* now depending on the sign of the destination */
4143 size = AOP_SIZE(result) - AOP_SIZE(right);
4144 /* Unsigned or not an integral type - right fill with zeros */
4145 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4147 aopPut(AOP(result),zero,offset++);
4149 /* we need to extend the sign :{ */
4150 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4153 emitcode("", "; genCast: sign extend untested.");
4154 emitcode("rla", "");
4155 emitcode("sbc", "a,a");
4157 aopPut(AOP(result),"a",offset++);
4161 freeAsmop(right, NULL, ic);
4162 freeAsmop(result, NULL, ic);
4165 /*-----------------------------------------------------------------*/
4166 /* genReceive - generate code for a receive iCode */
4167 /*-----------------------------------------------------------------*/
4168 static void genReceive (iCode *ic)
4170 if (isOperandInFarSpace(IC_RESULT(ic)) &&
4171 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4172 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4176 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4178 assignResultValue(IC_RESULT(ic));
4181 freeAsmop(IC_RESULT(ic),NULL,ic);
4184 /*-----------------------------------------------------------------*/
4185 /* genZ80Code - generate code for Z80 based controllers */
4186 /*-----------------------------------------------------------------*/
4187 void genZ80Code (iCode *lic)
4194 _fReturn = _gbz80_return;
4195 _fTmp = _gbz80_return;
4198 _fReturn = _z80_return;
4199 _fTmp = _z80_return;
4201 tsprintf(zero, "!zero");
4203 lineHead = lineCurr = NULL;
4205 /* if debug information required */
4206 if (options.debug && currFunc) {
4207 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4209 if (IS_STATIC(currFunc->etype))
4210 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4212 emitcode("","G$%s$0$0 ==.",currFunc->name);
4215 /* stack pointer name */
4219 for (ic = lic ; ic ; ic = ic->next ) {
4221 if ( cln != ic->lineno ) {
4222 if ( options.debug ) {
4224 emitcode("","C$%s$%d$%d$%d ==.",
4225 ic->filename,ic->lineno,
4226 ic->level,ic->block);
4229 emitcode(";","%s %d",ic->filename,ic->lineno);
4232 /* if the result is marked as
4233 spilt and rematerializable or code for
4234 this has already been generated then
4236 if (resultRemat(ic) || ic->generated )
4239 /* depending on the operation */
4242 emitcode("", "; genNot");
4247 emitcode("", "; genCpl");
4252 emitcode("", "; genUminus");
4257 emitcode("", "; genIpush");
4262 /* IPOP happens only when trying to restore a
4263 spilt live range, if there is an ifx statement
4264 following this pop then the if statement might
4265 be using some of the registers being popped which
4266 would destory the contents of the register so
4267 we need to check for this condition and handle it */
4269 ic->next->op == IFX &&
4270 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4271 emitcode("", "; genIfx");
4272 genIfx (ic->next,ic);
4275 emitcode("", "; genIpop");
4281 emitcode("", "; genCall");
4286 emitcode("", "; genPcall");
4291 emitcode("", "; genFunction");
4296 emitcode("", "; genEndFunction");
4297 genEndFunction (ic);
4301 emitcode("", "; genRet");
4306 emitcode("", "; genLabel");
4311 emitcode("", "; genGoto");
4316 emitcode("", "; genPlus");
4321 emitcode("", "; genMinus");
4326 emitcode("", "; genMult");
4331 emitcode("", "; genDiv");
4336 emitcode("", "; genMod");
4341 emitcode("", "; genCmpGt");
4342 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4346 emitcode("", "; genCmpLt");
4347 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4354 /* note these two are xlated by algebraic equivalence
4355 during parsing SDCC.y */
4356 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4357 "got '>=' or '<=' shouldn't have come here");
4361 emitcode("", "; genCmpEq");
4362 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4366 emitcode("", "; genAndOp");
4371 emitcode("", "; genOrOp");
4376 emitcode("", "; genXor");
4377 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4381 emitcode("", "; genOr");
4382 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4386 emitcode("", "; genAnd");
4387 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4391 emitcode("", "; genInline");
4396 emitcode("", "; genRRC");
4401 emitcode("", "; genRLC");
4406 emitcode("", "; genHBIT");
4410 emitcode("", "; genLeftShift");
4415 emitcode("", "; genRightShift");
4419 case GET_VALUE_AT_ADDRESS:
4420 emitcode("", "; genPointerGet");
4426 if (POINTER_SET(ic)) {
4427 emitcode("", "; genAssign (pointer)");
4431 emitcode("", "; genAssign");
4437 emitcode("", "; genIfx");
4442 emitcode("", "; genAddrOf");
4447 emitcode("", "; genJumpTab");
4452 emitcode("", "; genCast");
4457 emitcode("", "; genReceive");
4462 emitcode("", "; addSet");
4463 addSet(&sendSet,ic);
4468 /* piCode(ic,stdout); */
4474 /* now we are ready to call the
4475 peep hole optimizer */
4476 if (!options.nopeep)
4477 peepHole (&lineHead);
4479 /* now do the actual printing */
4480 printLine (lineHead,codeOutFile);