1 /*-------------------------------------------------------------------------
2 gen.c - Z80 specific code generator.
4 Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
6 Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
7 Improved WORD push 22784 144 19AE
8 With label1 on 22694 144 197E
9 With label2 on 22743 144 198A
10 With label3 on 22776 144 1999
11 With label4 on 22776 144 1999
12 With all 'label' on 22661 144 196F
13 With loopInvariant on 20919 156 19AB
14 With loopInduction on Breaks 198B
15 With all working on 20796 158 196C
16 Slightly better genCmp(signed) 20597 159 195B
17 Better reg packing, first peephole 20038 163 1873
18 With assign packing 19281 165 1849
20 Michael Hope <michaelh@earthling.net> 2000
21 Based on the mcs51 generator - Sandeep Dutta . sandeep.dutta@usa.net (1998)
22 and - Jean-Louis VERN.jlvern@writeme.com (1999)
24 This program is free software; you can redistribute it and/or modify it
25 under the terms of the GNU General Public License as published by the
26 Free Software Foundation; either version 2, or (at your option) any
29 This program is distributed in the hope that it will be useful,
30 but WITHOUT ANY WARRANTY; without even the implied warranty of
31 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 GNU General Public License for more details.
34 You should have received a copy of the GNU General Public License
35 along with this program; if not, write to the Free Software
36 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 In other words, you are welcome to use, share and improve this program.
39 You are forbidden to forbid anyone else to use, share and improve
40 what you give them. Help stamp out software-hoarding!
42 -------------------------------------------------------------------------*/
49 #ifdef HAVE_SYS_ISA_DEFS_H
50 #include <sys/isa_defs.h>
54 #include "SDCCpeeph.h"
58 /* this is the down and dirty file with all kinds of kludgy & hacky
59 stuff. This is what it is all about CODE GENERATION for a specific MCU.
60 Some of the routines may be reusable, will have to see */
63 static char *zero = "#0x00";
64 static char *one = "#0x01";
66 static char *_z80_return[] = {"l", "h", "e", "d" };
67 static char *_gbz80_return[] = { "e", "d", "l", "h" };
68 static char **_fReturn;
71 static char *accUse[] = {"a" };
77 extern int ptrRegReq ;
79 extern FILE *codeOutFile;
81 const char *_shortJP = "jp";
95 } _pairs[NUM_PAIRS] = {
102 #define RESULTONSTACK(x) \
103 (IC_RESULT(x) && IC_RESULT(x)->aop && \
104 IC_RESULT(x)->aop->type == AOP_STK )
106 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
107 #define CLRC emitcode("xor","a,a");
109 #define LABEL_STR "%05d$"
111 lineNode *lineHead = NULL;
112 lineNode *lineCurr = NULL;
114 unsigned char SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
115 0xE0, 0xC0, 0x80, 0x00};
116 unsigned char SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
117 0x07, 0x03, 0x01, 0x00};
119 static int _lastStack = 0;
120 static int _pushed = 0;
121 static int _spoffset;
144 static char *aopGet(asmop *aop, int offset, bool bit16);
146 /*-----------------------------------------------------------------*/
147 /* emitcode - writes the code into a file : for now it is simple */
148 /*-----------------------------------------------------------------*/
149 void emitcode (const char *inst, const char *fmt, ...)
152 char lb[MAX_INLINEASM];
158 sprintf(lb,"%s\t",inst);
159 vsprintf(lb+(strlen(lb)),fmt,ap);
163 while (isspace(*lbp)) lbp++;
166 lineCurr = (lineCurr ?
167 connectLine(lineCurr,newLineNode(lb)) :
168 (lineHead = newLineNode(lb)));
169 lineCurr->isInline = inLine;
170 lineCurr->isDebug = debugLine;
174 const char *getPairName(asmop *aop)
176 if (aop->type == AOP_REG) {
177 switch (aop->aopu.aop_reg[0]->rIdx) {
189 else if (aop->type == AOP_STR) {
190 switch (*aop->aopu.aop_str[0]) {
206 static int getPairId(asmop *aop)
208 if (aop->size == 2) {
209 if (aop->type == AOP_REG) {
210 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
213 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
216 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
220 if (aop->type == AOP_STR) {
221 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
224 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
227 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
235 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
236 bool isPair(asmop *aop)
238 return (getPairId(aop) != PAIR_INVALID);
241 /** Push a register pair onto the stack */
242 void genPairPush(asmop *aop)
244 emitcode("push", "%s", getPairName(aop));
247 static char *_strdup(const char *s)
250 ALLOC_ATOMIC(ret, strlen(s)+1);
256 /*-----------------------------------------------------------------*/
257 /* newAsmop - creates a new asmOp */
258 /*-----------------------------------------------------------------*/
259 static asmop *newAsmop (short type)
263 ALLOC(aop,sizeof(asmop));
268 /*-----------------------------------------------------------------*/
269 /* aopForSym - for a true symbol */
270 /*-----------------------------------------------------------------*/
271 static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
274 memmap *space= SPEC_OCLS(sym->etype);
276 /* if already has one */
280 /* Assign depending on the storage class */
281 if (sym->onStack || sym->iaccess) {
282 sym->aop = aop = newAsmop(AOP_STK);
283 aop->size = getSize(sym->type);
284 aop->aopu.aop_stk = sym->stack;
288 /* special case for a function */
289 if (IS_FUNC(sym->type)) {
290 sym->aop = aop = newAsmop(AOP_IMMD);
291 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
292 strcpy(aop->aopu.aop_immd,sym->rname);
299 /* if it is in direct space */
300 if (IN_DIRSPACE(space)) {
301 sym->aop = aop = newAsmop (AOP_DIR);
302 aop->aopu.aop_dir = sym->rname ;
303 aop->size = getSize(sym->type);
304 emitcode("", "; AOP_DIR for %s", sym->rname);
310 /* only remaining is far space */
311 /* in which case DPTR gets the address */
313 sym->aop = aop = newAsmop(AOP_HL);
316 sym->aop = aop = newAsmop(AOP_IY);
317 emitcode ("ld","iy,#%s ; a", sym->rname);
319 aop->size = getSize(sym->type);
320 aop->aopu.aop_dir = sym->rname;
322 /* if it is in code space */
323 if (IN_CODESPACE(space))
329 /*-----------------------------------------------------------------*/
330 /* aopForRemat - rematerialzes an object */
331 /*-----------------------------------------------------------------*/
332 static asmop *aopForRemat (symbol *sym)
335 iCode *ic = sym->rematiCode;
336 asmop *aop = newAsmop(AOP_IMMD);
339 /* if plus or minus print the right hand side */
340 if (ic->op == '+' || ic->op == '-') {
341 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
344 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
347 /* we reached the end */
348 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
352 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
353 strcpy(aop->aopu.aop_immd,buffer);
357 /*-----------------------------------------------------------------*/
358 /* regsInCommon - two operands have some registers in common */
359 /*-----------------------------------------------------------------*/
360 bool regsInCommon (operand *op1, operand *op2)
365 /* if they have registers in common */
366 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
369 sym1 = OP_SYMBOL(op1);
370 sym2 = OP_SYMBOL(op2);
372 if (sym1->nRegs == 0 || sym2->nRegs == 0)
375 for (i = 0 ; i < sym1->nRegs ; i++) {
380 for (j = 0 ; j < sym2->nRegs ;j++ ) {
384 if (sym2->regs[j] == sym1->regs[i])
392 /*-----------------------------------------------------------------*/
393 /* operandsEqu - equivalent */
394 /*-----------------------------------------------------------------*/
395 bool operandsEqu ( operand *op1, operand *op2)
399 /* if they not symbols */
400 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
403 sym1 = OP_SYMBOL(op1);
404 sym2 = OP_SYMBOL(op2);
406 /* if both are itemps & one is spilt
407 and the other is not then false */
408 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
409 sym1->isspilt != sym2->isspilt )
412 /* if they are the same */
416 if (strcmp(sym1->rname,sym2->rname) == 0)
420 /* if left is a tmp & right is not */
424 (sym1->usl.spillLoc == sym2))
431 (sym2->usl.spillLoc == sym1))
437 /*-----------------------------------------------------------------*/
438 /* sameRegs - two asmops have the same registers */
439 /*-----------------------------------------------------------------*/
440 bool sameRegs (asmop *aop1, asmop *aop2 )
447 if (aop1->type != AOP_REG ||
448 aop2->type != AOP_REG )
451 if (aop1->size != aop2->size)
454 for (i = 0 ; i < aop1->size ; i++ )
455 if (aop1->aopu.aop_reg[i] !=
456 aop2->aopu.aop_reg[i] )
462 /*-----------------------------------------------------------------*/
463 /* aopOp - allocates an asmop for an operand : */
464 /*-----------------------------------------------------------------*/
465 static void aopOp (operand *op, iCode *ic, bool result)
474 /* if this a literal */
475 if (IS_OP_LITERAL(op)) {
476 op->aop = aop = newAsmop(AOP_LIT);
477 aop->aopu.aop_lit = op->operand.valOperand;
478 aop->size = getSize(operandType(op));
482 /* if already has a asmop then continue */
486 /* if the underlying symbol has a aop */
487 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
488 op->aop = OP_SYMBOL(op)->aop;
492 /* if this is a true symbol */
493 if (IS_TRUE_SYMOP(op)) {
494 op->aop = aopForSym(ic,OP_SYMBOL(op),result);
498 /* this is a temporary : this has
504 e) can be a return use only */
508 /* if the type is a conditional */
509 if (sym->regType == REG_CND) {
510 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
515 /* if it is spilt then two situations
517 b) has a spill location */
518 if (sym->isspilt || sym->nRegs == 0) {
519 /* rematerialize it NOW */
521 sym->aop = op->aop = aop =
523 aop->size = getSize(sym->type);
529 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
530 aop->size = getSize(sym->type);
531 for ( i = 0 ; i < 2 ; i++ )
532 aop->aopu.aop_str[i] = accUse[i];
538 aop = op->aop = sym->aop = newAsmop(AOP_STR);
539 aop->size = getSize(sym->type);
540 for ( i = 0 ; i < 4 ; i++ )
541 aop->aopu.aop_str[i] = _fReturn[i];
545 /* else spill location */
546 sym->aop = op->aop = aop =
547 aopForSym(ic,sym->usl.spillLoc,result);
548 aop->size = getSize(sym->type);
552 /* must be in a register */
553 sym->aop = op->aop = aop = newAsmop(AOP_REG);
554 aop->size = sym->nRegs;
555 for ( i = 0 ; i < sym->nRegs ;i++)
556 aop->aopu.aop_reg[i] = sym->regs[i];
559 /*-----------------------------------------------------------------*/
560 /* freeAsmop - free up the asmop given to an operand */
561 /*----------------------------------------------------------------*/
562 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
580 /* all other cases just dealloc */
584 OP_SYMBOL(op)->aop = NULL;
585 /* if the symbol has a spill */
587 SPIL_LOC(op)->aop = NULL;
592 bool isLitWord(asmop *aop)
605 char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
610 if (aop->size != 2 && aop->type != AOP_HL)
612 wassert(offset == 0);
614 /* depending on type */
620 sprintf (s,"%s%s",with_hash ? "#" : "", aop->aopu.aop_immd);
621 ALLOC_ATOMIC(rs,strlen(s)+1);
625 value * val = aop->aopu.aop_lit;
626 /* if it is a float then it gets tricky */
627 /* otherwise it is fairly simple */
628 if (!IS_FLOAT(val->type)) {
629 unsigned long v = floatFromVal(val);
631 sprintf(buffer,"%s0x%04lx", with_hash ? "#" : "", v);
632 ALLOC_ATOMIC(rs,strlen(buffer)+1);
633 return strcpy (rs,buffer);
643 char *aopGetWord(asmop *aop, int offset)
645 return aopGetLitWordLong(aop, offset, TRUE);
648 bool isPtr(const char *s)
650 if (!strcmp(s, "hl"))
652 if (!strcmp(s, "ix"))
654 if (!strcmp(s, "iy"))
659 static void adjustPair(const char *pair, int *pold, int new)
663 while (*pold < new) {
664 emitcode("inc", "%s", pair);
667 while (*pold > new) {
668 emitcode("dec", "%s", pair);
673 static void spillHL(void)
675 _G.HL.last_type = AOP_INVALID;
679 static bool requiresHL(asmop *aop)
690 static void fetchLitPair(int pairId, asmop *left, int offset)
693 const char *pair = _pairs[pairId].name;
694 l = aopGetLitWordLong(left, 0, FALSE);
698 if (_G.HL.lit && !strcmp(_G.HL.lit, l) && abs(_G.HL.offset - offset) < 3) {
699 adjustPair(pair, &_G.HL.offset, offset);
702 _G.HL.last_type = left->type;
703 _G.HL.lit = _strdup(l);
704 _G.HL.offset = offset;
706 emitcode("ld", "%s,#%s + %d", pair, l, offset);
708 emitcode("ld", "%s,#%s", pair, l);
712 /* Both a lit on the right and a true symbol on the left */
714 emitcode("ld", "%s,#%s + %d", pair, l, offset);
716 emitcode("ld", "%s,#%s", pair, l);
720 static void fetchPair(int pairId, asmop *aop)
722 /* if this is remateriazable */
723 if (isLitWord(aop)) {
724 fetchLitPair(pairId, aop, 0);
726 else { /* we need to get it byte by byte */
727 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
728 aopGet(aop, 0, FALSE);
729 emitcode("ld", "a,(hl+)");
730 emitcode("ld", "h,(hl)");
731 emitcode("ld", "l,a");
734 emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, 0, FALSE));
735 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, 1, FALSE));
737 /* PENDING: check? */
738 if (pairId == PAIR_HL)
743 static void fetchHL(asmop *aop)
745 fetchPair(PAIR_HL, aop);
748 static void setupHL(asmop *aop, int offset)
753 fetchLitPair(PAIR_HL, aop, offset);
754 _G.HL.offset = offset;
757 /* Doesnt include _pushed */
758 int abso = aop->aopu.aop_stk + offset + _spoffset;
759 /* In some cases we can still inc or dec hl */
760 if (_G.HL.last_type == AOP_STK && abs(_G.HL.offset - abso) < 3) {
761 adjustPair("hl", &_G.HL.offset, abso);
764 emitcode("lda", "hl,%d+%d+%d(sp)", aop->aopu.aop_stk+offset, _pushed, _spoffset);
772 _G.HL.last_type = aop->type;
775 static void emitLabel(int key)
777 emitcode("", LABEL_STR ":", key);
781 /*-----------------------------------------------------------------*/
782 /* aopGet - for fetching value of the aop */
783 /*-----------------------------------------------------------------*/
784 static char *aopGet(asmop *aop, int offset, bool bit16)
789 /* offset is greater than size then zero */
790 /* PENDING: this seems a bit screwed in some pointer cases. */
791 if (offset > (aop->size - 1) &&
792 aop->type != AOP_LIT)
795 /* depending on type */
799 sprintf (s,"#%s ; 5",aop->aopu.aop_immd);
802 wassert(offset == 1);
809 ALLOC_ATOMIC(rs,strlen(s)+1);
815 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
817 ALLOC_ATOMIC(rs,strlen(s)+1);
822 return aop->aopu.aop_reg[offset]->name;
827 setupHL(aop, offset);
829 return _strdup("(hl)");
832 sprintf(s,"%d(iy)", offset);
833 ALLOC_ATOMIC(rs,strlen(s)+1);
839 setupHL(aop, offset);
843 sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
845 ALLOC_ATOMIC(rs,strlen(s)+1);
859 return aopLiteral (aop->aopu.aop_lit,offset);
863 return aop->aopu.aop_str[offset];
867 wassertl(0, "aopget got unsupported aop->type");
871 bool isRegString(char *s)
873 if (!strcmp(s, "b") ||
884 bool isConstant(const char *s)
889 bool canAssignToPtr(char *s)
898 /*-----------------------------------------------------------------*/
899 /* aopPut - puts a string for a aop */
900 /*-----------------------------------------------------------------*/
901 static void aopPut (asmop *aop, char *s, int offset)
903 if (aop->size && offset > ( aop->size - 1)) {
904 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
905 "aopPut got offset > aop->size");
909 /* will assign value to value */
910 /* depending on where it is ofcourse */
915 emitcode("ld", "a,%s", s);
916 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
920 /* Dont bother if it's a ld x,x */
921 if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
922 emitcode("ld","%s,%s",
923 aop->aopu.aop_reg[offset]->name,s);
929 if (!canAssignToPtr(s)) {
930 emitcode("ld", "a,%s", s);
931 emitcode("ld", "%d(iy),a", offset);
934 emitcode("ld", "%d(iy),%s", offset, s);
939 if (!strcmp(s, "(hl)")) {
940 emitcode("ld", "a,(hl)");
944 setupHL(aop, offset);
945 emitcode("ld", "(hl),%s", s);
950 if (!strcmp("(hl)", s)) {
951 emitcode("ld", "a,(hl)");
954 setupHL(aop, offset);
955 if (!canAssignToPtr(s)) {
956 emitcode("ld", "a,%s", s);
957 emitcode("ld", "(hl),a");
960 emitcode("ld", "(hl),%s", s);
963 if (!canAssignToPtr(s)) {
964 emitcode("ld", "a,%s", s);
965 emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
968 emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
973 /* if bit variable */
974 if (!aop->aopu.aop_dir) {
975 emitcode("ld", "a,#0");
978 /* In bit space but not in C - cant happen */
985 if (strcmp(aop->aopu.aop_str[offset],s)) {
986 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
992 if (!offset && (strcmp(s,"acc") == 0))
996 emitcode("", "; Error aopPut AOP_ACC");
999 if (strcmp(aop->aopu.aop_str[offset],s))
1000 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1005 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1006 "aopPut got unsupported aop->type");
1011 #define AOP(op) op->aop
1012 #define AOP_TYPE(op) AOP(op)->type
1013 #define AOP_SIZE(op) AOP(op)->size
1014 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1016 /*-----------------------------------------------------------------*/
1017 /* getDataSize - get the operand data size */
1018 /*-----------------------------------------------------------------*/
1019 int getDataSize(operand *op)
1022 size = AOP_SIZE(op);
1030 /*-----------------------------------------------------------------*/
1031 /* movLeft2Result - move byte from left to result */
1032 /*-----------------------------------------------------------------*/
1033 static void movLeft2Result (operand *left, int offl,
1034 operand *result, int offr, int sign)
1037 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1038 l = aopGet(AOP(left),offl,FALSE);
1041 aopPut(AOP(result),l,offr);
1050 /** Put Acc into a register set
1052 void outAcc(operand *result)
1055 size = getDataSize(result);
1057 aopPut(AOP(result),"a",0);
1060 /* unsigned or positive */
1062 aopPut(AOP(result),zero,offset++);
1067 /** Take the value in carry and put it into a register
1069 void outBitC(operand *result)
1071 /* if the result is bit */
1072 if (AOP_TYPE(result) == AOP_CRY) {
1073 emitcode("", "; Note: outBitC form 1");
1074 aopPut(AOP(result),"blah",0);
1077 emitcode("ld", "a,#0");
1078 emitcode("rla", "");
1083 /*-----------------------------------------------------------------*/
1084 /* toBoolean - emit code for orl a,operator(sizeop) */
1085 /*-----------------------------------------------------------------*/
1086 void toBoolean(operand *oper)
1088 int size = AOP_SIZE(oper);
1091 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1094 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1097 if (AOP(oper)->type != AOP_ACC) {
1099 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1104 /*-----------------------------------------------------------------*/
1105 /* genNot - generate code for ! operation */
1106 /*-----------------------------------------------------------------*/
1107 static void genNot (iCode *ic)
1109 link *optype = operandType(IC_LEFT(ic));
1111 /* assign asmOps to operand & result */
1112 aopOp (IC_LEFT(ic),ic,FALSE);
1113 aopOp (IC_RESULT(ic),ic,TRUE);
1115 /* if in bit space then a special case */
1116 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1120 /* if type float then do float */
1121 if (IS_FLOAT(optype)) {
1125 toBoolean(IC_LEFT(ic));
1130 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1131 emitcode("sub", "a,#0x01");
1132 outBitC(IC_RESULT(ic));
1134 /* release the aops */
1135 freeAsmop(IC_LEFT(ic),NULL,ic);
1136 freeAsmop(IC_RESULT(ic),NULL,ic);
1139 /*-----------------------------------------------------------------*/
1140 /* genCpl - generate code for complement */
1141 /*-----------------------------------------------------------------*/
1142 static void genCpl (iCode *ic)
1148 /* assign asmOps to operand & result */
1149 aopOp (IC_LEFT(ic),ic,FALSE);
1150 aopOp (IC_RESULT(ic),ic,TRUE);
1152 /* if both are in bit space then
1154 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1155 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1159 size = AOP_SIZE(IC_RESULT(ic));
1161 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1164 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1167 /* release the aops */
1168 freeAsmop(IC_LEFT(ic),NULL,ic);
1169 freeAsmop(IC_RESULT(ic),NULL,ic);
1172 /*-----------------------------------------------------------------*/
1173 /* genUminus - unary minus code generation */
1174 /*-----------------------------------------------------------------*/
1175 static void genUminus (iCode *ic)
1178 link *optype, *rtype;
1181 aopOp(IC_LEFT(ic),ic,FALSE);
1182 aopOp(IC_RESULT(ic),ic,TRUE);
1184 /* if both in bit space then special
1186 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1187 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1192 optype = operandType(IC_LEFT(ic));
1193 rtype = operandType(IC_RESULT(ic));
1195 /* if float then do float stuff */
1196 if (IS_FLOAT(optype)) {
1201 /* otherwise subtract from zero */
1202 size = AOP_SIZE(IC_LEFT(ic));
1206 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1207 emitcode("ld", "a,#0");
1208 emitcode("sbc","a,%s",l);
1209 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1212 /* if any remaining bytes in the result */
1213 /* we just need to propagate the sign */
1214 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1215 emitcode("rlc","a");
1216 emitcode("sbc","a,a");
1218 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1222 /* release the aops */
1223 freeAsmop(IC_LEFT(ic),NULL,ic);
1224 freeAsmop(IC_RESULT(ic),NULL,ic);
1227 /*-----------------------------------------------------------------*/
1228 /* assignResultValue - */
1229 /*-----------------------------------------------------------------*/
1230 void assignResultValue(operand * oper)
1233 int size = AOP_SIZE(oper);
1238 aopPut(AOP(oper),_fReturn[offset],offset);
1243 /*-----------------------------------------------------------------*/
1244 /* genIpush - genrate code for pushing this gets a little complex */
1245 /*-----------------------------------------------------------------*/
1246 static void genIpush (iCode *ic)
1248 int size, offset = 0 ;
1252 /* if this is not a parm push : ie. it is spill push
1253 and spill push is always done on the local stack */
1254 if (!ic->parmPush) {
1255 /* and the item is spilt then do nothing */
1256 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1259 aopOp(IC_LEFT(ic),ic,FALSE);
1260 size = AOP_SIZE(IC_LEFT(ic));
1261 /* push it on the stack */
1262 if (isPair(AOP(IC_LEFT(ic)))) {
1263 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1269 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1270 /* Simple for now - load into A and PUSH AF */
1271 emitcode("ld", "a,%s", l);
1272 emitcode("push", "af");
1273 emitcode("inc", "sp");
1280 /* Hmmm... what about saving the currently used registers
1283 /* then do the push */
1284 aopOp(IC_LEFT(ic),ic,FALSE);
1286 size = AOP_SIZE(IC_LEFT(ic));
1288 if (isPair(AOP(IC_LEFT(ic)))) {
1290 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1294 fetchHL(AOP(IC_LEFT(ic)));
1295 emitcode("push", "hl ; 2");
1302 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1303 emitcode("ld", "a,%s", l);
1304 emitcode("push", "af");
1305 emitcode("inc", "sp");
1310 freeAsmop(IC_LEFT(ic),NULL,ic);
1313 /*-----------------------------------------------------------------*/
1314 /* genIpop - recover the registers: can happen only for spilling */
1315 /*-----------------------------------------------------------------*/
1316 static void genIpop (iCode *ic)
1321 /* if the temp was not pushed then */
1322 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1325 aopOp(IC_LEFT(ic),ic,FALSE);
1326 size = AOP_SIZE(IC_LEFT(ic));
1328 if (isPair(AOP(IC_LEFT(ic)))) {
1329 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1333 emitcode("dec", "sp");
1334 emitcode("pop", "hl");
1336 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1340 freeAsmop(IC_LEFT(ic),NULL,ic);
1343 /** Emit the code for a call statement
1345 static void emitCall (iCode *ic, bool ispcall)
1347 /* if caller saves & we have not saved then */
1348 if (!ic->regsSaved) {
1352 /* if send set is not empty then assign */
1355 for (sic = setFirstItem(sendSet) ; sic ;
1356 sic = setNextItem(sendSet)) {
1357 int size, offset = 0;
1358 aopOp(IC_LEFT(sic),sic,FALSE);
1359 size = AOP_SIZE(IC_LEFT(sic));
1361 char *l = aopGet(AOP(IC_LEFT(sic)),offset,
1363 if (strcmp(l, _fReturn[offset]))
1364 emitcode("ld","%s,%s",
1369 freeAsmop (IC_LEFT(sic),NULL,sic);
1375 aopOp(IC_LEFT(ic),ic,FALSE);
1377 if (isLitWord(AOP(IC_LEFT(ic)))) {
1378 emitcode("", "; Special case where the pCall is to a constant");
1379 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1382 symbol *rlbl = newiTempLabel(NULL);
1384 emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
1385 emitcode("push", "hl");
1388 fetchHL(AOP(IC_LEFT(ic)));
1389 emitcode("jp", "(hl)");
1390 emitcode("","%05d$:",(rlbl->key+100));
1393 freeAsmop(IC_LEFT(ic),NULL,ic);
1397 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1398 OP_SYMBOL(IC_LEFT(ic))->rname :
1399 OP_SYMBOL(IC_LEFT(ic))->name;
1400 emitcode("call", "%s", name);
1404 /* if we need assign a result value */
1405 if ((IS_ITEMP(IC_RESULT(ic)) &&
1406 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1407 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1408 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1411 aopOp(IC_RESULT(ic),ic,FALSE);
1414 assignResultValue(IC_RESULT(ic));
1416 freeAsmop(IC_RESULT(ic),NULL, ic);
1419 /* adjust the stack for parameters if required */
1420 if (IC_LEFT(ic)->parmBytes) {
1421 int i = IC_LEFT(ic)->parmBytes;
1424 emitcode("lda", "sp,%d(sp)", i);
1429 emitcode("ld", "hl,#%d", i);
1430 emitcode("add", "hl,sp");
1431 emitcode("ld", "sp,hl");
1435 emitcode("pop", "hl");
1439 emitcode("inc", "sp");
1447 /*-----------------------------------------------------------------*/
1448 /* genCall - generates a call statement */
1449 /*-----------------------------------------------------------------*/
1450 static void genCall (iCode *ic)
1452 emitCall(ic, FALSE);
1455 /*-----------------------------------------------------------------*/
1456 /* genPcall - generates a call by pointer statement */
1457 /*-----------------------------------------------------------------*/
1458 static void genPcall (iCode *ic)
1463 /*-----------------------------------------------------------------*/
1464 /* resultRemat - result is rematerializable */
1465 /*-----------------------------------------------------------------*/
1466 static int resultRemat (iCode *ic)
1468 if (SKIP_IC(ic) || ic->op == IFX)
1471 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1472 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1473 if (sym->remat && !POINTER_SET(ic))
1480 /*-----------------------------------------------------------------*/
1481 /* genFunction - generated code for function entry */
1482 /*-----------------------------------------------------------------*/
1483 static void genFunction (iCode *ic)
1485 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1489 /* create the function header */
1490 emitcode(";","-----------------------------------------");
1491 emitcode(";"," function %s", sym->name);
1492 emitcode(";","-----------------------------------------");
1494 emitcode("", "__%s_start:", sym->rname);
1495 emitcode("","%s:",sym->rname);
1497 fetype = getSpec(operandType(IC_LEFT(ic)));
1499 /* if critical function then turn interrupts off */
1500 if (SPEC_CRTCL(fetype))
1503 /* if this is an interrupt service routine then
1504 save acc, b, dpl, dph */
1505 if (IS_ISR(sym->etype)) {
1506 emitcode("push", "af");
1507 emitcode("push", "bc");
1508 emitcode("push", "de");
1509 emitcode("push", "hl");
1511 /* PENDING: callee-save etc */
1513 /* adjust the stack for the function */
1514 emitcode("push", "bc");
1516 emitcode("push", "de");
1517 emitcode("push", "ix");
1518 emitcode("ld", "ix,#0");
1519 emitcode("add", "ix,sp");
1522 _lastStack = sym->stack;
1526 emitcode("lda", "sp,-%d(sp)", sym->stack);
1529 emitcode("ld", "hl,#-%d", sym->stack);
1530 emitcode("add", "hl,sp");
1531 emitcode("ld", "sp,hl");
1534 _spoffset = sym->stack;
1537 /*-----------------------------------------------------------------*/
1538 /* genEndFunction - generates epilogue for functions */
1539 /*-----------------------------------------------------------------*/
1540 static void genEndFunction (iCode *ic)
1542 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1544 if (IS_ISR(sym->etype)) {
1548 if (SPEC_CRTCL(sym->etype))
1551 /* PENDING: calleeSave */
1553 /* if debug then send end of function */
1554 if (options.debug && currFunc) {
1556 emitcode("","C$%s$%d$%d$%d ==.",
1557 ic->filename,currFunc->lastLine,
1558 ic->level,ic->block);
1559 if (IS_STATIC(currFunc->etype))
1560 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1562 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1566 emitcode("ld", "sp,ix");
1567 emitcode("pop", "ix");
1568 emitcode("pop", "de");
1572 emitcode("ld", "hl,#%d", _spoffset);
1573 emitcode("add", "hl,sp");
1574 emitcode("ld", "sp,hl");
1577 emitcode("pop", "bc");
1578 emitcode("ret", "");
1579 emitcode("; Useful for profiling and debugging", "");
1580 emitcode(".dw", "%s", sym->rname);
1581 emitcode("", "__%s_end:", sym->rname);
1587 /*-----------------------------------------------------------------*/
1588 /* genRet - generate code for return statement */
1589 /*-----------------------------------------------------------------*/
1590 static void genRet (iCode *ic)
1593 /* Errk. This is a hack until I can figure out how
1594 to cause dehl to spill on a call */
1595 int size,offset = 0;
1597 /* if we have no return value then
1598 just generate the "ret" */
1602 /* we have something to return then
1603 move the return value into place */
1604 aopOp(IC_LEFT(ic),ic,FALSE);
1605 size = AOP_SIZE(IC_LEFT(ic));
1607 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
1609 emitcode("ld", "de,%s", l);
1612 emitcode("ld", "hl,%s", l);
1617 l = aopGet(AOP(IC_LEFT(ic)),offset,
1619 if (strcmp(_fReturn[offset],l))
1620 emitcode("ld","%s,%s", _fReturn[offset++],l);
1623 freeAsmop (IC_LEFT(ic),NULL,ic);
1626 /* generate a jump to the return label
1627 if the next is not the return statement */
1628 if (!(ic->next && ic->next->op == LABEL &&
1629 IC_LABEL(ic->next) == returnLabel))
1631 emitcode("jp", LABEL_STR ,(returnLabel->key+100));
1634 /*-----------------------------------------------------------------*/
1635 /* genLabel - generates a label */
1636 /*-----------------------------------------------------------------*/
1637 static void genLabel (iCode *ic)
1639 /* special case never generate */
1640 if (IC_LABEL(ic) == entryLabel)
1643 emitLabel(IC_LABEL(ic)->key+100);
1646 /*-----------------------------------------------------------------*/
1647 /* genGoto - generates a ljmp */
1648 /*-----------------------------------------------------------------*/
1649 static void genGoto (iCode *ic)
1651 emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
1654 /*-----------------------------------------------------------------*/
1655 /* genPlusIncr :- does addition with increment if possible */
1656 /*-----------------------------------------------------------------*/
1657 static bool genPlusIncr (iCode *ic)
1659 unsigned int icount ;
1660 unsigned int size = getDataSize(IC_RESULT(ic));
1662 /* will try to generate an increment */
1663 /* if the right side is not a literal
1665 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1668 emitcode("", "; genPlusIncr");
1670 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1673 /* If result is a pair */
1674 if (isPair(AOP(IC_RESULT(ic))) && isLitWord(AOP(IC_LEFT(ic)))) {
1675 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
1679 /* if the literal value of the right hand side
1680 is greater than 4 then it is not worth it */
1685 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1686 isPair(AOP(IC_RESULT(ic)))) {
1688 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1692 /* if increment 16 bits in register */
1693 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1696 symbol *tlbl = newiTempLabel(NULL);
1697 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1698 emitcode(_shortJP, "nz," LABEL_STR ,tlbl->key+100);
1700 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1704 emitLabel(tlbl->key+100);
1708 /* If result is a pair */
1709 if (isPair(AOP(IC_RESULT(ic)))) {
1710 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1711 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1713 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
1717 /* if the sizes are greater than 1 then we cannot */
1718 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1719 AOP_SIZE(IC_LEFT(ic)) > 1 )
1722 /* we can if the aops of the left & result match or
1723 if they are in registers and the registers are the
1725 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
1727 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
1735 /*-----------------------------------------------------------------*/
1736 /* outBitAcc - output a bit in acc */
1737 /*-----------------------------------------------------------------*/
1738 void outBitAcc(operand *result)
1740 symbol *tlbl = newiTempLabel(NULL);
1741 /* if the result is a bit */
1742 if (AOP_TYPE(result) == AOP_CRY){
1746 emitcode(_shortJP,"z," LABEL_STR ,tlbl->key+100);
1747 emitcode("ld","a,%s",one);
1748 emitLabel(tlbl->key+100);
1753 /*-----------------------------------------------------------------*/
1754 /* genPlus - generates code for addition */
1755 /*-----------------------------------------------------------------*/
1756 static void genPlus (iCode *ic)
1758 int size, offset = 0;
1760 /* special cases :- */
1762 aopOp (IC_LEFT(ic),ic,FALSE);
1763 aopOp (IC_RIGHT(ic),ic,FALSE);
1764 aopOp (IC_RESULT(ic),ic,TRUE);
1766 /* Swap the left and right operands if:
1768 if literal, literal on the right or
1769 if left requires ACC or right is already
1772 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
1773 (AOP_NEEDSACC(IC_LEFT(ic))) ||
1774 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
1775 operand *t = IC_RIGHT(ic);
1776 IC_RIGHT(ic) = IC_LEFT(ic);
1780 /* if both left & right are in bit
1782 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1783 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1788 /* if left in bit space & right literal */
1789 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1790 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
1791 /* Can happen I guess */
1795 /* if I can do an increment instead
1796 of add then GOOD for ME */
1797 if (genPlusIncr (ic) == TRUE)
1800 size = getDataSize(IC_RESULT(ic));
1802 /* Special case when left and right are constant */
1803 if (isPair(AOP(IC_RESULT(ic)))) {
1806 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
1807 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
1808 if (left && right) {
1812 sprintf(buffer, "#(%s + %s)", left, right);
1813 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
1819 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
1820 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1822 emitcode("add","a,%s",
1823 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1825 emitcode("adc","a,%s",
1826 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1828 MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1830 emitcode("add","a,%s",
1831 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1833 emitcode("adc","a,%s",
1834 aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1836 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1839 /* Some kind of pointer arith. */
1840 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1841 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1842 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1845 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1846 AOP_SIZE(IC_RIGHT(ic)) == 3 &&
1847 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
1852 freeAsmop(IC_LEFT(ic),NULL,ic);
1853 freeAsmop(IC_RIGHT(ic),NULL,ic);
1854 freeAsmop(IC_RESULT(ic),NULL,ic);
1858 /*-----------------------------------------------------------------*/
1859 /* genMinusDec :- does subtraction with deccrement if possible */
1860 /*-----------------------------------------------------------------*/
1861 static bool genMinusDec (iCode *ic)
1863 unsigned int icount ;
1864 unsigned int size = getDataSize(IC_RESULT(ic));
1866 /* will try to generate an increment */
1867 /* if the right side is not a literal we cannot */
1868 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
1871 /* if the literal value of the right hand side
1872 is greater than 4 then it is not worth it */
1873 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
1876 size = getDataSize(IC_RESULT(ic));
1879 /* if increment 16 bits in register */
1880 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1883 symbol *tlbl = newiTempLabel(NULL);
1884 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
1885 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
1887 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
1891 emitLabel(tlbl->key+100);
1896 /* if decrement 16 bits in register */
1897 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
1898 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
1900 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1904 /* If result is a pair */
1905 if (isPair(AOP(IC_RESULT(ic)))) {
1906 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
1907 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
1909 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
1913 /* if the sizes are greater than 1 then we cannot */
1914 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
1915 AOP_SIZE(IC_LEFT(ic)) > 1 )
1918 /* we can if the aops of the left & result match or if they are in
1919 registers and the registers are the same */
1920 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
1922 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
1929 /*-----------------------------------------------------------------*/
1930 /* genMinus - generates code for subtraction */
1931 /*-----------------------------------------------------------------*/
1932 static void genMinus (iCode *ic)
1934 int size, offset = 0;
1935 unsigned long lit = 0L;
1937 aopOp (IC_LEFT(ic),ic,FALSE);
1938 aopOp (IC_RIGHT(ic),ic,FALSE);
1939 aopOp (IC_RESULT(ic),ic,TRUE);
1941 /* special cases :- */
1942 /* if both left & right are in bit space */
1943 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
1944 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
1949 /* if I can do an decrement instead of subtract then GOOD for ME */
1950 if (genMinusDec (ic) == TRUE)
1953 size = getDataSize(IC_RESULT(ic));
1955 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
1958 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
1963 /* if literal, add a,#-lit, else normal subb */
1965 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
1966 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
1968 emitcode("sub","a,%s",
1969 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1971 emitcode("sbc","a,%s",
1972 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
1975 /* first add without previous c */
1977 emitcode("add","a,#0x%02x",
1978 (unsigned int)(lit & 0x0FFL));
1980 emitcode("adc","a,#0x%02x",
1981 (unsigned int)((lit >> (offset*8)) & 0x0FFL));
1983 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1986 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
1987 AOP_SIZE(IC_LEFT(ic)) == 3 &&
1988 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
1992 freeAsmop(IC_LEFT(ic),NULL,ic);
1993 freeAsmop(IC_RIGHT(ic),NULL,ic);
1994 freeAsmop(IC_RESULT(ic),NULL,ic);
1997 /*-----------------------------------------------------------------*/
1998 /* genMult - generates code for multiplication */
1999 /*-----------------------------------------------------------------*/
2000 static void genMult (iCode *ic)
2002 /* Shouldn't occur - all done through function calls */
2006 /*-----------------------------------------------------------------*/
2007 /* genDiv - generates code for division */
2008 /*-----------------------------------------------------------------*/
2009 static void genDiv (iCode *ic)
2011 /* Shouldn't occur - all done through function calls */
2015 /*-----------------------------------------------------------------*/
2016 /* genMod - generates code for division */
2017 /*-----------------------------------------------------------------*/
2018 static void genMod (iCode *ic)
2020 /* Shouldn't occur - all done through function calls */
2024 /*-----------------------------------------------------------------*/
2025 /* genIfxJump :- will create a jump depending on the ifx */
2026 /*-----------------------------------------------------------------*/
2027 static void genIfxJump (iCode *ic, char *jval)
2032 /* if true label then we jump if condition
2034 if ( IC_TRUE(ic) ) {
2036 if (!strcmp(jval, "a")) {
2039 else if (!strcmp(jval, "c")) {
2043 /* The buffer contains the bit on A that we should test */
2048 /* false label is present */
2049 jlbl = IC_FALSE(ic) ;
2050 if (!strcmp(jval, "a")) {
2053 else if (!strcmp(jval, "c")) {
2057 /* The buffer contains the bit on A that we should test */
2061 /* Z80 can do a conditional long jump */
2062 if (!strcmp(jval, "a")) {
2063 emitcode("or", "a,a");
2065 else if (!strcmp(jval, "c")) {
2068 emitcode("bit", "%s,a", jval);
2070 emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
2072 /* mark the icode as generated */
2076 /** Generic compare for > or <
2078 static void genCmp (operand *left,operand *right,
2079 operand *result, iCode *ifx, int sign)
2081 int size, offset = 0 ;
2082 unsigned long lit = 0L;
2084 /* if left & right are bit variables */
2085 if (AOP_TYPE(left) == AOP_CRY &&
2086 AOP_TYPE(right) == AOP_CRY ) {
2087 /* Cant happen on the Z80 */
2090 /* subtract right from left if at the
2091 end the carry flag is set then we know that
2092 left is greater than right */
2093 size = max(AOP_SIZE(left),AOP_SIZE(right));
2095 /* if unsigned char cmp with lit, just compare */
2097 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2098 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2100 emitcode("xor", "a,#0x80");
2101 emitcode("cp", "%s^0x80", aopGet(AOP(right), offset, FALSE));
2104 emitcode("cp", "%s ; 7", aopGet(AOP(right), offset, FALSE));
2107 if(AOP_TYPE(right) == AOP_LIT) {
2108 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2109 /* optimize if(x < 0) or if(x >= 0) */
2112 /* No sign so it's always false */
2116 /* Just load in the top most bit */
2117 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2118 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2119 genIfxJump (ifx,"7");
2123 emitcode("rlc","a");
2129 /* First setup h and l contaning the top most bytes XORed */
2130 bool fDidXor = FALSE;
2131 if (AOP_TYPE(left) == AOP_LIT){
2132 unsigned long lit = (unsigned long)
2133 floatFromVal(AOP(left)->aopu.aop_lit);
2134 emitcode("ld", "%s,#0x%02x", _fTmp[0],
2135 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2138 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2139 emitcode("xor", "a,#0x80");
2140 emitcode("ld", "%s,a", _fTmp[0]);
2143 if (AOP_TYPE(right) == AOP_LIT) {
2144 unsigned long lit = (unsigned long)
2145 floatFromVal(AOP(right)->aopu.aop_lit);
2146 emitcode("ld", "%s,#0x%02x", _fTmp[1],
2147 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2150 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2151 emitcode("xor", "a,#0x80");
2152 emitcode("ld", "%s,a", _fTmp[1]);
2162 /* Do a long subtract */
2163 if (!sign || size ) {
2164 MOVA(aopGet(AOP(left),offset,FALSE));
2166 if (sign && size == 0) {
2167 emitcode("ld", "a,%s", _fTmp[0]);
2168 emitcode("sbc", "a,%s", _fTmp[1]);
2171 /* Subtract through, propagating the carry */
2172 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2179 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2182 /* if the result is used in the next
2183 ifx conditional branch then generate
2184 code a little differently */
2186 genIfxJump (ifx,"c");
2189 /* leave the result in acc */
2193 /*-----------------------------------------------------------------*/
2194 /* genCmpGt :- greater than comparison */
2195 /*-----------------------------------------------------------------*/
2196 static void genCmpGt (iCode *ic, iCode *ifx)
2198 operand *left, *right, *result;
2199 link *letype , *retype;
2203 right= IC_RIGHT(ic);
2204 result = IC_RESULT(ic);
2206 letype = getSpec(operandType(left));
2207 retype =getSpec(operandType(right));
2208 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2209 /* assign the amsops */
2210 aopOp (left,ic,FALSE);
2211 aopOp (right,ic,FALSE);
2212 aopOp (result,ic,TRUE);
2214 genCmp(right, left, result, ifx, sign);
2216 freeAsmop(left,NULL,ic);
2217 freeAsmop(right,NULL,ic);
2218 freeAsmop(result,NULL,ic);
2221 /*-----------------------------------------------------------------*/
2222 /* genCmpLt - less than comparisons */
2223 /*-----------------------------------------------------------------*/
2224 static void genCmpLt (iCode *ic, iCode *ifx)
2226 operand *left, *right, *result;
2227 link *letype , *retype;
2231 right= IC_RIGHT(ic);
2232 result = IC_RESULT(ic);
2234 letype = getSpec(operandType(left));
2235 retype =getSpec(operandType(right));
2236 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2238 /* assign the amsops */
2239 aopOp (left,ic,FALSE);
2240 aopOp (right,ic,FALSE);
2241 aopOp (result,ic,TRUE);
2243 genCmp(left, right, result, ifx, sign);
2245 freeAsmop(left,NULL,ic);
2246 freeAsmop(right,NULL,ic);
2247 freeAsmop(result,NULL,ic);
2250 /*-----------------------------------------------------------------*/
2251 /* gencjneshort - compare and jump if not equal */
2252 /*-----------------------------------------------------------------*/
2253 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2255 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2257 unsigned long lit = 0L;
2259 /* Swap the left and right if it makes the computation easier */
2260 if (AOP_TYPE(left) == AOP_LIT) {
2266 if(AOP_TYPE(right) == AOP_LIT)
2267 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2269 /* if the right side is a literal then anything goes */
2270 if (AOP_TYPE(right) == AOP_LIT &&
2271 AOP_TYPE(left) != AOP_DIR ) {
2273 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2278 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2282 emitcode("or", "a,a");
2284 emitcode("jp", "nz," LABEL_STR, lbl->key+100);
2288 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2289 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2290 emitcode("or", "a,a");
2292 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2293 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2298 /* if the right side is in a register or in direct space or
2299 if the left is a pointer register & right is not */
2300 else if (AOP_TYPE(right) == AOP_REG ||
2301 AOP_TYPE(right) == AOP_DIR ||
2302 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2304 MOVA(aopGet(AOP(left),offset,FALSE));
2305 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2306 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2308 emitcode("jp","nz," LABEL_STR ,lbl->key+100);
2310 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2311 emitcode("jp", "nz," LABEL_STR , lbl->key+100);
2316 /* right is a pointer reg need both a & b */
2317 /* PENDING: is this required? */
2319 MOVA(aopGet(AOP(right),offset,FALSE));
2320 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2321 emitcode("jr", "nz," LABEL_STR, lbl->key+100);
2327 /*-----------------------------------------------------------------*/
2328 /* gencjne - compare and jump if not equal */
2329 /*-----------------------------------------------------------------*/
2330 static void gencjne(operand *left, operand *right, symbol *lbl)
2332 symbol *tlbl = newiTempLabel(NULL);
2334 gencjneshort(left, right, lbl);
2337 emitcode("ld","a,%s",one);
2338 emitcode(_shortJP, LABEL_STR ,tlbl->key+100);
2339 emitLabel(lbl->key+100);
2340 emitcode("xor","a,a");
2341 emitLabel(tlbl->key+100);
2344 /*-----------------------------------------------------------------*/
2345 /* genCmpEq - generates code for equal to */
2346 /*-----------------------------------------------------------------*/
2347 static void genCmpEq (iCode *ic, iCode *ifx)
2349 operand *left, *right, *result;
2351 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2352 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2353 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2355 /* Swap operands if it makes the operation easier. ie if:
2356 1. Left is a literal.
2358 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2359 operand *t = IC_RIGHT(ic);
2360 IC_RIGHT(ic) = IC_LEFT(ic);
2364 if (ifx && !AOP_SIZE(result)){
2366 /* if they are both bit variables */
2367 if (AOP_TYPE(left) == AOP_CRY &&
2368 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2371 tlbl = newiTempLabel(NULL);
2372 gencjneshort(left, right, tlbl);
2373 if ( IC_TRUE(ifx) ) {
2374 emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
2375 emitLabel(tlbl->key+100);
2377 /* PENDING: do this better */
2378 symbol *lbl = newiTempLabel(NULL);
2379 emitcode(_shortJP, LABEL_STR ,lbl->key+100);
2380 emitLabel(tlbl->key+100);
2381 emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
2382 emitLabel(lbl->key+100);
2385 /* mark the icode as generated */
2390 /* if they are both bit variables */
2391 if (AOP_TYPE(left) == AOP_CRY &&
2392 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2395 gencjne(left,right,newiTempLabel(NULL));
2396 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2400 genIfxJump(ifx,"a");
2403 /* if the result is used in an arithmetic operation
2404 then put the result in place */
2405 if (AOP_TYPE(result) != AOP_CRY) {
2408 /* leave the result in acc */
2412 freeAsmop(left,NULL,ic);
2413 freeAsmop(right,NULL,ic);
2414 freeAsmop(result,NULL,ic);
2417 /*-----------------------------------------------------------------*/
2418 /* ifxForOp - returns the icode containing the ifx for operand */
2419 /*-----------------------------------------------------------------*/
2420 static iCode *ifxForOp ( operand *op, iCode *ic )
2422 /* if true symbol then needs to be assigned */
2423 if (IS_TRUE_SYMOP(op))
2426 /* if this has register type condition and
2427 the next instruction is ifx with the same operand
2428 and live to of the operand is upto the ifx only then */
2430 ic->next->op == IFX &&
2431 IC_COND(ic->next)->key == op->key &&
2432 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2438 /*-----------------------------------------------------------------*/
2439 /* genAndOp - for && operation */
2440 /*-----------------------------------------------------------------*/
2441 static void genAndOp (iCode *ic)
2443 operand *left,*right, *result;
2446 /* note here that && operations that are in an if statement are
2447 taken away by backPatchLabels only those used in arthmetic
2448 operations remain */
2449 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2450 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2451 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2453 /* if both are bit variables */
2454 if (AOP_TYPE(left) == AOP_CRY &&
2455 AOP_TYPE(right) == AOP_CRY ) {
2458 tlbl = newiTempLabel(NULL);
2460 emitcode(_shortJP, "z," LABEL_STR ,tlbl->key+100);
2462 emitLabel(tlbl->key+100);
2466 freeAsmop(left,NULL,ic);
2467 freeAsmop(right,NULL,ic);
2468 freeAsmop(result,NULL,ic);
2471 /*-----------------------------------------------------------------*/
2472 /* genOrOp - for || operation */
2473 /*-----------------------------------------------------------------*/
2474 static void genOrOp (iCode *ic)
2476 operand *left,*right, *result;
2479 /* note here that || operations that are in an
2480 if statement are taken away by backPatchLabels
2481 only those used in arthmetic operations remain */
2482 aopOp((left=IC_LEFT(ic)),ic,FALSE);
2483 aopOp((right=IC_RIGHT(ic)),ic,FALSE);
2484 aopOp((result=IC_RESULT(ic)),ic,FALSE);
2486 /* if both are bit variables */
2487 if (AOP_TYPE(left) == AOP_CRY &&
2488 AOP_TYPE(right) == AOP_CRY ) {
2491 tlbl = newiTempLabel(NULL);
2493 emitcode(_shortJP, "nz," LABEL_STR,tlbl->key+100);
2495 emitLabel(tlbl->key+100);
2499 freeAsmop(left,NULL,ic);
2500 freeAsmop(right,NULL,ic);
2501 freeAsmop(result,NULL,ic);
2504 /*-----------------------------------------------------------------*/
2505 /* isLiteralBit - test if lit == 2^n */
2506 /*-----------------------------------------------------------------*/
2507 int isLiteralBit(unsigned long lit)
2509 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
2510 0x100L,0x200L,0x400L,0x800L,
2511 0x1000L,0x2000L,0x4000L,0x8000L,
2512 0x10000L,0x20000L,0x40000L,0x80000L,
2513 0x100000L,0x200000L,0x400000L,0x800000L,
2514 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
2515 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
2518 for(idx = 0; idx < 32; idx++)
2524 /*-----------------------------------------------------------------*/
2525 /* jmpTrueOrFalse - */
2526 /*-----------------------------------------------------------------*/
2527 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
2529 // ugly but optimized by peephole
2531 symbol *nlbl = newiTempLabel(NULL);
2532 emitcode("jp", LABEL_STR, nlbl->key+100);
2533 emitLabel(tlbl->key+100);
2534 emitcode("jp",LABEL_STR,IC_TRUE(ic)->key+100);
2535 emitLabel(nlbl->key+100);
2538 emitcode("jp", LABEL_STR, IC_FALSE(ic)->key+100);
2539 emitLabel(tlbl->key+100);
2544 /*-----------------------------------------------------------------*/
2545 /* genAnd - code for and */
2546 /*-----------------------------------------------------------------*/
2547 static void genAnd (iCode *ic, iCode *ifx)
2549 operand *left, *right, *result;
2551 unsigned long lit = 0L;
2554 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2555 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2556 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2559 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2561 AOP_TYPE(left), AOP_TYPE(right));
2562 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2564 AOP_SIZE(left), AOP_SIZE(right));
2567 /* if left is a literal & right is not then exchange them */
2568 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2569 AOP_NEEDSACC(left)) {
2570 operand *tmp = right ;
2575 /* if result = right then exchange them */
2576 if(sameRegs(AOP(result),AOP(right))){
2577 operand *tmp = right ;
2582 /* if right is bit then exchange them */
2583 if (AOP_TYPE(right) == AOP_CRY &&
2584 AOP_TYPE(left) != AOP_CRY){
2585 operand *tmp = right ;
2589 if(AOP_TYPE(right) == AOP_LIT)
2590 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2592 size = AOP_SIZE(result);
2594 if (AOP_TYPE(left) == AOP_CRY){
2599 // if(val & 0xZZ) - size = 0, ifx != FALSE -
2600 // bit = val & 0xZZ - size = 1, ifx = FALSE -
2601 if((AOP_TYPE(right) == AOP_LIT) &&
2602 (AOP_TYPE(result) == AOP_CRY) &&
2603 (AOP_TYPE(left) != AOP_CRY)) {
2604 int posbit = isLiteralBit(lit);
2608 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
2612 emitcode("mov","c,acc.%d",posbit&0x07);
2617 sprintf(buffer, "%d", posbit&0x07);
2618 genIfxJump(ifx, buffer);
2626 symbol *tlbl = newiTempLabel(NULL);
2627 int sizel = AOP_SIZE(left);
2630 emitcode("setb","c");
2633 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
2634 MOVA( aopGet(AOP(left),offset,FALSE));
2636 if((posbit = isLiteralBit(bytelit)) != 0) {
2638 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
2641 if(bytelit != 0x0FFL)
2642 emitcode("and","a,%s",
2643 aopGet(AOP(right),offset,FALSE));
2644 emitcode("jr","nz, %05d$",tlbl->key+100);
2649 // bit = left & literal
2651 emitcode("clr","c");
2652 emitcode("","%05d$:",tlbl->key+100);
2654 // if(left & literal)
2657 jmpTrueOrFalse(ifx, tlbl);
2665 /* if left is same as result */
2666 if(sameRegs(AOP(result),AOP(left))){
2667 for(;size--; offset++) {
2668 if(AOP_TYPE(right) == AOP_LIT){
2669 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
2673 aopPut(AOP(result),zero,offset);
2675 MOVA(aopGet(AOP(left),offset,FALSE));
2676 emitcode("and","a,%s",
2677 aopGet(AOP(right),offset,FALSE));
2678 emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
2683 if (AOP_TYPE(left) == AOP_ACC) {
2687 MOVA(aopGet(AOP(right),offset,FALSE));
2688 emitcode("and","%s,a",
2689 aopGet(AOP(left),offset,FALSE));
2694 // left & result in different registers
2695 if(AOP_TYPE(result) == AOP_CRY){
2698 for(;(size--);offset++) {
2700 // result = left & right
2701 if(AOP_TYPE(right) == AOP_LIT){
2702 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
2704 aopGet(AOP(left),offset,FALSE),
2707 } else if(bytelit == 0){
2708 aopPut(AOP(result),zero,offset);
2712 // faster than result <- left, anl result,right
2713 // and better if result is SFR
2714 if (AOP_TYPE(left) == AOP_ACC)
2715 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
2717 MOVA(aopGet(AOP(right),offset,FALSE));
2718 emitcode("and","a,%s",
2719 aopGet(AOP(left),offset,FALSE));
2721 aopPut(AOP(result),"a",offset);
2728 freeAsmop(left,NULL,ic);
2729 freeAsmop(right,NULL,ic);
2730 freeAsmop(result,NULL,ic);
2733 /*-----------------------------------------------------------------*/
2734 /* genOr - code for or */
2735 /*-----------------------------------------------------------------*/
2736 static void genOr (iCode *ic, iCode *ifx)
2738 operand *left, *right, *result;
2740 unsigned long lit = 0L;
2742 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2743 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2744 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2747 emitcode("","; Type res[%d] = l[%d]&r[%d]",
2749 AOP_TYPE(left), AOP_TYPE(right));
2750 emitcode("","; Size res[%d] = l[%d]&r[%d]",
2752 AOP_SIZE(left), AOP_SIZE(right));
2755 /* if left is a literal & right is not then exchange them */
2756 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2757 AOP_NEEDSACC(left)) {
2758 operand *tmp = right ;
2763 /* if result = right then exchange them */
2764 if(sameRegs(AOP(result),AOP(right))){
2765 operand *tmp = right ;
2770 /* if right is bit then exchange them */
2771 if (AOP_TYPE(right) == AOP_CRY &&
2772 AOP_TYPE(left) != AOP_CRY){
2773 operand *tmp = right ;
2777 if(AOP_TYPE(right) == AOP_LIT)
2778 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2780 size = AOP_SIZE(result);
2782 if (AOP_TYPE(left) == AOP_CRY){
2787 if((AOP_TYPE(right) == AOP_LIT) &&
2788 (AOP_TYPE(result) == AOP_CRY) &&
2789 (AOP_TYPE(left) != AOP_CRY)){
2794 /* if left is same as result */
2795 if(sameRegs(AOP(result),AOP(left))){
2796 for(;size--; offset++) {
2797 if(AOP_TYPE(right) == AOP_LIT){
2798 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2801 MOVA(aopGet(AOP(right),offset,FALSE));
2802 emitcode("or","a,%s; 5",
2803 aopGet(AOP(left),offset,FALSE));
2804 aopPut(AOP(result),"a ; 8", offset);
2807 if (AOP_TYPE(left) == AOP_ACC)
2808 emitcode("or","a,%s ; 6",aopGet(AOP(right),offset,FALSE));
2810 MOVA(aopGet(AOP(right),offset,FALSE));
2811 emitcode("or","a,%s ; 7",
2812 aopGet(AOP(left),offset,FALSE));
2813 aopPut(AOP(result),"a ; 8", offset);
2818 // left & result in different registers
2819 if(AOP_TYPE(result) == AOP_CRY){
2821 } else for(;(size--);offset++){
2823 // result = left & right
2824 if(AOP_TYPE(right) == AOP_LIT){
2825 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2827 aopGet(AOP(left),offset,FALSE),
2832 // faster than result <- left, anl result,right
2833 // and better if result is SFR
2834 if (AOP_TYPE(left) == AOP_ACC)
2835 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
2837 MOVA(aopGet(AOP(right),offset,FALSE));
2838 emitcode("or","a,%s",
2839 aopGet(AOP(left),offset,FALSE));
2841 aopPut(AOP(result),"a",offset);
2842 /* PENDING: something weird is going on here. Add exception. */
2843 if (AOP_TYPE(result) == AOP_ACC)
2849 freeAsmop(left,NULL,ic);
2850 freeAsmop(right,NULL,ic);
2851 freeAsmop(result,NULL,ic);
2854 /*-----------------------------------------------------------------*/
2855 /* genXor - code for xclusive or */
2856 /*-----------------------------------------------------------------*/
2857 static void genXor (iCode *ic, iCode *ifx)
2859 operand *left, *right, *result;
2861 unsigned long lit = 0L;
2863 aopOp((left = IC_LEFT(ic)),ic,FALSE);
2864 aopOp((right= IC_RIGHT(ic)),ic,FALSE);
2865 aopOp((result=IC_RESULT(ic)),ic,TRUE);
2867 /* if left is a literal & right is not then exchange them */
2868 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
2869 AOP_NEEDSACC(left)) {
2870 operand *tmp = right ;
2875 /* if result = right then exchange them */
2876 if(sameRegs(AOP(result),AOP(right))){
2877 operand *tmp = right ;
2882 /* if right is bit then exchange them */
2883 if (AOP_TYPE(right) == AOP_CRY &&
2884 AOP_TYPE(left) != AOP_CRY){
2885 operand *tmp = right ;
2889 if(AOP_TYPE(right) == AOP_LIT)
2890 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
2892 size = AOP_SIZE(result);
2894 if (AOP_TYPE(left) == AOP_CRY){
2899 if((AOP_TYPE(right) == AOP_LIT) &&
2900 (AOP_TYPE(result) == AOP_CRY) &&
2901 (AOP_TYPE(left) != AOP_CRY)){
2906 /* if left is same as result */
2907 if(sameRegs(AOP(result),AOP(left))){
2908 for(;size--; offset++) {
2909 if(AOP_TYPE(right) == AOP_LIT){
2910 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
2913 MOVA(aopGet(AOP(right),offset,FALSE));
2914 emitcode("xor","a,%s",
2915 aopGet(AOP(left),offset,FALSE));
2916 aopPut(AOP(result),"a",0);
2919 if (AOP_TYPE(left) == AOP_ACC)
2920 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2922 MOVA(aopGet(AOP(right),offset,FALSE));
2923 emitcode("xor","a,%s",
2924 aopGet(AOP(left),offset,FALSE));
2925 aopPut(AOP(result),"a",0);
2930 // left & result in different registers
2931 if(AOP_TYPE(result) == AOP_CRY){
2933 } else for(;(size--);offset++){
2935 // result = left & right
2936 if(AOP_TYPE(right) == AOP_LIT){
2937 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
2939 aopGet(AOP(left),offset,FALSE),
2944 // faster than result <- left, anl result,right
2945 // and better if result is SFR
2946 if (AOP_TYPE(left) == AOP_ACC)
2947 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
2949 MOVA(aopGet(AOP(right),offset,FALSE));
2950 emitcode("xor","a,%s",
2951 aopGet(AOP(left),offset,FALSE));
2952 aopPut(AOP(result),"a",0);
2954 aopPut(AOP(result),"a",offset);
2959 freeAsmop(left,NULL,ic);
2960 freeAsmop(right,NULL,ic);
2961 freeAsmop(result,NULL,ic);
2964 /*-----------------------------------------------------------------*/
2965 /* genInline - write the inline code out */
2966 /*-----------------------------------------------------------------*/
2967 static void genInline (iCode *ic)
2969 char buffer[MAX_INLINEASM];
2973 inLine += (!options.asmpeep);
2974 strcpy(buffer,IC_INLINE(ic));
2976 /* emit each line as a code */
2995 /* emitcode("",buffer); */
2996 inLine -= (!options.asmpeep);
2999 /*-----------------------------------------------------------------*/
3000 /* genRRC - rotate right with carry */
3001 /*-----------------------------------------------------------------*/
3002 static void genRRC (iCode *ic)
3007 /*-----------------------------------------------------------------*/
3008 /* genRLC - generate code for rotate left with carry */
3009 /*-----------------------------------------------------------------*/
3010 static void genRLC (iCode *ic)
3015 /*-----------------------------------------------------------------*/
3016 /* shiftR2Left2Result - shift right two bytes from left to result */
3017 /*-----------------------------------------------------------------*/
3018 static void shiftR2Left2Result (operand *left, int offl,
3019 operand *result, int offr,
3020 int shCount, int sign)
3022 if(sameRegs(AOP(result), AOP(left)) &&
3023 ((offl + MSB16) == offr)){
3026 movLeft2Result(left, offl, result, offr, 0);
3027 movLeft2Result(left, offl+1, result, offr+1, 0);
3034 /* if (AOP(result)->type == AOP_REG) {*/
3037 symbol *tlbl , *tlbl1;
3040 /* Left is already in result - so now do the shift */
3042 emitcode("ld","a,#%u+1", shCount);
3043 tlbl = newiTempLabel(NULL);
3044 tlbl1 = newiTempLabel(NULL);
3045 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3046 emitLabel(tlbl->key+100);
3049 emitcode("or", "a,a");
3052 l = aopGet(AOP(result), --offset, FALSE);
3053 emitcode("rr","%s", l);
3056 emitLabel(tlbl1->key+100);
3057 emitcode("dec", "a");
3058 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3063 /*-----------------------------------------------------------------*/
3064 /* shiftL2Left2Result - shift left two bytes from left to result */
3065 /*-----------------------------------------------------------------*/
3066 static void shiftL2Left2Result (operand *left, int offl,
3067 operand *result, int offr, int shCount)
3069 if(sameRegs(AOP(result), AOP(left)) &&
3070 ((offl + MSB16) == offr)){
3073 /* Copy left into result */
3074 movLeft2Result(left, offl, result, offr, 0);
3075 movLeft2Result(left, offl+1, result, offr+1, 0);
3077 /* PENDING: for now just see if it'll work. */
3078 /*if (AOP(result)->type == AOP_REG) { */
3082 symbol *tlbl , *tlbl1;
3085 /* Left is already in result - so now do the shift */
3087 emitcode("ld","a,#%u+1", shCount);
3088 tlbl = newiTempLabel(NULL);
3089 tlbl1 = newiTempLabel(NULL);
3090 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3091 emitLabel(tlbl->key+100);
3094 emitcode("or", "a,a");
3096 l = aopGet(AOP(result),offset++,FALSE);
3097 emitcode("rl","%s", l);
3100 emitLabel(tlbl1->key+100);
3101 emitcode("dec", "a");
3102 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3107 /*-----------------------------------------------------------------*/
3108 /* AccRol - rotate left accumulator by known count */
3109 /*-----------------------------------------------------------------*/
3110 static void AccRol (int shCount)
3112 shCount &= 0x0007; // shCount : 0..7
3149 /*-----------------------------------------------------------------*/
3150 /* AccLsh - left shift accumulator by known count */
3151 /*-----------------------------------------------------------------*/
3152 static void AccLsh (int shCount)
3156 emitcode("add","a,a");
3159 emitcode("add","a,a");
3160 emitcode("add","a,a");
3162 /* rotate left accumulator */
3164 /* and kill the lower order bits */
3165 emitcode("and","a,#0x%02x", SLMask[shCount]);
3170 /*-----------------------------------------------------------------*/
3171 /* shiftL1Left2Result - shift left one byte from left to result */
3172 /*-----------------------------------------------------------------*/
3173 static void shiftL1Left2Result (operand *left, int offl,
3174 operand *result, int offr, int shCount)
3177 l = aopGet(AOP(left),offl,FALSE);
3179 /* shift left accumulator */
3181 aopPut(AOP(result),"a",offr);
3185 /*-----------------------------------------------------------------*/
3186 /* genlshTwo - left shift two bytes by known amount != 0 */
3187 /*-----------------------------------------------------------------*/
3188 static void genlshTwo (operand *result,operand *left, int shCount)
3190 int size = AOP_SIZE(result);
3194 /* if shCount >= 8 */
3200 movLeft2Result(left, LSB, result, MSB16, 0);
3201 aopPut(AOP(result),zero, 0);
3202 shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
3205 movLeft2Result(left, LSB, result, MSB16, 0);
3206 aopPut(AOP(result),zero, 0);
3209 aopPut(AOP(result),zero,LSB);
3211 /* 1 <= shCount <= 7 */
3217 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3222 /*-----------------------------------------------------------------*/
3223 /* genlshOne - left shift a one byte quantity by known count */
3224 /*-----------------------------------------------------------------*/
3225 static void genlshOne (operand *result, operand *left, int shCount)
3227 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3230 /*-----------------------------------------------------------------*/
3231 /* genLeftShiftLiteral - left shifting by known count */
3232 /*-----------------------------------------------------------------*/
3233 static void genLeftShiftLiteral (operand *left,
3238 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3241 freeAsmop(right,NULL,ic);
3243 aopOp(left,ic,FALSE);
3244 aopOp(result,ic,FALSE);
3246 size = getSize(operandType(result));
3249 emitcode("; shift left ","result %d, left %d",size,
3253 /* I suppose that the left size >= result size */
3258 else if(shCount >= (size * 8))
3260 aopPut(AOP(result),zero,size);
3264 genlshOne (result,left,shCount);
3267 genlshTwo (result,left,shCount);
3276 freeAsmop(left,NULL,ic);
3277 freeAsmop(result,NULL,ic);
3280 /*-----------------------------------------------------------------*/
3281 /* genLeftShift - generates code for left shifting */
3282 /*-----------------------------------------------------------------*/
3283 static void genLeftShift (iCode *ic)
3287 symbol *tlbl , *tlbl1;
3288 operand *left,*right, *result;
3290 right = IC_RIGHT(ic);
3292 result = IC_RESULT(ic);
3294 aopOp(right,ic,FALSE);
3296 /* if the shift count is known then do it
3297 as efficiently as possible */
3298 if (AOP_TYPE(right) == AOP_LIT) {
3299 genLeftShiftLiteral (left,right,result,ic);
3303 /* shift count is unknown then we have to form a loop get the loop
3304 count in B : Note: we take only the lower order byte since
3305 shifting more that 32 bits make no sense anyway, ( the largest
3306 size of an object can be only 32 bits ) */
3307 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3308 emitcode("inc","a");
3309 freeAsmop (right,NULL,ic);
3310 aopOp(left,ic,FALSE);
3311 aopOp(result,ic,FALSE);
3313 /* now move the left to the result if they are not the
3316 if (!sameRegs(AOP(left),AOP(result))) {
3318 size = AOP_SIZE(result);
3321 l = aopGet(AOP(left),offset,FALSE);
3322 aopPut(AOP(result),l,offset);
3327 size = AOP_SIZE(result);
3330 l = aopGet(AOP(left),offset,FALSE);
3331 aopPut(AOP(result),l,offset);
3337 tlbl = newiTempLabel(NULL);
3338 size = AOP_SIZE(result);
3340 tlbl1 = newiTempLabel(NULL);
3342 emitcode(_shortJP, LABEL_STR ,tlbl1->key+100);
3343 emitLabel(tlbl->key+100);
3344 l = aopGet(AOP(result),offset,FALSE);
3345 emitcode("or", "a,a");
3347 l = aopGet(AOP(result),offset++,FALSE);
3348 emitcode("rl","%s", l);
3350 emitLabel(tlbl1->key+100);
3351 emitcode("dec", "a");
3352 emitcode(_shortJP,"nz," LABEL_STR ,tlbl->key+100);
3354 freeAsmop(left,NULL,ic);
3355 freeAsmop(result,NULL,ic);
3358 /* genlshTwo - left shift two bytes by known amount != 0 */
3359 /*-----------------------------------------------------------------*/
3360 static void genrshOne (operand *result,operand *left, int shCount)
3363 int size = AOP_SIZE(result);
3369 l = aopGet(AOP(left),0,FALSE);
3370 if (AOP(result)->type == AOP_REG) {
3371 aopPut(AOP(result), l, 0);
3372 l = aopGet(AOP(result), 0, FALSE);
3374 emitcode("srl", "%s", l);
3379 emitcode("srl", "a");
3381 aopPut(AOP(result),"a",0);
3385 /*-----------------------------------------------------------------*/
3386 /* AccRsh - right shift accumulator by known count */
3387 /*-----------------------------------------------------------------*/
3388 static void AccRsh (int shCount)
3395 /* rotate right accumulator */
3396 AccRol(8 - shCount);
3397 /* and kill the higher order bits */
3398 emitcode("and","a,#0x%02x", SRMask[shCount]);
3403 /*-----------------------------------------------------------------*/
3404 /* shiftR1Left2Result - shift right one byte from left to result */
3405 /*-----------------------------------------------------------------*/
3406 static void shiftR1Left2Result (operand *left, int offl,
3407 operand *result, int offr,
3408 int shCount, int sign)
3410 MOVA(aopGet(AOP(left),offl,FALSE));
3417 aopPut(AOP(result),"a",offr);
3420 /*-----------------------------------------------------------------*/
3421 /* genrshTwo - right shift two bytes by known amount != 0 */
3422 /*-----------------------------------------------------------------*/
3423 static void genrshTwo (operand *result,operand *left,
3424 int shCount, int sign)
3426 /* if shCount >= 8 */
3431 shiftR1Left2Result(left, MSB16, result, LSB,
3435 movLeft2Result(left, MSB16, result, LSB, sign);
3436 aopPut(AOP(result),zero,1);
3439 /* 1 <= shCount <= 7 */
3441 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3445 /*-----------------------------------------------------------------*/
3446 /* genRightShiftLiteral - left shifting by known count */
3447 /*-----------------------------------------------------------------*/
3448 static void genRightShiftLiteral (operand *left,
3453 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3456 freeAsmop(right,NULL,ic);
3458 aopOp(left,ic,FALSE);
3459 aopOp(result,ic,FALSE);
3461 size = getSize(operandType(result));
3463 emitcode("; shift right ","result %d, left %d",size,
3466 /* I suppose that the left size >= result size */
3471 else if(shCount >= (size * 8))
3473 aopPut(AOP(result),zero,size);
3477 genrshOne(result, left, shCount);
3480 /* PENDING: sign support */
3481 genrshTwo(result, left, shCount, FALSE);
3490 freeAsmop(left,NULL,ic);
3491 freeAsmop(result,NULL,ic);
3494 /*-----------------------------------------------------------------*/
3495 /* genRightShift - generate code for right shifting */
3496 /*-----------------------------------------------------------------*/
3497 static void genRightShift (iCode *ic)
3499 operand *left,*right, *result;
3501 right = IC_RIGHT(ic);
3503 result = IC_RESULT(ic);
3505 aopOp(right,ic,FALSE);
3507 /* if the shift count is known then do it
3508 as efficiently as possible */
3509 if (AOP_TYPE(right) == AOP_LIT) {
3510 genRightShiftLiteral (left,right,result,ic);
3518 /*-----------------------------------------------------------------*/
3519 /* genGenPointerGet - gget value from generic pointer space */
3520 /*-----------------------------------------------------------------*/
3521 static void genGenPointerGet (operand *left,
3522 operand *result, iCode *ic)
3525 link *retype = getSpec(operandType(result));
3531 aopOp(left,ic,FALSE);
3532 aopOp(result,ic,FALSE);
3534 if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
3536 emitcode("ld", "a,(%s)", getPairName(AOP(left)));
3537 aopPut(AOP(result),"a", 0);
3538 freeAsmop(left,NULL,ic);
3542 /* For now we always load into IY */
3543 /* if this is remateriazable */
3544 fetchPair(pair, AOP(left));
3546 /* so iy now contains the address */
3547 freeAsmop(left,NULL,ic);
3549 /* if bit then unpack */
3550 if (IS_BITVAR(retype)) {
3554 size = AOP_SIZE(result);
3558 /* PENDING: make this better */
3559 if (!IS_GB && AOP(result)->type == AOP_REG) {
3560 aopPut(AOP(result),"(hl)",offset++);
3563 emitcode("ld", "a,(%s)", _pairs[pair].name, offset);
3564 aopPut(AOP(result),"a",offset++);
3567 emitcode("inc", "%s", _pairs[pair].name);
3573 freeAsmop(result,NULL,ic);
3576 /*-----------------------------------------------------------------*/
3577 /* genPointerGet - generate code for pointer get */
3578 /*-----------------------------------------------------------------*/
3579 static void genPointerGet (iCode *ic)
3581 operand *left, *result ;
3585 result = IC_RESULT(ic) ;
3587 /* depending on the type of pointer we need to
3588 move it to the correct pointer register */
3589 type = operandType(left);
3590 etype = getSpec(type);
3592 genGenPointerGet (left,result,ic);
3595 bool isRegOrLit(asmop *aop)
3597 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
3602 /*-----------------------------------------------------------------*/
3603 /* genGenPointerSet - stores the value into a pointer location */
3604 /*-----------------------------------------------------------------*/
3605 static void genGenPointerSet (operand *right,
3606 operand *result, iCode *ic)
3609 link *retype = getSpec(operandType(right));
3610 int pairId = PAIR_HL;
3612 aopOp(result,ic,FALSE);
3613 aopOp(right,ic,FALSE);
3618 /* Handle the exceptions first */
3619 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
3621 char *l = aopGet(AOP(right), 0, FALSE);
3622 const char *pair = getPairName(AOP(result));
3623 if (canAssignToPtr(l) && isPtr(pair)) {
3624 emitcode("ld", "(%s),%s", pair, l);
3628 emitcode("ld", "(%s),a ; 1", pair);
3633 /* if the operand is already in dptr
3634 then we do nothing else we move the value to dptr */
3635 if (AOP_TYPE(result) != AOP_STR) {
3636 fetchPair(pairId, AOP(result));
3638 /* so hl know contains the address */
3639 freeAsmop(result,NULL,ic);
3641 /* if bit then unpack */
3642 if (IS_BITVAR(retype)) {
3646 size = AOP_SIZE(right);
3650 char *l = aopGet(AOP(right),offset,FALSE);
3651 if (isRegOrLit(AOP(right)) && !IS_GB) {
3652 emitcode("ld", "(%s),%s ; 2", _pairs[pairId].name, l);
3656 emitcode("ld", "(%s),a ; 3", _pairs[pairId].name, offset);
3659 emitcode("inc", _pairs[pairId].name);
3665 freeAsmop(right,NULL,ic);
3668 /*-----------------------------------------------------------------*/
3669 /* genPointerSet - stores the value into a pointer location */
3670 /*-----------------------------------------------------------------*/
3671 static void genPointerSet (iCode *ic)
3673 operand *right, *result ;
3676 right = IC_RIGHT(ic);
3677 result = IC_RESULT(ic) ;
3679 /* depending on the type of pointer we need to
3680 move it to the correct pointer register */
3681 type = operandType(result);
3682 etype = getSpec(type);
3684 genGenPointerSet (right,result,ic);
3687 /*-----------------------------------------------------------------*/
3688 /* genIfx - generate code for Ifx statement */
3689 /*-----------------------------------------------------------------*/
3690 static void genIfx (iCode *ic, iCode *popIc)
3692 operand *cond = IC_COND(ic);
3695 aopOp(cond,ic,FALSE);
3697 /* get the value into acc */
3698 if (AOP_TYPE(cond) != AOP_CRY)
3702 /* the result is now in the accumulator */
3703 freeAsmop(cond,NULL,ic);
3705 /* if there was something to be popped then do it */
3709 /* if the condition is a bit variable */
3710 if (isbit && IS_ITEMP(cond) &&
3712 genIfxJump(ic,SPIL_LOC(cond)->rname);
3714 if (isbit && !IS_ITEMP(cond))
3715 genIfxJump(ic,OP_SYMBOL(cond)->rname);
3722 /*-----------------------------------------------------------------*/
3723 /* genAddrOf - generates code for address of */
3724 /*-----------------------------------------------------------------*/
3725 static void genAddrOf (iCode *ic)
3727 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
3729 aopOp(IC_RESULT(ic),ic,FALSE);
3731 /* if the operand is on the stack then we
3732 need to get the stack offset of this
3737 emitcode("lda", "hl,%d+%d+%d(sp)", sym->stack, _pushed, _spoffset);
3738 emitcode("ld", "d,h");
3739 emitcode("ld", "e,l");
3742 emitcode("ld", "de,#%s", sym->rname);
3744 aopPut(AOP(IC_RESULT(ic)), "e", 0);
3745 aopPut(AOP(IC_RESULT(ic)), "d", 1);
3750 /* if it has an offset then we need to compute it */
3751 emitcode("push", "de");
3752 emitcode("push", "ix");
3753 emitcode("pop", "hl");
3754 emitcode("ld", "de,#%d", sym->stack);
3755 emitcode("add", "hl,de");
3756 emitcode("pop", "de");
3759 emitcode("ld", "hl,#%s", sym->rname);
3761 aopPut(AOP(IC_RESULT(ic)), "l", 0);
3762 aopPut(AOP(IC_RESULT(ic)), "h", 1);
3764 freeAsmop(IC_RESULT(ic),NULL,ic);
3767 /*-----------------------------------------------------------------*/
3768 /* genAssign - generate code for assignment */
3769 /*-----------------------------------------------------------------*/
3770 static void genAssign (iCode *ic)
3772 operand *result, *right;
3774 unsigned long lit = 0L;
3776 result = IC_RESULT(ic);
3777 right = IC_RIGHT(ic) ;
3780 /* Dont bother assigning if they are the same */
3781 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
3782 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
3787 aopOp(right,ic,FALSE);
3788 aopOp(result,ic,TRUE);
3790 /* if they are the same registers */
3791 if (sameRegs(AOP(right),AOP(result))) {
3792 emitcode("", "; (registers are the same)");
3796 /* if the result is a bit */
3797 if (AOP_TYPE(result) == AOP_CRY) {
3802 size = AOP_SIZE(result);
3805 if(AOP_TYPE(right) == AOP_LIT)
3806 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
3807 if (isPair(AOP(result)) && AOP_TYPE(right) == AOP_LIT) {
3808 emitcode("ld", "%s,%s", getPairName(AOP(result)), aopGetWord(AOP(right), 0));
3810 else if((size > 1) &&
3811 (AOP_TYPE(result) != AOP_REG) &&
3812 (AOP_TYPE(right) == AOP_LIT) &&
3813 !IS_FLOAT(operandType(right)) &&
3815 bool fXored = FALSE;
3817 /* Work from the top down.
3818 Done this way so that we can use the cached copy of 0
3819 in A for a fast clear */
3821 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
3822 if (!fXored && size>1) {
3823 emitcode("xor", "a,a");
3827 aopPut(AOP(result),"a",offset);
3830 aopPut(AOP(result), "#0", offset);
3835 aopGet(AOP(right),offset,FALSE),
3840 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result))) {
3841 /* Special case. Load into a and d, then load out. */
3842 MOVA(aopGet(AOP(right), 0, FALSE));
3843 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
3844 aopPut(AOP(result), "a", 0);
3845 aopPut(AOP(result), "e", 1);
3849 aopGet(AOP(right),offset,FALSE),
3856 freeAsmop(right,NULL,ic);
3857 freeAsmop(result,NULL,ic);
3860 /*-----------------------------------------------------------------*/
3861 /* genJumpTab - genrates code for jump table */
3862 /*-----------------------------------------------------------------*/
3863 static void genJumpTab (iCode *ic)
3868 aopOp(IC_JTCOND(ic),ic,FALSE);
3869 /* get the condition into accumulator */
3870 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
3873 emitcode("push", "de");
3874 emitcode("ld", "e,%s", l);
3875 emitcode("ld", "d,#0");
3876 jtab = newiTempLabel(NULL);
3878 emitcode("ld", "hl,#" LABEL_STR, jtab->key+100);
3879 emitcode("add", "hl,de");
3880 emitcode("add", "hl,de");
3881 emitcode("add", "hl,de");
3882 freeAsmop(IC_JTCOND(ic),NULL,ic);
3884 emitcode("pop", "de");
3885 emitcode("jp", "(hl)");
3886 emitLabel(jtab->key+100);
3887 /* now generate the jump labels */
3888 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
3889 jtab = setNextItem(IC_JTLABELS(ic)))
3890 emitcode("jp", LABEL_STR, jtab->key+100);
3893 /*-----------------------------------------------------------------*/
3894 /* genCast - gen code for casting */
3895 /*-----------------------------------------------------------------*/
3896 static void genCast (iCode *ic)
3898 operand *result = IC_RESULT(ic);
3899 link *ctype = operandType(IC_LEFT(ic));
3900 operand *right = IC_RIGHT(ic);
3903 /* if they are equivalent then do nothing */
3904 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
3907 aopOp(right,ic,FALSE) ;
3908 aopOp(result,ic,FALSE);
3910 /* if the result is a bit */
3911 if (AOP_TYPE(result) == AOP_CRY) {
3915 /* if they are the same size : or less */
3916 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
3918 /* if they are in the same place */
3919 if (sameRegs(AOP(right),AOP(result)))
3922 /* if they in different places then copy */
3923 size = AOP_SIZE(result);
3927 aopGet(AOP(right),offset,FALSE),
3934 /* PENDING: should be OK. */
3936 /* if the result is of type pointer */
3937 if (IS_PTR(ctype)) {
3942 /* so we now know that the size of destination is greater
3943 than the size of the source */
3944 /* we move to result for the size of source */
3945 size = AOP_SIZE(right);
3949 aopGet(AOP(right),offset,FALSE),
3954 /* now depending on the sign of the destination */
3955 size = AOP_SIZE(result) - AOP_SIZE(right);
3956 /* Unsigned or not an integral type - right fill with zeros */
3957 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
3959 aopPut(AOP(result),zero,offset++);
3961 /* we need to extend the sign :{ */
3962 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
3965 emitcode("", "; genCast: sign extend untested.");
3966 emitcode("rla", "");
3967 emitcode("sbc", "a,a");
3969 aopPut(AOP(result),"a",offset++);
3973 freeAsmop(right, NULL, ic);
3974 freeAsmop(result, NULL, ic);
3977 /*-----------------------------------------------------------------*/
3978 /* genReceive - generate code for a receive iCode */
3979 /*-----------------------------------------------------------------*/
3980 static void genReceive (iCode *ic)
3982 if (isOperandInFarSpace(IC_RESULT(ic)) &&
3983 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
3984 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
3988 aopOp(IC_RESULT(ic),ic,FALSE);
3990 assignResultValue(IC_RESULT(ic));
3993 freeAsmop(IC_RESULT(ic),NULL,ic);
3996 /*-----------------------------------------------------------------*/
3997 /* genZ80Code - generate code for Z80 based controllers */
3998 /*-----------------------------------------------------------------*/
3999 void genZ80Code (iCode *lic)
4006 _fReturn = _gbz80_return;
4007 _fTmp = _gbz80_return;
4011 _fReturn = _z80_return;
4012 _fTmp = _z80_return;
4016 lineHead = lineCurr = NULL;
4018 /* if debug information required */
4019 if (options.debug && currFunc) {
4020 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4022 if (IS_STATIC(currFunc->etype))
4023 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4025 emitcode("","G$%s$0$0 ==.",currFunc->name);
4028 /* stack pointer name */
4032 for (ic = lic ; ic ; ic = ic->next ) {
4034 if ( cln != ic->lineno ) {
4035 if ( options.debug ) {
4037 emitcode("","C$%s$%d$%d$%d ==.",
4038 ic->filename,ic->lineno,
4039 ic->level,ic->block);
4042 emitcode(";","%s %d",ic->filename,ic->lineno);
4045 /* if the result is marked as
4046 spilt and rematerializable or code for
4047 this has already been generated then
4049 if (resultRemat(ic) || ic->generated )
4052 /* depending on the operation */
4055 emitcode("", "; genNot");
4060 emitcode("", "; genCpl");
4065 emitcode("", "; genUminus");
4070 emitcode("", "; genIpush");
4075 /* IPOP happens only when trying to restore a
4076 spilt live range, if there is an ifx statement
4077 following this pop then the if statement might
4078 be using some of the registers being popped which
4079 would destory the contents of the register so
4080 we need to check for this condition and handle it */
4082 ic->next->op == IFX &&
4083 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4084 emitcode("", "; genIfx");
4085 genIfx (ic->next,ic);
4088 emitcode("", "; genIpop");
4094 emitcode("", "; genCall");
4099 emitcode("", "; genPcall");
4104 emitcode("", "; genFunction");
4109 emitcode("", "; genEndFunction");
4110 genEndFunction (ic);
4114 emitcode("", "; genRet");
4119 emitcode("", "; genLabel");
4124 emitcode("", "; genGoto");
4129 emitcode("", "; genPlus");
4134 emitcode("", "; genMinus");
4139 emitcode("", "; genMult");
4144 emitcode("", "; genDiv");
4149 emitcode("", "; genMod");
4154 emitcode("", "; genCmpGt");
4155 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4159 emitcode("", "; genCmpLt");
4160 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4167 /* note these two are xlated by algebraic equivalence
4168 during parsing SDCC.y */
4169 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4170 "got '>=' or '<=' shouldn't have come here");
4174 emitcode("", "; genCmpEq");
4175 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4179 emitcode("", "; genAndOp");
4184 emitcode("", "; genOrOp");
4189 emitcode("", "; genXor");
4190 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4194 emitcode("", "; genOr");
4195 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4199 emitcode("", "; genAnd");
4200 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4204 emitcode("", "; genInline");
4209 emitcode("", "; genRRC");
4214 emitcode("", "; genRLC");
4219 emitcode("", "; genHBIT");
4223 emitcode("", "; genLeftShift");
4228 emitcode("", "; genRightShift");
4232 case GET_VALUE_AT_ADDRESS:
4233 emitcode("", "; genPointerGet");
4239 if (POINTER_SET(ic)) {
4240 emitcode("", "; genAssign (pointer)");
4244 emitcode("", "; genAssign");
4250 emitcode("", "; genIfx");
4255 emitcode("", "; genAddrOf");
4260 emitcode("", "; genJumpTab");
4265 emitcode("", "; genCast");
4270 emitcode("", "; genReceive");
4275 emitcode("", "; addSet");
4276 addSet(&sendSet,ic);
4281 /* piCode(ic,stdout); */
4287 /* now we are ready to call the
4288 peep hole optimizer */
4289 if (!options.nopeep)
4290 peepHole (&lineHead);
4292 /* now do the actual printing */
4293 printLine (lineHead,codeOutFile);