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);
729 tsprintf(buffer, "!immedword", v);
731 tsprintf(buffer, "!constword", v);
732 ALLOC_ATOMIC(rs,strlen(buffer)+1);
733 return strcpy (rs,buffer);
738 convertFloat(&f, floatFromVal(val));
740 tsprintf(buffer, "!immedword", f.w[offset/2]);
742 tsprintf(buffer, "!constword", f.w[offset/2]);
743 ALLOC_ATOMIC(rs,strlen(buffer)+1);
744 return strcpy (rs,buffer);
752 char *aopGetWord(asmop *aop, int offset)
754 return aopGetLitWordLong(aop, offset, TRUE);
757 bool isPtr(const char *s)
759 if (!strcmp(s, "hl"))
761 if (!strcmp(s, "ix"))
763 if (!strcmp(s, "iy"))
768 static void adjustPair(const char *pair, int *pold, int new)
772 while (*pold < new) {
773 emitcode("inc", "%s", pair);
776 while (*pold > new) {
777 emitcode("dec", "%s", pair);
782 static void spillPair(PAIR_ID pairId)
784 _G.pairs[pairId].last_type = AOP_INVALID;
785 _G.pairs[pairId].lit = NULL;
788 static void spillCached(void)
794 static bool requiresHL(asmop *aop)
805 static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
808 const char *pair = _pairs[pairId].name;
809 l = aopGetLitWordLong(left, 0, FALSE);
813 if (pairId == PAIR_HL || pairId == PAIR_IY) {
814 if (_G.pairs[pairId].last_type == left->type) {
815 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
816 if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
817 adjustPair(pair, &_G.pairs[pairId].offset, offset);
820 if (pairId == PAIR_IY && abs(offset)<127) {
826 _G.pairs[pairId].last_type = left->type;
827 _G.pairs[pairId].lit = gc_strdup(l);
828 _G.pairs[pairId].offset = offset;
830 if (IS_GB && pairId == PAIR_DE) {
831 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
832 if (abs(_G.pairs[pairId].offset - offset) < 3) {
833 adjustPair(pair, &_G.pairs[pairId].offset, offset);
837 _G.pairs[pairId].last_type = left->type;
838 _G.pairs[pairId].lit = gc_strdup(l);
839 _G.pairs[pairId].offset = offset;
841 /* Both a lit on the right and a true symbol on the left */
843 emit2("ld %s,!hashedstr + %u", pair, l, offset);
845 emit2("ld %s,!hashedstr", pair, l);
848 static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
850 /* if this is remateriazable */
851 if (isLitWord(aop)) {
852 fetchLitPair(pairId, aop, offset);
854 else { /* we need to get it byte by byte */
855 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
856 aopGet(aop, offset, FALSE);
860 emit2("ld h,!immedbyte", 0);
868 emit2("; WARNING: mlh woosed out. This code is invalid.");
871 else if (IS_Z80 && aop->type == AOP_IY) {
872 /* Instead of fetching relative to IY, just grab directly
873 from the address IY refers to */
874 char *l = aopGetLitWordLong(aop, offset, FALSE);
876 emit2("ld %s,(%s)", _pairs[pairId].name, l);
879 emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE));
880 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, offset+1, FALSE));
882 /* PENDING: check? */
883 if (pairId == PAIR_HL)
888 static void fetchPair(PAIR_ID pairId, asmop *aop)
890 fetchPairLong(pairId, aop, 0);
893 static void fetchHL(asmop *aop)
895 fetchPair(PAIR_HL, aop);
898 static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
900 assert(pairId == PAIR_HL || pairId == PAIR_IY);
904 fetchLitPair(pairId, aop, 0);
907 fetchLitPair(pairId, aop, offset);
908 _G.pairs[pairId].offset = offset;
911 /* Doesnt include _G.stack.pushed */
912 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
913 if (aop->aopu.aop_stk > 0) {
914 abso += _G.stack.param_offset;
916 assert(pairId == PAIR_HL);
917 /* In some cases we can still inc or dec hl */
918 if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
919 adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
922 emit2("!ldahlsp", abso +_G.stack.pushed);
924 _G.pairs[pairId].offset = abso;
930 _G.pairs[pairId].last_type = aop->type;
933 static void emitLabel(int key)
935 emit2("!tlabeldef", key);
939 /*-----------------------------------------------------------------*/
940 /* aopGet - for fetching value of the aop */
941 /*-----------------------------------------------------------------*/
942 static char *aopGet(asmop *aop, int offset, bool bit16)
947 /* offset is greater than size then zero */
948 /* PENDING: this seems a bit screwed in some pointer cases. */
949 if (offset > (aop->size - 1) &&
950 aop->type != AOP_LIT)
953 /* depending on type */
956 /* PENDING: re-target */
958 tsprintf (s,"!immedwords", aop->aopu.aop_immd);
962 tsprintf(s, "!bankimmeds", aop->aopu.aop_immd);
965 tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
968 tsprintf(s, "!lsbimmeds", aop->aopu.aop_immd);
973 ALLOC_ATOMIC(rs,strlen(s)+1);
979 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
981 ALLOC_ATOMIC(rs,strlen(s)+1);
987 emitcode("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
989 ALLOC_ATOMIC(rs,strlen(s)+1);
994 return aop->aopu.aop_reg[offset]->name;
998 setupPair(PAIR_HL, aop, offset);
1000 return gc_strdup(s);
1004 setupPair(PAIR_IY, aop, offset);
1005 tsprintf(s,"!*iyx", offset);
1006 ALLOC_ATOMIC(rs,strlen(s)+1);
1012 setupPair(PAIR_HL, aop, offset);
1013 tsprintf(s, "!*hl");
1016 tsprintf(s,"!*ixx", aop->aopu.aop_stk+offset);
1018 ALLOC_ATOMIC(rs,strlen(s)+1);
1032 wassert(offset < 2);
1033 return aop->aopu.aop_str[offset];
1036 return aopLiteral (aop->aopu.aop_lit,offset);
1040 return aop->aopu.aop_str[offset];
1044 wassertl(0, "aopget got unsupported aop->type");
1048 bool isRegString(const char *s)
1050 if (!strcmp(s, "b") ||
1061 bool isConstant(const char *s)
1063 /* This is a bit of a hack... */
1064 return (*s == '#' || *s == '$');
1067 bool canAssignToPtr(const char *s)
1076 /*-----------------------------------------------------------------*/
1077 /* aopPut - puts a string for a aop */
1078 /*-----------------------------------------------------------------*/
1079 static void aopPut (asmop *aop, const char *s, int offset)
1081 if (aop->size && offset > ( aop->size - 1)) {
1082 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1083 "aopPut got offset > aop->size");
1087 /* will assign value to value */
1088 /* depending on where it is ofcourse */
1089 switch (aop->type) {
1094 emitcode("ld", "a,%s", s);
1095 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1101 emitcode("ld", "a,%s", s);
1102 emitcode("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
1106 if (!strcmp(s, "!*hl"))
1107 emit2("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1110 aop->aopu.aop_reg[offset]->name, s);
1115 setupPair(PAIR_IY, aop, offset);
1116 if (!canAssignToPtr(s)) {
1117 emit2("ld a,%s", s);
1118 emit2("ld !*iyx,a", offset);
1121 emit2("ld !*iyx,%s", offset, s);
1126 /* PENDING: for re-target */
1127 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1131 setupPair(PAIR_HL, aop, offset);
1133 emit2("ld !*hl,%s", s);
1138 /* PENDING: re-target */
1139 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1143 setupPair(PAIR_HL, aop, offset);
1144 if (!canAssignToPtr(s)) {
1145 emit2("ld a,%s", s);
1149 emit2("ld !*hl,%s", s);
1152 if (!canAssignToPtr(s)) {
1153 emit2("ld a,%s", s);
1154 emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
1157 emit2("ld !*ixx,%s", aop->aopu.aop_stk+offset, s);
1162 /* if bit variable */
1163 if (!aop->aopu.aop_dir) {
1167 /* In bit space but not in C - cant happen */
1174 if (strcmp(aop->aopu.aop_str[offset],s)) {
1175 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1181 if (!offset && (strcmp(s,"acc") == 0))
1185 emitcode("", "; Error aopPut AOP_ACC");
1188 if (strcmp(aop->aopu.aop_str[offset],s))
1189 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1194 wassert(offset < 2);
1195 emit2("ld %s,%s", aop->aopu.aop_str[offset], s);
1199 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1200 "aopPut got unsupported aop->type");
1205 #define AOP(op) op->aop
1206 #define AOP_TYPE(op) AOP(op)->type
1207 #define AOP_SIZE(op) AOP(op)->size
1208 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1210 static void commitPair(asmop *aop, PAIR_ID id)
1212 if (id == PAIR_HL && requiresHL(aop)) {
1215 aopPut(aop, "a", 0);
1216 aopPut(aop, "d", 1);
1219 aopPut(aop, _pairs[id].l, 0);
1220 aopPut(aop, _pairs[id].h, 1);
1224 /*-----------------------------------------------------------------*/
1225 /* getDataSize - get the operand data size */
1226 /*-----------------------------------------------------------------*/
1227 int getDataSize(operand *op)
1230 size = AOP_SIZE(op);
1238 /*-----------------------------------------------------------------*/
1239 /* movLeft2Result - move byte from left to result */
1240 /*-----------------------------------------------------------------*/
1241 static void movLeft2Result (operand *left, int offl,
1242 operand *result, int offr, int sign)
1245 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1246 l = aopGet(AOP(left),offl,FALSE);
1249 aopPut(AOP(result),l,offr);
1258 /** Put Acc into a register set
1260 void outAcc(operand *result)
1263 size = getDataSize(result);
1265 aopPut(AOP(result),"a",0);
1268 /* unsigned or positive */
1270 aopPut(AOP(result), zero, offset++);
1275 /** Take the value in carry and put it into a register
1277 void outBitC(operand *result)
1279 /* if the result is bit */
1280 if (AOP_TYPE(result) == AOP_CRY) {
1281 emitcode("", "; Note: outBitC form 1");
1282 aopPut(AOP(result),"blah",0);
1285 emit2("ld a,!zero");
1291 /*-----------------------------------------------------------------*/
1292 /* toBoolean - emit code for orl a,operator(sizeop) */
1293 /*-----------------------------------------------------------------*/
1294 void toBoolean(operand *oper)
1296 int size = AOP_SIZE(oper);
1299 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1302 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1305 if (AOP(oper)->type != AOP_ACC) {
1307 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1312 /*-----------------------------------------------------------------*/
1313 /* genNot - generate code for ! operation */
1314 /*-----------------------------------------------------------------*/
1315 static void genNot (iCode *ic)
1317 link *optype = operandType(IC_LEFT(ic));
1319 /* assign asmOps to operand & result */
1320 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
1321 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1323 /* if in bit space then a special case */
1324 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1328 /* if type float then do float */
1329 if (IS_FLOAT(optype)) {
1333 toBoolean(IC_LEFT(ic));
1338 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1339 emit2("sub a,!one");
1340 outBitC(IC_RESULT(ic));
1342 /* release the aops */
1343 freeAsmop(IC_LEFT(ic),NULL,ic);
1344 freeAsmop(IC_RESULT(ic),NULL,ic);
1347 /*-----------------------------------------------------------------*/
1348 /* genCpl - generate code for complement */
1349 /*-----------------------------------------------------------------*/
1350 static void genCpl (iCode *ic)
1356 /* assign asmOps to operand & result */
1357 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1358 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1360 /* if both are in bit space then
1362 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1363 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1367 size = AOP_SIZE(IC_RESULT(ic));
1369 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1372 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1375 /* release the aops */
1376 freeAsmop(IC_LEFT(ic),NULL,ic);
1377 freeAsmop(IC_RESULT(ic),NULL,ic);
1380 /*-----------------------------------------------------------------*/
1381 /* genUminus - unary minus code generation */
1382 /*-----------------------------------------------------------------*/
1383 static void genUminus (iCode *ic)
1386 link *optype, *rtype;
1389 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1390 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
1392 /* if both in bit space then special
1394 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1395 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1400 optype = operandType(IC_LEFT(ic));
1401 rtype = operandType(IC_RESULT(ic));
1403 /* if float then do float stuff */
1404 if (IS_FLOAT(optype)) {
1409 /* otherwise subtract from zero */
1410 size = AOP_SIZE(IC_LEFT(ic));
1414 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1415 emit2("ld a,!zero");
1416 emit2("sbc a,%s",l);
1417 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1420 /* if any remaining bytes in the result */
1421 /* we just need to propagate the sign */
1422 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1426 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1430 /* release the aops */
1431 freeAsmop(IC_LEFT(ic),NULL,ic);
1432 freeAsmop(IC_RESULT(ic),NULL,ic);
1435 static void _push(PAIR_ID pairId)
1437 emit2("push %s", _pairs[pairId].name);
1438 _G.stack.pushed += 2;
1441 static void _pop(PAIR_ID pairId)
1443 emit2("pop %s", _pairs[pairId].name);
1444 _G.stack.pushed -= 2;
1448 /*-----------------------------------------------------------------*/
1449 /* assignResultValue - */
1450 /*-----------------------------------------------------------------*/
1451 void assignResultValue(operand * oper)
1453 int size = AOP_SIZE(oper);
1457 topInA = requiresHL(AOP(oper));
1463 if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
1464 /* We do it the hard way here. */
1466 aopPut(AOP(oper), _fReturn[0], 0);
1467 aopPut(AOP(oper), _fReturn[1], 1);
1468 emitcode("pop", "de");
1469 _G.stack.pushed -= 2;
1470 aopPut(AOP(oper), _fReturn[0], 2);
1471 aopPut(AOP(oper), _fReturn[1], 3);
1475 aopPut(AOP(oper), _fReturn[size], size);
1480 /*-----------------------------------------------------------------*/
1481 /* genIpush - genrate code for pushing this gets a little complex */
1482 /*-----------------------------------------------------------------*/
1483 static void genIpush (iCode *ic)
1485 int size, offset = 0 ;
1488 /* if this is not a parm push : ie. it is spill push
1489 and spill push is always done on the local stack */
1490 if (!ic->parmPush) {
1491 /* and the item is spilt then do nothing */
1492 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1495 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1496 size = AOP_SIZE(IC_LEFT(ic));
1497 /* push it on the stack */
1498 if (isPair(AOP(IC_LEFT(ic)))) {
1499 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1500 _G.stack.pushed += 2;
1505 /* Simple for now - load into A and PUSH AF */
1506 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1507 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1509 emit2("ld a,(%s)", l);
1512 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1513 emit2("ld a,%s", l);
1523 /* Hmmm... what about saving the currently used registers
1526 /* then do the push */
1527 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1529 size = AOP_SIZE(IC_LEFT(ic));
1531 if (isPair(AOP(IC_LEFT(ic)))) {
1533 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1537 fetchHL(AOP(IC_LEFT(ic)));
1538 emitcode("push", "hl");
1540 _G.stack.pushed += 2;
1544 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
1545 emitcode("push", "hl");
1547 _G.stack.pushed += 2;
1548 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 0);
1549 emitcode("push", "hl");
1551 _G.stack.pushed += 2;
1556 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1557 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1559 emit2("ld a,(%s)", l);
1562 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1563 emit2("ld a,%s", l);
1565 emitcode("push", "af");
1566 emitcode("inc", "sp");
1571 freeAsmop(IC_LEFT(ic),NULL,ic);
1574 /*-----------------------------------------------------------------*/
1575 /* genIpop - recover the registers: can happen only for spilling */
1576 /*-----------------------------------------------------------------*/
1577 static void genIpop (iCode *ic)
1582 /* if the temp was not pushed then */
1583 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1586 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1587 size = AOP_SIZE(IC_LEFT(ic));
1589 if (isPair(AOP(IC_LEFT(ic)))) {
1590 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1594 emitcode("dec", "sp");
1595 emitcode("pop", "hl");
1597 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1601 freeAsmop(IC_LEFT(ic),NULL,ic);
1604 static int _isPairUsed(iCode *ic, PAIR_ID pairId)
1609 if (bitVectBitValue(ic->rUsed, D_IDX))
1611 if (bitVectBitValue(ic->rUsed, E_IDX))
1620 static int _opUsesPair(operand *op, iCode *ic, PAIR_ID pairId)
1624 symbol *sym = OP_SYMBOL(op);
1626 if (sym->isspilt || sym->nRegs == 0)
1629 aopOp(op, ic, FALSE, FALSE);
1632 if (aop->type == AOP_REG) {
1634 for (i=0; i < aop->size; i++) {
1635 if (pairId == PAIR_DE) {
1636 emit2("; name %s", aop->aopu.aop_reg[i]->name);
1637 if (!strcmp(aop->aopu.aop_reg[i]->name, "e"))
1639 if (!strcmp(aop->aopu.aop_reg[i]->name, "d"))
1648 freeAsmop(IC_LEFT(ic),NULL,ic);
1652 /* This is quite unfortunate */
1653 static void setArea(int inHome)
1655 static int lastArea = 0;
1658 if (_G.in_home != inHome) {
1660 const char *sz = port->mem.code_name;
1661 port->mem.code_name = "HOME";
1662 emit2("!area", CODE_NAME);
1663 port->mem.code_name = sz;
1666 emit2("!area", CODE_NAME);*/
1667 _G.in_home = inHome;
1671 static bool isInHome(void)
1676 /** Emit the code for a call statement
1678 static void emitCall(iCode *ic, bool ispcall)
1681 link *detype = getSpec(operandType(IC_LEFT(ic)));
1683 if (IS_BANKED(detype))
1684 emit2("; call to a banked function");
1686 /* if caller saves & we have not saved then */
1687 if (!ic->regsSaved) {
1691 /* if send set is not empty then assign */
1695 int n = elementsInSet(sendSet);
1696 if (IS_Z80 && n == 2 && _isPairUsed(ic, PAIR_DE)) {
1697 /* Only push de if it is used and if it's not used
1698 in the return value */
1699 /* Panic if partly used */
1700 if (_opUsesPair(IC_RESULT(ic), ic, PAIR_DE) == 1) {
1701 emit2("; Warning: de crossover");
1703 else if (!_opUsesPair(IC_RESULT(ic), ic, PAIR_DE)) {
1710 if (IS_Z80 && n == 2 ) {
1711 /* Want to load HL first, then DE as HL may = DE */
1712 sic = setFirstItem(sendSet);
1713 sic = setNextItem(sendSet);
1714 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1715 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1717 freeAsmop (IC_LEFT(sic),NULL,sic);
1718 sic = setFirstItem(sendSet);
1719 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1720 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1722 freeAsmop (IC_LEFT(sic),NULL,sic);
1725 for (sic = setFirstItem(sendSet) ; sic ;
1726 sic = setNextItem(sendSet)) {
1728 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1729 size = AOP_SIZE(IC_LEFT(sic));
1731 /* Always send in pairs */
1734 if (IS_Z80 && n == 1)
1735 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1737 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1740 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1743 /* Send set too big */
1747 freeAsmop (IC_LEFT(sic),NULL,sic);
1756 if (IS_BANKED(detype)) {
1757 werror(W_INDIR_BANKED);
1759 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1761 if (isLitWord(AOP(IC_LEFT(ic)))) {
1762 emitcode("", "; Special case where the pCall is to a constant");
1763 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1766 symbol *rlbl = newiTempLabel(NULL);
1768 emit2("ld hl,!immed!tlabel", (rlbl->key+100));
1769 emitcode("push", "hl");
1770 _G.stack.pushed += 2;
1772 fetchHL(AOP(IC_LEFT(ic)));
1774 emit2("!tlabeldef", (rlbl->key+100));
1775 _G.stack.pushed -= 2;
1777 freeAsmop(IC_LEFT(ic),NULL,ic);
1780 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1781 OP_SYMBOL(IC_LEFT(ic))->rname :
1782 OP_SYMBOL(IC_LEFT(ic))->name;
1783 if (IS_BANKED(detype)) {
1784 emit2("call banked_call");
1785 emit2("!dws", name);
1786 emit2("!dw !bankimmeds", name);
1790 emit2("call %s", name);
1795 /* if we need assign a result value */
1796 if ((IS_ITEMP(IC_RESULT(ic)) &&
1797 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1798 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1799 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1802 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1805 assignResultValue(IC_RESULT(ic));
1807 freeAsmop(IC_RESULT(ic),NULL, ic);
1810 /* adjust the stack for parameters if required */
1811 if (IC_LEFT(ic)->parmBytes) {
1812 int i = IC_LEFT(ic)->parmBytes;
1813 _G.stack.pushed -= i;
1815 emit2("!ldaspsp", i);
1820 emitcode("ld", "hl,#%d", i);
1821 emitcode("add", "hl,sp");
1822 emitcode("ld", "sp,hl");
1826 emitcode("pop", "hl");
1830 emitcode("inc", "sp");
1839 /*-----------------------------------------------------------------*/
1840 /* genCall - generates a call statement */
1841 /*-----------------------------------------------------------------*/
1842 static void genCall (iCode *ic)
1844 link *detype = getSpec(operandType(IC_LEFT(ic)));
1845 emitCall(ic, FALSE);
1848 /*-----------------------------------------------------------------*/
1849 /* genPcall - generates a call by pointer statement */
1850 /*-----------------------------------------------------------------*/
1851 static void genPcall (iCode *ic)
1856 /*-----------------------------------------------------------------*/
1857 /* resultRemat - result is rematerializable */
1858 /*-----------------------------------------------------------------*/
1859 static int resultRemat (iCode *ic)
1861 if (SKIP_IC(ic) || ic->op == IFX)
1864 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1865 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1866 if (sym->remat && !POINTER_SET(ic))
1873 /*-----------------------------------------------------------------*/
1874 /* genFunction - generated code for function entry */
1875 /*-----------------------------------------------------------------*/
1876 static void genFunction (iCode *ic)
1878 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1882 setArea(IS_NONBANKED(sym->etype));
1884 /* create the function header */
1885 emit2("!functionheader", sym->name);
1886 /* PENDING: portability. */
1887 emit2("__%s_start:", sym->rname);
1888 emit2("!functionlabeldef", sym->rname);
1890 fetype = getSpec(operandType(IC_LEFT(ic)));
1892 /* if critical function then turn interrupts off */
1893 if (SPEC_CRTCL(fetype))
1896 /* if this is an interrupt service routine then
1897 save acc, b, dpl, dph */
1898 if (IS_ISR(sym->etype)) {
1901 /* PENDING: callee-save etc */
1903 /* If BC or DE are used, then push */
1904 _G.stack.pushed_bc = 0;
1905 _G.stack.pushed_de = 0;
1906 _G.stack.param_offset = 0;
1907 if (sym->regsUsed) {
1909 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1910 if (bitVectBitValue(sym->regsUsed, i)) {
1914 _G.stack.pushed_bc = 1;
1919 _G.stack.pushed_de = 1;
1924 if (_G.stack.pushed_bc) {
1926 _G.stack.param_offset += 2;
1928 if (_G.stack.pushed_de) {
1930 _G.stack.param_offset += 2;
1934 /* adjust the stack for the function */
1935 _G.stack.last = sym->stack;
1938 emit2("!enterx", sym->stack);
1941 _G.stack.offset = sym->stack;
1944 /*-----------------------------------------------------------------*/
1945 /* genEndFunction - generates epilogue for functions */
1946 /*-----------------------------------------------------------------*/
1947 static void genEndFunction (iCode *ic)
1949 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1951 if (IS_ISR(sym->etype)) {
1955 if (SPEC_CRTCL(sym->etype))
1958 /* PENDING: calleeSave */
1960 /* if debug then send end of function */
1961 if (options.debug && currFunc) {
1963 emitcode("","C$%s$%d$%d$%d ==.",
1964 ic->filename,currFunc->lastLine,
1965 ic->level,ic->block);
1966 if (IS_STATIC(currFunc->etype))
1967 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
1969 emitcode("","XG$%s$0$0 ==.",currFunc->name);
1972 if (_G.stack.offset)
1973 emit2("!leavex", _G.stack.offset);
1977 if (_G.stack.pushed_de)
1979 if (_G.stack.pushed_bc)
1981 /* Both baned and non-banked just ret */
1984 /* PENDING: portability. */
1985 emit2("__%s_end:", sym->rname);
1987 _G.flush_statics = 1;
1988 _G.stack.pushed = 0;
1989 _G.stack.offset = 0;
1992 /*-----------------------------------------------------------------*/
1993 /* genRet - generate code for return statement */
1994 /*-----------------------------------------------------------------*/
1995 static void genRet (iCode *ic)
1998 /* Errk. This is a hack until I can figure out how
1999 to cause dehl to spill on a call */
2000 int size,offset = 0;
2002 /* if we have no return value then
2003 just generate the "ret" */
2007 /* we have something to return then
2008 move the return value into place */
2009 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2010 size = AOP_SIZE(IC_LEFT(ic));
2012 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
2014 emitcode("ld", "de,%s", l);
2017 emitcode("ld", "hl,%s", l);
2021 if (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
2022 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2023 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
2027 l = aopGet(AOP(IC_LEFT(ic)),offset,
2029 if (strcmp(_fReturn[offset],l))
2030 emitcode("ld","%s,%s", _fReturn[offset++],l);
2034 freeAsmop (IC_LEFT(ic),NULL,ic);
2037 /* generate a jump to the return label
2038 if the next is not the return statement */
2039 if (!(ic->next && ic->next->op == LABEL &&
2040 IC_LABEL(ic->next) == returnLabel))
2042 emit2("jp !tlabel", returnLabel->key+100);
2045 /*-----------------------------------------------------------------*/
2046 /* genLabel - generates a label */
2047 /*-----------------------------------------------------------------*/
2048 static void genLabel (iCode *ic)
2050 /* special case never generate */
2051 if (IC_LABEL(ic) == entryLabel)
2054 emitLabel(IC_LABEL(ic)->key+100);
2057 /*-----------------------------------------------------------------*/
2058 /* genGoto - generates a ljmp */
2059 /*-----------------------------------------------------------------*/
2060 static void genGoto (iCode *ic)
2062 emit2("jp !tlabel", IC_LABEL(ic)->key+100);
2065 /*-----------------------------------------------------------------*/
2066 /* genPlusIncr :- does addition with increment if possible */
2067 /*-----------------------------------------------------------------*/
2068 static bool genPlusIncr (iCode *ic)
2070 unsigned int icount ;
2071 unsigned int size = getDataSize(IC_RESULT(ic));
2072 PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
2074 /* will try to generate an increment */
2075 /* if the right side is not a literal
2077 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2080 emitcode("", "; genPlusIncr");
2082 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2084 /* If result is a pair */
2085 if (resultId != PAIR_INVALID) {
2086 if (isLitWord(AOP(IC_LEFT(ic)))) {
2087 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
2090 if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
2091 fetchPair(resultId, AOP(IC_RIGHT(ic)));
2092 emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
2098 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2101 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2102 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2105 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
2110 /* if the literal value of the right hand side
2111 is greater than 4 then it is not worth it */
2115 /* if increment 16 bits in register */
2116 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2121 symbol *tlbl = NULL;
2122 tlbl = newiTempLabel(NULL);
2124 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)), offset++, FALSE));
2126 emit2("!shortjp nz,!tlabel", tlbl->key+100);
2129 emitLabel(tlbl->key+100);
2133 /* if the sizes are greater than 1 then we cannot */
2134 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2135 AOP_SIZE(IC_LEFT(ic)) > 1 )
2138 /* we can if the aops of the left & result match or
2139 if they are in registers and the registers are the
2141 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2143 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
2150 /*-----------------------------------------------------------------*/
2151 /* outBitAcc - output a bit in acc */
2152 /*-----------------------------------------------------------------*/
2153 void outBitAcc(operand *result)
2155 symbol *tlbl = newiTempLabel(NULL);
2156 /* if the result is a bit */
2157 if (AOP_TYPE(result) == AOP_CRY){
2161 emit2("!shortjp z,!tlabel", tlbl->key+100);
2163 emitLabel(tlbl->key+100);
2168 /*-----------------------------------------------------------------*/
2169 /* genPlus - generates code for addition */
2170 /*-----------------------------------------------------------------*/
2171 static void genPlus (iCode *ic)
2173 int size, offset = 0;
2175 /* special cases :- */
2177 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2178 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2179 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2181 /* Swap the left and right operands if:
2183 if literal, literal on the right or
2184 if left requires ACC or right is already
2187 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2188 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2189 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2190 operand *t = IC_RIGHT(ic);
2191 IC_RIGHT(ic) = IC_LEFT(ic);
2195 /* if both left & right are in bit
2197 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2198 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2203 /* if left in bit space & right literal */
2204 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2205 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2206 /* Can happen I guess */
2210 /* if I can do an increment instead
2211 of add then GOOD for ME */
2212 if (genPlusIncr (ic) == TRUE)
2215 emit2("; genPlusIncr failed");
2217 size = getDataSize(IC_RESULT(ic));
2219 /* Special case when left and right are constant */
2220 if (isPair(AOP(IC_RESULT(ic)))) {
2223 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
2224 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
2225 if (left && right) {
2229 sprintf(buffer, "#(%s + %s)", left, right);
2230 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
2235 if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
2236 /* Fetch into HL then do the add */
2238 fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
2239 emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
2244 ld hl,sp+n trashes C so we cant afford to do it during an
2245 add with stack based varibles. Worst case is:
2258 So you cant afford to load up hl if either left, right, or result
2259 is on the stack (*sigh*) The alt is:
2267 Combinations in here are:
2268 * If left or right are in bc then the loss is small - trap later
2269 * If the result is in bc then the loss is also small
2272 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2273 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2274 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2275 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2276 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2277 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2278 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2279 if (getPairId(AOP(IC_RIGHT(ic))) == PAIR_BC) {
2280 /* Swap left and right */
2281 operand *t = IC_RIGHT(ic);
2282 IC_RIGHT(ic) = IC_LEFT(ic);
2285 if (getPairId(AOP(IC_LEFT(ic))) == PAIR_BC) {
2286 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2290 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2291 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2294 commitPair(AOP(IC_RESULT(ic)), PAIR_HL);
2297 else if (size == 4) {
2298 emit2("; WARNING: This add is probably broken.\n");
2304 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2305 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2308 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2311 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2313 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2316 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2319 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2321 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2325 freeAsmop(IC_LEFT(ic),NULL,ic);
2326 freeAsmop(IC_RIGHT(ic),NULL,ic);
2327 freeAsmop(IC_RESULT(ic),NULL,ic);
2331 /*-----------------------------------------------------------------*/
2332 /* genMinusDec :- does subtraction with deccrement if possible */
2333 /*-----------------------------------------------------------------*/
2334 static bool genMinusDec (iCode *ic)
2336 unsigned int icount ;
2337 unsigned int size = getDataSize(IC_RESULT(ic));
2339 /* will try to generate an increment */
2340 /* if the right side is not a literal we cannot */
2341 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2344 /* if the literal value of the right hand side
2345 is greater than 4 then it is not worth it */
2346 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2349 size = getDataSize(IC_RESULT(ic));
2352 /* if increment 16 bits in register */
2353 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2356 symbol *tlbl = newiTempLabel(NULL);
2357 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
2358 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
2360 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
2364 emitLabel(tlbl->key+100);
2369 /* if decrement 16 bits in register */
2370 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2371 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
2373 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2377 /* If result is a pair */
2378 if (isPair(AOP(IC_RESULT(ic)))) {
2379 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2380 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2382 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2386 /* if the sizes are greater than 1 then we cannot */
2387 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2388 AOP_SIZE(IC_LEFT(ic)) > 1 )
2391 /* we can if the aops of the left & result match or if they are in
2392 registers and the registers are the same */
2393 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2395 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
2402 /*-----------------------------------------------------------------*/
2403 /* genMinus - generates code for subtraction */
2404 /*-----------------------------------------------------------------*/
2405 static void genMinus (iCode *ic)
2407 int size, offset = 0;
2408 unsigned long lit = 0L;
2410 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2411 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2412 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2414 /* special cases :- */
2415 /* if both left & right are in bit space */
2416 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2417 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2422 /* if I can do an decrement instead of subtract then GOOD for ME */
2423 if (genMinusDec (ic) == TRUE)
2426 size = getDataSize(IC_RESULT(ic));
2428 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2431 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2435 /* Same logic as genPlus */
2437 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2438 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2439 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2440 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2441 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2442 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2443 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2444 PAIR_ID left = getPairId(AOP(IC_LEFT(ic)));
2445 PAIR_ID right = getPairId(AOP(IC_RIGHT(ic)));
2447 if (left == PAIR_INVALID && right == PAIR_INVALID) {
2451 else if (right == PAIR_INVALID)
2453 else if (left == PAIR_INVALID)
2456 fetchPair(left, AOP(IC_LEFT(ic)));
2457 /* Order is important. Right may be HL */
2458 fetchPair(right, AOP(IC_RIGHT(ic)));
2460 emit2("ld a,%s", _pairs[left].l);
2461 emit2("sub a,%s", _pairs[right].l);
2463 emit2("ld a,%s", _pairs[left].h);
2464 emit2("sbc a,%s", _pairs[right].h);
2466 aopPut(AOP(IC_RESULT(ic)), "a", 1);
2467 aopPut(AOP(IC_RESULT(ic)), "e", 0);
2470 else if (size == 4) {
2471 emit2("; WARNING: This sub is probably broken.\n");
2476 /* if literal, add a,#-lit, else normal subb */
2478 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2479 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2481 emitcode("sub","a,%s",
2482 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2484 emitcode("sbc","a,%s",
2485 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2488 /* first add without previous c */
2490 emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL));
2492 emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2494 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2497 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2498 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2499 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2503 freeAsmop(IC_LEFT(ic),NULL,ic);
2504 freeAsmop(IC_RIGHT(ic),NULL,ic);
2505 freeAsmop(IC_RESULT(ic),NULL,ic);
2508 /*-----------------------------------------------------------------*/
2509 /* genMult - generates code for multiplication */
2510 /*-----------------------------------------------------------------*/
2511 static void genMult (iCode *ic)
2513 /* Shouldn't occur - all done through function calls */
2517 /*-----------------------------------------------------------------*/
2518 /* genDiv - generates code for division */
2519 /*-----------------------------------------------------------------*/
2520 static void genDiv (iCode *ic)
2522 /* Shouldn't occur - all done through function calls */
2526 /*-----------------------------------------------------------------*/
2527 /* genMod - generates code for division */
2528 /*-----------------------------------------------------------------*/
2529 static void genMod (iCode *ic)
2531 /* Shouldn't occur - all done through function calls */
2535 /*-----------------------------------------------------------------*/
2536 /* genIfxJump :- will create a jump depending on the ifx */
2537 /*-----------------------------------------------------------------*/
2538 static void genIfxJump (iCode *ic, char *jval)
2543 /* if true label then we jump if condition
2545 if ( IC_TRUE(ic) ) {
2547 if (!strcmp(jval, "a")) {
2550 else if (!strcmp(jval, "c")) {
2554 /* The buffer contains the bit on A that we should test */
2559 /* false label is present */
2560 jlbl = IC_FALSE(ic) ;
2561 if (!strcmp(jval, "a")) {
2564 else if (!strcmp(jval, "c")) {
2568 /* The buffer contains the bit on A that we should test */
2572 /* Z80 can do a conditional long jump */
2573 if (!strcmp(jval, "a")) {
2574 emitcode("or", "a,a");
2576 else if (!strcmp(jval, "c")) {
2579 emitcode("bit", "%s,a", jval);
2581 emit2("jp %s,!tlabel", inst, jlbl->key+100);
2583 /* mark the icode as generated */
2587 /** Generic compare for > or <
2589 static void genCmp (operand *left,operand *right,
2590 operand *result, iCode *ifx, int sign)
2592 int size, offset = 0 ;
2593 unsigned long lit = 0L;
2595 /* if left & right are bit variables */
2596 if (AOP_TYPE(left) == AOP_CRY &&
2597 AOP_TYPE(right) == AOP_CRY ) {
2598 /* Cant happen on the Z80 */
2601 /* subtract right from left if at the
2602 end the carry flag is set then we know that
2603 left is greater than right */
2604 size = max(AOP_SIZE(left),AOP_SIZE(right));
2606 /* if unsigned char cmp with lit, just compare */
2608 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2609 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2611 emit2("xor a,!immedbyte", 0x80);
2612 emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80);
2615 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
2618 if(AOP_TYPE(right) == AOP_LIT) {
2619 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2620 /* optimize if(x < 0) or if(x >= 0) */
2623 /* No sign so it's always false */
2627 /* Just load in the top most bit */
2628 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2629 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2630 genIfxJump (ifx,"7");
2634 emitcode("rlc","a");
2640 /* First setup h and l contaning the top most bytes XORed */
2641 bool fDidXor = FALSE;
2642 if (AOP_TYPE(left) == AOP_LIT){
2643 unsigned long lit = (unsigned long)
2644 floatFromVal(AOP(left)->aopu.aop_lit);
2645 emit2("ld %s,!immedbyte", _fTmp[0],
2646 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2649 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2650 emit2("xor a,!immedbyte", 0x80);
2651 emitcode("ld", "%s,a", _fTmp[0]);
2654 if (AOP_TYPE(right) == AOP_LIT) {
2655 unsigned long lit = (unsigned long)
2656 floatFromVal(AOP(right)->aopu.aop_lit);
2657 emit2("ld %s,!immedbyte", _fTmp[1],
2658 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2661 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2662 emit2("xor a,!immedbyte", 0x80);
2663 emitcode("ld", "%s,a", _fTmp[1]);
2673 /* Do a long subtract */
2674 if (!sign || size ) {
2675 MOVA(aopGet(AOP(left),offset,FALSE));
2677 if (sign && size == 0) {
2678 emitcode("ld", "a,%s", _fTmp[0]);
2679 emitcode("sbc", "a,%s", _fTmp[1]);
2682 /* Subtract through, propagating the carry */
2683 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2690 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2693 /* if the result is used in the next
2694 ifx conditional branch then generate
2695 code a little differently */
2697 genIfxJump (ifx,"c");
2700 /* leave the result in acc */
2704 /*-----------------------------------------------------------------*/
2705 /* genCmpGt :- greater than comparison */
2706 /*-----------------------------------------------------------------*/
2707 static void genCmpGt (iCode *ic, iCode *ifx)
2709 operand *left, *right, *result;
2710 link *letype , *retype;
2714 right= IC_RIGHT(ic);
2715 result = IC_RESULT(ic);
2717 letype = getSpec(operandType(left));
2718 retype =getSpec(operandType(right));
2719 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2720 /* assign the amsops */
2721 aopOp (left,ic,FALSE, FALSE);
2722 aopOp (right,ic,FALSE, FALSE);
2723 aopOp (result,ic,TRUE, FALSE);
2725 genCmp(right, left, result, ifx, sign);
2727 freeAsmop(left,NULL,ic);
2728 freeAsmop(right,NULL,ic);
2729 freeAsmop(result,NULL,ic);
2732 /*-----------------------------------------------------------------*/
2733 /* genCmpLt - less than comparisons */
2734 /*-----------------------------------------------------------------*/
2735 static void genCmpLt (iCode *ic, iCode *ifx)
2737 operand *left, *right, *result;
2738 link *letype , *retype;
2742 right= IC_RIGHT(ic);
2743 result = IC_RESULT(ic);
2745 letype = getSpec(operandType(left));
2746 retype =getSpec(operandType(right));
2747 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2749 /* assign the amsops */
2750 aopOp (left,ic,FALSE, FALSE);
2751 aopOp (right,ic,FALSE, FALSE);
2752 aopOp (result,ic,TRUE, FALSE);
2754 genCmp(left, right, result, ifx, sign);
2756 freeAsmop(left,NULL,ic);
2757 freeAsmop(right,NULL,ic);
2758 freeAsmop(result,NULL,ic);
2761 /*-----------------------------------------------------------------*/
2762 /* gencjneshort - compare and jump if not equal */
2763 /*-----------------------------------------------------------------*/
2764 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2766 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2768 unsigned long lit = 0L;
2770 /* Swap the left and right if it makes the computation easier */
2771 if (AOP_TYPE(left) == AOP_LIT) {
2777 if(AOP_TYPE(right) == AOP_LIT)
2778 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2780 /* if the right side is a literal then anything goes */
2781 if (AOP_TYPE(right) == AOP_LIT &&
2782 AOP_TYPE(left) != AOP_DIR ) {
2784 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2789 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2793 emitcode("or", "a,a");
2795 emit2("jp nz,!tlabel", lbl->key+100);
2799 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2800 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2801 emitcode("or", "a,a");
2803 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2804 emit2("jp nz,!tlabel", lbl->key+100);
2809 /* if the right side is in a register or in direct space or
2810 if the left is a pointer register & right is not */
2811 else if (AOP_TYPE(right) == AOP_REG ||
2812 AOP_TYPE(right) == AOP_DIR ||
2813 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2815 MOVA(aopGet(AOP(left),offset,FALSE));
2816 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2817 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2819 emit2("jp nz,!tlabel", lbl->key+100);
2821 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2822 emit2("jp nz,!tlabel", lbl->key+100);
2827 /* right is a pointer reg need both a & b */
2828 /* PENDING: is this required? */
2830 MOVA(aopGet(AOP(right),offset,FALSE));
2831 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2832 emit2("!shortjp nz,!tlabel", lbl->key+100);
2838 /*-----------------------------------------------------------------*/
2839 /* gencjne - compare and jump if not equal */
2840 /*-----------------------------------------------------------------*/
2841 static void gencjne(operand *left, operand *right, symbol *lbl)
2843 symbol *tlbl = newiTempLabel(NULL);
2845 gencjneshort(left, right, lbl);
2849 emit2("!shortjp !tlabel", tlbl->key+100);
2850 emitLabel(lbl->key+100);
2851 emitcode("xor","a,a");
2852 emitLabel(tlbl->key+100);
2855 /*-----------------------------------------------------------------*/
2856 /* genCmpEq - generates code for equal to */
2857 /*-----------------------------------------------------------------*/
2858 static void genCmpEq (iCode *ic, iCode *ifx)
2860 operand *left, *right, *result;
2862 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
2863 aopOp((right=IC_RIGHT(ic)),ic,FALSE, FALSE);
2864 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
2866 /* Swap operands if it makes the operation easier. ie if:
2867 1. Left is a literal.
2869 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2870 operand *t = IC_RIGHT(ic);
2871 IC_RIGHT(ic) = IC_LEFT(ic);
2875 if (ifx && !AOP_SIZE(result)){
2877 /* if they are both bit variables */
2878 if (AOP_TYPE(left) == AOP_CRY &&
2879 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2882 tlbl = newiTempLabel(NULL);
2883 gencjneshort(left, right, tlbl);
2884 if ( IC_TRUE(ifx) ) {
2885 emit2("jp !tlabel", IC_TRUE(ifx)->key+100);
2886 emitLabel(tlbl->key+100);
2888 /* PENDING: do this better */
2889 symbol *lbl = newiTempLabel(NULL);
2890 emit2("!shortjp !tlabel", lbl->key+100);
2891 emitLabel(tlbl->key+100);
2892 emit2("jp !tlabel", IC_FALSE(ifx)->key+100);
2893 emitLabel(lbl->key+100);
2896 /* mark the icode as generated */
2901 /* if they are both bit variables */
2902 if (AOP_TYPE(left) == AOP_CRY &&
2903 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2906 gencjne(left,right,newiTempLabel(NULL));
2907 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2911 genIfxJump(ifx,"a");
2914 /* if the result is used in an arithmetic operation
2915 then put the result in place */
2916 if (AOP_TYPE(result) != AOP_CRY) {
2919 /* leave the result in acc */
2923 freeAsmop(left,NULL,ic);
2924 freeAsmop(right,NULL,ic);
2925 freeAsmop(result,NULL,ic);
2928 /*-----------------------------------------------------------------*/
2929 /* ifxForOp - returns the icode containing the ifx for operand */
2930 /*-----------------------------------------------------------------*/
2931 static iCode *ifxForOp ( operand *op, iCode *ic )
2933 /* if true symbol then needs to be assigned */
2934 if (IS_TRUE_SYMOP(op))
2937 /* if this has register type condition and
2938 the next instruction is ifx with the same operand
2939 and live to of the operand is upto the ifx only then */
2941 ic->next->op == IFX &&
2942 IC_COND(ic->next)->key == op->key &&
2943 OP_SYMBOL(op)->liveTo <= ic->next->seq )
2949 /*-----------------------------------------------------------------*/
2950 /* genAndOp - for && operation */
2951 /*-----------------------------------------------------------------*/
2952 static void genAndOp (iCode *ic)
2954 operand *left,*right, *result;
2957 /* note here that && operations that are in an if statement are
2958 taken away by backPatchLabels only those used in arthmetic
2959 operations remain */
2960 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
2961 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
2962 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
2964 /* if both are bit variables */
2965 if (AOP_TYPE(left) == AOP_CRY &&
2966 AOP_TYPE(right) == AOP_CRY ) {
2969 tlbl = newiTempLabel(NULL);
2971 emit2("!shortjp z,!tlabel", tlbl->key+100);
2973 emitLabel(tlbl->key+100);
2977 freeAsmop(left,NULL,ic);
2978 freeAsmop(right,NULL,ic);
2979 freeAsmop(result,NULL,ic);
2982 /*-----------------------------------------------------------------*/
2983 /* genOrOp - for || operation */
2984 /*-----------------------------------------------------------------*/
2985 static void genOrOp (iCode *ic)
2987 operand *left,*right, *result;
2990 /* note here that || operations that are in an
2991 if statement are taken away by backPatchLabels
2992 only those used in arthmetic operations remain */
2993 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
2994 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
2995 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
2997 /* if both are bit variables */
2998 if (AOP_TYPE(left) == AOP_CRY &&
2999 AOP_TYPE(right) == AOP_CRY ) {
3002 tlbl = newiTempLabel(NULL);
3004 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3006 emitLabel(tlbl->key+100);
3010 freeAsmop(left,NULL,ic);
3011 freeAsmop(right,NULL,ic);
3012 freeAsmop(result,NULL,ic);
3015 /*-----------------------------------------------------------------*/
3016 /* isLiteralBit - test if lit == 2^n */
3017 /*-----------------------------------------------------------------*/
3018 int isLiteralBit(unsigned long lit)
3020 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3021 0x100L,0x200L,0x400L,0x800L,
3022 0x1000L,0x2000L,0x4000L,0x8000L,
3023 0x10000L,0x20000L,0x40000L,0x80000L,
3024 0x100000L,0x200000L,0x400000L,0x800000L,
3025 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3026 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3029 for(idx = 0; idx < 32; idx++)
3035 /*-----------------------------------------------------------------*/
3036 /* jmpTrueOrFalse - */
3037 /*-----------------------------------------------------------------*/
3038 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3040 // ugly but optimized by peephole
3042 symbol *nlbl = newiTempLabel(NULL);
3043 emit2("jp !tlabel", nlbl->key+100);
3044 emitLabel(tlbl->key+100);
3045 emit2("jp !tlabel", IC_TRUE(ic)->key+100);
3046 emitLabel(nlbl->key+100);
3049 emit2("jp !tlabel", IC_FALSE(ic)->key+100);
3050 emitLabel(tlbl->key+100);
3055 /*-----------------------------------------------------------------*/
3056 /* genAnd - code for and */
3057 /*-----------------------------------------------------------------*/
3058 static void genAnd (iCode *ic, iCode *ifx)
3060 operand *left, *right, *result;
3062 unsigned long lit = 0L;
3065 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3066 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3067 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3070 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3072 AOP_TYPE(left), AOP_TYPE(right));
3073 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3075 AOP_SIZE(left), AOP_SIZE(right));
3078 /* if left is a literal & right is not then exchange them */
3079 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3080 AOP_NEEDSACC(left)) {
3081 operand *tmp = right ;
3086 /* if result = right then exchange them */
3087 if(sameRegs(AOP(result),AOP(right))){
3088 operand *tmp = right ;
3093 /* if right is bit then exchange them */
3094 if (AOP_TYPE(right) == AOP_CRY &&
3095 AOP_TYPE(left) != AOP_CRY){
3096 operand *tmp = right ;
3100 if(AOP_TYPE(right) == AOP_LIT)
3101 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3103 size = AOP_SIZE(result);
3105 if (AOP_TYPE(left) == AOP_CRY){
3110 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3111 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3112 if((AOP_TYPE(right) == AOP_LIT) &&
3113 (AOP_TYPE(result) == AOP_CRY) &&
3114 (AOP_TYPE(left) != AOP_CRY)) {
3115 int posbit = isLiteralBit(lit);
3119 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
3123 emitcode("mov","c,acc.%d",posbit&0x07);
3128 sprintf(buffer, "%d", posbit&0x07);
3129 genIfxJump(ifx, buffer);
3137 symbol *tlbl = newiTempLabel(NULL);
3138 int sizel = AOP_SIZE(left);
3141 emitcode("setb","c");
3144 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3145 MOVA( aopGet(AOP(left),offset,FALSE));
3147 if((posbit = isLiteralBit(bytelit)) != 0) {
3149 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3152 if(bytelit != 0x0FFL)
3153 emitcode("and","a,%s",
3154 aopGet(AOP(right),offset,FALSE));
3158 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3163 // bit = left & literal
3165 emitcode("clr","c");
3166 emit2("!tlabeldef", tlbl->key+100);
3168 // if(left & literal)
3171 jmpTrueOrFalse(ifx, tlbl);
3179 /* if left is same as result */
3180 if(sameRegs(AOP(result),AOP(left))){
3181 for(;size--; offset++) {
3182 if(AOP_TYPE(right) == AOP_LIT){
3183 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3187 aopPut(AOP(result),zero,offset);
3189 MOVA(aopGet(AOP(left),offset,FALSE));
3190 emitcode("and","a,%s",
3191 aopGet(AOP(right),offset,FALSE));
3192 aopPut(AOP(left), "a", offset);
3197 if (AOP_TYPE(left) == AOP_ACC) {
3201 MOVA(aopGet(AOP(left),offset,FALSE));
3202 emitcode("and","a,%s",
3203 aopGet(AOP(right),offset,FALSE));
3204 aopPut(AOP(left), "a", offset);
3209 // left & result in different registers
3210 if(AOP_TYPE(result) == AOP_CRY){
3213 for(;(size--);offset++) {
3215 // result = left & right
3216 if(AOP_TYPE(right) == AOP_LIT){
3217 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3219 aopGet(AOP(left),offset,FALSE),
3222 } else if(bytelit == 0){
3223 aopPut(AOP(result),zero,offset);
3227 // faster than result <- left, anl result,right
3228 // and better if result is SFR
3229 if (AOP_TYPE(left) == AOP_ACC)
3230 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
3232 MOVA(aopGet(AOP(left),offset,FALSE));
3233 emitcode("and","a,%s",
3234 aopGet(AOP(right),offset,FALSE));
3236 aopPut(AOP(result),"a",offset);
3243 freeAsmop(left,NULL,ic);
3244 freeAsmop(right,NULL,ic);
3245 freeAsmop(result,NULL,ic);
3248 /*-----------------------------------------------------------------*/
3249 /* genOr - code for or */
3250 /*-----------------------------------------------------------------*/
3251 static void genOr (iCode *ic, iCode *ifx)
3253 operand *left, *right, *result;
3255 unsigned long lit = 0L;
3257 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3258 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3259 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3262 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3264 AOP_TYPE(left), AOP_TYPE(right));
3265 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3267 AOP_SIZE(left), AOP_SIZE(right));
3270 /* if left is a literal & right is not then exchange them */
3271 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3272 AOP_NEEDSACC(left)) {
3273 operand *tmp = right ;
3278 /* if result = right then exchange them */
3279 if(sameRegs(AOP(result),AOP(right))){
3280 operand *tmp = right ;
3285 /* if right is bit then exchange them */
3286 if (AOP_TYPE(right) == AOP_CRY &&
3287 AOP_TYPE(left) != AOP_CRY){
3288 operand *tmp = right ;
3292 if(AOP_TYPE(right) == AOP_LIT)
3293 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3295 size = AOP_SIZE(result);
3297 if (AOP_TYPE(left) == AOP_CRY){
3302 if((AOP_TYPE(right) == AOP_LIT) &&
3303 (AOP_TYPE(result) == AOP_CRY) &&
3304 (AOP_TYPE(left) != AOP_CRY)){
3309 /* if left is same as result */
3310 if(sameRegs(AOP(result),AOP(left))){
3311 for(;size--; offset++) {
3312 if(AOP_TYPE(right) == AOP_LIT){
3313 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3316 MOVA(aopGet(AOP(left),offset,FALSE));
3317 emitcode("or","a,%s",
3318 aopGet(AOP(right),offset,FALSE));
3319 aopPut(AOP(result),"a", offset);
3322 if (AOP_TYPE(left) == AOP_ACC)
3323 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3325 MOVA(aopGet(AOP(left),offset,FALSE));
3326 emitcode("or","a,%s",
3327 aopGet(AOP(right),offset,FALSE));
3328 aopPut(AOP(result),"a", offset);
3333 // left & result in different registers
3334 if(AOP_TYPE(result) == AOP_CRY){
3336 } else for(;(size--);offset++){
3338 // result = left & right
3339 if(AOP_TYPE(right) == AOP_LIT){
3340 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3342 aopGet(AOP(left),offset,FALSE),
3347 // faster than result <- left, anl result,right
3348 // and better if result is SFR
3349 if (AOP_TYPE(left) == AOP_ACC)
3350 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3352 MOVA(aopGet(AOP(left),offset,FALSE));
3353 emitcode("or","a,%s",
3354 aopGet(AOP(right),offset,FALSE));
3356 aopPut(AOP(result),"a",offset);
3357 /* PENDING: something weird is going on here. Add exception. */
3358 if (AOP_TYPE(result) == AOP_ACC)
3364 freeAsmop(left,NULL,ic);
3365 freeAsmop(right,NULL,ic);
3366 freeAsmop(result,NULL,ic);
3369 /*-----------------------------------------------------------------*/
3370 /* genXor - code for xclusive or */
3371 /*-----------------------------------------------------------------*/
3372 static void genXor (iCode *ic, iCode *ifx)
3374 operand *left, *right, *result;
3376 unsigned long lit = 0L;
3378 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3379 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3380 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3382 /* if left is a literal & right is not then exchange them */
3383 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3384 AOP_NEEDSACC(left)) {
3385 operand *tmp = right ;
3390 /* if result = right then exchange them */
3391 if(sameRegs(AOP(result),AOP(right))){
3392 operand *tmp = right ;
3397 /* if right is bit then exchange them */
3398 if (AOP_TYPE(right) == AOP_CRY &&
3399 AOP_TYPE(left) != AOP_CRY){
3400 operand *tmp = right ;
3404 if(AOP_TYPE(right) == AOP_LIT)
3405 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3407 size = AOP_SIZE(result);
3409 if (AOP_TYPE(left) == AOP_CRY){
3414 if((AOP_TYPE(right) == AOP_LIT) &&
3415 (AOP_TYPE(result) == AOP_CRY) &&
3416 (AOP_TYPE(left) != AOP_CRY)){
3421 /* if left is same as result */
3422 if(sameRegs(AOP(result),AOP(left))){
3423 for(;size--; offset++) {
3424 if(AOP_TYPE(right) == AOP_LIT){
3425 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3428 MOVA(aopGet(AOP(right),offset,FALSE));
3429 emitcode("xor","a,%s",
3430 aopGet(AOP(left),offset,FALSE));
3431 aopPut(AOP(result),"a",0);
3434 if (AOP_TYPE(left) == AOP_ACC)
3435 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3437 MOVA(aopGet(AOP(right),offset,FALSE));
3438 emitcode("xor","a,%s",
3439 aopGet(AOP(left),offset,FALSE));
3440 aopPut(AOP(result),"a",0);
3445 // left & result in different registers
3446 if(AOP_TYPE(result) == AOP_CRY){
3448 } else for(;(size--);offset++){
3450 // result = left & right
3451 if(AOP_TYPE(right) == AOP_LIT){
3452 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3454 aopGet(AOP(left),offset,FALSE),
3459 // faster than result <- left, anl result,right
3460 // and better if result is SFR
3461 if (AOP_TYPE(left) == AOP_ACC)
3462 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3464 MOVA(aopGet(AOP(right),offset,FALSE));
3465 emitcode("xor","a,%s",
3466 aopGet(AOP(left),offset,FALSE));
3467 aopPut(AOP(result),"a",0);
3469 aopPut(AOP(result),"a",offset);
3474 freeAsmop(left,NULL,ic);
3475 freeAsmop(right,NULL,ic);
3476 freeAsmop(result,NULL,ic);
3479 /*-----------------------------------------------------------------*/
3480 /* genInline - write the inline code out */
3481 /*-----------------------------------------------------------------*/
3482 static void genInline (iCode *ic)
3484 char buffer[MAX_INLINEASM];
3488 inLine += (!options.asmpeep);
3489 strcpy(buffer,IC_INLINE(ic));
3491 /* emit each line as a code */
3510 /* emitcode("",buffer); */
3511 inLine -= (!options.asmpeep);
3514 /*-----------------------------------------------------------------*/
3515 /* genRRC - rotate right with carry */
3516 /*-----------------------------------------------------------------*/
3517 static void genRRC (iCode *ic)
3522 /*-----------------------------------------------------------------*/
3523 /* genRLC - generate code for rotate left with carry */
3524 /*-----------------------------------------------------------------*/
3525 static void genRLC (iCode *ic)
3530 /*-----------------------------------------------------------------*/
3531 /* shiftR2Left2Result - shift right two bytes from left to result */
3532 /*-----------------------------------------------------------------*/
3533 static void shiftR2Left2Result (operand *left, int offl,
3534 operand *result, int offr,
3535 int shCount, int sign)
3537 movLeft2Result(left, offl, result, offr, 0);
3538 movLeft2Result(left, offl+1, result, offr+1, 0);
3544 /* if (AOP(result)->type == AOP_REG) {*/
3547 symbol *tlbl , *tlbl1;
3550 tlbl = newiTempLabel(NULL);
3551 tlbl1 = newiTempLabel(NULL);
3553 /* Left is already in result - so now do the shift */
3555 emit2("ld a,!immedbyte+1", shCount);
3556 emit2("!shortjp !tlabel", tlbl1->key+100);
3557 emitLabel(tlbl->key+100);
3560 emitcode("or", "a,a");
3563 l = aopGet(AOP(result), --offset, FALSE);
3564 emitcode("rr","%s", l);
3567 emitLabel(tlbl1->key+100);
3568 emitcode("dec", "a");
3569 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3574 /*-----------------------------------------------------------------*/
3575 /* shiftL2Left2Result - shift left two bytes from left to result */
3576 /*-----------------------------------------------------------------*/
3577 static void shiftL2Left2Result (operand *left, int offl,
3578 operand *result, int offr, int shCount)
3580 if(sameRegs(AOP(result), AOP(left)) &&
3581 ((offl + MSB16) == offr)){
3584 /* Copy left into result */
3585 movLeft2Result(left, offl, result, offr, 0);
3586 movLeft2Result(left, offl+1, result, offr+1, 0);
3588 /* PENDING: for now just see if it'll work. */
3589 /*if (AOP(result)->type == AOP_REG) { */
3593 symbol *tlbl , *tlbl1;
3596 tlbl = newiTempLabel(NULL);
3597 tlbl1 = newiTempLabel(NULL);
3599 /* Left is already in result - so now do the shift */
3601 emit2("ld a,!immedbyte+1", shCount);
3602 emit2("!shortjp !tlabel", tlbl1->key+100);
3603 emitLabel(tlbl->key+100);
3606 emitcode("or", "a,a");
3608 l = aopGet(AOP(result),offset++,FALSE);
3609 emitcode("rl","%s", l);
3612 emitLabel(tlbl1->key+100);
3613 emitcode("dec", "a");
3614 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3619 /*-----------------------------------------------------------------*/
3620 /* AccRol - rotate left accumulator by known count */
3621 /*-----------------------------------------------------------------*/
3622 static void AccRol (int shCount)
3624 shCount &= 0x0007; // shCount : 0..7
3661 /*-----------------------------------------------------------------*/
3662 /* AccLsh - left shift accumulator by known count */
3663 /*-----------------------------------------------------------------*/
3664 static void AccLsh (int shCount)
3668 emitcode("add","a,a");
3670 else if(shCount == 2) {
3671 emitcode("add","a,a");
3672 emitcode("add","a,a");
3674 /* rotate left accumulator */
3676 /* and kill the lower order bits */
3677 emit2("and a,!immedbyte", SLMask[shCount]);
3682 /*-----------------------------------------------------------------*/
3683 /* shiftL1Left2Result - shift left one byte from left to result */
3684 /*-----------------------------------------------------------------*/
3685 static void shiftL1Left2Result (operand *left, int offl,
3686 operand *result, int offr, int shCount)
3689 l = aopGet(AOP(left),offl,FALSE);
3691 /* shift left accumulator */
3693 aopPut(AOP(result),"a",offr);
3697 /*-----------------------------------------------------------------*/
3698 /* genlshTwo - left shift two bytes by known amount != 0 */
3699 /*-----------------------------------------------------------------*/
3700 static void genlshTwo (operand *result,operand *left, int shCount)
3702 int size = AOP_SIZE(result);
3706 /* if shCount >= 8 */
3711 movLeft2Result(left, LSB, result, MSB16, 0);
3712 aopPut(AOP(result),zero, 0);
3713 shiftL1Left2Result(left, MSB16, result, MSB16, shCount);
3716 movLeft2Result(left, LSB, result, MSB16, 0);
3717 aopPut(AOP(result),zero, 0);
3721 aopPut(AOP(result),zero,LSB);
3724 /* 1 <= shCount <= 7 */
3730 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3735 /*-----------------------------------------------------------------*/
3736 /* genlshOne - left shift a one byte quantity by known count */
3737 /*-----------------------------------------------------------------*/
3738 static void genlshOne (operand *result, operand *left, int shCount)
3740 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3743 /*-----------------------------------------------------------------*/
3744 /* genLeftShiftLiteral - left shifting by known count */
3745 /*-----------------------------------------------------------------*/
3746 static void genLeftShiftLiteral (operand *left,
3751 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3754 freeAsmop(right,NULL,ic);
3756 aopOp(left,ic,FALSE, FALSE);
3757 aopOp(result,ic,FALSE, FALSE);
3759 size = getSize(operandType(result));
3762 emitcode("; shift left ","result %d, left %d",size,
3766 /* I suppose that the left size >= result size */
3771 else if(shCount >= (size * 8))
3773 aopPut(AOP(result),zero,size);
3777 genlshOne (result,left,shCount);
3780 genlshTwo (result,left,shCount);
3789 freeAsmop(left,NULL,ic);
3790 freeAsmop(result,NULL,ic);
3793 /*-----------------------------------------------------------------*/
3794 /* genLeftShift - generates code for left shifting */
3795 /*-----------------------------------------------------------------*/
3796 static void genLeftShift (iCode *ic)
3800 symbol *tlbl , *tlbl1;
3801 operand *left,*right, *result;
3803 right = IC_RIGHT(ic);
3805 result = IC_RESULT(ic);
3807 aopOp(right,ic,FALSE, FALSE);
3809 /* if the shift count is known then do it
3810 as efficiently as possible */
3811 if (AOP_TYPE(right) == AOP_LIT) {
3812 genLeftShiftLiteral (left,right,result,ic);
3816 /* shift count is unknown then we have to form a loop get the loop
3817 count in B : Note: we take only the lower order byte since
3818 shifting more that 32 bits make no sense anyway, ( the largest
3819 size of an object can be only 32 bits ) */
3820 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3821 emitcode("inc","a");
3822 freeAsmop (right,NULL,ic);
3823 aopOp(left,ic,FALSE, FALSE);
3824 aopOp(result,ic,FALSE, FALSE);
3826 /* now move the left to the result if they are not the
3829 if (!sameRegs(AOP(left),AOP(result))) {
3831 size = AOP_SIZE(result);
3834 l = aopGet(AOP(left),offset,FALSE);
3835 aopPut(AOP(result),l,offset);
3840 size = AOP_SIZE(result);
3843 l = aopGet(AOP(left),offset,FALSE);
3844 aopPut(AOP(result),l,offset);
3850 tlbl = newiTempLabel(NULL);
3851 size = AOP_SIZE(result);
3853 tlbl1 = newiTempLabel(NULL);
3855 emit2("!shortjp !tlabel", tlbl1->key+100);
3856 emitLabel(tlbl->key+100);
3857 l = aopGet(AOP(result),offset,FALSE);
3858 emitcode("or", "a,a");
3860 l = aopGet(AOP(result),offset++,FALSE);
3861 emitcode("rl","%s", l);
3863 emitLabel(tlbl1->key+100);
3864 emitcode("dec", "a");
3865 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3867 freeAsmop(left,NULL,ic);
3868 freeAsmop(result,NULL,ic);
3871 /*-----------------------------------------------------------------*/
3872 /* genrshOne - left shift two bytes by known amount != 0 */
3873 /*-----------------------------------------------------------------*/
3874 static void genrshOne (operand *result,operand *left, int shCount)
3877 int size = AOP_SIZE(result);
3883 l = aopGet(AOP(left),0,FALSE);
3884 if (AOP(result)->type == AOP_REG) {
3885 aopPut(AOP(result), l, 0);
3886 l = aopGet(AOP(result), 0, FALSE);
3888 emitcode("srl", "%s", l);
3893 emitcode("srl", "a");
3895 aopPut(AOP(result),"a",0);
3899 /*-----------------------------------------------------------------*/
3900 /* AccRsh - right shift accumulator by known count */
3901 /*-----------------------------------------------------------------*/
3902 static void AccRsh (int shCount)
3905 /* rotate right accumulator */
3906 AccRol(8 - shCount);
3907 /* and kill the higher order bits */
3908 emit2("and a,!immedbyte", SRMask[shCount]);
3912 /*-----------------------------------------------------------------*/
3913 /* shiftR1Left2Result - shift right one byte from left to result */
3914 /*-----------------------------------------------------------------*/
3915 static void shiftR1Left2Result (operand *left, int offl,
3916 operand *result, int offr,
3917 int shCount, int sign)
3919 MOVA(aopGet(AOP(left),offl,FALSE));
3926 aopPut(AOP(result),"a",offr);
3929 /*-----------------------------------------------------------------*/
3930 /* genrshTwo - right shift two bytes by known amount != 0 */
3931 /*-----------------------------------------------------------------*/
3932 static void genrshTwo (operand *result,operand *left,
3933 int shCount, int sign)
3935 /* if shCount >= 8 */
3939 shiftR1Left2Result(left, MSB16, result, LSB,
3943 movLeft2Result(left, MSB16, result, LSB, sign);
3945 aopPut(AOP(result),zero,1);
3947 /* 1 <= shCount <= 7 */
3949 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
3953 /*-----------------------------------------------------------------*/
3954 /* genRightShiftLiteral - left shifting by known count */
3955 /*-----------------------------------------------------------------*/
3956 static void genRightShiftLiteral (operand *left,
3961 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3964 freeAsmop(right,NULL,ic);
3966 aopOp(left,ic,FALSE, FALSE);
3967 aopOp(result,ic,FALSE, FALSE);
3969 size = getSize(operandType(result));
3971 emitcode("; shift right ","result %d, left %d",size,
3974 /* I suppose that the left size >= result size */
3979 else if(shCount >= (size * 8))
3981 aopPut(AOP(result),zero,size);
3985 genrshOne(result, left, shCount);
3988 /* PENDING: sign support */
3989 genrshTwo(result, left, shCount, FALSE);
3998 freeAsmop(left,NULL,ic);
3999 freeAsmop(result,NULL,ic);
4002 /*-----------------------------------------------------------------*/
4003 /* genRightShift - generate code for right shifting */
4004 /*-----------------------------------------------------------------*/
4005 static void genRightShift (iCode *ic)
4007 operand *right, *left, *result;
4009 int size, offset, first = 1;
4013 symbol *tlbl, *tlbl1 ;
4015 /* if signed then we do it the hard way preserve the
4016 sign bit moving it inwards */
4017 retype = getSpec(operandType(IC_RESULT(ic)));
4019 is_signed = !SPEC_USIGN(retype);
4021 /* signed & unsigned types are treated the same : i.e. the
4022 signed is NOT propagated inwards : quoting from the
4023 ANSI - standard : "for E1 >> E2, is equivalent to division
4024 by 2**E2 if unsigned or if it has a non-negative value,
4025 otherwise the result is implementation defined ", MY definition
4026 is that the sign does not get propagated */
4028 right = IC_RIGHT(ic);
4030 result = IC_RESULT(ic);
4032 aopOp(right,ic,FALSE, FALSE);
4034 /* if the shift count is known then do it
4035 as efficiently as possible */
4036 if (AOP_TYPE(right) == AOP_LIT) {
4037 genRightShiftLiteral(left,right,result,ic);
4041 aopOp(left,ic,FALSE, FALSE);
4042 aopOp(result,ic,FALSE, FALSE);
4044 /* now move the left to the result if they are not the
4046 if (!sameRegs(AOP(left),AOP(result)) &&
4047 AOP_SIZE(result) > 1) {
4049 size = AOP_SIZE(result);
4052 l = aopGet(AOP(left),offset,FALSE);
4053 aopPut(AOP(result),l,offset);
4058 emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
4059 emitcode("inc","a");
4060 freeAsmop (right, NULL, ic);
4062 tlbl = newiTempLabel(NULL);
4063 tlbl1= newiTempLabel(NULL);
4064 size = AOP_SIZE(result);
4067 emit2("!shortjp !tlabel", tlbl1->key+100);
4068 emitLabel(tlbl->key+100);
4070 l = aopGet(AOP(result),offset--,FALSE);
4073 emitcode("sra", "%s", l);
4075 emitcode("srl", "%s", l);
4079 emitcode("rr", "%s", l);
4081 emitLabel(tlbl1->key+100);
4082 emitcode("dec", "a");
4083 emit2("!shortjp nz,!tlabel", tlbl->key+100);
4085 freeAsmop(left,NULL,ic);
4086 freeAsmop(result,NULL,ic);
4089 /*-----------------------------------------------------------------*/
4090 /* genGenPointerGet - get value from generic pointer space */
4091 /*-----------------------------------------------------------------*/
4092 static void genGenPointerGet (operand *left,
4093 operand *result, iCode *ic)
4096 link *retype = getSpec(operandType(result));
4102 aopOp(left,ic,FALSE, FALSE);
4103 aopOp(result,ic,FALSE, FALSE);
4105 if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
4107 if (isPtrPair(AOP(left)))
4109 tsprintf(buffer, "!*pair", getPairName(AOP(left)));
4110 aopPut(AOP(result), buffer, 0);
4113 emit2("ld a,!*pair", getPairName(AOP(left)));
4114 aopPut(AOP(result),"a", 0);
4116 freeAsmop(left,NULL,ic);
4120 /* For now we always load into IY */
4121 /* if this is remateriazable */
4122 fetchPair(pair, AOP(left));
4124 /* so iy now contains the address */
4125 freeAsmop(left,NULL,ic);
4127 /* if bit then unpack */
4128 if (IS_BITVAR(retype)) {
4132 size = AOP_SIZE(result);
4136 /* PENDING: make this better */
4137 if (!IS_GB && AOP(result)->type == AOP_REG) {
4138 aopPut(AOP(result), "!*hl", offset++);
4141 emit2("ld a,!*pair", _pairs[pair].name);
4142 aopPut(AOP(result),"a",offset++);
4145 emit2("inc %s", _pairs[pair].name);
4146 _G.pairs[pair].offset++;
4152 freeAsmop(result,NULL,ic);
4155 /*-----------------------------------------------------------------*/
4156 /* genPointerGet - generate code for pointer get */
4157 /*-----------------------------------------------------------------*/
4158 static void genPointerGet (iCode *ic)
4160 operand *left, *result ;
4164 result = IC_RESULT(ic) ;
4166 /* depending on the type of pointer we need to
4167 move it to the correct pointer register */
4168 type = operandType(left);
4169 etype = getSpec(type);
4171 genGenPointerGet (left,result,ic);
4174 bool isRegOrLit(asmop *aop)
4176 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4181 /*-----------------------------------------------------------------*/
4182 /* genGenPointerSet - stores the value into a pointer location */
4183 /*-----------------------------------------------------------------*/
4184 static void genGenPointerSet (operand *right,
4185 operand *result, iCode *ic)
4188 link *retype = getSpec(operandType(right));
4189 PAIR_ID pairId = PAIR_HL;
4191 aopOp(result,ic,FALSE, FALSE);
4192 aopOp(right,ic,FALSE, FALSE);
4197 /* Handle the exceptions first */
4198 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
4200 char *l = aopGet(AOP(right), 0, FALSE);
4201 const char *pair = getPairName(AOP(result));
4202 if (canAssignToPtr(l) && isPtr(pair)) {
4203 emit2("ld !*pair,%s", pair, l);
4207 emit2("ld !*pair,a", pair);
4212 /* if the operand is already in dptr
4213 then we do nothing else we move the value to dptr */
4214 if (AOP_TYPE(result) != AOP_STR) {
4215 fetchPair(pairId, AOP(result));
4217 /* so hl know contains the address */
4218 freeAsmop(result,NULL,ic);
4220 /* if bit then unpack */
4221 if (IS_BITVAR(retype)) {
4225 size = AOP_SIZE(right);
4229 char *l = aopGet(AOP(right),offset,FALSE);
4230 if (isRegOrLit(AOP(right)) && !IS_GB) {
4231 emit2("ld !*pair,%s", _pairs[pairId].name, l);
4235 emit2("ld !*pair,a", _pairs[pairId].name);
4238 emitcode("inc", _pairs[pairId].name);
4239 _G.pairs[pairId].offset++;
4245 freeAsmop(right,NULL,ic);
4248 /*-----------------------------------------------------------------*/
4249 /* genPointerSet - stores the value into a pointer location */
4250 /*-----------------------------------------------------------------*/
4251 static void genPointerSet (iCode *ic)
4253 operand *right, *result ;
4256 right = IC_RIGHT(ic);
4257 result = IC_RESULT(ic) ;
4259 /* depending on the type of pointer we need to
4260 move it to the correct pointer register */
4261 type = operandType(result);
4262 etype = getSpec(type);
4264 genGenPointerSet (right,result,ic);
4267 /*-----------------------------------------------------------------*/
4268 /* genIfx - generate code for Ifx statement */
4269 /*-----------------------------------------------------------------*/
4270 static void genIfx (iCode *ic, iCode *popIc)
4272 operand *cond = IC_COND(ic);
4275 aopOp(cond,ic,FALSE, TRUE);
4277 /* get the value into acc */
4278 if (AOP_TYPE(cond) != AOP_CRY)
4282 /* the result is now in the accumulator */
4283 freeAsmop(cond,NULL,ic);
4285 /* if there was something to be popped then do it */
4289 /* if the condition is a bit variable */
4290 if (isbit && IS_ITEMP(cond) &&
4292 genIfxJump(ic,SPIL_LOC(cond)->rname);
4294 if (isbit && !IS_ITEMP(cond))
4295 genIfxJump(ic,OP_SYMBOL(cond)->rname);
4302 /*-----------------------------------------------------------------*/
4303 /* genAddrOf - generates code for address of */
4304 /*-----------------------------------------------------------------*/
4305 static void genAddrOf (iCode *ic)
4307 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4309 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4311 /* if the operand is on the stack then we
4312 need to get the stack offset of this
4317 if (sym->stack <= 0) {
4318 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
4321 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
4323 emitcode("ld", "d,h");
4324 emitcode("ld", "e,l");
4327 emit2("ld de,!hashedstr", sym->rname);
4329 aopPut(AOP(IC_RESULT(ic)), "e", 0);
4330 aopPut(AOP(IC_RESULT(ic)), "d", 1);
4335 /* if it has an offset then we need to compute it */
4336 emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
4337 emitcode("add", "hl,sp");
4340 emitcode("ld", "hl,#%s", sym->rname);
4342 aopPut(AOP(IC_RESULT(ic)), "l", 0);
4343 aopPut(AOP(IC_RESULT(ic)), "h", 1);
4345 freeAsmop(IC_RESULT(ic),NULL,ic);
4348 /*-----------------------------------------------------------------*/
4349 /* genAssign - generate code for assignment */
4350 /*-----------------------------------------------------------------*/
4351 static void genAssign (iCode *ic)
4353 operand *result, *right;
4355 unsigned long lit = 0L;
4357 result = IC_RESULT(ic);
4358 right = IC_RIGHT(ic) ;
4361 /* Dont bother assigning if they are the same */
4362 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
4363 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
4368 aopOp(right,ic,FALSE, FALSE);
4369 aopOp(result,ic,TRUE, FALSE);
4371 /* if they are the same registers */
4372 if (sameRegs(AOP(right),AOP(result))) {
4373 emitcode("", "; (registers are the same)");
4377 /* if the result is a bit */
4378 if (AOP_TYPE(result) == AOP_CRY) {
4383 size = AOP_SIZE(result);
4386 if(AOP_TYPE(right) == AOP_LIT)
4387 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4388 if (isPair(AOP(result))) {
4389 fetchPair(getPairId(AOP(result)), AOP(right));
4391 else if((size > 1) &&
4392 (AOP_TYPE(result) != AOP_REG) &&
4393 (AOP_TYPE(right) == AOP_LIT) &&
4394 !IS_FLOAT(operandType(right)) &&
4396 bool fXored = FALSE;
4398 /* Work from the top down.
4399 Done this way so that we can use the cached copy of 0
4400 in A for a fast clear */
4402 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
4403 if (!fXored && size>1) {
4404 emitcode("xor", "a,a");
4408 aopPut(AOP(result),"a",offset);
4411 aopPut(AOP(result), zero, offset);
4416 aopGet(AOP(right),offset,FALSE),
4421 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result)) && IS_GB) {
4422 /* Special case. Load into a and d, then load out. */
4423 MOVA(aopGet(AOP(right), 0, FALSE));
4424 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
4425 aopPut(AOP(result), "a", 0);
4426 aopPut(AOP(result), "e", 1);
4429 /* PENDING: do this check better */
4430 if (requiresHL(AOP(right)) && requiresHL(AOP(result))) {
4431 MOVA(aopGet(AOP(right), offset, FALSE));
4432 aopPut(AOP(result), "a", offset);
4436 aopGet(AOP(right),offset,FALSE),
4443 freeAsmop(right,NULL,ic);
4444 freeAsmop(result,NULL,ic);
4447 /*-----------------------------------------------------------------*/
4448 /* genJumpTab - genrates code for jump table */
4449 /*-----------------------------------------------------------------*/
4450 static void genJumpTab (iCode *ic)
4455 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
4456 /* get the condition into accumulator */
4457 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
4459 emitcode("push", "de");
4460 emitcode("ld", "e,%s", l);
4461 emit2("ld d,!zero");
4462 jtab = newiTempLabel(NULL);
4464 emit2("ld hl,!immed!tlabel", jtab->key+100);
4465 emitcode("add", "hl,de");
4466 emitcode("add", "hl,de");
4467 emitcode("add", "hl,de");
4468 freeAsmop(IC_JTCOND(ic),NULL,ic);
4470 emitcode("pop", "de");
4472 emitLabel(jtab->key+100);
4473 /* now generate the jump labels */
4474 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4475 jtab = setNextItem(IC_JTLABELS(ic)))
4476 emit2("jp !tlabel", jtab->key+100);
4479 /*-----------------------------------------------------------------*/
4480 /* genCast - gen code for casting */
4481 /*-----------------------------------------------------------------*/
4482 static void genCast (iCode *ic)
4484 operand *result = IC_RESULT(ic);
4485 link *ctype = operandType(IC_LEFT(ic));
4486 operand *right = IC_RIGHT(ic);
4489 /* if they are equivalent then do nothing */
4490 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4493 aopOp(right,ic,FALSE, FALSE);
4494 aopOp(result,ic,FALSE, FALSE);
4496 /* if the result is a bit */
4497 if (AOP_TYPE(result) == AOP_CRY) {
4501 /* if they are the same size : or less */
4502 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4504 /* if they are in the same place */
4505 if (sameRegs(AOP(right),AOP(result)))
4508 /* if they in different places then copy */
4509 size = AOP_SIZE(result);
4513 aopGet(AOP(right),offset,FALSE),
4520 /* PENDING: should be OK. */
4522 /* if the result is of type pointer */
4523 if (IS_PTR(ctype)) {
4528 /* so we now know that the size of destination is greater
4529 than the size of the source */
4530 /* we move to result for the size of source */
4531 size = AOP_SIZE(right);
4535 aopGet(AOP(right),offset,FALSE),
4540 /* now depending on the sign of the destination */
4541 size = AOP_SIZE(result) - AOP_SIZE(right);
4542 /* Unsigned or not an integral type - right fill with zeros */
4543 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4545 aopPut(AOP(result),zero,offset++);
4547 /* we need to extend the sign :{ */
4548 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4551 emitcode("", "; genCast: sign extend untested.");
4552 emitcode("rla", "");
4553 emitcode("sbc", "a,a");
4555 aopPut(AOP(result),"a",offset++);
4559 freeAsmop(right, NULL, ic);
4560 freeAsmop(result, NULL, ic);
4563 /*-----------------------------------------------------------------*/
4564 /* genReceive - generate code for a receive iCode */
4565 /*-----------------------------------------------------------------*/
4566 static void genReceive (iCode *ic)
4568 if (isOperandInFarSpace(IC_RESULT(ic)) &&
4569 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4570 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4574 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4576 assignResultValue(IC_RESULT(ic));
4579 freeAsmop(IC_RESULT(ic),NULL,ic);
4582 /*-----------------------------------------------------------------*/
4583 /* genZ80Code - generate code for Z80 based controllers */
4584 /*-----------------------------------------------------------------*/
4585 void genZ80Code (iCode *lic)
4592 _fReturn = _gbz80_return;
4593 _fTmp = _gbz80_return;
4596 _fReturn = _z80_return;
4597 _fTmp = _z80_return;
4599 tsprintf(zero, "!zero");
4601 lineHead = lineCurr = NULL;
4603 /* if debug information required */
4604 if (options.debug && currFunc) {
4605 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4607 if (IS_STATIC(currFunc->etype))
4608 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4610 emitcode("","G$%s$0$0 ==.",currFunc->name);
4613 /* stack pointer name */
4617 for (ic = lic ; ic ; ic = ic->next ) {
4619 if ( cln != ic->lineno ) {
4620 if ( options.debug ) {
4622 emitcode("","C$%s$%d$%d$%d ==.",
4623 ic->filename,ic->lineno,
4624 ic->level,ic->block);
4627 emitcode(";","%s %d",ic->filename,ic->lineno);
4630 /* if the result is marked as
4631 spilt and rematerializable or code for
4632 this has already been generated then
4634 if (resultRemat(ic) || ic->generated )
4637 /* depending on the operation */
4640 emitcode("", "; genNot");
4645 emitcode("", "; genCpl");
4650 emitcode("", "; genUminus");
4655 emitcode("", "; genIpush");
4660 /* IPOP happens only when trying to restore a
4661 spilt live range, if there is an ifx statement
4662 following this pop then the if statement might
4663 be using some of the registers being popped which
4664 would destory the contents of the register so
4665 we need to check for this condition and handle it */
4667 ic->next->op == IFX &&
4668 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4669 emitcode("", "; genIfx");
4670 genIfx (ic->next,ic);
4673 emitcode("", "; genIpop");
4679 emitcode("", "; genCall");
4684 emitcode("", "; genPcall");
4689 emitcode("", "; genFunction");
4694 emitcode("", "; genEndFunction");
4695 genEndFunction (ic);
4699 emitcode("", "; genRet");
4704 emitcode("", "; genLabel");
4709 emitcode("", "; genGoto");
4714 emitcode("", "; genPlus");
4719 emitcode("", "; genMinus");
4724 emitcode("", "; genMult");
4729 emitcode("", "; genDiv");
4734 emitcode("", "; genMod");
4739 emitcode("", "; genCmpGt");
4740 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4744 emitcode("", "; genCmpLt");
4745 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4752 /* note these two are xlated by algebraic equivalence
4753 during parsing SDCC.y */
4754 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4755 "got '>=' or '<=' shouldn't have come here");
4759 emitcode("", "; genCmpEq");
4760 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4764 emitcode("", "; genAndOp");
4769 emitcode("", "; genOrOp");
4774 emitcode("", "; genXor");
4775 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4779 emitcode("", "; genOr");
4780 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4784 emitcode("", "; genAnd");
4785 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4789 emitcode("", "; genInline");
4794 emitcode("", "; genRRC");
4799 emitcode("", "; genRLC");
4804 emitcode("", "; genHBIT");
4808 emitcode("", "; genLeftShift");
4813 emitcode("", "; genRightShift");
4817 case GET_VALUE_AT_ADDRESS:
4818 emitcode("", "; genPointerGet");
4824 if (POINTER_SET(ic)) {
4825 emitcode("", "; genAssign (pointer)");
4829 emitcode("", "; genAssign");
4835 emitcode("", "; genIfx");
4840 emitcode("", "; genAddrOf");
4845 emitcode("", "; genJumpTab");
4850 emitcode("", "; genCast");
4855 emitcode("", "; genReceive");
4860 emitcode("", "; addSet");
4861 addSet(&sendSet,ic);
4866 /* piCode(ic,stdout); */
4872 /* now we are ready to call the
4873 peep hole optimizer */
4874 if (!options.nopeep)
4875 peepHole (&lineHead);
4877 /* This is unfortunate */
4878 /* now do the actual printing */
4880 FILE *fp = codeOutFile;
4881 if (isInHome() && codeOutFile == code->oFile)
4882 codeOutFile = home->oFile;
4883 printLine (lineHead, codeOutFile);
4884 if (_G.flush_statics) {
4886 _G.flush_statics = 0;