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 -
23 Sandeep Dutta . sandeep.dutta@usa.net (1998)
24 and - Jean-Louis VERN.jlvern@writeme.com (1999)
26 This program is free software; you can redistribute it and/or modify it
27 under the terms of the GNU General Public License as published by the
28 Free Software Foundation; either version 2, or (at your option) any
31 This program is distributed in the hope that it will be useful,
32 but WITHOUT ANY WARRANTY; without even the implied warranty of
33 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
34 GNU General Public License for more details.
37 You should have received a copy of the GNU General Public License
38 along with this program; if not, write to the Free Software
39 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
41 In other words, you are welcome to use, share and improve this program.
42 You are forbidden to forbid anyone else to use, share and improve
43 what you give them. Help stamp out software-hoarding!
45 -------------------------------------------------------------------------*/
52 #ifdef HAVE_SYS_ISA_DEFS_H
53 #include <sys/isa_defs.h>
57 #include "SDCCpeeph.h"
61 /* this is the down and dirty file with all kinds of kludgy & hacky
62 stuff. This is what it is all about CODE GENERATION for a specific MCU.
63 Some of the routines may be reusable, will have to see */
66 static char *_z80_return[] = {"l", "h", "e", "d" };
67 static char *_gbz80_return[] = { "e", "d", "l", "h" };
68 static char **_fReturn;
74 static char *accUse[] = {"a" };
75 static char *hlUse[] = { "l", "h" };
81 extern int ptrRegReq ;
83 extern FILE *codeOutFile;
100 } _pairs[NUM_PAIRS] = {
105 { "iy", "iy.l?", "iy.h?" },
106 { "ix", "ix.l?", "ix.h?" }
109 #define RESULTONSTACK(x) \
110 (IC_RESULT(x) && IC_RESULT(x)->aop && \
111 IC_RESULT(x)->aop->type == AOP_STK )
113 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
114 #define CLRC emitcode("xor","a,a");
116 lineNode *lineHead = NULL;
117 lineNode *lineCurr = NULL;
119 static const unsigned char SLMask[] =
120 {0xFF ,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
121 static const unsigned char SRMask[] =
122 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
155 static char *aopGet(asmop *aop, int offset, bool bit16);
157 static void _tidyUp(char *buf)
159 /* Clean up the line so that it is 'prettier' */
160 if (strchr(buf, ':')) {
161 /* Is a label - cant do anything */
164 /* Change the first (and probably only) ' ' to a tab so
176 static void emit2(const char *szFormat, ...)
181 va_start(ap, szFormat);
183 tvsprintf(buffer, szFormat, ap);
186 lineCurr = (lineCurr ?
187 connectLine(lineCurr,newLineNode(buffer)) :
188 (lineHead = newLineNode(buffer)));
190 lineCurr->isInline = inLine;
191 lineCurr->isDebug = debugLine;
194 /*-----------------------------------------------------------------*/
195 /* emitcode - writes the code into a file : for now it is simple */
196 /*-----------------------------------------------------------------*/
197 void emitcode (const char *inst, const char *fmt, ...)
200 char lb[MAX_INLINEASM];
206 sprintf(lb,"%s\t",inst);
207 vsprintf(lb+(strlen(lb)),fmt,ap);
211 while (isspace(*lbp)) lbp++;
214 lineCurr = (lineCurr ?
215 connectLine(lineCurr,newLineNode(lb)) :
216 (lineHead = newLineNode(lb)));
217 lineCurr->isInline = inLine;
218 lineCurr->isDebug = debugLine;
235 emitcode("ld", "sp,ix");
236 emitcode("pop", "ix");
237 emitcode("pop", "de");
242 const char *getPairName(asmop *aop)
244 if (aop->type == AOP_REG) {
245 switch (aop->aopu.aop_reg[0]->rIdx) {
257 else if (aop->type == AOP_STR) {
258 switch (*aop->aopu.aop_str[0]) {
274 static PAIR_ID getPairId(asmop *aop)
276 if (aop->size == 2) {
277 if (aop->type == AOP_REG) {
278 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
281 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
284 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
288 if (aop->type == AOP_STR) {
289 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
292 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
295 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
303 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
304 bool isPair(asmop *aop)
306 return (getPairId(aop) != PAIR_INVALID);
309 bool isPtrPair(asmop *aop)
311 PAIR_ID pairId = getPairId(aop);
321 /** Push a register pair onto the stack */
322 void genPairPush(asmop *aop)
324 emitcode("push", "%s", getPairName(aop));
328 /*-----------------------------------------------------------------*/
329 /* newAsmop - creates a new asmOp */
330 /*-----------------------------------------------------------------*/
331 static asmop *newAsmop (short type)
335 ALLOC(aop,sizeof(asmop));
340 /*-----------------------------------------------------------------*/
341 /* aopForSym - for a true symbol */
342 /*-----------------------------------------------------------------*/
343 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool requires_a)
352 space = SPEC_OCLS(sym->etype);
354 /* if already has one */
358 /* Assign depending on the storage class */
359 if (sym->onStack || sym->iaccess) {
360 emitcode("", "; AOP_STK for %s", sym->rname);
361 sym->aop = aop = newAsmop(AOP_STK);
362 aop->size = getSize(sym->type);
363 aop->aopu.aop_stk = sym->stack;
367 /* special case for a function */
368 if (IS_FUNC(sym->type)) {
369 sym->aop = aop = newAsmop(AOP_IMMD);
370 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
371 strcpy(aop->aopu.aop_immd,sym->rname);
377 /* if it is in direct space */
378 if (IN_REGSP(space) && !requires_a) {
379 sym->aop = aop = newAsmop (AOP_SFR);
380 aop->aopu.aop_dir = sym->rname ;
381 aop->size = getSize(sym->type);
382 emitcode("", "; AOP_SFR for %s", sym->rname);
387 /* only remaining is far space */
388 /* in which case DPTR gets the address */
390 emitcode("", "; AOP_HL for %s", sym->rname);
391 sym->aop = aop = newAsmop(AOP_HL);
394 sym->aop = aop = newAsmop(AOP_IY);
396 aop->size = getSize(sym->type);
397 aop->aopu.aop_dir = sym->rname;
399 /* if it is in code space */
400 if (IN_CODESPACE(space))
406 /*-----------------------------------------------------------------*/
407 /* aopForRemat - rematerialzes an object */
408 /*-----------------------------------------------------------------*/
409 static asmop *aopForRemat (symbol *sym)
412 iCode *ic = sym->rematiCode;
413 asmop *aop = newAsmop(AOP_IMMD);
416 /* if plus or minus print the right hand side */
417 if (ic->op == '+' || ic->op == '-') {
418 /* PENDING: for re-target */
419 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
422 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
425 /* we reached the end */
426 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
430 ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
431 strcpy(aop->aopu.aop_immd,buffer);
435 /*-----------------------------------------------------------------*/
436 /* regsInCommon - two operands have some registers in common */
437 /*-----------------------------------------------------------------*/
438 bool regsInCommon (operand *op1, operand *op2)
443 /* if they have registers in common */
444 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
447 sym1 = OP_SYMBOL(op1);
448 sym2 = OP_SYMBOL(op2);
450 if (sym1->nRegs == 0 || sym2->nRegs == 0)
453 for (i = 0 ; i < sym1->nRegs ; i++) {
458 for (j = 0 ; j < sym2->nRegs ;j++ ) {
462 if (sym2->regs[j] == sym1->regs[i])
470 /*-----------------------------------------------------------------*/
471 /* operandsEqu - equivalent */
472 /*-----------------------------------------------------------------*/
473 bool operandsEqu ( operand *op1, operand *op2)
477 /* if they not symbols */
478 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
481 sym1 = OP_SYMBOL(op1);
482 sym2 = OP_SYMBOL(op2);
484 /* if both are itemps & one is spilt
485 and the other is not then false */
486 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
487 sym1->isspilt != sym2->isspilt )
490 /* if they are the same */
494 if (strcmp(sym1->rname,sym2->rname) == 0)
498 /* if left is a tmp & right is not */
502 (sym1->usl.spillLoc == sym2))
509 (sym2->usl.spillLoc == sym1))
515 /*-----------------------------------------------------------------*/
516 /* sameRegs - two asmops have the same registers */
517 /*-----------------------------------------------------------------*/
518 bool sameRegs (asmop *aop1, asmop *aop2 )
522 if (aop1->type == AOP_SFR ||
523 aop2->type == AOP_SFR)
529 if (aop1->type != AOP_REG ||
530 aop2->type != AOP_REG )
533 if (aop1->size != aop2->size)
536 for (i = 0 ; i < aop1->size ; i++ )
537 if (aop1->aopu.aop_reg[i] !=
538 aop2->aopu.aop_reg[i] )
544 /*-----------------------------------------------------------------*/
545 /* aopOp - allocates an asmop for an operand : */
546 /*-----------------------------------------------------------------*/
547 static void aopOp (operand *op, iCode *ic, bool result, bool requires_a)
556 /* if this a literal */
557 if (IS_OP_LITERAL(op)) {
558 op->aop = aop = newAsmop(AOP_LIT);
559 aop->aopu.aop_lit = op->operand.valOperand;
560 aop->size = getSize(operandType(op));
564 /* if already has a asmop then continue */
568 /* if the underlying symbol has a aop */
569 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
570 op->aop = OP_SYMBOL(op)->aop;
574 /* if this is a true symbol */
575 if (IS_TRUE_SYMOP(op)) {
576 op->aop = aopForSym(ic, OP_SYMBOL(op), result, requires_a);
580 /* this is a temporary : this has
586 e) can be a return use only */
590 /* if the type is a conditional */
591 if (sym->regType == REG_CND) {
592 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
597 /* if it is spilt then two situations
599 b) has a spill location */
600 if (sym->isspilt || sym->nRegs == 0) {
601 /* rematerialize it NOW */
603 sym->aop = op->aop = aop =
605 aop->size = getSize(sym->type);
611 if (sym->accuse == ACCUSE_A) {
612 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
613 aop->size = getSize(sym->type);
614 for ( i = 0 ; i < 2 ; i++ )
615 aop->aopu.aop_str[i] = accUse[i];
617 else if (sym->accuse == ACCUSE_HL) {
619 aop = op->aop = sym->aop = newAsmop(AOP_HLREG);
620 aop->size = getSize(sym->type);
621 for ( i = 0 ; i < 2 ; i++ )
622 aop->aopu.aop_str[i] = hlUse[i];
631 aop = op->aop = sym->aop = newAsmop(AOP_STR);
632 aop->size = getSize(sym->type);
633 for ( i = 0 ; i < 4 ; i++ )
634 aop->aopu.aop_str[i] = _fReturn[i];
638 /* else spill location */
639 sym->aop = op->aop = aop =
640 aopForSym(ic,sym->usl.spillLoc,result, requires_a);
641 aop->size = getSize(sym->type);
645 /* must be in a register */
646 sym->aop = op->aop = aop = newAsmop(AOP_REG);
647 aop->size = sym->nRegs;
648 for ( i = 0 ; i < sym->nRegs ;i++)
649 aop->aopu.aop_reg[i] = sym->regs[i];
652 /*-----------------------------------------------------------------*/
653 /* freeAsmop - free up the asmop given to an operand */
654 /*----------------------------------------------------------------*/
655 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
673 /* all other cases just dealloc */
677 OP_SYMBOL(op)->aop = NULL;
678 /* if the symbol has a spill */
680 SPIL_LOC(op)->aop = NULL;
685 bool isLitWord(asmop *aop)
687 /* if (aop->size != 2)
698 char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
704 if (aop->size != 2 && aop->type != AOP_HL)
707 /* depending on type */
712 /* PENDING: for re-target */
714 tsprintf(s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
716 tsprintf(s, "%s + %d", aop->aopu.aop_immd, offset);
717 ALLOC_ATOMIC(rs,strlen(s)+1);
721 value * val = aop->aopu.aop_lit;
722 /* if it is a float then it gets tricky */
723 /* otherwise it is fairly simple */
724 if (!IS_FLOAT(val->type)) {
725 unsigned long v = floatFromVal(val);
731 tsprintf(buffer, "!immedword", v);
733 tsprintf(buffer, "!constword", v);
734 ALLOC_ATOMIC(rs,strlen(buffer)+1);
735 return strcpy (rs,buffer);
740 convertFloat(&f, floatFromVal(val));
742 tsprintf(buffer, "!immedword", f.w[offset/2]);
744 tsprintf(buffer, "!constword", f.w[offset/2]);
745 ALLOC_ATOMIC(rs,strlen(buffer)+1);
746 return strcpy (rs,buffer);
754 char *aopGetWord(asmop *aop, int offset)
756 return aopGetLitWordLong(aop, offset, TRUE);
759 bool isPtr(const char *s)
761 if (!strcmp(s, "hl"))
763 if (!strcmp(s, "ix"))
765 if (!strcmp(s, "iy"))
770 static void adjustPair(const char *pair, int *pold, int new)
774 while (*pold < new) {
775 emitcode("inc", "%s", pair);
778 while (*pold > new) {
779 emitcode("dec", "%s", pair);
784 static void spillPair(PAIR_ID pairId)
786 _G.pairs[pairId].last_type = AOP_INVALID;
787 _G.pairs[pairId].lit = NULL;
790 static void spillCached(void)
796 static bool requiresHL(asmop *aop)
807 static char *fetchLitSpecial(asmop *aop, bool negate, bool xor)
810 value * val = aop->aopu.aop_lit;
812 wassert(aop->type == AOP_LIT);
813 wassert(!IS_FLOAT(val->type));
815 v = floatFromVal(val);
823 tsprintf(buffer, "!immedword", v);
824 return gc_strdup(buffer);
827 static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
830 const char *pair = _pairs[pairId].name;
831 l = aopGetLitWordLong(left, 0, FALSE);
835 if (pairId == PAIR_HL || pairId == PAIR_IY) {
836 if (_G.pairs[pairId].last_type == left->type) {
837 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
838 if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
839 adjustPair(pair, &_G.pairs[pairId].offset, offset);
842 if (pairId == PAIR_IY && abs(offset)<127) {
848 _G.pairs[pairId].last_type = left->type;
849 _G.pairs[pairId].lit = gc_strdup(l);
850 _G.pairs[pairId].offset = offset;
852 if (IS_GB && pairId == PAIR_DE && 0) {
853 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
854 if (abs(_G.pairs[pairId].offset - offset) < 3) {
855 adjustPair(pair, &_G.pairs[pairId].offset, offset);
859 _G.pairs[pairId].last_type = left->type;
860 _G.pairs[pairId].lit = gc_strdup(l);
861 _G.pairs[pairId].offset = offset;
863 /* Both a lit on the right and a true symbol on the left */
865 emit2("ld %s,!hashedstr + %u", pair, l, offset);
867 emit2("ld %s,!hashedstr", pair, l);
870 static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
872 /* if this is remateriazable */
873 if (isLitWord(aop)) {
874 fetchLitPair(pairId, aop, offset);
876 else { /* we need to get it byte by byte */
877 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
878 aopGet(aop, offset, FALSE);
882 emit2("ld h,!immedbyte", 0);
890 emit2("; WARNING: mlh woosed out. This code is invalid.");
893 else if (IS_Z80 && aop->type == AOP_IY) {
894 /* Instead of fetching relative to IY, just grab directly
895 from the address IY refers to */
896 char *l = aopGetLitWordLong(aop, offset, FALSE);
898 emit2("ld %s,(%s)", _pairs[pairId].name, l);
901 emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE));
902 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, offset+1, FALSE));
904 /* PENDING: check? */
905 if (pairId == PAIR_HL)
910 static void fetchPair(PAIR_ID pairId, asmop *aop)
912 fetchPairLong(pairId, aop, 0);
915 static void fetchHL(asmop *aop)
917 fetchPair(PAIR_HL, aop);
920 static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
922 assert(pairId == PAIR_HL || pairId == PAIR_IY);
926 fetchLitPair(pairId, aop, 0);
929 fetchLitPair(pairId, aop, offset);
930 _G.pairs[pairId].offset = offset;
933 /* Doesnt include _G.stack.pushed */
934 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
935 if (aop->aopu.aop_stk > 0) {
936 abso += _G.stack.param_offset;
938 assert(pairId == PAIR_HL);
939 /* In some cases we can still inc or dec hl */
940 if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
941 adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
944 emit2("!ldahlsp", abso +_G.stack.pushed);
946 _G.pairs[pairId].offset = abso;
952 _G.pairs[pairId].last_type = aop->type;
955 static void emitLabel(int key)
957 emit2("!tlabeldef", key);
961 /*-----------------------------------------------------------------*/
962 /* aopGet - for fetching value of the aop */
963 /*-----------------------------------------------------------------*/
964 static char *aopGet(asmop *aop, int offset, bool bit16)
969 /* offset is greater than size then zero */
970 /* PENDING: this seems a bit screwed in some pointer cases. */
971 if (offset > (aop->size - 1) &&
972 aop->type != AOP_LIT)
975 /* depending on type */
978 /* PENDING: re-target */
980 tsprintf (s,"!immedwords", aop->aopu.aop_immd);
984 tsprintf(s, "!bankimmeds", aop->aopu.aop_immd);
987 tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
990 tsprintf(s, "!lsbimmeds", aop->aopu.aop_immd);
995 ALLOC_ATOMIC(rs,strlen(s)+1);
1001 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1003 ALLOC_ATOMIC(rs,strlen(s)+1);
1009 emitcode("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1011 ALLOC_ATOMIC(rs,strlen(s)+1);
1016 return aop->aopu.aop_reg[offset]->name;
1020 setupPair(PAIR_HL, aop, offset);
1021 tsprintf(s, "!*hl");
1022 return gc_strdup(s);
1026 setupPair(PAIR_IY, aop, offset);
1027 tsprintf(s,"!*iyx", offset);
1028 ALLOC_ATOMIC(rs,strlen(s)+1);
1034 setupPair(PAIR_HL, aop, offset);
1035 tsprintf(s, "!*hl");
1038 tsprintf(s,"!*ixx", aop->aopu.aop_stk+offset);
1040 ALLOC_ATOMIC(rs,strlen(s)+1);
1054 wassert(offset < 2);
1055 return aop->aopu.aop_str[offset];
1058 return aopLiteral (aop->aopu.aop_lit,offset);
1062 return aop->aopu.aop_str[offset];
1066 wassertl(0, "aopget got unsupported aop->type");
1070 bool isRegString(const char *s)
1072 if (!strcmp(s, "b") ||
1083 bool isConstant(const char *s)
1085 /* This is a bit of a hack... */
1086 return (*s == '#' || *s == '$');
1089 bool canAssignToPtr(const char *s)
1098 /*-----------------------------------------------------------------*/
1099 /* aopPut - puts a string for a aop */
1100 /*-----------------------------------------------------------------*/
1101 static void aopPut (asmop *aop, const char *s, int offset)
1103 if (aop->size && offset > ( aop->size - 1)) {
1104 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1105 "aopPut got offset > aop->size");
1109 /* will assign value to value */
1110 /* depending on where it is ofcourse */
1111 switch (aop->type) {
1116 emitcode("ld", "a,%s", s);
1117 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1123 emitcode("ld", "a,%s", s);
1124 emitcode("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
1128 if (!strcmp(s, "!*hl"))
1129 emit2("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1132 aop->aopu.aop_reg[offset]->name, s);
1137 setupPair(PAIR_IY, aop, offset);
1138 if (!canAssignToPtr(s)) {
1139 emit2("ld a,%s", s);
1140 emit2("ld !*iyx,a", offset);
1143 emit2("ld !*iyx,%s", offset, s);
1148 /* PENDING: for re-target */
1149 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1153 setupPair(PAIR_HL, aop, offset);
1155 emit2("ld !*hl,%s", s);
1160 /* PENDING: re-target */
1161 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1165 setupPair(PAIR_HL, aop, offset);
1166 if (!canAssignToPtr(s)) {
1167 emit2("ld a,%s", s);
1171 emit2("ld !*hl,%s", s);
1174 if (!canAssignToPtr(s)) {
1175 emit2("ld a,%s", s);
1176 emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
1179 emit2("ld !*ixx,%s", aop->aopu.aop_stk+offset, s);
1184 /* if bit variable */
1185 if (!aop->aopu.aop_dir) {
1189 /* In bit space but not in C - cant happen */
1196 if (strcmp(aop->aopu.aop_str[offset],s)) {
1197 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1203 if (!offset && (strcmp(s,"acc") == 0))
1207 emitcode("", "; Error aopPut AOP_ACC");
1210 if (strcmp(aop->aopu.aop_str[offset],s))
1211 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1216 wassert(offset < 2);
1217 emit2("ld %s,%s", aop->aopu.aop_str[offset], s);
1221 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1222 "aopPut got unsupported aop->type");
1227 #define AOP(op) op->aop
1228 #define AOP_TYPE(op) AOP(op)->type
1229 #define AOP_SIZE(op) AOP(op)->size
1230 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1232 static void commitPair(asmop *aop, PAIR_ID id)
1234 if (id == PAIR_HL && requiresHL(aop)) {
1237 aopPut(aop, "a", 0);
1238 aopPut(aop, "d", 1);
1241 aopPut(aop, _pairs[id].l, 0);
1242 aopPut(aop, _pairs[id].h, 1);
1246 /*-----------------------------------------------------------------*/
1247 /* getDataSize - get the operand data size */
1248 /*-----------------------------------------------------------------*/
1249 int getDataSize(operand *op)
1252 size = AOP_SIZE(op);
1260 /*-----------------------------------------------------------------*/
1261 /* movLeft2Result - move byte from left to result */
1262 /*-----------------------------------------------------------------*/
1263 static void movLeft2Result (operand *left, int offl,
1264 operand *result, int offr, int sign)
1267 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1268 l = aopGet(AOP(left),offl,FALSE);
1271 aopPut(AOP(result),l,offr);
1280 /** Put Acc into a register set
1282 void outAcc(operand *result)
1285 size = getDataSize(result);
1287 aopPut(AOP(result),"a",0);
1290 /* unsigned or positive */
1292 aopPut(AOP(result), zero, offset++);
1297 /** Take the value in carry and put it into a register
1299 void outBitCLong(operand *result, bool swap_sense)
1301 /* if the result is bit */
1302 if (AOP_TYPE(result) == AOP_CRY) {
1303 emitcode("", "; Note: outBitC form 1");
1304 aopPut(AOP(result),"blah",0);
1307 emit2("ld a,!zero");
1310 emit2("xor a,!immedbyte", 1);
1315 void outBitC(operand *result)
1317 outBitCLong(result, FALSE);
1320 /*-----------------------------------------------------------------*/
1321 /* toBoolean - emit code for orl a,operator(sizeop) */
1322 /*-----------------------------------------------------------------*/
1323 void toBoolean(operand *oper)
1325 int size = AOP_SIZE(oper);
1328 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1331 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1334 if (AOP(oper)->type != AOP_ACC) {
1336 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1341 /*-----------------------------------------------------------------*/
1342 /* genNot - generate code for ! operation */
1343 /*-----------------------------------------------------------------*/
1344 static void genNot (iCode *ic)
1346 link *optype = operandType(IC_LEFT(ic));
1348 /* assign asmOps to operand & result */
1349 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
1350 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1352 /* if in bit space then a special case */
1353 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1357 /* if type float then do float */
1358 if (IS_FLOAT(optype)) {
1362 toBoolean(IC_LEFT(ic));
1367 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1368 emit2("sub a,!one");
1369 outBitC(IC_RESULT(ic));
1371 /* release the aops */
1372 freeAsmop(IC_LEFT(ic),NULL,ic);
1373 freeAsmop(IC_RESULT(ic),NULL,ic);
1376 /*-----------------------------------------------------------------*/
1377 /* genCpl - generate code for complement */
1378 /*-----------------------------------------------------------------*/
1379 static void genCpl (iCode *ic)
1385 /* assign asmOps to operand & result */
1386 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1387 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1389 /* if both are in bit space then
1391 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1392 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1396 size = AOP_SIZE(IC_RESULT(ic));
1398 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1401 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1404 /* release the aops */
1405 freeAsmop(IC_LEFT(ic),NULL,ic);
1406 freeAsmop(IC_RESULT(ic),NULL,ic);
1409 /*-----------------------------------------------------------------*/
1410 /* genUminus - unary minus code generation */
1411 /*-----------------------------------------------------------------*/
1412 static void genUminus (iCode *ic)
1415 link *optype, *rtype;
1418 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1419 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
1421 /* if both in bit space then special
1423 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1424 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1429 optype = operandType(IC_LEFT(ic));
1430 rtype = operandType(IC_RESULT(ic));
1432 /* if float then do float stuff */
1433 if (IS_FLOAT(optype)) {
1438 /* otherwise subtract from zero */
1439 size = AOP_SIZE(IC_LEFT(ic));
1443 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1444 emit2("ld a,!zero");
1445 emit2("sbc a,%s",l);
1446 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1449 /* if any remaining bytes in the result */
1450 /* we just need to propagate the sign */
1451 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1455 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1459 /* release the aops */
1460 freeAsmop(IC_LEFT(ic),NULL,ic);
1461 freeAsmop(IC_RESULT(ic),NULL,ic);
1464 static void _push(PAIR_ID pairId)
1466 emit2("push %s", _pairs[pairId].name);
1467 _G.stack.pushed += 2;
1470 static void _pop(PAIR_ID pairId)
1472 emit2("pop %s", _pairs[pairId].name);
1473 _G.stack.pushed -= 2;
1477 /*-----------------------------------------------------------------*/
1478 /* assignResultValue - */
1479 /*-----------------------------------------------------------------*/
1480 void assignResultValue(operand * oper)
1482 int size = AOP_SIZE(oper);
1486 topInA = requiresHL(AOP(oper));
1492 if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
1493 /* We do it the hard way here. */
1495 aopPut(AOP(oper), _fReturn[0], 0);
1496 aopPut(AOP(oper), _fReturn[1], 1);
1497 emitcode("pop", "de");
1498 _G.stack.pushed -= 2;
1499 aopPut(AOP(oper), _fReturn[0], 2);
1500 aopPut(AOP(oper), _fReturn[1], 3);
1504 aopPut(AOP(oper), _fReturn[size], size);
1509 /*-----------------------------------------------------------------*/
1510 /* genIpush - genrate code for pushing this gets a little complex */
1511 /*-----------------------------------------------------------------*/
1512 static void genIpush (iCode *ic)
1514 int size, offset = 0 ;
1517 /* if this is not a parm push : ie. it is spill push
1518 and spill push is always done on the local stack */
1519 if (!ic->parmPush) {
1520 /* and the item is spilt then do nothing */
1521 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1524 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1525 size = AOP_SIZE(IC_LEFT(ic));
1526 /* push it on the stack */
1527 if (isPair(AOP(IC_LEFT(ic)))) {
1528 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1529 _G.stack.pushed += 2;
1534 /* Simple for now - load into A and PUSH AF */
1535 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1536 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1538 emit2("ld a,(%s)", l);
1541 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1542 emit2("ld a,%s", l);
1552 /* Hmmm... what about saving the currently used registers
1555 /* then do the push */
1556 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1558 size = AOP_SIZE(IC_LEFT(ic));
1560 if (isPair(AOP(IC_LEFT(ic)))) {
1562 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1566 fetchHL(AOP(IC_LEFT(ic)));
1567 emitcode("push", "hl");
1569 _G.stack.pushed += 2;
1573 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
1574 emitcode("push", "hl");
1576 _G.stack.pushed += 2;
1577 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 0);
1578 emitcode("push", "hl");
1580 _G.stack.pushed += 2;
1585 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1586 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1588 emit2("ld a,(%s)", l);
1591 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1592 emit2("ld a,%s", l);
1594 emitcode("push", "af");
1595 emitcode("inc", "sp");
1600 freeAsmop(IC_LEFT(ic),NULL,ic);
1603 /*-----------------------------------------------------------------*/
1604 /* genIpop - recover the registers: can happen only for spilling */
1605 /*-----------------------------------------------------------------*/
1606 static void genIpop (iCode *ic)
1611 /* if the temp was not pushed then */
1612 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1615 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1616 size = AOP_SIZE(IC_LEFT(ic));
1618 if (isPair(AOP(IC_LEFT(ic)))) {
1619 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1623 emitcode("dec", "sp");
1624 emitcode("pop", "hl");
1626 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1630 freeAsmop(IC_LEFT(ic),NULL,ic);
1633 static int _isPairUsed(iCode *ic, PAIR_ID pairId)
1638 if (bitVectBitValue(ic->rUsed, D_IDX))
1640 if (bitVectBitValue(ic->rUsed, E_IDX))
1649 static int _opUsesPair(operand *op, iCode *ic, PAIR_ID pairId)
1653 symbol *sym = OP_SYMBOL(op);
1655 if (sym->isspilt || sym->nRegs == 0)
1658 aopOp(op, ic, FALSE, FALSE);
1661 if (aop->type == AOP_REG) {
1663 for (i=0; i < aop->size; i++) {
1664 if (pairId == PAIR_DE) {
1665 emit2("; name %s", aop->aopu.aop_reg[i]->name);
1666 if (!strcmp(aop->aopu.aop_reg[i]->name, "e"))
1668 if (!strcmp(aop->aopu.aop_reg[i]->name, "d"))
1677 freeAsmop(IC_LEFT(ic),NULL,ic);
1681 /* This is quite unfortunate */
1682 static void setArea(int inHome)
1684 static int lastArea = 0;
1687 if (_G.in_home != inHome) {
1689 const char *sz = port->mem.code_name;
1690 port->mem.code_name = "HOME";
1691 emit2("!area", CODE_NAME);
1692 port->mem.code_name = sz;
1695 emit2("!area", CODE_NAME);*/
1696 _G.in_home = inHome;
1700 static bool isInHome(void)
1705 /** Emit the code for a call statement
1707 static void emitCall(iCode *ic, bool ispcall)
1710 link *detype = getSpec(operandType(IC_LEFT(ic)));
1712 /* if caller saves & we have not saved then */
1713 if (!ic->regsSaved) {
1717 /* if send set is not empty then assign */
1721 int n = elementsInSet(sendSet);
1722 if (IS_Z80 && n == 2 && _isPairUsed(ic, PAIR_DE)) {
1723 /* Only push de if it is used and if it's not used
1724 in the return value */
1725 /* Panic if partly used */
1726 if (_opUsesPair(IC_RESULT(ic), ic, PAIR_DE) == 1) {
1727 emit2("; Warning: de crossover");
1729 else if (!_opUsesPair(IC_RESULT(ic), ic, PAIR_DE)) {
1736 if (IS_Z80 && n == 2 ) {
1737 /* Want to load HL first, then DE as HL may = DE */
1738 sic = setFirstItem(sendSet);
1739 sic = setNextItem(sendSet);
1740 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1741 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1743 freeAsmop (IC_LEFT(sic),NULL,sic);
1744 sic = setFirstItem(sendSet);
1745 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1746 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1748 freeAsmop (IC_LEFT(sic),NULL,sic);
1751 for (sic = setFirstItem(sendSet) ; sic ;
1752 sic = setNextItem(sendSet)) {
1754 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1755 size = AOP_SIZE(IC_LEFT(sic));
1757 /* Always send in pairs */
1760 if (IS_Z80 && n == 1)
1761 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1763 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1766 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1769 /* Send set too big */
1773 freeAsmop (IC_LEFT(sic),NULL,sic);
1782 if (IS_BANKEDCALL(detype)) {
1783 werror(W_INDIR_BANKED);
1785 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1787 if (isLitWord(AOP(IC_LEFT(ic)))) {
1788 emitcode("", "; Special case where the pCall is to a constant");
1789 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1792 symbol *rlbl = newiTempLabel(NULL);
1794 emit2("ld hl,!immed!tlabel", (rlbl->key+100));
1795 emitcode("push", "hl");
1796 _G.stack.pushed += 2;
1798 fetchHL(AOP(IC_LEFT(ic)));
1800 emit2("!tlabeldef", (rlbl->key+100));
1801 _G.stack.pushed -= 2;
1803 freeAsmop(IC_LEFT(ic),NULL,ic);
1806 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1807 OP_SYMBOL(IC_LEFT(ic))->rname :
1808 OP_SYMBOL(IC_LEFT(ic))->name;
1809 if (IS_BANKEDCALL(detype)) {
1810 emit2("call banked_call");
1811 emit2("!dws", name);
1812 emit2("!dw !bankimmeds", name);
1816 emit2("call %s", name);
1821 /* if we need assign a result value */
1822 if ((IS_ITEMP(IC_RESULT(ic)) &&
1823 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1824 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1825 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1828 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1831 assignResultValue(IC_RESULT(ic));
1833 freeAsmop(IC_RESULT(ic),NULL, ic);
1836 /* adjust the stack for parameters if required */
1837 if (IC_LEFT(ic)->parmBytes) {
1838 int i = IC_LEFT(ic)->parmBytes;
1839 _G.stack.pushed -= i;
1841 emit2("!ldaspsp", i);
1846 emitcode("ld", "hl,#%d", i);
1847 emitcode("add", "hl,sp");
1848 emitcode("ld", "sp,hl");
1852 emitcode("pop", "hl");
1856 emitcode("inc", "sp");
1865 /*-----------------------------------------------------------------*/
1866 /* genCall - generates a call statement */
1867 /*-----------------------------------------------------------------*/
1868 static void genCall (iCode *ic)
1870 link *detype = getSpec(operandType(IC_LEFT(ic)));
1871 emitCall(ic, FALSE);
1874 /*-----------------------------------------------------------------*/
1875 /* genPcall - generates a call by pointer statement */
1876 /*-----------------------------------------------------------------*/
1877 static void genPcall (iCode *ic)
1882 /*-----------------------------------------------------------------*/
1883 /* resultRemat - result is rematerializable */
1884 /*-----------------------------------------------------------------*/
1885 static int resultRemat (iCode *ic)
1887 if (SKIP_IC(ic) || ic->op == IFX)
1890 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1891 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1892 if (sym->remat && !POINTER_SET(ic))
1899 extern set *publics;
1901 /*-----------------------------------------------------------------*/
1902 /* genFunction - generated code for function entry */
1903 /*-----------------------------------------------------------------*/
1904 static void genFunction (iCode *ic)
1906 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1910 setArea(IS_NONBANKED(sym->etype));
1913 if (!IS_STATIC(sym->etype)) {
1914 addSetIfnotP(&publics, sym);
1917 /* create the function header */
1918 emit2("!functionheader", sym->name);
1919 /* PENDING: portability. */
1920 emit2("__%s_start:", sym->rname);
1921 emit2("!functionlabeldef", sym->rname);
1923 fetype = getSpec(operandType(IC_LEFT(ic)));
1925 /* if critical function then turn interrupts off */
1926 if (SPEC_CRTCL(fetype))
1929 /* if this is an interrupt service routine then
1930 save acc, b, dpl, dph */
1931 if (IS_ISR(sym->etype)) {
1934 /* PENDING: callee-save etc */
1936 /* If BC or DE are used, then push */
1937 _G.stack.pushed_bc = 0;
1938 _G.stack.pushed_de = 0;
1939 _G.stack.param_offset = 0;
1940 if (sym->regsUsed) {
1942 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1943 if (bitVectBitValue(sym->regsUsed, i)) {
1947 _G.stack.pushed_bc = 1;
1952 _G.stack.pushed_de = 1;
1957 if (_G.stack.pushed_bc) {
1959 _G.stack.param_offset += 2;
1961 if (_G.stack.pushed_de) {
1963 _G.stack.param_offset += 2;
1967 /* adjust the stack for the function */
1968 _G.stack.last = sym->stack;
1971 emit2("!enterx", sym->stack);
1974 _G.stack.offset = sym->stack;
1977 /*-----------------------------------------------------------------*/
1978 /* genEndFunction - generates epilogue for functions */
1979 /*-----------------------------------------------------------------*/
1980 static void genEndFunction (iCode *ic)
1982 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1984 if (IS_ISR(sym->etype)) {
1988 if (SPEC_CRTCL(sym->etype))
1991 /* PENDING: calleeSave */
1993 /* if debug then send end of function */
1994 if (options.debug && currFunc) {
1996 emitcode("","C$%s$%d$%d$%d ==.",
1997 ic->filename,currFunc->lastLine,
1998 ic->level,ic->block);
1999 if (IS_STATIC(currFunc->etype))
2000 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2002 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2005 if (_G.stack.offset)
2006 emit2("!leavex", _G.stack.offset);
2010 if (_G.stack.pushed_de)
2012 if (_G.stack.pushed_bc)
2014 /* Both baned and non-banked just ret */
2017 /* PENDING: portability. */
2018 emit2("__%s_end:", sym->rname);
2020 _G.flush_statics = 1;
2021 _G.stack.pushed = 0;
2022 _G.stack.offset = 0;
2025 /*-----------------------------------------------------------------*/
2026 /* genRet - generate code for return statement */
2027 /*-----------------------------------------------------------------*/
2028 static void genRet (iCode *ic)
2031 /* Errk. This is a hack until I can figure out how
2032 to cause dehl to spill on a call */
2033 int size,offset = 0;
2035 /* if we have no return value then
2036 just generate the "ret" */
2040 /* we have something to return then
2041 move the return value into place */
2042 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2043 size = AOP_SIZE(IC_LEFT(ic));
2045 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
2047 emitcode("ld", "de,%s", l);
2050 emitcode("ld", "hl,%s", l);
2054 if (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
2055 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2056 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
2060 l = aopGet(AOP(IC_LEFT(ic)),offset,
2062 if (strcmp(_fReturn[offset],l))
2063 emitcode("ld","%s,%s", _fReturn[offset++],l);
2067 freeAsmop (IC_LEFT(ic),NULL,ic);
2070 /* generate a jump to the return label
2071 if the next is not the return statement */
2072 if (!(ic->next && ic->next->op == LABEL &&
2073 IC_LABEL(ic->next) == returnLabel))
2075 emit2("jp !tlabel", returnLabel->key+100);
2078 /*-----------------------------------------------------------------*/
2079 /* genLabel - generates a label */
2080 /*-----------------------------------------------------------------*/
2081 static void genLabel (iCode *ic)
2083 /* special case never generate */
2084 if (IC_LABEL(ic) == entryLabel)
2087 emitLabel(IC_LABEL(ic)->key+100);
2090 /*-----------------------------------------------------------------*/
2091 /* genGoto - generates a ljmp */
2092 /*-----------------------------------------------------------------*/
2093 static void genGoto (iCode *ic)
2095 emit2("jp !tlabel", IC_LABEL(ic)->key+100);
2098 /*-----------------------------------------------------------------*/
2099 /* genPlusIncr :- does addition with increment if possible */
2100 /*-----------------------------------------------------------------*/
2101 static bool genPlusIncr (iCode *ic)
2103 unsigned int icount ;
2104 unsigned int size = getDataSize(IC_RESULT(ic));
2105 PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
2107 /* will try to generate an increment */
2108 /* if the right side is not a literal
2110 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2113 emitcode("", "; genPlusIncr");
2115 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2117 /* If result is a pair */
2118 if (resultId != PAIR_INVALID) {
2119 if (isLitWord(AOP(IC_LEFT(ic)))) {
2120 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
2123 if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
2124 fetchPair(resultId, AOP(IC_RIGHT(ic)));
2125 emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
2131 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2134 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2135 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2138 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
2143 /* if the literal value of the right hand side
2144 is greater than 4 then it is not worth it */
2148 /* if increment 16 bits in register */
2149 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2154 symbol *tlbl = NULL;
2155 tlbl = newiTempLabel(NULL);
2157 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)), offset++, FALSE));
2159 emit2("!shortjp nz,!tlabel", tlbl->key+100);
2162 emitLabel(tlbl->key+100);
2166 /* if the sizes are greater than 1 then we cannot */
2167 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2168 AOP_SIZE(IC_LEFT(ic)) > 1 )
2171 /* we can if the aops of the left & result match or
2172 if they are in registers and the registers are the
2174 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2176 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
2183 /*-----------------------------------------------------------------*/
2184 /* outBitAcc - output a bit in acc */
2185 /*-----------------------------------------------------------------*/
2186 void outBitAcc(operand *result)
2188 symbol *tlbl = newiTempLabel(NULL);
2189 /* if the result is a bit */
2190 if (AOP_TYPE(result) == AOP_CRY){
2194 emit2("!shortjp z,!tlabel", tlbl->key+100);
2196 emitLabel(tlbl->key+100);
2201 /*-----------------------------------------------------------------*/
2202 /* genPlus - generates code for addition */
2203 /*-----------------------------------------------------------------*/
2204 static void genPlus (iCode *ic)
2206 int size, offset = 0;
2208 /* special cases :- */
2210 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2211 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2212 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2214 /* Swap the left and right operands if:
2216 if literal, literal on the right or
2217 if left requires ACC or right is already
2220 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2221 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2222 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2223 operand *t = IC_RIGHT(ic);
2224 IC_RIGHT(ic) = IC_LEFT(ic);
2228 /* if both left & right are in bit
2230 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2231 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2236 /* if left in bit space & right literal */
2237 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2238 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2239 /* Can happen I guess */
2243 /* if I can do an increment instead
2244 of add then GOOD for ME */
2245 if (genPlusIncr (ic) == TRUE)
2248 emit2("; genPlusIncr failed");
2250 size = getDataSize(IC_RESULT(ic));
2252 /* Special case when left and right are constant */
2253 if (isPair(AOP(IC_RESULT(ic)))) {
2256 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
2257 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
2258 if (left && right) {
2262 sprintf(buffer, "#(%s + %s)", left, right);
2263 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
2268 if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
2269 /* Fetch into HL then do the add */
2271 fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
2272 emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
2277 ld hl,sp+n trashes C so we cant afford to do it during an
2278 add with stack based varibles. Worst case is:
2291 So you cant afford to load up hl if either left, right, or result
2292 is on the stack (*sigh*) The alt is:
2300 Combinations in here are:
2301 * If left or right are in bc then the loss is small - trap later
2302 * If the result is in bc then the loss is also small
2305 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2306 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2307 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2308 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2309 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2310 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2311 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2312 if (getPairId(AOP(IC_RIGHT(ic))) == PAIR_BC) {
2313 /* Swap left and right */
2314 operand *t = IC_RIGHT(ic);
2315 IC_RIGHT(ic) = IC_LEFT(ic);
2318 if (getPairId(AOP(IC_LEFT(ic))) == PAIR_BC) {
2319 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2323 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2324 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2327 commitPair(AOP(IC_RESULT(ic)), PAIR_HL);
2330 else if (size == 4) {
2331 emit2("; WARNING: This add is probably broken.\n");
2337 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2338 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2341 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2344 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2346 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2349 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2352 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2354 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2358 freeAsmop(IC_LEFT(ic),NULL,ic);
2359 freeAsmop(IC_RIGHT(ic),NULL,ic);
2360 freeAsmop(IC_RESULT(ic),NULL,ic);
2364 /*-----------------------------------------------------------------*/
2365 /* genMinusDec :- does subtraction with deccrement if possible */
2366 /*-----------------------------------------------------------------*/
2367 static bool genMinusDec (iCode *ic)
2369 unsigned int icount ;
2370 unsigned int size = getDataSize(IC_RESULT(ic));
2372 /* will try to generate an increment */
2373 /* if the right side is not a literal we cannot */
2374 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2377 /* if the literal value of the right hand side
2378 is greater than 4 then it is not worth it */
2379 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2382 size = getDataSize(IC_RESULT(ic));
2385 /* if increment 16 bits in register */
2386 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2389 symbol *tlbl = newiTempLabel(NULL);
2390 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
2391 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
2393 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
2397 emitLabel(tlbl->key+100);
2402 /* if decrement 16 bits in register */
2403 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2404 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
2406 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2410 /* If result is a pair */
2411 if (isPair(AOP(IC_RESULT(ic)))) {
2412 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2413 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2415 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2419 /* if the sizes are greater than 1 then we cannot */
2420 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2421 AOP_SIZE(IC_LEFT(ic)) > 1 )
2424 /* we can if the aops of the left & result match or if they are in
2425 registers and the registers are the same */
2426 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2428 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
2435 /*-----------------------------------------------------------------*/
2436 /* genMinus - generates code for subtraction */
2437 /*-----------------------------------------------------------------*/
2438 static void genMinus (iCode *ic)
2440 int size, offset = 0;
2441 unsigned long lit = 0L;
2443 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2444 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2445 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2447 /* special cases :- */
2448 /* if both left & right are in bit space */
2449 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2450 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2455 /* if I can do an decrement instead of subtract then GOOD for ME */
2456 if (genMinusDec (ic) == TRUE)
2459 size = getDataSize(IC_RESULT(ic));
2461 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2464 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2468 /* Same logic as genPlus */
2470 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2471 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2472 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2473 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2474 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2475 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2476 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2477 PAIR_ID left = getPairId(AOP(IC_LEFT(ic)));
2478 PAIR_ID right = getPairId(AOP(IC_RIGHT(ic)));
2480 if (left == PAIR_INVALID && right == PAIR_INVALID) {
2484 else if (right == PAIR_INVALID)
2486 else if (left == PAIR_INVALID)
2489 fetchPair(left, AOP(IC_LEFT(ic)));
2490 /* Order is important. Right may be HL */
2491 fetchPair(right, AOP(IC_RIGHT(ic)));
2493 emit2("ld a,%s", _pairs[left].l);
2494 emit2("sub a,%s", _pairs[right].l);
2496 emit2("ld a,%s", _pairs[left].h);
2497 emit2("sbc a,%s", _pairs[right].h);
2499 aopPut(AOP(IC_RESULT(ic)), "a", 1);
2500 aopPut(AOP(IC_RESULT(ic)), "e", 0);
2503 else if (size == 4) {
2504 emit2("; WARNING: This sub is probably broken.\n");
2509 /* if literal, add a,#-lit, else normal subb */
2511 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2512 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2514 emitcode("sub","a,%s",
2515 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2517 emitcode("sbc","a,%s",
2518 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2521 /* first add without previous c */
2523 emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL));
2525 emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2527 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2530 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2531 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2532 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2536 freeAsmop(IC_LEFT(ic),NULL,ic);
2537 freeAsmop(IC_RIGHT(ic),NULL,ic);
2538 freeAsmop(IC_RESULT(ic),NULL,ic);
2541 /*-----------------------------------------------------------------*/
2542 /* genMult - generates code for multiplication */
2543 /*-----------------------------------------------------------------*/
2544 static void genMult (iCode *ic)
2546 /* Shouldn't occur - all done through function calls */
2550 /*-----------------------------------------------------------------*/
2551 /* genDiv - generates code for division */
2552 /*-----------------------------------------------------------------*/
2553 static void genDiv (iCode *ic)
2555 /* Shouldn't occur - all done through function calls */
2559 /*-----------------------------------------------------------------*/
2560 /* genMod - generates code for division */
2561 /*-----------------------------------------------------------------*/
2562 static void genMod (iCode *ic)
2564 /* Shouldn't occur - all done through function calls */
2568 /*-----------------------------------------------------------------*/
2569 /* genIfxJump :- will create a jump depending on the ifx */
2570 /*-----------------------------------------------------------------*/
2571 static void genIfxJump (iCode *ic, char *jval)
2576 /* if true label then we jump if condition
2580 if (!strcmp(jval, "a")) {
2583 else if (!strcmp(jval, "c")) {
2586 else if (!strcmp(jval, "nc")) {
2590 /* The buffer contains the bit on A that we should test */
2595 /* false label is present */
2596 jlbl = IC_FALSE(ic) ;
2597 if (!strcmp(jval, "a")) {
2600 else if (!strcmp(jval, "c")) {
2603 else if (!strcmp(jval, "nc")) {
2607 /* The buffer contains the bit on A that we should test */
2611 /* Z80 can do a conditional long jump */
2612 if (!strcmp(jval, "a")) {
2613 emitcode("or", "a,a");
2615 else if (!strcmp(jval, "c")) {
2617 else if (!strcmp(jval, "nc")) {
2620 emitcode("bit", "%s,a", jval);
2622 emit2("jp %s,!tlabel", inst, jlbl->key+100);
2624 /* mark the icode as generated */
2628 const char *getPairIdName(PAIR_ID id)
2630 return _pairs[id].name;
2633 /** Generic compare for > or <
2635 static void genCmp (operand *left,operand *right,
2636 operand *result, iCode *ifx, int sign)
2638 int size, offset = 0 ;
2639 unsigned long lit = 0L;
2640 bool swap_sense = FALSE;
2642 /* if left & right are bit variables */
2643 if (AOP_TYPE(left) == AOP_CRY &&
2644 AOP_TYPE(right) == AOP_CRY ) {
2645 /* Cant happen on the Z80 */
2648 /* subtract right from left if at the
2649 end the carry flag is set then we know that
2650 left is greater than right */
2651 size = max(AOP_SIZE(left),AOP_SIZE(right));
2653 /* if unsigned char cmp with lit, just compare */
2655 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2656 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2658 emit2("xor a,!immedbyte", 0x80);
2659 emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80);
2662 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
2667 If the left or the right is a lit:
2668 Load -lit into HL, add to right via, check sense.
2670 if (size == 2 && (AOP_TYPE(right) == AOP_LIT || AOP_TYPE(left) == AOP_LIT)) {
2671 asmop *lit = AOP(right);
2672 asmop *op = AOP(left);
2674 if (AOP_TYPE(left) == AOP_LIT) {
2680 emit2("ld e,%s", aopGet(op, 0, 0));
2681 emit2("ld a,%s", aopGet(op, 1, 0));
2682 emit2("xor a,!immedbyte", 0x80);
2685 emit2("ld hl,%s", fetchLitSpecial(lit, TRUE, sign));
2689 if(AOP_TYPE(right) == AOP_LIT) {
2690 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2691 /* optimize if(x < 0) or if(x >= 0) */
2694 /* No sign so it's always false */
2698 /* Just load in the top most bit */
2699 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2700 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2701 genIfxJump (ifx,"7");
2705 emitcode("rlc","a");
2711 /* First setup h and l contaning the top most bytes XORed */
2712 bool fDidXor = FALSE;
2713 if (AOP_TYPE(left) == AOP_LIT){
2714 unsigned long lit = (unsigned long)
2715 floatFromVal(AOP(left)->aopu.aop_lit);
2716 emit2("ld %s,!immedbyte", _fTmp[0],
2717 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2720 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2721 emit2("xor a,!immedbyte", 0x80);
2722 emitcode("ld", "%s,a", _fTmp[0]);
2725 if (AOP_TYPE(right) == AOP_LIT) {
2726 unsigned long lit = (unsigned long)
2727 floatFromVal(AOP(right)->aopu.aop_lit);
2728 emit2("ld %s,!immedbyte", _fTmp[1],
2729 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2732 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2733 emit2("xor a,!immedbyte", 0x80);
2734 emitcode("ld", "%s,a", _fTmp[1]);
2744 /* Do a long subtract */
2745 if (!sign || size ) {
2746 MOVA(aopGet(AOP(left),offset,FALSE));
2748 if (sign && size == 0) {
2749 emitcode("ld", "a,%s", _fTmp[0]);
2750 emitcode("sbc", "a,%s", _fTmp[1]);
2753 /* Subtract through, propagating the carry */
2754 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2761 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2762 outBitCLong(result, swap_sense);
2764 /* if the result is used in the next
2765 ifx conditional branch then generate
2766 code a little differently */
2768 genIfxJump(ifx, swap_sense ? "nc" : "c");
2770 outBitCLong(result, swap_sense);
2771 /* leave the result in acc */
2775 /*-----------------------------------------------------------------*/
2776 /* genCmpGt :- greater than comparison */
2777 /*-----------------------------------------------------------------*/
2778 static void genCmpGt (iCode *ic, iCode *ifx)
2780 operand *left, *right, *result;
2781 link *letype , *retype;
2785 right= IC_RIGHT(ic);
2786 result = IC_RESULT(ic);
2788 letype = getSpec(operandType(left));
2789 retype =getSpec(operandType(right));
2790 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2791 /* assign the amsops */
2792 aopOp (left,ic,FALSE, FALSE);
2793 aopOp (right,ic,FALSE, FALSE);
2794 aopOp (result,ic,TRUE, FALSE);
2796 genCmp(right, left, result, ifx, sign);
2798 freeAsmop(left,NULL,ic);
2799 freeAsmop(right,NULL,ic);
2800 freeAsmop(result,NULL,ic);
2803 /*-----------------------------------------------------------------*/
2804 /* genCmpLt - less than comparisons */
2805 /*-----------------------------------------------------------------*/
2806 static void genCmpLt (iCode *ic, iCode *ifx)
2808 operand *left, *right, *result;
2809 link *letype , *retype;
2813 right= IC_RIGHT(ic);
2814 result = IC_RESULT(ic);
2816 letype = getSpec(operandType(left));
2817 retype =getSpec(operandType(right));
2818 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2820 /* assign the amsops */
2821 aopOp (left,ic,FALSE, FALSE);
2822 aopOp (right,ic,FALSE, FALSE);
2823 aopOp (result,ic,TRUE, FALSE);
2825 genCmp(left, right, result, ifx, sign);
2827 freeAsmop(left,NULL,ic);
2828 freeAsmop(right,NULL,ic);
2829 freeAsmop(result,NULL,ic);
2832 /*-----------------------------------------------------------------*/
2833 /* gencjneshort - compare and jump if not equal */
2834 /*-----------------------------------------------------------------*/
2835 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2837 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2839 unsigned long lit = 0L;
2841 /* Swap the left and right if it makes the computation easier */
2842 if (AOP_TYPE(left) == AOP_LIT) {
2848 if(AOP_TYPE(right) == AOP_LIT)
2849 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2851 /* if the right side is a literal then anything goes */
2852 if (AOP_TYPE(right) == AOP_LIT &&
2853 AOP_TYPE(left) != AOP_DIR ) {
2855 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2860 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2864 emitcode("or", "a,a");
2866 emit2("jp nz,!tlabel", lbl->key+100);
2870 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2871 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2872 emitcode("or", "a,a");
2874 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2875 emit2("jp nz,!tlabel", lbl->key+100);
2880 /* if the right side is in a register or in direct space or
2881 if the left is a pointer register & right is not */
2882 else if (AOP_TYPE(right) == AOP_REG ||
2883 AOP_TYPE(right) == AOP_DIR ||
2884 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2886 MOVA(aopGet(AOP(left),offset,FALSE));
2887 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2888 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2890 emit2("jp nz,!tlabel", lbl->key+100);
2892 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2893 emit2("jp nz,!tlabel", lbl->key+100);
2898 /* right is a pointer reg need both a & b */
2899 /* PENDING: is this required? */
2901 MOVA(aopGet(AOP(right),offset,FALSE));
2902 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2903 emit2("!shortjp nz,!tlabel", lbl->key+100);
2909 /*-----------------------------------------------------------------*/
2910 /* gencjne - compare and jump if not equal */
2911 /*-----------------------------------------------------------------*/
2912 static void gencjne(operand *left, operand *right, symbol *lbl)
2914 symbol *tlbl = newiTempLabel(NULL);
2916 gencjneshort(left, right, lbl);
2920 emit2("!shortjp !tlabel", tlbl->key+100);
2921 emitLabel(lbl->key+100);
2922 emitcode("xor","a,a");
2923 emitLabel(tlbl->key+100);
2926 /*-----------------------------------------------------------------*/
2927 /* genCmpEq - generates code for equal to */
2928 /*-----------------------------------------------------------------*/
2929 static void genCmpEq (iCode *ic, iCode *ifx)
2931 operand *left, *right, *result;
2933 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
2934 aopOp((right=IC_RIGHT(ic)),ic,FALSE, FALSE);
2935 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
2937 /* Swap operands if it makes the operation easier. ie if:
2938 1. Left is a literal.
2940 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2941 operand *t = IC_RIGHT(ic);
2942 IC_RIGHT(ic) = IC_LEFT(ic);
2946 if (ifx && !AOP_SIZE(result)){
2948 /* if they are both bit variables */
2949 if (AOP_TYPE(left) == AOP_CRY &&
2950 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2953 tlbl = newiTempLabel(NULL);
2954 gencjneshort(left, right, tlbl);
2955 if ( IC_TRUE(ifx) ) {
2956 emit2("jp !tlabel", IC_TRUE(ifx)->key+100);
2957 emitLabel(tlbl->key+100);
2959 /* PENDING: do this better */
2960 symbol *lbl = newiTempLabel(NULL);
2961 emit2("!shortjp !tlabel", lbl->key+100);
2962 emitLabel(tlbl->key+100);
2963 emit2("jp !tlabel", IC_FALSE(ifx)->key+100);
2964 emitLabel(lbl->key+100);
2967 /* mark the icode as generated */
2972 /* if they are both bit variables */
2973 if (AOP_TYPE(left) == AOP_CRY &&
2974 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2977 gencjne(left,right,newiTempLabel(NULL));
2978 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2982 genIfxJump(ifx,"a");
2985 /* if the result is used in an arithmetic operation
2986 then put the result in place */
2987 if (AOP_TYPE(result) != AOP_CRY) {
2990 /* leave the result in acc */
2994 freeAsmop(left,NULL,ic);
2995 freeAsmop(right,NULL,ic);
2996 freeAsmop(result,NULL,ic);
2999 /*-----------------------------------------------------------------*/
3000 /* ifxForOp - returns the icode containing the ifx for operand */
3001 /*-----------------------------------------------------------------*/
3002 static iCode *ifxForOp ( operand *op, iCode *ic )
3004 /* if true symbol then needs to be assigned */
3005 if (IS_TRUE_SYMOP(op))
3008 /* if this has register type condition and
3009 the next instruction is ifx with the same operand
3010 and live to of the operand is upto the ifx only then */
3012 ic->next->op == IFX &&
3013 IC_COND(ic->next)->key == op->key &&
3014 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3020 /*-----------------------------------------------------------------*/
3021 /* genAndOp - for && operation */
3022 /*-----------------------------------------------------------------*/
3023 static void genAndOp (iCode *ic)
3025 operand *left,*right, *result;
3028 /* note here that && operations that are in an if statement are
3029 taken away by backPatchLabels only those used in arthmetic
3030 operations remain */
3031 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
3032 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3033 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
3035 /* if both are bit variables */
3036 if (AOP_TYPE(left) == AOP_CRY &&
3037 AOP_TYPE(right) == AOP_CRY ) {
3040 tlbl = newiTempLabel(NULL);
3042 emit2("!shortjp z,!tlabel", tlbl->key+100);
3044 emitLabel(tlbl->key+100);
3048 freeAsmop(left,NULL,ic);
3049 freeAsmop(right,NULL,ic);
3050 freeAsmop(result,NULL,ic);
3053 /*-----------------------------------------------------------------*/
3054 /* genOrOp - for || operation */
3055 /*-----------------------------------------------------------------*/
3056 static void genOrOp (iCode *ic)
3058 operand *left,*right, *result;
3061 /* note here that || operations that are in an
3062 if statement are taken away by backPatchLabels
3063 only those used in arthmetic operations remain */
3064 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
3065 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3066 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
3068 /* if both are bit variables */
3069 if (AOP_TYPE(left) == AOP_CRY &&
3070 AOP_TYPE(right) == AOP_CRY ) {
3073 tlbl = newiTempLabel(NULL);
3075 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3077 emitLabel(tlbl->key+100);
3081 freeAsmop(left,NULL,ic);
3082 freeAsmop(right,NULL,ic);
3083 freeAsmop(result,NULL,ic);
3086 /*-----------------------------------------------------------------*/
3087 /* isLiteralBit - test if lit == 2^n */
3088 /*-----------------------------------------------------------------*/
3089 int isLiteralBit(unsigned long lit)
3091 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3092 0x100L,0x200L,0x400L,0x800L,
3093 0x1000L,0x2000L,0x4000L,0x8000L,
3094 0x10000L,0x20000L,0x40000L,0x80000L,
3095 0x100000L,0x200000L,0x400000L,0x800000L,
3096 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3097 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3100 for(idx = 0; idx < 32; idx++)
3106 /*-----------------------------------------------------------------*/
3107 /* jmpTrueOrFalse - */
3108 /*-----------------------------------------------------------------*/
3109 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3111 // ugly but optimized by peephole
3113 symbol *nlbl = newiTempLabel(NULL);
3114 emit2("jp !tlabel", nlbl->key+100);
3115 emitLabel(tlbl->key+100);
3116 emit2("jp !tlabel", IC_TRUE(ic)->key+100);
3117 emitLabel(nlbl->key+100);
3120 emit2("jp !tlabel", IC_FALSE(ic)->key+100);
3121 emitLabel(tlbl->key+100);
3126 /*-----------------------------------------------------------------*/
3127 /* genAnd - code for and */
3128 /*-----------------------------------------------------------------*/
3129 static void genAnd (iCode *ic, iCode *ifx)
3131 operand *left, *right, *result;
3133 unsigned long lit = 0L;
3136 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3137 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3138 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3141 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3143 AOP_TYPE(left), AOP_TYPE(right));
3144 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3146 AOP_SIZE(left), AOP_SIZE(right));
3149 /* if left is a literal & right is not then exchange them */
3150 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3151 AOP_NEEDSACC(left)) {
3152 operand *tmp = right ;
3157 /* if result = right then exchange them */
3158 if(sameRegs(AOP(result),AOP(right))){
3159 operand *tmp = right ;
3164 /* if right is bit then exchange them */
3165 if (AOP_TYPE(right) == AOP_CRY &&
3166 AOP_TYPE(left) != AOP_CRY){
3167 operand *tmp = right ;
3171 if(AOP_TYPE(right) == AOP_LIT)
3172 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3174 size = AOP_SIZE(result);
3176 if (AOP_TYPE(left) == AOP_CRY){
3181 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3182 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3183 if((AOP_TYPE(right) == AOP_LIT) &&
3184 (AOP_TYPE(result) == AOP_CRY) &&
3185 (AOP_TYPE(left) != AOP_CRY)) {
3186 int posbit = isLiteralBit(lit);
3190 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
3194 emitcode("mov","c,acc.%d",posbit&0x07);
3199 sprintf(buffer, "%d", posbit&0x07);
3200 genIfxJump(ifx, buffer);
3208 symbol *tlbl = newiTempLabel(NULL);
3209 int sizel = AOP_SIZE(left);
3212 emitcode("setb","c");
3215 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3216 MOVA( aopGet(AOP(left),offset,FALSE));
3218 if((posbit = isLiteralBit(bytelit)) != 0) {
3220 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3223 if(bytelit != 0x0FFL)
3224 emitcode("and","a,%s",
3225 aopGet(AOP(right),offset,FALSE));
3229 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3234 // bit = left & literal
3236 emitcode("clr","c");
3237 emit2("!tlabeldef", tlbl->key+100);
3239 // if(left & literal)
3242 jmpTrueOrFalse(ifx, tlbl);
3250 /* if left is same as result */
3251 if(sameRegs(AOP(result),AOP(left))){
3252 for(;size--; offset++) {
3253 if(AOP_TYPE(right) == AOP_LIT){
3254 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3258 aopPut(AOP(result),zero,offset);
3260 MOVA(aopGet(AOP(left),offset,FALSE));
3261 emitcode("and","a,%s",
3262 aopGet(AOP(right),offset,FALSE));
3263 aopPut(AOP(left), "a", offset);
3268 if (AOP_TYPE(left) == AOP_ACC) {
3272 MOVA(aopGet(AOP(left),offset,FALSE));
3273 emitcode("and","a,%s",
3274 aopGet(AOP(right),offset,FALSE));
3275 aopPut(AOP(left), "a", offset);
3280 // left & result in different registers
3281 if(AOP_TYPE(result) == AOP_CRY){
3284 for(;(size--);offset++) {
3286 // result = left & right
3287 if(AOP_TYPE(right) == AOP_LIT){
3288 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3290 aopGet(AOP(left),offset,FALSE),
3293 } else if(bytelit == 0){
3294 aopPut(AOP(result),zero,offset);
3298 // faster than result <- left, anl result,right
3299 // and better if result is SFR
3300 if (AOP_TYPE(left) == AOP_ACC)
3301 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
3303 MOVA(aopGet(AOP(left),offset,FALSE));
3304 emitcode("and","a,%s",
3305 aopGet(AOP(right),offset,FALSE));
3307 aopPut(AOP(result),"a",offset);
3314 freeAsmop(left,NULL,ic);
3315 freeAsmop(right,NULL,ic);
3316 freeAsmop(result,NULL,ic);
3319 /*-----------------------------------------------------------------*/
3320 /* genOr - code for or */
3321 /*-----------------------------------------------------------------*/
3322 static void genOr (iCode *ic, iCode *ifx)
3324 operand *left, *right, *result;
3326 unsigned long lit = 0L;
3328 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3329 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3330 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3333 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3335 AOP_TYPE(left), AOP_TYPE(right));
3336 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3338 AOP_SIZE(left), AOP_SIZE(right));
3341 /* if left is a literal & right is not then exchange them */
3342 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3343 AOP_NEEDSACC(left)) {
3344 operand *tmp = right ;
3349 /* if result = right then exchange them */
3350 if(sameRegs(AOP(result),AOP(right))){
3351 operand *tmp = right ;
3356 /* if right is bit then exchange them */
3357 if (AOP_TYPE(right) == AOP_CRY &&
3358 AOP_TYPE(left) != AOP_CRY){
3359 operand *tmp = right ;
3363 if(AOP_TYPE(right) == AOP_LIT)
3364 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3366 size = AOP_SIZE(result);
3368 if (AOP_TYPE(left) == AOP_CRY){
3373 if((AOP_TYPE(right) == AOP_LIT) &&
3374 (AOP_TYPE(result) == AOP_CRY) &&
3375 (AOP_TYPE(left) != AOP_CRY)){
3380 /* if left is same as result */
3381 if(sameRegs(AOP(result),AOP(left))){
3382 for(;size--; offset++) {
3383 if(AOP_TYPE(right) == AOP_LIT){
3384 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3387 MOVA(aopGet(AOP(left),offset,FALSE));
3388 emitcode("or","a,%s",
3389 aopGet(AOP(right),offset,FALSE));
3390 aopPut(AOP(result),"a", offset);
3393 if (AOP_TYPE(left) == AOP_ACC)
3394 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3396 MOVA(aopGet(AOP(left),offset,FALSE));
3397 emitcode("or","a,%s",
3398 aopGet(AOP(right),offset,FALSE));
3399 aopPut(AOP(result),"a", offset);
3404 // left & result in different registers
3405 if(AOP_TYPE(result) == AOP_CRY){
3407 } else for(;(size--);offset++){
3409 // result = left & right
3410 if(AOP_TYPE(right) == AOP_LIT){
3411 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3413 aopGet(AOP(left),offset,FALSE),
3418 // faster than result <- left, anl result,right
3419 // and better if result is SFR
3420 if (AOP_TYPE(left) == AOP_ACC)
3421 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3423 MOVA(aopGet(AOP(left),offset,FALSE));
3424 emitcode("or","a,%s",
3425 aopGet(AOP(right),offset,FALSE));
3427 aopPut(AOP(result),"a",offset);
3428 /* PENDING: something weird is going on here. Add exception. */
3429 if (AOP_TYPE(result) == AOP_ACC)
3435 freeAsmop(left,NULL,ic);
3436 freeAsmop(right,NULL,ic);
3437 freeAsmop(result,NULL,ic);
3440 /*-----------------------------------------------------------------*/
3441 /* genXor - code for xclusive or */
3442 /*-----------------------------------------------------------------*/
3443 static void genXor (iCode *ic, iCode *ifx)
3445 operand *left, *right, *result;
3447 unsigned long lit = 0L;
3449 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3450 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3451 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3453 /* if left is a literal & right is not then exchange them */
3454 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3455 AOP_NEEDSACC(left)) {
3456 operand *tmp = right ;
3461 /* if result = right then exchange them */
3462 if(sameRegs(AOP(result),AOP(right))){
3463 operand *tmp = right ;
3468 /* if right is bit then exchange them */
3469 if (AOP_TYPE(right) == AOP_CRY &&
3470 AOP_TYPE(left) != AOP_CRY){
3471 operand *tmp = right ;
3475 if(AOP_TYPE(right) == AOP_LIT)
3476 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3478 size = AOP_SIZE(result);
3480 if (AOP_TYPE(left) == AOP_CRY){
3485 if((AOP_TYPE(right) == AOP_LIT) &&
3486 (AOP_TYPE(result) == AOP_CRY) &&
3487 (AOP_TYPE(left) != AOP_CRY)){
3492 /* if left is same as result */
3493 if(sameRegs(AOP(result),AOP(left))){
3494 for(;size--; offset++) {
3495 if(AOP_TYPE(right) == AOP_LIT){
3496 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3499 MOVA(aopGet(AOP(right),offset,FALSE));
3500 emitcode("xor","a,%s",
3501 aopGet(AOP(left),offset,FALSE));
3502 aopPut(AOP(result),"a",0);
3505 if (AOP_TYPE(left) == AOP_ACC)
3506 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3508 MOVA(aopGet(AOP(right),offset,FALSE));
3509 emitcode("xor","a,%s",
3510 aopGet(AOP(left),offset,FALSE));
3511 aopPut(AOP(result),"a",0);
3516 // left & result in different registers
3517 if(AOP_TYPE(result) == AOP_CRY){
3519 } else for(;(size--);offset++){
3521 // result = left & right
3522 if(AOP_TYPE(right) == AOP_LIT){
3523 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3525 aopGet(AOP(left),offset,FALSE),
3530 // faster than result <- left, anl result,right
3531 // and better if result is SFR
3532 if (AOP_TYPE(left) == AOP_ACC)
3533 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3535 MOVA(aopGet(AOP(right),offset,FALSE));
3536 emitcode("xor","a,%s",
3537 aopGet(AOP(left),offset,FALSE));
3538 aopPut(AOP(result),"a",0);
3540 aopPut(AOP(result),"a",offset);
3545 freeAsmop(left,NULL,ic);
3546 freeAsmop(right,NULL,ic);
3547 freeAsmop(result,NULL,ic);
3550 /*-----------------------------------------------------------------*/
3551 /* genInline - write the inline code out */
3552 /*-----------------------------------------------------------------*/
3553 static void genInline (iCode *ic)
3555 char buffer[MAX_INLINEASM];
3559 inLine += (!options.asmpeep);
3560 strcpy(buffer,IC_INLINE(ic));
3562 /* emit each line as a code */
3581 /* emitcode("",buffer); */
3582 inLine -= (!options.asmpeep);
3585 /*-----------------------------------------------------------------*/
3586 /* genRRC - rotate right with carry */
3587 /*-----------------------------------------------------------------*/
3588 static void genRRC (iCode *ic)
3593 /*-----------------------------------------------------------------*/
3594 /* genRLC - generate code for rotate left with carry */
3595 /*-----------------------------------------------------------------*/
3596 static void genRLC (iCode *ic)
3601 /*-----------------------------------------------------------------*/
3602 /* shiftR2Left2Result - shift right two bytes from left to result */
3603 /*-----------------------------------------------------------------*/
3604 static void shiftR2Left2Result (operand *left, int offl,
3605 operand *result, int offr,
3606 int shCount, int sign)
3608 movLeft2Result(left, offl, result, offr, 0);
3609 movLeft2Result(left, offl+1, result, offr+1, 0);
3615 /* if (AOP(result)->type == AOP_REG) {*/
3618 symbol *tlbl , *tlbl1;
3621 tlbl = newiTempLabel(NULL);
3622 tlbl1 = newiTempLabel(NULL);
3624 /* Left is already in result - so now do the shift */
3626 emit2("ld a,!immedbyte+1", shCount);
3627 emit2("!shortjp !tlabel", tlbl1->key+100);
3628 emitLabel(tlbl->key+100);
3631 emitcode("or", "a,a");
3634 l = aopGet(AOP(result), --offset, FALSE);
3635 emitcode("rr","%s", l);
3638 emitLabel(tlbl1->key+100);
3639 emitcode("dec", "a");
3640 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3645 /*-----------------------------------------------------------------*/
3646 /* shiftL2Left2Result - shift left two bytes from left to result */
3647 /*-----------------------------------------------------------------*/
3648 static void shiftL2Left2Result (operand *left, int offl,
3649 operand *result, int offr, int shCount)
3651 if(sameRegs(AOP(result), AOP(left)) &&
3652 ((offl + MSB16) == offr)){
3655 /* Copy left into result */
3656 movLeft2Result(left, offl, result, offr, 0);
3657 movLeft2Result(left, offl+1, result, offr+1, 0);
3659 /* PENDING: for now just see if it'll work. */
3660 /*if (AOP(result)->type == AOP_REG) { */
3664 symbol *tlbl , *tlbl1;
3667 tlbl = newiTempLabel(NULL);
3668 tlbl1 = newiTempLabel(NULL);
3670 /* Left is already in result - so now do the shift */
3672 emit2("ld a,!immedbyte+1", shCount);
3673 emit2("!shortjp !tlabel", tlbl1->key+100);
3674 emitLabel(tlbl->key+100);
3677 emitcode("or", "a,a");
3679 l = aopGet(AOP(result),offset++,FALSE);
3680 emitcode("rl","%s", l);
3683 emitLabel(tlbl1->key+100);
3684 emitcode("dec", "a");
3685 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3690 /*-----------------------------------------------------------------*/
3691 /* AccRol - rotate left accumulator by known count */
3692 /*-----------------------------------------------------------------*/
3693 static void AccRol (int shCount)
3695 shCount &= 0x0007; // shCount : 0..7
3732 /*-----------------------------------------------------------------*/
3733 /* AccLsh - left shift accumulator by known count */
3734 /*-----------------------------------------------------------------*/
3735 static void AccLsh (int shCount)
3739 emitcode("add","a,a");
3741 else if(shCount == 2) {
3742 emitcode("add","a,a");
3743 emitcode("add","a,a");
3745 /* rotate left accumulator */
3747 /* and kill the lower order bits */
3748 emit2("and a,!immedbyte", SLMask[shCount]);
3753 /*-----------------------------------------------------------------*/
3754 /* shiftL1Left2Result - shift left one byte from left to result */
3755 /*-----------------------------------------------------------------*/
3756 static void shiftL1Left2Result (operand *left, int offl,
3757 operand *result, int offr, int shCount)
3760 l = aopGet(AOP(left),offl,FALSE);
3762 /* shift left accumulator */
3764 aopPut(AOP(result),"a",offr);
3768 /*-----------------------------------------------------------------*/
3769 /* genlshTwo - left shift two bytes by known amount != 0 */
3770 /*-----------------------------------------------------------------*/
3771 static void genlshTwo (operand *result,operand *left, int shCount)
3773 int size = AOP_SIZE(result);
3777 /* if shCount >= 8 */
3782 movLeft2Result(left, LSB, result, MSB16, 0);
3783 aopPut(AOP(result),zero, 0);
3784 shiftL1Left2Result(left, MSB16, result, MSB16, shCount);
3787 movLeft2Result(left, LSB, result, MSB16, 0);
3788 aopPut(AOP(result),zero, 0);
3792 aopPut(AOP(result),zero,LSB);
3795 /* 1 <= shCount <= 7 */
3801 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3806 /*-----------------------------------------------------------------*/
3807 /* genlshOne - left shift a one byte quantity by known count */
3808 /*-----------------------------------------------------------------*/
3809 static void genlshOne (operand *result, operand *left, int shCount)
3811 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3814 /*-----------------------------------------------------------------*/
3815 /* genLeftShiftLiteral - left shifting by known count */
3816 /*-----------------------------------------------------------------*/
3817 static void genLeftShiftLiteral (operand *left,
3822 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3825 freeAsmop(right,NULL,ic);
3827 aopOp(left,ic,FALSE, FALSE);
3828 aopOp(result,ic,FALSE, FALSE);
3830 size = getSize(operandType(result));
3833 emitcode("; shift left ","result %d, left %d",size,
3837 /* I suppose that the left size >= result size */
3842 else if(shCount >= (size * 8))
3844 aopPut(AOP(result),zero,size);
3848 genlshOne (result,left,shCount);
3851 genlshTwo (result,left,shCount);
3860 freeAsmop(left,NULL,ic);
3861 freeAsmop(result,NULL,ic);
3864 /*-----------------------------------------------------------------*/
3865 /* genLeftShift - generates code for left shifting */
3866 /*-----------------------------------------------------------------*/
3867 static void genLeftShift (iCode *ic)
3871 symbol *tlbl , *tlbl1;
3872 operand *left,*right, *result;
3874 right = IC_RIGHT(ic);
3876 result = IC_RESULT(ic);
3878 aopOp(right,ic,FALSE, FALSE);
3880 /* if the shift count is known then do it
3881 as efficiently as possible */
3882 if (AOP_TYPE(right) == AOP_LIT) {
3883 genLeftShiftLiteral (left,right,result,ic);
3887 /* shift count is unknown then we have to form a loop get the loop
3888 count in B : Note: we take only the lower order byte since
3889 shifting more that 32 bits make no sense anyway, ( the largest
3890 size of an object can be only 32 bits ) */
3891 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3892 emitcode("inc","a");
3893 freeAsmop (right,NULL,ic);
3894 aopOp(left,ic,FALSE, FALSE);
3895 aopOp(result,ic,FALSE, FALSE);
3897 /* now move the left to the result if they are not the
3900 if (!sameRegs(AOP(left),AOP(result))) {
3902 size = AOP_SIZE(result);
3905 l = aopGet(AOP(left),offset,FALSE);
3906 aopPut(AOP(result),l,offset);
3911 size = AOP_SIZE(result);
3914 l = aopGet(AOP(left),offset,FALSE);
3915 aopPut(AOP(result),l,offset);
3921 tlbl = newiTempLabel(NULL);
3922 size = AOP_SIZE(result);
3924 tlbl1 = newiTempLabel(NULL);
3926 emit2("!shortjp !tlabel", tlbl1->key+100);
3927 emitLabel(tlbl->key+100);
3928 l = aopGet(AOP(result),offset,FALSE);
3929 emitcode("or", "a,a");
3931 l = aopGet(AOP(result),offset++,FALSE);
3932 emitcode("rl","%s", l);
3934 emitLabel(tlbl1->key+100);
3935 emitcode("dec", "a");
3936 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3938 freeAsmop(left,NULL,ic);
3939 freeAsmop(result,NULL,ic);
3942 /*-----------------------------------------------------------------*/
3943 /* genrshOne - left shift two bytes by known amount != 0 */
3944 /*-----------------------------------------------------------------*/
3945 static void genrshOne (operand *result,operand *left, int shCount)
3948 int size = AOP_SIZE(result);
3954 l = aopGet(AOP(left),0,FALSE);
3955 if (AOP(result)->type == AOP_REG) {
3956 aopPut(AOP(result), l, 0);
3957 l = aopGet(AOP(result), 0, FALSE);
3959 emitcode("srl", "%s", l);
3964 emitcode("srl", "a");
3966 aopPut(AOP(result),"a",0);
3970 /*-----------------------------------------------------------------*/
3971 /* AccRsh - right shift accumulator by known count */
3972 /*-----------------------------------------------------------------*/
3973 static void AccRsh (int shCount)
3976 /* rotate right accumulator */
3977 AccRol(8 - shCount);
3978 /* and kill the higher order bits */
3979 emit2("and a,!immedbyte", SRMask[shCount]);
3983 /*-----------------------------------------------------------------*/
3984 /* shiftR1Left2Result - shift right one byte from left to result */
3985 /*-----------------------------------------------------------------*/
3986 static void shiftR1Left2Result (operand *left, int offl,
3987 operand *result, int offr,
3988 int shCount, int sign)
3990 MOVA(aopGet(AOP(left),offl,FALSE));
3997 aopPut(AOP(result),"a",offr);
4000 /*-----------------------------------------------------------------*/
4001 /* genrshTwo - right shift two bytes by known amount != 0 */
4002 /*-----------------------------------------------------------------*/
4003 static void genrshTwo (operand *result,operand *left,
4004 int shCount, int sign)
4006 /* if shCount >= 8 */
4010 shiftR1Left2Result(left, MSB16, result, LSB,
4014 movLeft2Result(left, MSB16, result, LSB, sign);
4016 aopPut(AOP(result),zero,1);
4018 /* 1 <= shCount <= 7 */
4020 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
4024 /*-----------------------------------------------------------------*/
4025 /* genRightShiftLiteral - left shifting by known count */
4026 /*-----------------------------------------------------------------*/
4027 static void genRightShiftLiteral (operand *left,
4032 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
4035 freeAsmop(right,NULL,ic);
4037 aopOp(left,ic,FALSE, FALSE);
4038 aopOp(result,ic,FALSE, FALSE);
4040 size = getSize(operandType(result));
4042 emitcode("; shift right ","result %d, left %d",size,
4045 /* I suppose that the left size >= result size */
4050 else if(shCount >= (size * 8))
4052 aopPut(AOP(result),zero,size);
4056 genrshOne(result, left, shCount);
4059 /* PENDING: sign support */
4060 genrshTwo(result, left, shCount, FALSE);
4069 freeAsmop(left,NULL,ic);
4070 freeAsmop(result,NULL,ic);
4073 /*-----------------------------------------------------------------*/
4074 /* genRightShift - generate code for right shifting */
4075 /*-----------------------------------------------------------------*/
4076 static void genRightShift (iCode *ic)
4078 operand *right, *left, *result;
4080 int size, offset, first = 1;
4084 symbol *tlbl, *tlbl1 ;
4086 /* if signed then we do it the hard way preserve the
4087 sign bit moving it inwards */
4088 retype = getSpec(operandType(IC_RESULT(ic)));
4090 is_signed = !SPEC_USIGN(retype);
4092 /* signed & unsigned types are treated the same : i.e. the
4093 signed is NOT propagated inwards : quoting from the
4094 ANSI - standard : "for E1 >> E2, is equivalent to division
4095 by 2**E2 if unsigned or if it has a non-negative value,
4096 otherwise the result is implementation defined ", MY definition
4097 is that the sign does not get propagated */
4099 right = IC_RIGHT(ic);
4101 result = IC_RESULT(ic);
4103 aopOp(right,ic,FALSE, FALSE);
4105 /* if the shift count is known then do it
4106 as efficiently as possible */
4107 if (AOP_TYPE(right) == AOP_LIT) {
4108 genRightShiftLiteral(left,right,result,ic);
4112 aopOp(left,ic,FALSE, FALSE);
4113 aopOp(result,ic,FALSE, FALSE);
4115 /* now move the left to the result if they are not the
4117 if (!sameRegs(AOP(left),AOP(result)) &&
4118 AOP_SIZE(result) > 1) {
4120 size = AOP_SIZE(result);
4123 l = aopGet(AOP(left),offset,FALSE);
4124 aopPut(AOP(result),l,offset);
4129 emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
4130 emitcode("inc","a");
4131 freeAsmop (right, NULL, ic);
4133 tlbl = newiTempLabel(NULL);
4134 tlbl1= newiTempLabel(NULL);
4135 size = AOP_SIZE(result);
4138 emit2("!shortjp !tlabel", tlbl1->key+100);
4139 emitLabel(tlbl->key+100);
4141 l = aopGet(AOP(result),offset--,FALSE);
4144 emitcode("sra", "%s", l);
4146 emitcode("srl", "%s", l);
4150 emitcode("rr", "%s", l);
4152 emitLabel(tlbl1->key+100);
4153 emitcode("dec", "a");
4154 emit2("!shortjp nz,!tlabel", tlbl->key+100);
4156 freeAsmop(left,NULL,ic);
4157 freeAsmop(result,NULL,ic);
4160 /*-----------------------------------------------------------------*/
4161 /* genGenPointerGet - get value from generic pointer space */
4162 /*-----------------------------------------------------------------*/
4163 static void genGenPointerGet (operand *left,
4164 operand *result, iCode *ic)
4167 link *retype = getSpec(operandType(result));
4173 aopOp(left,ic,FALSE, FALSE);
4174 aopOp(result,ic,FALSE, FALSE);
4176 if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
4178 if (isPtrPair(AOP(left)))
4180 tsprintf(buffer, "!*pair", getPairName(AOP(left)));
4181 aopPut(AOP(result), buffer, 0);
4184 emit2("ld a,!*pair", getPairName(AOP(left)));
4185 aopPut(AOP(result),"a", 0);
4187 freeAsmop(left,NULL,ic);
4191 /* For now we always load into IY */
4192 /* if this is remateriazable */
4193 fetchPair(pair, AOP(left));
4195 /* so iy now contains the address */
4196 freeAsmop(left,NULL,ic);
4198 /* if bit then unpack */
4199 if (IS_BITVAR(retype)) {
4203 size = AOP_SIZE(result);
4207 /* PENDING: make this better */
4208 if (!IS_GB && AOP(result)->type == AOP_REG) {
4209 aopPut(AOP(result), "!*hl", offset++);
4212 emit2("ld a,!*pair", _pairs[pair].name);
4213 aopPut(AOP(result),"a",offset++);
4216 emit2("inc %s", _pairs[pair].name);
4217 _G.pairs[pair].offset++;
4223 freeAsmop(result,NULL,ic);
4226 /*-----------------------------------------------------------------*/
4227 /* genPointerGet - generate code for pointer get */
4228 /*-----------------------------------------------------------------*/
4229 static void genPointerGet (iCode *ic)
4231 operand *left, *result ;
4235 result = IC_RESULT(ic) ;
4237 /* depending on the type of pointer we need to
4238 move it to the correct pointer register */
4239 type = operandType(left);
4240 etype = getSpec(type);
4242 genGenPointerGet (left,result,ic);
4245 bool isRegOrLit(asmop *aop)
4247 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4252 /*-----------------------------------------------------------------*/
4253 /* genGenPointerSet - stores the value into a pointer location */
4254 /*-----------------------------------------------------------------*/
4255 static void genGenPointerSet (operand *right,
4256 operand *result, iCode *ic)
4259 link *retype = getSpec(operandType(right));
4260 PAIR_ID pairId = PAIR_HL;
4262 aopOp(result,ic,FALSE, FALSE);
4263 aopOp(right,ic,FALSE, FALSE);
4268 /* Handle the exceptions first */
4269 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
4271 char *l = aopGet(AOP(right), 0, FALSE);
4272 const char *pair = getPairName(AOP(result));
4273 if (canAssignToPtr(l) && isPtr(pair)) {
4274 emit2("ld !*pair,%s", pair, l);
4278 emit2("ld !*pair,a", pair);
4283 /* if the operand is already in dptr
4284 then we do nothing else we move the value to dptr */
4285 if (AOP_TYPE(result) != AOP_STR) {
4286 fetchPair(pairId, AOP(result));
4288 /* so hl know contains the address */
4289 freeAsmop(result,NULL,ic);
4291 /* if bit then unpack */
4292 if (IS_BITVAR(retype)) {
4296 size = AOP_SIZE(right);
4300 char *l = aopGet(AOP(right),offset,FALSE);
4301 if (isRegOrLit(AOP(right)) && !IS_GB) {
4302 emit2("ld !*pair,%s", _pairs[pairId].name, l);
4306 emit2("ld !*pair,a", _pairs[pairId].name);
4309 emitcode("inc", _pairs[pairId].name);
4310 _G.pairs[pairId].offset++;
4316 freeAsmop(right,NULL,ic);
4319 /*-----------------------------------------------------------------*/
4320 /* genPointerSet - stores the value into a pointer location */
4321 /*-----------------------------------------------------------------*/
4322 static void genPointerSet (iCode *ic)
4324 operand *right, *result ;
4327 right = IC_RIGHT(ic);
4328 result = IC_RESULT(ic) ;
4330 /* depending on the type of pointer we need to
4331 move it to the correct pointer register */
4332 type = operandType(result);
4333 etype = getSpec(type);
4335 genGenPointerSet (right,result,ic);
4338 /*-----------------------------------------------------------------*/
4339 /* genIfx - generate code for Ifx statement */
4340 /*-----------------------------------------------------------------*/
4341 static void genIfx (iCode *ic, iCode *popIc)
4343 operand *cond = IC_COND(ic);
4346 aopOp(cond,ic,FALSE, TRUE);
4348 /* get the value into acc */
4349 if (AOP_TYPE(cond) != AOP_CRY)
4353 /* the result is now in the accumulator */
4354 freeAsmop(cond,NULL,ic);
4356 /* if there was something to be popped then do it */
4360 /* if the condition is a bit variable */
4361 if (isbit && IS_ITEMP(cond) &&
4363 genIfxJump(ic,SPIL_LOC(cond)->rname);
4365 if (isbit && !IS_ITEMP(cond))
4366 genIfxJump(ic,OP_SYMBOL(cond)->rname);
4373 /*-----------------------------------------------------------------*/
4374 /* genAddrOf - generates code for address of */
4375 /*-----------------------------------------------------------------*/
4376 static void genAddrOf (iCode *ic)
4378 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4380 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4382 /* if the operand is on the stack then we
4383 need to get the stack offset of this
4388 if (sym->stack <= 0) {
4389 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
4392 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
4394 emitcode("ld", "d,h");
4395 emitcode("ld", "e,l");
4398 emit2("ld de,!hashedstr", sym->rname);
4400 aopPut(AOP(IC_RESULT(ic)), "e", 0);
4401 aopPut(AOP(IC_RESULT(ic)), "d", 1);
4406 /* if it has an offset then we need to compute it */
4407 emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
4408 emitcode("add", "hl,sp");
4411 emitcode("ld", "hl,#%s", sym->rname);
4413 aopPut(AOP(IC_RESULT(ic)), "l", 0);
4414 aopPut(AOP(IC_RESULT(ic)), "h", 1);
4416 freeAsmop(IC_RESULT(ic),NULL,ic);
4419 /*-----------------------------------------------------------------*/
4420 /* genAssign - generate code for assignment */
4421 /*-----------------------------------------------------------------*/
4422 static void genAssign (iCode *ic)
4424 operand *result, *right;
4426 unsigned long lit = 0L;
4428 result = IC_RESULT(ic);
4429 right = IC_RIGHT(ic) ;
4432 /* Dont bother assigning if they are the same */
4433 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
4434 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
4439 aopOp(right,ic,FALSE, FALSE);
4440 aopOp(result,ic,TRUE, FALSE);
4442 /* if they are the same registers */
4443 if (sameRegs(AOP(right),AOP(result))) {
4444 emitcode("", "; (registers are the same)");
4448 /* if the result is a bit */
4449 if (AOP_TYPE(result) == AOP_CRY) {
4454 size = AOP_SIZE(result);
4457 if(AOP_TYPE(right) == AOP_LIT)
4458 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4459 if (isPair(AOP(result))) {
4460 fetchPair(getPairId(AOP(result)), AOP(right));
4462 else if((size > 1) &&
4463 (AOP_TYPE(result) != AOP_REG) &&
4464 (AOP_TYPE(right) == AOP_LIT) &&
4465 !IS_FLOAT(operandType(right)) &&
4467 bool fXored = FALSE;
4469 /* Work from the top down.
4470 Done this way so that we can use the cached copy of 0
4471 in A for a fast clear */
4473 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
4474 if (!fXored && size>1) {
4475 emitcode("xor", "a,a");
4479 aopPut(AOP(result),"a",offset);
4482 aopPut(AOP(result), zero, offset);
4487 aopGet(AOP(right),offset,FALSE),
4492 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result)) && IS_GB) {
4493 /* Special case. Load into a and d, then load out. */
4494 MOVA(aopGet(AOP(right), 0, FALSE));
4495 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
4496 aopPut(AOP(result), "a", 0);
4497 aopPut(AOP(result), "e", 1);
4500 /* PENDING: do this check better */
4501 if (requiresHL(AOP(right)) && requiresHL(AOP(result))) {
4502 MOVA(aopGet(AOP(right), offset, FALSE));
4503 aopPut(AOP(result), "a", offset);
4507 aopGet(AOP(right),offset,FALSE),
4514 freeAsmop(right,NULL,ic);
4515 freeAsmop(result,NULL,ic);
4518 /*-----------------------------------------------------------------*/
4519 /* genJumpTab - genrates code for jump table */
4520 /*-----------------------------------------------------------------*/
4521 static void genJumpTab (iCode *ic)
4526 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
4527 /* get the condition into accumulator */
4528 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
4530 emitcode("push", "de");
4531 emitcode("ld", "e,%s", l);
4532 emit2("ld d,!zero");
4533 jtab = newiTempLabel(NULL);
4535 emit2("ld hl,!immed!tlabel", jtab->key+100);
4536 emitcode("add", "hl,de");
4537 emitcode("add", "hl,de");
4538 emitcode("add", "hl,de");
4539 freeAsmop(IC_JTCOND(ic),NULL,ic);
4541 emitcode("pop", "de");
4543 emitLabel(jtab->key+100);
4544 /* now generate the jump labels */
4545 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4546 jtab = setNextItem(IC_JTLABELS(ic)))
4547 emit2("jp !tlabel", jtab->key+100);
4550 /*-----------------------------------------------------------------*/
4551 /* genCast - gen code for casting */
4552 /*-----------------------------------------------------------------*/
4553 static void genCast (iCode *ic)
4555 operand *result = IC_RESULT(ic);
4556 link *ctype = operandType(IC_LEFT(ic));
4557 operand *right = IC_RIGHT(ic);
4560 /* if they are equivalent then do nothing */
4561 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4564 aopOp(right,ic,FALSE, FALSE);
4565 aopOp(result,ic,FALSE, FALSE);
4567 /* if the result is a bit */
4568 if (AOP_TYPE(result) == AOP_CRY) {
4572 /* if they are the same size : or less */
4573 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4575 /* if they are in the same place */
4576 if (sameRegs(AOP(right),AOP(result)))
4579 /* if they in different places then copy */
4580 size = AOP_SIZE(result);
4584 aopGet(AOP(right),offset,FALSE),
4591 /* PENDING: should be OK. */
4593 /* if the result is of type pointer */
4594 if (IS_PTR(ctype)) {
4599 /* so we now know that the size of destination is greater
4600 than the size of the source */
4601 /* we move to result for the size of source */
4602 size = AOP_SIZE(right);
4606 aopGet(AOP(right),offset,FALSE),
4611 /* now depending on the sign of the destination */
4612 size = AOP_SIZE(result) - AOP_SIZE(right);
4613 /* Unsigned or not an integral type - right fill with zeros */
4614 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4616 aopPut(AOP(result),zero,offset++);
4618 /* we need to extend the sign :{ */
4619 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4622 emitcode("", "; genCast: sign extend untested.");
4623 emitcode("rla", "");
4624 emitcode("sbc", "a,a");
4626 aopPut(AOP(result),"a",offset++);
4630 freeAsmop(right, NULL, ic);
4631 freeAsmop(result, NULL, ic);
4634 /*-----------------------------------------------------------------*/
4635 /* genReceive - generate code for a receive iCode */
4636 /*-----------------------------------------------------------------*/
4637 static void genReceive (iCode *ic)
4639 if (isOperandInFarSpace(IC_RESULT(ic)) &&
4640 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4641 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4645 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4647 assignResultValue(IC_RESULT(ic));
4650 freeAsmop(IC_RESULT(ic),NULL,ic);
4653 /*-----------------------------------------------------------------*/
4654 /* genZ80Code - generate code for Z80 based controllers */
4655 /*-----------------------------------------------------------------*/
4656 void genZ80Code (iCode *lic)
4663 _fReturn = _gbz80_return;
4664 _fTmp = _gbz80_return;
4667 _fReturn = _z80_return;
4668 _fTmp = _z80_return;
4670 tsprintf(zero, "!zero");
4672 lineHead = lineCurr = NULL;
4674 /* if debug information required */
4675 if (options.debug && currFunc) {
4676 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4678 if (IS_STATIC(currFunc->etype))
4679 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4681 emitcode("","G$%s$0$0 ==.",currFunc->name);
4684 /* stack pointer name */
4688 for (ic = lic ; ic ; ic = ic->next ) {
4690 if ( cln != ic->lineno ) {
4691 if ( options.debug ) {
4693 emitcode("","C$%s$%d$%d$%d ==.",
4694 ic->filename,ic->lineno,
4695 ic->level,ic->block);
4698 emitcode(";","%s %d",ic->filename,ic->lineno);
4701 /* if the result is marked as
4702 spilt and rematerializable or code for
4703 this has already been generated then
4705 if (resultRemat(ic) || ic->generated )
4708 /* depending on the operation */
4711 emitcode("", "; genNot");
4716 emitcode("", "; genCpl");
4721 emitcode("", "; genUminus");
4726 emitcode("", "; genIpush");
4731 /* IPOP happens only when trying to restore a
4732 spilt live range, if there is an ifx statement
4733 following this pop then the if statement might
4734 be using some of the registers being popped which
4735 would destory the contents of the register so
4736 we need to check for this condition and handle it */
4738 ic->next->op == IFX &&
4739 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4740 emitcode("", "; genIfx");
4741 genIfx (ic->next,ic);
4744 emitcode("", "; genIpop");
4750 emitcode("", "; genCall");
4755 emitcode("", "; genPcall");
4760 emitcode("", "; genFunction");
4765 emitcode("", "; genEndFunction");
4766 genEndFunction (ic);
4770 emitcode("", "; genRet");
4775 emitcode("", "; genLabel");
4780 emitcode("", "; genGoto");
4785 emitcode("", "; genPlus");
4790 emitcode("", "; genMinus");
4795 emitcode("", "; genMult");
4800 emitcode("", "; genDiv");
4805 emitcode("", "; genMod");
4810 emitcode("", "; genCmpGt");
4811 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4815 emitcode("", "; genCmpLt");
4816 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4823 /* note these two are xlated by algebraic equivalence
4824 during parsing SDCC.y */
4825 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4826 "got '>=' or '<=' shouldn't have come here");
4830 emitcode("", "; genCmpEq");
4831 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4835 emitcode("", "; genAndOp");
4840 emitcode("", "; genOrOp");
4845 emitcode("", "; genXor");
4846 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4850 emitcode("", "; genOr");
4851 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4855 emitcode("", "; genAnd");
4856 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4860 emitcode("", "; genInline");
4865 emitcode("", "; genRRC");
4870 emitcode("", "; genRLC");
4875 emitcode("", "; genHBIT");
4879 emitcode("", "; genLeftShift");
4884 emitcode("", "; genRightShift");
4888 case GET_VALUE_AT_ADDRESS:
4889 emitcode("", "; genPointerGet");
4895 if (POINTER_SET(ic)) {
4896 emitcode("", "; genAssign (pointer)");
4900 emitcode("", "; genAssign");
4906 emitcode("", "; genIfx");
4911 emitcode("", "; genAddrOf");
4916 emitcode("", "; genJumpTab");
4921 emitcode("", "; genCast");
4926 emitcode("", "; genReceive");
4931 emitcode("", "; addSet");
4932 addSet(&sendSet,ic);
4937 /* piCode(ic,stdout); */
4943 /* now we are ready to call the
4944 peep hole optimizer */
4945 if (!options.nopeep)
4946 peepHole (&lineHead);
4948 /* This is unfortunate */
4949 /* now do the actual printing */
4951 FILE *fp = codeOutFile;
4952 if (isInHome() && codeOutFile == code->oFile)
4953 codeOutFile = home->oFile;
4954 printLine (lineHead, codeOutFile);
4955 if (_G.flush_statics) {
4957 _G.flush_statics = 0;