1 /*-------------------------------------------------------------------------
2 gen.c - Z80 specific code generator.
4 Benchmarks on dhry.c 2.1 with 32766 loops and a 10ms clock:
6 Base with asm strcpy / strcmp / memcpy: 23198 141 1A14
7 Improved WORD push 22784 144 19AE
8 With label1 on 22694 144 197E
9 With label2 on 22743 144 198A
10 With label3 on 22776 144 1999
11 With label4 on 22776 144 1999
12 With all 'label' on 22661 144 196F
13 With loopInvariant on 20919 156 19AB
14 With loopInduction on Breaks 198B
15 With all working on 20796 158 196C
16 Slightly better genCmp(signed) 20597 159 195B
17 Better reg packing, first peephole 20038 163 1873
18 With assign packing 19281 165 1849
20 With reg params for mul and div 16234 202 162D
22 Michael Hope <michaelh@earthling.net> 2000
23 Based on the mcs51 generator -
24 Sandeep Dutta . sandeep.dutta@usa.net (1998)
25 and - Jean-Louis VERN.jlvern@writeme.com (1999)
27 This program is free software; you can redistribute it and/or modify it
28 under the terms of the GNU General Public License as published by the
29 Free Software Foundation; either version 2, or (at your option) any
32 This program is distributed in the hope that it will be useful,
33 but WITHOUT ANY WARRANTY; without even the implied warranty of
34 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
35 GNU General Public License for more details.
38 You should have received a copy of the GNU General Public License
39 along with this program; if not, write to the Free Software
40 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
42 In other words, you are welcome to use, share and improve this program.
43 You are forbidden to forbid anyone else to use, share and improve
44 what you give them. Help stamp out software-hoarding!
46 -------------------------------------------------------------------------*/
53 #ifdef HAVE_SYS_ISA_DEFS_H
54 #include <sys/isa_defs.h>
58 #include "SDCCglobl.h"
59 #include "SDCCpeeph.h"
63 /* this is the down and dirty file with all kinds of kludgy & hacky
64 stuff. This is what it is all about CODE GENERATION for a specific MCU.
65 Some of the routines may be reusable, will have to see */
68 static char *_z80_return[] = {"l", "h", "e", "d" };
69 static char *_gbz80_return[] = { "e", "d", "l", "h" };
70 static char **_fReturn;
76 static char *accUse[] = {"a" };
77 static char *hlUse[] = { "l", "h" };
83 extern int ptrRegReq ;
85 extern FILE *codeOutFile;
102 } _pairs[NUM_PAIRS] = {
107 { "iy", "iy.l?", "iy.h?" },
108 { "ix", "ix.l?", "ix.h?" }
111 #define RESULTONSTACK(x) \
112 (IC_RESULT(x) && IC_RESULT(x)->aop && \
113 IC_RESULT(x)->aop->type == AOP_STK )
115 #define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
116 #define CLRC emitcode("xor","a,a");
118 lineNode *lineHead = NULL;
119 lineNode *lineCurr = NULL;
121 static const unsigned char SLMask[] =
122 {0xFF ,0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
123 static const unsigned char SRMask[] =
124 {0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
157 static char *aopGet(asmop *aop, int offset, bool bit16);
159 static void _tidyUp(char *buf)
161 /* Clean up the line so that it is 'prettier' */
162 if (strchr(buf, ':')) {
163 /* Is a label - cant do anything */
166 /* Change the first (and probably only) ' ' to a tab so
178 static void emit2(const char *szFormat, ...)
183 va_start(ap, szFormat);
185 tvsprintf(buffer, szFormat, ap);
188 lineCurr = (lineCurr ?
189 connectLine(lineCurr,newLineNode(buffer)) :
190 (lineHead = newLineNode(buffer)));
192 lineCurr->isInline = inLine;
193 lineCurr->isDebug = debugLine;
196 /*-----------------------------------------------------------------*/
197 /* emitcode - writes the code into a file : for now it is simple */
198 /*-----------------------------------------------------------------*/
199 void emitcode (const char *inst, const char *fmt, ...)
202 char lb[MAX_INLINEASM];
208 sprintf(lb,"%s\t",inst);
209 vsprintf(lb+(strlen(lb)),fmt,ap);
213 while (isspace(*lbp)) lbp++;
216 lineCurr = (lineCurr ?
217 connectLine(lineCurr,newLineNode(lb)) :
218 (lineHead = newLineNode(lb)));
219 lineCurr->isInline = inLine;
220 lineCurr->isDebug = debugLine;
237 emitcode("ld", "sp,ix");
238 emitcode("pop", "ix");
239 emitcode("pop", "de");
244 const char *getPairName(asmop *aop)
246 if (aop->type == AOP_REG) {
247 switch (aop->aopu.aop_reg[0]->rIdx) {
259 else if (aop->type == AOP_STR) {
260 switch (*aop->aopu.aop_str[0]) {
276 static PAIR_ID getPairId(asmop *aop)
278 if (aop->size == 2) {
279 if (aop->type == AOP_REG) {
280 if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
283 if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
286 if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
290 if (aop->type == AOP_STR) {
291 if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
294 if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
297 if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
305 /** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
306 bool isPair(asmop *aop)
308 return (getPairId(aop) != PAIR_INVALID);
311 bool isPtrPair(asmop *aop)
313 PAIR_ID pairId = getPairId(aop);
323 /** Push a register pair onto the stack */
324 void genPairPush(asmop *aop)
326 emitcode("push", "%s", getPairName(aop));
330 /*-----------------------------------------------------------------*/
331 /* newAsmop - creates a new asmOp */
332 /*-----------------------------------------------------------------*/
333 static asmop *newAsmop (short type)
337 ALLOC(aop,sizeof(asmop));
342 /*-----------------------------------------------------------------*/
343 /* aopForSym - for a true symbol */
344 /*-----------------------------------------------------------------*/
345 static asmop *aopForSym (iCode *ic,symbol *sym,bool result, bool requires_a)
354 space = SPEC_OCLS(sym->etype);
356 /* if already has one */
360 /* Assign depending on the storage class */
361 if (sym->onStack || sym->iaccess) {
362 emitcode("", "; AOP_STK for %s", sym->rname);
363 sym->aop = aop = newAsmop(AOP_STK);
364 aop->size = getSize(sym->type);
365 aop->aopu.aop_stk = sym->stack;
369 /* special case for a function */
370 if (IS_FUNC(sym->type)) {
371 sym->aop = aop = newAsmop(AOP_IMMD);
372 ALLOC(aop->aopu.aop_immd,strlen(sym->rname)+1);
373 strcpy(aop->aopu.aop_immd,sym->rname);
379 /* if it is in direct space */
380 if (IN_REGSP(space) && !requires_a) {
381 sym->aop = aop = newAsmop (AOP_SFR);
382 aop->aopu.aop_dir = sym->rname ;
383 aop->size = getSize(sym->type);
384 emitcode("", "; AOP_SFR for %s", sym->rname);
389 /* only remaining is far space */
390 /* in which case DPTR gets the address */
392 emitcode("", "; AOP_HL for %s", sym->rname);
393 sym->aop = aop = newAsmop(AOP_HL);
396 sym->aop = aop = newAsmop(AOP_IY);
398 aop->size = getSize(sym->type);
399 aop->aopu.aop_dir = sym->rname;
401 /* if it is in code space */
402 if (IN_CODESPACE(space))
408 /*-----------------------------------------------------------------*/
409 /* aopForRemat - rematerialzes an object */
410 /*-----------------------------------------------------------------*/
411 static asmop *aopForRemat (symbol *sym)
414 iCode *ic = sym->rematiCode;
415 asmop *aop = newAsmop(AOP_IMMD);
418 /* if plus or minus print the right hand side */
419 if (ic->op == '+' || ic->op == '-') {
420 /* PENDING: for re-target */
421 sprintf(s,"0x%04x %c ",(int) operandLitValue(IC_RIGHT(ic)),
424 ic = OP_SYMBOL(IC_LEFT(ic))->rematiCode;
427 /* we reached the end */
428 sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
432 ALLOC(aop->aopu.aop_immd,strlen(buffer)+1);
433 strcpy(aop->aopu.aop_immd,buffer);
437 /*-----------------------------------------------------------------*/
438 /* regsInCommon - two operands have some registers in common */
439 /*-----------------------------------------------------------------*/
440 bool regsInCommon (operand *op1, operand *op2)
445 /* if they have registers in common */
446 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
449 sym1 = OP_SYMBOL(op1);
450 sym2 = OP_SYMBOL(op2);
452 if (sym1->nRegs == 0 || sym2->nRegs == 0)
455 for (i = 0 ; i < sym1->nRegs ; i++) {
460 for (j = 0 ; j < sym2->nRegs ;j++ ) {
464 if (sym2->regs[j] == sym1->regs[i])
472 /*-----------------------------------------------------------------*/
473 /* operandsEqu - equivalent */
474 /*-----------------------------------------------------------------*/
475 bool operandsEqu ( operand *op1, operand *op2)
479 /* if they not symbols */
480 if (!IS_SYMOP(op1) || !IS_SYMOP(op2))
483 sym1 = OP_SYMBOL(op1);
484 sym2 = OP_SYMBOL(op2);
486 /* if both are itemps & one is spilt
487 and the other is not then false */
488 if (IS_ITEMP(op1) && IS_ITEMP(op2) &&
489 sym1->isspilt != sym2->isspilt )
492 /* if they are the same */
496 if (strcmp(sym1->rname,sym2->rname) == 0)
500 /* if left is a tmp & right is not */
504 (sym1->usl.spillLoc == sym2))
511 (sym2->usl.spillLoc == sym1))
517 /*-----------------------------------------------------------------*/
518 /* sameRegs - two asmops have the same registers */
519 /*-----------------------------------------------------------------*/
520 bool sameRegs (asmop *aop1, asmop *aop2 )
524 if (aop1->type == AOP_SFR ||
525 aop2->type == AOP_SFR)
531 if (aop1->type != AOP_REG ||
532 aop2->type != AOP_REG )
535 if (aop1->size != aop2->size)
538 for (i = 0 ; i < aop1->size ; i++ )
539 if (aop1->aopu.aop_reg[i] !=
540 aop2->aopu.aop_reg[i] )
546 /*-----------------------------------------------------------------*/
547 /* aopOp - allocates an asmop for an operand : */
548 /*-----------------------------------------------------------------*/
549 static void aopOp (operand *op, iCode *ic, bool result, bool requires_a)
558 /* if this a literal */
559 if (IS_OP_LITERAL(op)) {
560 op->aop = aop = newAsmop(AOP_LIT);
561 aop->aopu.aop_lit = op->operand.valOperand;
562 aop->size = getSize(operandType(op));
566 /* if already has a asmop then continue */
570 /* if the underlying symbol has a aop */
571 if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
572 op->aop = OP_SYMBOL(op)->aop;
576 /* if this is a true symbol */
577 if (IS_TRUE_SYMOP(op)) {
578 op->aop = aopForSym(ic, OP_SYMBOL(op), result, requires_a);
582 /* this is a temporary : this has
588 e) can be a return use only */
592 /* if the type is a conditional */
593 if (sym->regType == REG_CND) {
594 aop = op->aop = sym->aop = newAsmop(AOP_CRY);
599 /* if it is spilt then two situations
601 b) has a spill location */
602 if (sym->isspilt || sym->nRegs == 0) {
603 /* rematerialize it NOW */
605 sym->aop = op->aop = aop =
607 aop->size = getSize(sym->type);
613 if (sym->accuse == ACCUSE_A) {
614 aop = op->aop = sym->aop = newAsmop(AOP_ACC);
615 aop->size = getSize(sym->type);
616 for ( i = 0 ; i < 2 ; i++ )
617 aop->aopu.aop_str[i] = accUse[i];
619 else if (sym->accuse == ACCUSE_HL) {
621 aop = op->aop = sym->aop = newAsmop(AOP_HLREG);
622 aop->size = getSize(sym->type);
623 for ( i = 0 ; i < 2 ; i++ )
624 aop->aopu.aop_str[i] = hlUse[i];
633 aop = op->aop = sym->aop = newAsmop(AOP_STR);
634 aop->size = getSize(sym->type);
635 for ( i = 0 ; i < 4 ; i++ )
636 aop->aopu.aop_str[i] = _fReturn[i];
640 /* else spill location */
641 sym->aop = op->aop = aop =
642 aopForSym(ic,sym->usl.spillLoc,result, requires_a);
643 aop->size = getSize(sym->type);
647 /* must be in a register */
648 sym->aop = op->aop = aop = newAsmop(AOP_REG);
649 aop->size = sym->nRegs;
650 for ( i = 0 ; i < sym->nRegs ;i++)
651 aop->aopu.aop_reg[i] = sym->regs[i];
654 /*-----------------------------------------------------------------*/
655 /* freeAsmop - free up the asmop given to an operand */
656 /*----------------------------------------------------------------*/
657 static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
675 /* all other cases just dealloc */
679 OP_SYMBOL(op)->aop = NULL;
680 /* if the symbol has a spill */
682 SPIL_LOC(op)->aop = NULL;
687 bool isLitWord(asmop *aop)
689 /* if (aop->size != 2)
700 char *aopGetLitWordLong(asmop *aop, int offset, bool with_hash)
706 if (aop->size != 2 && aop->type != AOP_HL)
709 /* depending on type */
714 /* PENDING: for re-target */
716 tsprintf(s, "!hashedstr + %d", aop->aopu.aop_immd, offset);
718 tsprintf(s, "%s + %d", aop->aopu.aop_immd, offset);
719 ALLOC(rs,strlen(s)+1);
723 value * val = aop->aopu.aop_lit;
724 /* if it is a float then it gets tricky */
725 /* otherwise it is fairly simple */
726 if (!IS_FLOAT(val->type)) {
727 unsigned long v = floatFromVal(val);
733 tsprintf(buffer, "!immedword", v);
735 tsprintf(buffer, "!constword", v);
736 ALLOC(rs,strlen(buffer)+1);
737 return strcpy (rs,buffer);
742 convertFloat(&f, floatFromVal(val));
744 tsprintf(buffer, "!immedword", f.w[offset/2]);
746 tsprintf(buffer, "!constword", f.w[offset/2]);
747 ALLOC(rs,strlen(buffer)+1);
748 return strcpy (rs,buffer);
756 char *aopGetWord(asmop *aop, int offset)
758 return aopGetLitWordLong(aop, offset, TRUE);
761 bool isPtr(const char *s)
763 if (!strcmp(s, "hl"))
765 if (!strcmp(s, "ix"))
767 if (!strcmp(s, "iy"))
772 static void adjustPair(const char *pair, int *pold, int new)
776 while (*pold < new) {
777 emitcode("inc", "%s", pair);
780 while (*pold > new) {
781 emitcode("dec", "%s", pair);
786 static void spillPair(PAIR_ID pairId)
788 _G.pairs[pairId].last_type = AOP_INVALID;
789 _G.pairs[pairId].lit = NULL;
792 static void spillCached(void)
798 static bool requiresHL(asmop *aop)
809 static char *fetchLitSpecial(asmop *aop, bool negate, bool xor)
812 value * val = aop->aopu.aop_lit;
814 wassert(aop->type == AOP_LIT);
815 wassert(!IS_FLOAT(val->type));
817 v = floatFromVal(val);
825 tsprintf(buffer, "!immedword", v);
826 return gc_strdup(buffer);
829 static void fetchLitPair(PAIR_ID pairId, asmop *left, int offset)
832 const char *pair = _pairs[pairId].name;
833 l = aopGetLitWordLong(left, 0, FALSE);
837 if (pairId == PAIR_HL || pairId == PAIR_IY) {
838 if (_G.pairs[pairId].last_type == left->type) {
839 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
840 if (pairId == PAIR_HL && abs(_G.pairs[pairId].offset - offset) < 3) {
841 adjustPair(pair, &_G.pairs[pairId].offset, offset);
844 if (pairId == PAIR_IY && abs(offset)<127) {
850 _G.pairs[pairId].last_type = left->type;
851 _G.pairs[pairId].lit = gc_strdup(l);
852 _G.pairs[pairId].offset = offset;
854 if (IS_GB && pairId == PAIR_DE && 0) {
855 if (_G.pairs[pairId].lit && !strcmp(_G.pairs[pairId].lit, l)) {
856 if (abs(_G.pairs[pairId].offset - offset) < 3) {
857 adjustPair(pair, &_G.pairs[pairId].offset, offset);
861 _G.pairs[pairId].last_type = left->type;
862 _G.pairs[pairId].lit = gc_strdup(l);
863 _G.pairs[pairId].offset = offset;
865 /* Both a lit on the right and a true symbol on the left */
867 emit2("ld %s,!hashedstr + %u", pair, l, offset);
869 emit2("ld %s,!hashedstr", pair, l);
872 static void fetchPairLong(PAIR_ID pairId, asmop *aop, int offset)
874 /* if this is remateriazable */
875 if (isLitWord(aop)) {
876 fetchLitPair(pairId, aop, offset);
878 else { /* we need to get it byte by byte */
879 if (pairId == PAIR_HL && IS_GB && requiresHL(aop)) {
880 aopGet(aop, offset, FALSE);
884 emit2("ld h,!immedbyte", 0);
892 emit2("; WARNING: mlh woosed out. This code is invalid.");
895 else if (IS_Z80 && aop->type == AOP_IY) {
896 /* Instead of fetching relative to IY, just grab directly
897 from the address IY refers to */
898 char *l = aopGetLitWordLong(aop, offset, FALSE);
900 emit2("ld %s,(%s)", _pairs[pairId].name, l);
903 emitcode("ld", "%s,%s", _pairs[pairId].l, aopGet(aop, offset, FALSE));
904 emitcode("ld", "%s,%s", _pairs[pairId].h, aopGet(aop, offset+1, FALSE));
906 /* PENDING: check? */
907 if (pairId == PAIR_HL)
912 static void fetchPair(PAIR_ID pairId, asmop *aop)
914 fetchPairLong(pairId, aop, 0);
917 static void fetchHL(asmop *aop)
919 fetchPair(PAIR_HL, aop);
922 static void setupPair(PAIR_ID pairId, asmop *aop, int offset)
924 assert(pairId == PAIR_HL || pairId == PAIR_IY);
928 fetchLitPair(pairId, aop, 0);
931 fetchLitPair(pairId, aop, offset);
932 _G.pairs[pairId].offset = offset;
935 /* Doesnt include _G.stack.pushed */
936 int abso = aop->aopu.aop_stk + offset + _G.stack.offset;
937 if (aop->aopu.aop_stk > 0) {
938 abso += _G.stack.param_offset;
940 assert(pairId == PAIR_HL);
941 /* In some cases we can still inc or dec hl */
942 if (_G.pairs[pairId].last_type == AOP_STK && abs(_G.pairs[pairId].offset - abso) < 3) {
943 adjustPair(_pairs[pairId].name, &_G.pairs[pairId].offset, abso);
946 emit2("!ldahlsp", abso +_G.stack.pushed);
948 _G.pairs[pairId].offset = abso;
954 _G.pairs[pairId].last_type = aop->type;
957 static void emitLabel(int key)
959 emit2("!tlabeldef", key);
963 /*-----------------------------------------------------------------*/
964 /* aopGet - for fetching value of the aop */
965 /*-----------------------------------------------------------------*/
966 static char *aopGet(asmop *aop, int offset, bool bit16)
971 /* offset is greater than size then zero */
972 /* PENDING: this seems a bit screwed in some pointer cases. */
973 if (offset > (aop->size - 1) &&
974 aop->type != AOP_LIT)
977 /* depending on type */
980 /* PENDING: re-target */
982 tsprintf (s,"!immedwords", aop->aopu.aop_immd);
986 tsprintf(s, "!bankimmeds", aop->aopu.aop_immd);
989 tsprintf(s, "!msbimmeds", aop->aopu.aop_immd);
992 tsprintf(s, "!lsbimmeds", aop->aopu.aop_immd);
997 ALLOC(rs,strlen(s)+1);
1003 emitcode("ld", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1005 ALLOC(rs,strlen(s)+1);
1011 emitcode("ldh", "a,(%s+%d) ; x", aop->aopu.aop_dir, offset);
1013 ALLOC(rs,strlen(s)+1);
1018 return aop->aopu.aop_reg[offset]->name;
1022 setupPair(PAIR_HL, aop, offset);
1023 tsprintf(s, "!*hl");
1024 return gc_strdup(s);
1028 setupPair(PAIR_IY, aop, offset);
1029 tsprintf(s,"!*iyx", offset);
1030 ALLOC(rs,strlen(s)+1);
1036 setupPair(PAIR_HL, aop, offset);
1037 tsprintf(s, "!*hl");
1040 if (aop->aopu.aop_stk >= 0)
1041 offset += _G.stack.param_offset;
1042 tsprintf(s,"!*ixx ; x", aop->aopu.aop_stk+offset);
1044 ALLOC(rs,strlen(s)+1);
1058 wassert(offset < 2);
1059 return aop->aopu.aop_str[offset];
1062 return aopLiteral (aop->aopu.aop_lit,offset);
1066 return aop->aopu.aop_str[offset];
1070 wassertl(0, "aopget got unsupported aop->type");
1074 bool isRegString(const char *s)
1076 if (!strcmp(s, "b") ||
1087 bool isConstant(const char *s)
1089 /* This is a bit of a hack... */
1090 return (*s == '#' || *s == '$');
1093 bool canAssignToPtr(const char *s)
1102 /*-----------------------------------------------------------------*/
1103 /* aopPut - puts a string for a aop */
1104 /*-----------------------------------------------------------------*/
1105 static void aopPut (asmop *aop, const char *s, int offset)
1107 if (aop->size && offset > ( aop->size - 1)) {
1108 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1109 "aopPut got offset > aop->size");
1113 /* will assign value to value */
1114 /* depending on where it is ofcourse */
1115 switch (aop->type) {
1120 emitcode("ld", "a,%s", s);
1121 emitcode("ld", "(%s+%d),a", aop->aopu.aop_dir, offset);
1127 emitcode("ld", "a,%s", s);
1128 emitcode("ldh", "(%s+%d),a", aop->aopu.aop_dir, offset);
1132 if (!strcmp(s, "!*hl"))
1133 emit2("ld %s,!*hl", aop->aopu.aop_reg[offset]->name);
1136 aop->aopu.aop_reg[offset]->name, s);
1141 setupPair(PAIR_IY, aop, offset);
1142 if (!canAssignToPtr(s)) {
1143 emit2("ld a,%s", s);
1144 emit2("ld !*iyx,a", offset);
1147 emit2("ld !*iyx,%s", offset, s);
1152 /* PENDING: for re-target */
1153 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1157 setupPair(PAIR_HL, aop, offset);
1159 emit2("ld !*hl,%s", s);
1164 /* PENDING: re-target */
1165 if (!strcmp(s, "!*hl") || !strcmp(s, "(hl)") || !strcmp(s, "[hl]")) {
1169 setupPair(PAIR_HL, aop, offset);
1170 if (!canAssignToPtr(s)) {
1171 emit2("ld a,%s", s);
1175 emit2("ld !*hl,%s", s);
1178 if (aop->aopu.aop_stk >= 0)
1179 offset += _G.stack.param_offset;
1180 if (!canAssignToPtr(s)) {
1181 emit2("ld a,%s", s);
1182 emit2("ld !*ixx,a", aop->aopu.aop_stk+offset);
1185 emit2("ld !*ixx,%s", aop->aopu.aop_stk+offset, s);
1190 /* if bit variable */
1191 if (!aop->aopu.aop_dir) {
1195 /* In bit space but not in C - cant happen */
1202 if (strcmp(aop->aopu.aop_str[offset],s)) {
1203 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1209 if (!offset && (strcmp(s,"acc") == 0))
1213 emitcode("", "; Error aopPut AOP_ACC");
1216 if (strcmp(aop->aopu.aop_str[offset],s))
1217 emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
1222 wassert(offset < 2);
1223 emit2("ld %s,%s", aop->aopu.aop_str[offset], s);
1227 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
1228 "aopPut got unsupported aop->type");
1233 #define AOP(op) op->aop
1234 #define AOP_TYPE(op) AOP(op)->type
1235 #define AOP_SIZE(op) AOP(op)->size
1236 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
1238 static void commitPair(asmop *aop, PAIR_ID id)
1240 if (id == PAIR_HL && requiresHL(aop)) {
1243 aopPut(aop, "a", 0);
1244 aopPut(aop, "d", 1);
1247 aopPut(aop, _pairs[id].l, 0);
1248 aopPut(aop, _pairs[id].h, 1);
1252 /*-----------------------------------------------------------------*/
1253 /* getDataSize - get the operand data size */
1254 /*-----------------------------------------------------------------*/
1255 int getDataSize(operand *op)
1258 size = AOP_SIZE(op);
1266 /*-----------------------------------------------------------------*/
1267 /* movLeft2Result - move byte from left to result */
1268 /*-----------------------------------------------------------------*/
1269 static void movLeft2Result (operand *left, int offl,
1270 operand *result, int offr, int sign)
1273 if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
1274 l = aopGet(AOP(left),offl,FALSE);
1277 aopPut(AOP(result),l,offr);
1286 /** Put Acc into a register set
1288 void outAcc(operand *result)
1291 size = getDataSize(result);
1293 aopPut(AOP(result),"a",0);
1296 /* unsigned or positive */
1298 aopPut(AOP(result), zero, offset++);
1303 /** Take the value in carry and put it into a register
1305 void outBitCLong(operand *result, bool swap_sense)
1307 /* if the result is bit */
1308 if (AOP_TYPE(result) == AOP_CRY) {
1309 emitcode("", "; Note: outBitC form 1");
1310 aopPut(AOP(result),"blah",0);
1313 emit2("ld a,!zero");
1316 emit2("xor a,!immedbyte", 1);
1321 void outBitC(operand *result)
1323 outBitCLong(result, FALSE);
1326 /*-----------------------------------------------------------------*/
1327 /* toBoolean - emit code for orl a,operator(sizeop) */
1328 /*-----------------------------------------------------------------*/
1329 void toBoolean(operand *oper)
1331 int size = AOP_SIZE(oper);
1334 emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
1337 emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
1340 if (AOP(oper)->type != AOP_ACC) {
1342 emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
1347 /*-----------------------------------------------------------------*/
1348 /* genNot - generate code for ! operation */
1349 /*-----------------------------------------------------------------*/
1350 static void genNot (iCode *ic)
1352 sym_link *optype = operandType(IC_LEFT(ic));
1354 /* assign asmOps to operand & result */
1355 aopOp (IC_LEFT(ic),ic,FALSE, TRUE);
1356 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1358 /* if in bit space then a special case */
1359 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
1363 /* if type float then do float */
1364 if (IS_FLOAT(optype)) {
1368 toBoolean(IC_LEFT(ic));
1373 So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
1374 emit2("sub a,!one");
1375 outBitC(IC_RESULT(ic));
1377 /* release the aops */
1378 freeAsmop(IC_LEFT(ic),NULL,ic);
1379 freeAsmop(IC_RESULT(ic),NULL,ic);
1382 /*-----------------------------------------------------------------*/
1383 /* genCpl - generate code for complement */
1384 /*-----------------------------------------------------------------*/
1385 static void genCpl (iCode *ic)
1391 /* assign asmOps to operand & result */
1392 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
1393 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
1395 /* if both are in bit space then
1397 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1398 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1402 size = AOP_SIZE(IC_RESULT(ic));
1404 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1407 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1410 /* release the aops */
1411 freeAsmop(IC_LEFT(ic),NULL,ic);
1412 freeAsmop(IC_RESULT(ic),NULL,ic);
1415 /*-----------------------------------------------------------------*/
1416 /* genUminus - unary minus code generation */
1417 /*-----------------------------------------------------------------*/
1418 static void genUminus (iCode *ic)
1421 sym_link *optype, *rtype;
1424 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1425 aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
1427 /* if both in bit space then special
1429 if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
1430 AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) {
1435 optype = operandType(IC_LEFT(ic));
1436 rtype = operandType(IC_RESULT(ic));
1438 /* if float then do float stuff */
1439 if (IS_FLOAT(optype)) {
1444 /* otherwise subtract from zero */
1445 size = AOP_SIZE(IC_LEFT(ic));
1449 char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
1450 emit2("ld a,!zero");
1451 emit2("sbc a,%s",l);
1452 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1455 /* if any remaining bytes in the result */
1456 /* we just need to propagate the sign */
1457 if ((size = (AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_LEFT(ic))))) {
1461 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
1465 /* release the aops */
1466 freeAsmop(IC_LEFT(ic),NULL,ic);
1467 freeAsmop(IC_RESULT(ic),NULL,ic);
1470 static void _push(PAIR_ID pairId)
1472 emit2("push %s", _pairs[pairId].name);
1473 _G.stack.pushed += 2;
1476 static void _pop(PAIR_ID pairId)
1478 emit2("pop %s", _pairs[pairId].name);
1479 _G.stack.pushed -= 2;
1483 /*-----------------------------------------------------------------*/
1484 /* assignResultValue - */
1485 /*-----------------------------------------------------------------*/
1486 void assignResultValue(operand * oper)
1488 int size = AOP_SIZE(oper);
1492 topInA = requiresHL(AOP(oper));
1498 if (IS_GB && size == 4 && requiresHL(AOP(oper))) {
1499 /* We do it the hard way here. */
1501 aopPut(AOP(oper), _fReturn[0], 0);
1502 aopPut(AOP(oper), _fReturn[1], 1);
1503 emitcode("pop", "de");
1504 _G.stack.pushed -= 2;
1505 aopPut(AOP(oper), _fReturn[0], 2);
1506 aopPut(AOP(oper), _fReturn[1], 3);
1510 aopPut(AOP(oper), _fReturn[size], size);
1515 /*-----------------------------------------------------------------*/
1516 /* genIpush - genrate code for pushing this gets a little complex */
1517 /*-----------------------------------------------------------------*/
1518 static void genIpush (iCode *ic)
1520 int size, offset = 0 ;
1523 /* if this is not a parm push : ie. it is spill push
1524 and spill push is always done on the local stack */
1525 if (!ic->parmPush) {
1526 /* and the item is spilt then do nothing */
1527 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1530 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1531 size = AOP_SIZE(IC_LEFT(ic));
1532 /* push it on the stack */
1533 if (isPair(AOP(IC_LEFT(ic)))) {
1534 emitcode("push", getPairName(AOP(IC_LEFT(ic))));
1535 _G.stack.pushed += 2;
1540 /* Simple for now - load into A and PUSH AF */
1541 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1542 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1544 emit2("ld a,(%s)", l);
1547 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1548 emit2("ld a,%s", l);
1558 /* Hmmm... what about saving the currently used registers
1561 /* then do the push */
1562 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1564 size = AOP_SIZE(IC_LEFT(ic));
1566 if (isPair(AOP(IC_LEFT(ic)))) {
1568 emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
1572 fetchHL(AOP(IC_LEFT(ic)));
1573 emitcode("push", "hl");
1575 _G.stack.pushed += 2;
1579 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
1580 emitcode("push", "hl");
1582 _G.stack.pushed += 2;
1583 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 0);
1584 emitcode("push", "hl");
1586 _G.stack.pushed += 2;
1591 if (AOP(IC_LEFT(ic))->type == AOP_IY) {
1592 char *l = aopGetLitWordLong(AOP(IC_LEFT(ic)), --offset, FALSE);
1594 emit2("ld a,(%s)", l);
1597 l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
1598 emit2("ld a,%s", l);
1600 emitcode("push", "af");
1601 emitcode("inc", "sp");
1606 freeAsmop(IC_LEFT(ic),NULL,ic);
1609 /*-----------------------------------------------------------------*/
1610 /* genIpop - recover the registers: can happen only for spilling */
1611 /*-----------------------------------------------------------------*/
1612 static void genIpop (iCode *ic)
1617 /* if the temp was not pushed then */
1618 if (OP_SYMBOL(IC_LEFT(ic))->isspilt)
1621 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1622 size = AOP_SIZE(IC_LEFT(ic));
1624 if (isPair(AOP(IC_LEFT(ic)))) {
1625 emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
1629 emitcode("dec", "sp");
1630 emitcode("pop", "hl");
1632 aopPut(AOP(IC_LEFT(ic)), "l", offset--);
1636 freeAsmop(IC_LEFT(ic),NULL,ic);
1639 static int _isPairUsed(iCode *ic, PAIR_ID pairId)
1644 if (bitVectBitValue(ic->rUsed, D_IDX))
1646 if (bitVectBitValue(ic->rUsed, E_IDX))
1655 static int _opUsesPair(operand *op, iCode *ic, PAIR_ID pairId)
1659 symbol *sym = OP_SYMBOL(op);
1661 if (sym->isspilt || sym->nRegs == 0)
1664 aopOp(op, ic, FALSE, FALSE);
1667 if (aop->type == AOP_REG) {
1669 for (i=0; i < aop->size; i++) {
1670 if (pairId == PAIR_DE) {
1671 emit2("; name %s", aop->aopu.aop_reg[i]->name);
1672 if (!strcmp(aop->aopu.aop_reg[i]->name, "e"))
1674 if (!strcmp(aop->aopu.aop_reg[i]->name, "d"))
1683 freeAsmop(IC_LEFT(ic),NULL,ic);
1687 /* This is quite unfortunate */
1688 static void setArea(int inHome)
1690 static int lastArea = 0;
1693 if (_G.in_home != inHome) {
1695 const char *sz = port->mem.code_name;
1696 port->mem.code_name = "HOME";
1697 emit2("!area", CODE_NAME);
1698 port->mem.code_name = sz;
1701 emit2("!area", CODE_NAME);*/
1702 _G.in_home = inHome;
1706 static bool isInHome(void)
1711 /** Emit the code for a call statement
1713 static void emitCall(iCode *ic, bool ispcall)
1716 sym_link *detype = getSpec(operandType(IC_LEFT(ic)));
1718 /* if caller saves & we have not saved then */
1719 if (!ic->regsSaved) {
1723 /* if send set is not empty then assign */
1727 int n = elementsInSet(sendSet);
1728 if (IS_Z80 && n == 2 && _isPairUsed(ic, PAIR_DE)) {
1729 /* Only push de if it is used and if it's not used
1730 in the return value */
1731 /* Panic if partly used */
1732 if (_opUsesPair(IC_RESULT(ic), ic, PAIR_DE) == 1) {
1733 emit2("; Warning: de crossover");
1735 else if (!_opUsesPair(IC_RESULT(ic), ic, PAIR_DE)) {
1742 if (IS_Z80 && n == 2 ) {
1743 /* Want to load HL first, then DE as HL may = DE */
1744 sic = setFirstItem(sendSet);
1745 sic = setNextItem(sendSet);
1746 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1747 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1749 freeAsmop (IC_LEFT(sic),NULL,sic);
1750 sic = setFirstItem(sendSet);
1751 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1752 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1754 freeAsmop (IC_LEFT(sic),NULL,sic);
1757 for (sic = setFirstItem(sendSet) ; sic ;
1758 sic = setNextItem(sendSet)) {
1760 aopOp(IC_LEFT(sic),sic,FALSE, FALSE);
1761 size = AOP_SIZE(IC_LEFT(sic));
1763 /* Always send in pairs */
1766 if (IS_Z80 && n == 1)
1767 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1769 fetchPair(PAIR_DE, AOP(IC_LEFT(sic)));
1772 fetchPair(PAIR_HL, AOP(IC_LEFT(sic)));
1775 /* Send set too big */
1779 freeAsmop (IC_LEFT(sic),NULL,sic);
1788 if (IS_BANKEDCALL(detype)) {
1789 werror(W_INDIR_BANKED);
1791 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
1793 if (isLitWord(AOP(IC_LEFT(ic)))) {
1794 emitcode("", "; Special case where the pCall is to a constant");
1795 emitcode("call", aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE));
1798 symbol *rlbl = newiTempLabel(NULL);
1800 emit2("ld hl,!immed!tlabel", (rlbl->key+100));
1801 emitcode("push", "hl");
1802 _G.stack.pushed += 2;
1804 fetchHL(AOP(IC_LEFT(ic)));
1806 emit2("!tlabeldef", (rlbl->key+100));
1807 _G.stack.pushed -= 2;
1809 freeAsmop(IC_LEFT(ic),NULL,ic);
1812 char *name = OP_SYMBOL(IC_LEFT(ic))->rname[0] ?
1813 OP_SYMBOL(IC_LEFT(ic))->rname :
1814 OP_SYMBOL(IC_LEFT(ic))->name;
1815 if (IS_BANKEDCALL(detype)) {
1816 emit2("call banked_call");
1817 emit2("!dws", name);
1818 emit2("!dw !bankimmeds", name);
1822 emit2("call %s", name);
1827 /* if we need assign a result value */
1828 if ((IS_ITEMP(IC_RESULT(ic)) &&
1829 (OP_SYMBOL(IC_RESULT(ic))->nRegs ||
1830 OP_SYMBOL(IC_RESULT(ic))->spildir )) ||
1831 IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
1834 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
1837 assignResultValue(IC_RESULT(ic));
1839 freeAsmop(IC_RESULT(ic),NULL, ic);
1842 /* adjust the stack for parameters if required */
1843 if (IC_LEFT(ic)->parmBytes) {
1844 int i = IC_LEFT(ic)->parmBytes;
1845 _G.stack.pushed -= i;
1847 emit2("!ldaspsp", i);
1852 emitcode("ld", "hl,#%d", i);
1853 emitcode("add", "hl,sp");
1854 emitcode("ld", "sp,hl");
1858 emitcode("pop", "hl");
1862 emitcode("inc", "sp");
1871 /*-----------------------------------------------------------------*/
1872 /* genCall - generates a call statement */
1873 /*-----------------------------------------------------------------*/
1874 static void genCall (iCode *ic)
1876 sym_link *detype = getSpec(operandType(IC_LEFT(ic)));
1877 emitCall(ic, FALSE);
1880 /*-----------------------------------------------------------------*/
1881 /* genPcall - generates a call by pointer statement */
1882 /*-----------------------------------------------------------------*/
1883 static void genPcall (iCode *ic)
1888 /*-----------------------------------------------------------------*/
1889 /* resultRemat - result is rematerializable */
1890 /*-----------------------------------------------------------------*/
1891 static int resultRemat (iCode *ic)
1893 if (SKIP_IC(ic) || ic->op == IFX)
1896 if (IC_RESULT(ic) && IS_ITEMP(IC_RESULT(ic))) {
1897 symbol *sym = OP_SYMBOL(IC_RESULT(ic));
1898 if (sym->remat && !POINTER_SET(ic))
1905 extern set *publics;
1907 /*-----------------------------------------------------------------*/
1908 /* genFunction - generated code for function entry */
1909 /*-----------------------------------------------------------------*/
1910 static void genFunction (iCode *ic)
1912 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1916 setArea(IS_NONBANKED(sym->etype));
1919 if (!IS_STATIC(sym->etype)) {
1920 addSetIfnotP(&publics, sym);
1923 /* create the function header */
1924 emit2("!functionheader", sym->name);
1925 /* PENDING: portability. */
1926 emit2("__%s_start:", sym->rname);
1927 emit2("!functionlabeldef", sym->rname);
1929 fetype = getSpec(operandType(IC_LEFT(ic)));
1931 /* if critical function then turn interrupts off */
1932 if (SPEC_CRTCL(fetype))
1935 /* if this is an interrupt service routine then
1936 save acc, b, dpl, dph */
1937 if (IS_ISR(sym->etype)) {
1940 /* PENDING: callee-save etc */
1942 /* If BC or DE are used, then push */
1943 _G.stack.pushed_bc = 0;
1944 _G.stack.pushed_de = 0;
1945 _G.stack.param_offset = 0;
1946 if (sym->regsUsed) {
1948 for ( i = 0 ; i < sym->regsUsed->size ; i++) {
1949 if (bitVectBitValue(sym->regsUsed, i)) {
1953 _G.stack.pushed_bc = 1;
1958 _G.stack.pushed_de = 1;
1963 if (_G.stack.pushed_bc) {
1965 _G.stack.param_offset += 2;
1967 if (_G.stack.pushed_de) {
1969 _G.stack.param_offset += 2;
1973 /* adjust the stack for the function */
1974 _G.stack.last = sym->stack;
1977 emit2("!enterx", sym->stack);
1980 _G.stack.offset = sym->stack;
1983 /*-----------------------------------------------------------------*/
1984 /* genEndFunction - generates epilogue for functions */
1985 /*-----------------------------------------------------------------*/
1986 static void genEndFunction (iCode *ic)
1988 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
1990 if (IS_ISR(sym->etype)) {
1994 if (SPEC_CRTCL(sym->etype))
1997 /* PENDING: calleeSave */
1999 /* if debug then send end of function */
2000 if (options.debug && currFunc) {
2002 emitcode("","C$%s$%d$%d$%d ==.",
2003 ic->filename,currFunc->lastLine,
2004 ic->level,ic->block);
2005 if (IS_STATIC(currFunc->etype))
2006 emitcode("","XF%s$%s$0$0 ==.",moduleName,currFunc->name);
2008 emitcode("","XG$%s$0$0 ==.",currFunc->name);
2011 if (_G.stack.offset)
2012 emit2("!leavex", _G.stack.offset);
2016 if (_G.stack.pushed_de)
2018 if (_G.stack.pushed_bc)
2020 /* Both baned and non-banked just ret */
2023 /* PENDING: portability. */
2024 emit2("__%s_end:", sym->rname);
2026 _G.flush_statics = 1;
2027 _G.stack.pushed = 0;
2028 _G.stack.offset = 0;
2031 /*-----------------------------------------------------------------*/
2032 /* genRet - generate code for return statement */
2033 /*-----------------------------------------------------------------*/
2034 static void genRet (iCode *ic)
2037 /* Errk. This is a hack until I can figure out how
2038 to cause dehl to spill on a call */
2039 int size,offset = 0;
2041 /* if we have no return value then
2042 just generate the "ret" */
2046 /* we have something to return then
2047 move the return value into place */
2048 aopOp(IC_LEFT(ic),ic,FALSE, FALSE);
2049 size = AOP_SIZE(IC_LEFT(ic));
2051 if ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
2053 emitcode("ld", "de,%s", l);
2056 emitcode("ld", "hl,%s", l);
2060 if (IS_GB && size == 4 && requiresHL(AOP(IC_LEFT(ic)))) {
2061 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2062 fetchPairLong(PAIR_HL, AOP(IC_LEFT(ic)), 2);
2066 l = aopGet(AOP(IC_LEFT(ic)),offset,
2068 if (strcmp(_fReturn[offset],l))
2069 emitcode("ld","%s,%s", _fReturn[offset++],l);
2073 freeAsmop (IC_LEFT(ic),NULL,ic);
2076 /* generate a jump to the return label
2077 if the next is not the return statement */
2078 if (!(ic->next && ic->next->op == LABEL &&
2079 IC_LABEL(ic->next) == returnLabel))
2081 emit2("jp !tlabel", returnLabel->key+100);
2084 /*-----------------------------------------------------------------*/
2085 /* genLabel - generates a label */
2086 /*-----------------------------------------------------------------*/
2087 static void genLabel (iCode *ic)
2089 /* special case never generate */
2090 if (IC_LABEL(ic) == entryLabel)
2093 emitLabel(IC_LABEL(ic)->key+100);
2096 /*-----------------------------------------------------------------*/
2097 /* genGoto - generates a ljmp */
2098 /*-----------------------------------------------------------------*/
2099 static void genGoto (iCode *ic)
2101 emit2("jp !tlabel", IC_LABEL(ic)->key+100);
2104 /*-----------------------------------------------------------------*/
2105 /* genPlusIncr :- does addition with increment if possible */
2106 /*-----------------------------------------------------------------*/
2107 static bool genPlusIncr (iCode *ic)
2109 unsigned int icount ;
2110 unsigned int size = getDataSize(IC_RESULT(ic));
2111 PAIR_ID resultId = getPairId(AOP(IC_RESULT(ic)));
2113 /* will try to generate an increment */
2114 /* if the right side is not a literal
2116 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2119 emitcode("", "; genPlusIncr");
2121 icount = floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2123 /* If result is a pair */
2124 if (resultId != PAIR_INVALID) {
2125 if (isLitWord(AOP(IC_LEFT(ic)))) {
2126 fetchLitPair(getPairId(AOP(IC_RESULT(ic))), AOP(IC_LEFT(ic)), icount);
2129 if (isPair(AOP(IC_LEFT(ic))) && resultId == PAIR_HL && icount > 2) {
2130 fetchPair(resultId, AOP(IC_RIGHT(ic)));
2131 emitcode("add", "hl,%s", getPairName(AOP(IC_LEFT(ic))));
2137 if (!sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2140 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2141 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2144 emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
2149 /* if the literal value of the right hand side
2150 is greater than 4 then it is not worth it */
2154 /* if increment 16 bits in register */
2155 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2160 symbol *tlbl = NULL;
2161 tlbl = newiTempLabel(NULL);
2163 emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)), offset++, FALSE));
2165 emit2("!shortjp nz,!tlabel", tlbl->key+100);
2168 emitLabel(tlbl->key+100);
2172 /* if the sizes are greater than 1 then we cannot */
2173 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2174 AOP_SIZE(IC_LEFT(ic)) > 1 )
2177 /* we can if the aops of the left & result match or
2178 if they are in registers and the registers are the
2180 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
2182 emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
2189 /*-----------------------------------------------------------------*/
2190 /* outBitAcc - output a bit in acc */
2191 /*-----------------------------------------------------------------*/
2192 void outBitAcc(operand *result)
2194 symbol *tlbl = newiTempLabel(NULL);
2195 /* if the result is a bit */
2196 if (AOP_TYPE(result) == AOP_CRY){
2200 emit2("!shortjp z,!tlabel", tlbl->key+100);
2202 emitLabel(tlbl->key+100);
2207 /*-----------------------------------------------------------------*/
2208 /* genPlus - generates code for addition */
2209 /*-----------------------------------------------------------------*/
2210 static void genPlus (iCode *ic)
2212 int size, offset = 0;
2214 /* special cases :- */
2216 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2217 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2218 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2220 /* Swap the left and right operands if:
2222 if literal, literal on the right or
2223 if left requires ACC or right is already
2226 if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
2227 (AOP_NEEDSACC(IC_LEFT(ic))) ||
2228 AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
2229 operand *t = IC_RIGHT(ic);
2230 IC_RIGHT(ic) = IC_LEFT(ic);
2234 /* if both left & right are in bit
2236 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2237 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2242 /* if left in bit space & right literal */
2243 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2244 AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
2245 /* Can happen I guess */
2249 /* if I can do an increment instead
2250 of add then GOOD for ME */
2251 if (genPlusIncr (ic) == TRUE)
2254 emit2("; genPlusIncr failed");
2256 size = getDataSize(IC_RESULT(ic));
2258 /* Special case when left and right are constant */
2259 if (isPair(AOP(IC_RESULT(ic)))) {
2262 left = aopGetLitWordLong(AOP(IC_LEFT(ic)), 0, FALSE);
2263 right = aopGetLitWordLong(AOP(IC_RIGHT(ic)), 0, FALSE);
2264 if (left && right) {
2268 sprintf(buffer, "#(%s + %s)", left, right);
2269 emitcode("ld", "%s,%s", getPairName(AOP(IC_RESULT(ic))), buffer);
2274 if (isPair(AOP(IC_RIGHT(ic))) && getPairId(AOP(IC_RESULT(ic))) == PAIR_HL) {
2275 /* Fetch into HL then do the add */
2277 fetchPair(PAIR_HL, AOP(IC_LEFT(ic)));
2278 emitcode("add", "hl,%s", getPairName(AOP(IC_RIGHT(ic))));
2283 ld hl,sp+n trashes C so we cant afford to do it during an
2284 add with stack based varibles. Worst case is:
2297 So you cant afford to load up hl if either left, right, or result
2298 is on the stack (*sigh*) The alt is:
2306 Combinations in here are:
2307 * If left or right are in bc then the loss is small - trap later
2308 * If the result is in bc then the loss is also small
2311 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2312 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2313 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2314 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2315 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2316 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2317 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2318 if (getPairId(AOP(IC_RIGHT(ic))) == PAIR_BC) {
2319 /* Swap left and right */
2320 operand *t = IC_RIGHT(ic);
2321 IC_RIGHT(ic) = IC_LEFT(ic);
2324 if (getPairId(AOP(IC_LEFT(ic))) == PAIR_BC) {
2325 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2329 fetchPair(PAIR_DE, AOP(IC_LEFT(ic)));
2330 fetchPair(PAIR_HL, AOP(IC_RIGHT(ic)));
2333 commitPair(AOP(IC_RESULT(ic)), PAIR_HL);
2336 else if (size == 4) {
2337 emit2("; WARNING: This add is probably broken.\n");
2343 if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
2344 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2347 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2350 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2352 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2355 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2358 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2360 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2364 freeAsmop(IC_LEFT(ic),NULL,ic);
2365 freeAsmop(IC_RIGHT(ic),NULL,ic);
2366 freeAsmop(IC_RESULT(ic),NULL,ic);
2370 /*-----------------------------------------------------------------*/
2371 /* genMinusDec :- does subtraction with deccrement if possible */
2372 /*-----------------------------------------------------------------*/
2373 static bool genMinusDec (iCode *ic)
2375 unsigned int icount ;
2376 unsigned int size = getDataSize(IC_RESULT(ic));
2378 /* will try to generate an increment */
2379 /* if the right side is not a literal we cannot */
2380 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)
2383 /* if the literal value of the right hand side
2384 is greater than 4 then it is not worth it */
2385 if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
2388 size = getDataSize(IC_RESULT(ic));
2391 /* if increment 16 bits in register */
2392 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2395 symbol *tlbl = newiTempLabel(NULL);
2396 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
2397 emitcode("jp", "np," LABEL_STR ,tlbl->key+100);
2399 emitcode("dec","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
2403 emitLabel(tlbl->key+100);
2408 /* if decrement 16 bits in register */
2409 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
2410 (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
2412 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2416 /* If result is a pair */
2417 if (isPair(AOP(IC_RESULT(ic)))) {
2418 movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
2419 movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
2421 emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
2425 /* if the sizes are greater than 1 then we cannot */
2426 if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
2427 AOP_SIZE(IC_LEFT(ic)) > 1 )
2430 /* we can if the aops of the left & result match or if they are in
2431 registers and the registers are the same */
2432 if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
2434 emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
2441 /*-----------------------------------------------------------------*/
2442 /* genMinus - generates code for subtraction */
2443 /*-----------------------------------------------------------------*/
2444 static void genMinus (iCode *ic)
2446 int size, offset = 0;
2447 unsigned long lit = 0L;
2449 aopOp (IC_LEFT(ic),ic,FALSE, FALSE);
2450 aopOp (IC_RIGHT(ic),ic,FALSE, FALSE);
2451 aopOp (IC_RESULT(ic),ic,TRUE, FALSE);
2453 /* special cases :- */
2454 /* if both left & right are in bit space */
2455 if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
2456 AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
2461 /* if I can do an decrement instead of subtract then GOOD for ME */
2462 if (genMinusDec (ic) == TRUE)
2465 size = getDataSize(IC_RESULT(ic));
2467 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
2470 lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
2474 /* Same logic as genPlus */
2476 if (AOP_TYPE(IC_LEFT(ic)) == AOP_STK ||
2477 AOP_TYPE(IC_RIGHT(ic)) == AOP_STK ||
2478 AOP_TYPE(IC_RESULT(ic)) == AOP_STK) {
2479 if ((AOP_SIZE(IC_LEFT(ic)) == 2 ||
2480 AOP_SIZE(IC_RIGHT(ic)) == 2) &&
2481 (AOP_SIZE(IC_LEFT(ic)) <= 2 &&
2482 AOP_SIZE(IC_RIGHT(ic)) <= 2)) {
2483 PAIR_ID left = getPairId(AOP(IC_LEFT(ic)));
2484 PAIR_ID right = getPairId(AOP(IC_RIGHT(ic)));
2486 if (left == PAIR_INVALID && right == PAIR_INVALID) {
2490 else if (right == PAIR_INVALID)
2492 else if (left == PAIR_INVALID)
2495 fetchPair(left, AOP(IC_LEFT(ic)));
2496 /* Order is important. Right may be HL */
2497 fetchPair(right, AOP(IC_RIGHT(ic)));
2499 emit2("ld a,%s", _pairs[left].l);
2500 emit2("sub a,%s", _pairs[right].l);
2502 emit2("ld a,%s", _pairs[left].h);
2503 emit2("sbc a,%s", _pairs[right].h);
2505 aopPut(AOP(IC_RESULT(ic)), "a", 1);
2506 aopPut(AOP(IC_RESULT(ic)), "e", 0);
2509 else if (size == 4) {
2510 emit2("; WARNING: This sub is probably broken.\n");
2515 /* if literal, add a,#-lit, else normal subb */
2517 MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
2518 if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT) {
2520 emitcode("sub","a,%s",
2521 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2523 emitcode("sbc","a,%s",
2524 aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
2527 /* first add without previous c */
2529 emit2("add a,!immedbyte", (unsigned int)(lit & 0x0FFL));
2531 emit2("adc a,!immedbyte", (unsigned int)((lit >> (offset*8)) & 0x0FFL));
2533 aopPut(AOP(IC_RESULT(ic)),"a",offset++);
2536 if (AOP_SIZE(IC_RESULT(ic)) == 3 &&
2537 AOP_SIZE(IC_LEFT(ic)) == 3 &&
2538 !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
2542 freeAsmop(IC_LEFT(ic),NULL,ic);
2543 freeAsmop(IC_RIGHT(ic),NULL,ic);
2544 freeAsmop(IC_RESULT(ic),NULL,ic);
2547 /*-----------------------------------------------------------------*/
2548 /* genMult - generates code for multiplication */
2549 /*-----------------------------------------------------------------*/
2550 static void genMult (iCode *ic)
2552 /* Shouldn't occur - all done through function calls */
2556 /*-----------------------------------------------------------------*/
2557 /* genDiv - generates code for division */
2558 /*-----------------------------------------------------------------*/
2559 static void genDiv (iCode *ic)
2561 /* Shouldn't occur - all done through function calls */
2565 /*-----------------------------------------------------------------*/
2566 /* genMod - generates code for division */
2567 /*-----------------------------------------------------------------*/
2568 static void genMod (iCode *ic)
2570 /* Shouldn't occur - all done through function calls */
2574 /*-----------------------------------------------------------------*/
2575 /* genIfxJump :- will create a jump depending on the ifx */
2576 /*-----------------------------------------------------------------*/
2577 static void genIfxJump (iCode *ic, char *jval)
2582 /* if true label then we jump if condition
2586 if (!strcmp(jval, "a")) {
2589 else if (!strcmp(jval, "c")) {
2592 else if (!strcmp(jval, "nc")) {
2596 /* The buffer contains the bit on A that we should test */
2601 /* false label is present */
2602 jlbl = IC_FALSE(ic) ;
2603 if (!strcmp(jval, "a")) {
2606 else if (!strcmp(jval, "c")) {
2609 else if (!strcmp(jval, "nc")) {
2613 /* The buffer contains the bit on A that we should test */
2617 /* Z80 can do a conditional long jump */
2618 if (!strcmp(jval, "a")) {
2619 emitcode("or", "a,a");
2621 else if (!strcmp(jval, "c")) {
2623 else if (!strcmp(jval, "nc")) {
2626 emitcode("bit", "%s,a", jval);
2628 emit2("jp %s,!tlabel", inst, jlbl->key+100);
2630 /* mark the icode as generated */
2634 static const char *_getPairIdName(PAIR_ID id)
2636 return _pairs[id].name;
2639 /** Generic compare for > or <
2641 static void genCmp (operand *left,operand *right,
2642 operand *result, iCode *ifx, int sign)
2644 int size, offset = 0 ;
2645 unsigned long lit = 0L;
2646 bool swap_sense = FALSE;
2648 /* if left & right are bit variables */
2649 if (AOP_TYPE(left) == AOP_CRY &&
2650 AOP_TYPE(right) == AOP_CRY ) {
2651 /* Cant happen on the Z80 */
2654 /* subtract right from left if at the
2655 end the carry flag is set then we know that
2656 left is greater than right */
2657 size = max(AOP_SIZE(left),AOP_SIZE(right));
2659 /* if unsigned char cmp with lit, just compare */
2661 (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
2662 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2664 emit2("xor a,!immedbyte", 0x80);
2665 emit2("cp %s^!constbyte", aopGet(AOP(right), offset, FALSE), 0x80);
2668 emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
2673 If the left or the right is a lit:
2674 Load -lit into HL, add to right via, check sense.
2676 if (size == 2 && (AOP_TYPE(right) == AOP_LIT || AOP_TYPE(left) == AOP_LIT)) {
2677 PAIR_ID id = PAIR_DE;
2678 asmop *lit = AOP(right);
2679 asmop *op = AOP(left);
2682 if (AOP_TYPE(left) == AOP_LIT) {
2688 emit2("ld e,%s", aopGet(op, 0, 0));
2689 emit2("ld a,%s", aopGet(op, 1, 0));
2690 emit2("xor a,!immedbyte", 0x80);
2695 if (id == PAIR_INVALID) {
2696 fetchPair(PAIR_DE, op);
2701 emit2("ld hl,%s", fetchLitSpecial(lit, TRUE, sign));
2702 emit2("add hl,%s", _getPairIdName(id));
2705 if(AOP_TYPE(right) == AOP_LIT) {
2706 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2707 /* optimize if(x < 0) or if(x >= 0) */
2710 /* No sign so it's always false */
2714 /* Just load in the top most bit */
2715 MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
2716 if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
2717 genIfxJump (ifx,"7");
2721 emitcode("rlc","a");
2727 /* First setup h and l contaning the top most bytes XORed */
2728 bool fDidXor = FALSE;
2729 if (AOP_TYPE(left) == AOP_LIT){
2730 unsigned long lit = (unsigned long)
2731 floatFromVal(AOP(left)->aopu.aop_lit);
2732 emit2("ld %s,!immedbyte", _fTmp[0],
2733 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2736 emitcode("ld", "a,%s", aopGet(AOP(left), size-1, FALSE));
2737 emit2("xor a,!immedbyte", 0x80);
2738 emitcode("ld", "%s,a", _fTmp[0]);
2741 if (AOP_TYPE(right) == AOP_LIT) {
2742 unsigned long lit = (unsigned long)
2743 floatFromVal(AOP(right)->aopu.aop_lit);
2744 emit2("ld %s,!immedbyte", _fTmp[1],
2745 0x80 ^ (unsigned int)((lit >> ((size-1)*8)) & 0x0FFL));
2748 emitcode("ld", "a,%s", aopGet(AOP(right), size-1, FALSE));
2749 emit2("xor a,!immedbyte", 0x80);
2750 emitcode("ld", "%s,a", _fTmp[1]);
2760 /* Do a long subtract */
2761 if (!sign || size ) {
2762 MOVA(aopGet(AOP(left),offset,FALSE));
2764 if (sign && size == 0) {
2765 emitcode("ld", "a,%s", _fTmp[0]);
2766 emitcode("sbc", "a,%s", _fTmp[1]);
2769 /* Subtract through, propagating the carry */
2770 emitcode("sbc","a,%s ; 2",aopGet(AOP(right),offset++,FALSE));
2777 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2778 outBitCLong(result, swap_sense);
2780 /* if the result is used in the next
2781 ifx conditional branch then generate
2782 code a little differently */
2784 genIfxJump(ifx, swap_sense ? "nc" : "c");
2786 outBitCLong(result, swap_sense);
2787 /* leave the result in acc */
2791 /*-----------------------------------------------------------------*/
2792 /* genCmpGt :- greater than comparison */
2793 /*-----------------------------------------------------------------*/
2794 static void genCmpGt (iCode *ic, iCode *ifx)
2796 operand *left, *right, *result;
2797 sym_link *letype , *retype;
2801 right= IC_RIGHT(ic);
2802 result = IC_RESULT(ic);
2804 letype = getSpec(operandType(left));
2805 retype =getSpec(operandType(right));
2806 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2807 /* assign the amsops */
2808 aopOp (left,ic,FALSE, FALSE);
2809 aopOp (right,ic,FALSE, FALSE);
2810 aopOp (result,ic,TRUE, FALSE);
2812 genCmp(right, left, result, ifx, sign);
2814 freeAsmop(left,NULL,ic);
2815 freeAsmop(right,NULL,ic);
2816 freeAsmop(result,NULL,ic);
2819 /*-----------------------------------------------------------------*/
2820 /* genCmpLt - less than comparisons */
2821 /*-----------------------------------------------------------------*/
2822 static void genCmpLt (iCode *ic, iCode *ifx)
2824 operand *left, *right, *result;
2825 sym_link *letype , *retype;
2829 right= IC_RIGHT(ic);
2830 result = IC_RESULT(ic);
2832 letype = getSpec(operandType(left));
2833 retype =getSpec(operandType(right));
2834 sign = !(SPEC_USIGN(letype) | SPEC_USIGN(retype));
2836 /* assign the amsops */
2837 aopOp (left,ic,FALSE, FALSE);
2838 aopOp (right,ic,FALSE, FALSE);
2839 aopOp (result,ic,TRUE, FALSE);
2841 genCmp(left, right, result, ifx, sign);
2843 freeAsmop(left,NULL,ic);
2844 freeAsmop(right,NULL,ic);
2845 freeAsmop(result,NULL,ic);
2848 /*-----------------------------------------------------------------*/
2849 /* gencjneshort - compare and jump if not equal */
2850 /*-----------------------------------------------------------------*/
2851 static void gencjneshort(operand *left, operand *right, symbol *lbl)
2853 int size = max(AOP_SIZE(left),AOP_SIZE(right));
2855 unsigned long lit = 0L;
2857 /* Swap the left and right if it makes the computation easier */
2858 if (AOP_TYPE(left) == AOP_LIT) {
2864 if(AOP_TYPE(right) == AOP_LIT)
2865 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
2867 /* if the right side is a literal then anything goes */
2868 if (AOP_TYPE(right) == AOP_LIT &&
2869 AOP_TYPE(left) != AOP_DIR ) {
2871 emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
2876 emitcode("or", "a,%s", aopGet(AOP(left), offset, FALSE));
2880 emitcode("or", "a,a");
2882 emit2("jp nz,!tlabel", lbl->key+100);
2886 emitcode("ld", "a,%s ; 2", aopGet(AOP(left),offset,FALSE));
2887 if ((AOP_TYPE(right) == AOP_LIT) && lit == 0)
2888 emitcode("or", "a,a");
2890 emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
2891 emit2("jp nz,!tlabel", lbl->key+100);
2896 /* if the right side is in a register or in direct space or
2897 if the left is a pointer register & right is not */
2898 else if (AOP_TYPE(right) == AOP_REG ||
2899 AOP_TYPE(right) == AOP_DIR ||
2900 (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
2902 MOVA(aopGet(AOP(left),offset,FALSE));
2903 if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
2904 ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
2906 emit2("jp nz,!tlabel", lbl->key+100);
2908 emitcode("cp", "%s ; 4", aopGet(AOP(right),offset,FALSE));
2909 emit2("jp nz,!tlabel", lbl->key+100);
2914 /* right is a pointer reg need both a & b */
2915 /* PENDING: is this required? */
2917 MOVA(aopGet(AOP(right),offset,FALSE));
2918 emitcode("cp", "%s ; 5", aopGet(AOP(left), offset, FALSE));
2919 emit2("!shortjp nz,!tlabel", lbl->key+100);
2925 /*-----------------------------------------------------------------*/
2926 /* gencjne - compare and jump if not equal */
2927 /*-----------------------------------------------------------------*/
2928 static void gencjne(operand *left, operand *right, symbol *lbl)
2930 symbol *tlbl = newiTempLabel(NULL);
2932 gencjneshort(left, right, lbl);
2936 emit2("!shortjp !tlabel", tlbl->key+100);
2937 emitLabel(lbl->key+100);
2938 emitcode("xor","a,a");
2939 emitLabel(tlbl->key+100);
2942 /*-----------------------------------------------------------------*/
2943 /* genCmpEq - generates code for equal to */
2944 /*-----------------------------------------------------------------*/
2945 static void genCmpEq (iCode *ic, iCode *ifx)
2947 operand *left, *right, *result;
2949 aopOp((left=IC_LEFT(ic)),ic,FALSE, FALSE);
2950 aopOp((right=IC_RIGHT(ic)),ic,FALSE, FALSE);
2951 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
2953 /* Swap operands if it makes the operation easier. ie if:
2954 1. Left is a literal.
2956 if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
2957 operand *t = IC_RIGHT(ic);
2958 IC_RIGHT(ic) = IC_LEFT(ic);
2962 if (ifx && !AOP_SIZE(result)){
2964 /* if they are both bit variables */
2965 if (AOP_TYPE(left) == AOP_CRY &&
2966 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2969 tlbl = newiTempLabel(NULL);
2970 gencjneshort(left, right, tlbl);
2971 if ( IC_TRUE(ifx) ) {
2972 emit2("jp !tlabel", IC_TRUE(ifx)->key+100);
2973 emitLabel(tlbl->key+100);
2975 /* PENDING: do this better */
2976 symbol *lbl = newiTempLabel(NULL);
2977 emit2("!shortjp !tlabel", lbl->key+100);
2978 emitLabel(tlbl->key+100);
2979 emit2("jp !tlabel", IC_FALSE(ifx)->key+100);
2980 emitLabel(lbl->key+100);
2983 /* mark the icode as generated */
2988 /* if they are both bit variables */
2989 if (AOP_TYPE(left) == AOP_CRY &&
2990 ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
2993 gencjne(left,right,newiTempLabel(NULL));
2994 if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
2998 genIfxJump(ifx,"a");
3001 /* if the result is used in an arithmetic operation
3002 then put the result in place */
3003 if (AOP_TYPE(result) != AOP_CRY) {
3006 /* leave the result in acc */
3010 freeAsmop(left,NULL,ic);
3011 freeAsmop(right,NULL,ic);
3012 freeAsmop(result,NULL,ic);
3015 /*-----------------------------------------------------------------*/
3016 /* ifxForOp - returns the icode containing the ifx for operand */
3017 /*-----------------------------------------------------------------*/
3018 static iCode *ifxForOp ( operand *op, iCode *ic )
3020 /* if true symbol then needs to be assigned */
3021 if (IS_TRUE_SYMOP(op))
3024 /* if this has register type condition and
3025 the next instruction is ifx with the same operand
3026 and live to of the operand is upto the ifx only then */
3028 ic->next->op == IFX &&
3029 IC_COND(ic->next)->key == op->key &&
3030 OP_SYMBOL(op)->liveTo <= ic->next->seq )
3036 /*-----------------------------------------------------------------*/
3037 /* genAndOp - for && operation */
3038 /*-----------------------------------------------------------------*/
3039 static void genAndOp (iCode *ic)
3041 operand *left,*right, *result;
3044 /* note here that && operations that are in an if statement are
3045 taken away by backPatchLabels only those used in arthmetic
3046 operations remain */
3047 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
3048 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3049 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
3051 /* if both are bit variables */
3052 if (AOP_TYPE(left) == AOP_CRY &&
3053 AOP_TYPE(right) == AOP_CRY ) {
3056 tlbl = newiTempLabel(NULL);
3058 emit2("!shortjp z,!tlabel", tlbl->key+100);
3060 emitLabel(tlbl->key+100);
3064 freeAsmop(left,NULL,ic);
3065 freeAsmop(right,NULL,ic);
3066 freeAsmop(result,NULL,ic);
3069 /*-----------------------------------------------------------------*/
3070 /* genOrOp - for || operation */
3071 /*-----------------------------------------------------------------*/
3072 static void genOrOp (iCode *ic)
3074 operand *left,*right, *result;
3077 /* note here that || operations that are in an
3078 if statement are taken away by backPatchLabels
3079 only those used in arthmetic operations remain */
3080 aopOp((left=IC_LEFT(ic)),ic,FALSE, TRUE);
3081 aopOp((right=IC_RIGHT(ic)),ic,FALSE, TRUE);
3082 aopOp((result=IC_RESULT(ic)),ic,FALSE, FALSE);
3084 /* if both are bit variables */
3085 if (AOP_TYPE(left) == AOP_CRY &&
3086 AOP_TYPE(right) == AOP_CRY ) {
3089 tlbl = newiTempLabel(NULL);
3091 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3093 emitLabel(tlbl->key+100);
3097 freeAsmop(left,NULL,ic);
3098 freeAsmop(right,NULL,ic);
3099 freeAsmop(result,NULL,ic);
3102 /*-----------------------------------------------------------------*/
3103 /* isLiteralBit - test if lit == 2^n */
3104 /*-----------------------------------------------------------------*/
3105 int isLiteralBit(unsigned long lit)
3107 unsigned long pw[32] = {1L,2L,4L,8L,16L,32L,64L,128L,
3108 0x100L,0x200L,0x400L,0x800L,
3109 0x1000L,0x2000L,0x4000L,0x8000L,
3110 0x10000L,0x20000L,0x40000L,0x80000L,
3111 0x100000L,0x200000L,0x400000L,0x800000L,
3112 0x1000000L,0x2000000L,0x4000000L,0x8000000L,
3113 0x10000000L,0x20000000L,0x40000000L,0x80000000L};
3116 for(idx = 0; idx < 32; idx++)
3122 /*-----------------------------------------------------------------*/
3123 /* jmpTrueOrFalse - */
3124 /*-----------------------------------------------------------------*/
3125 static void jmpTrueOrFalse (iCode *ic, symbol *tlbl)
3127 // ugly but optimized by peephole
3129 symbol *nlbl = newiTempLabel(NULL);
3130 emit2("jp !tlabel", nlbl->key+100);
3131 emitLabel(tlbl->key+100);
3132 emit2("jp !tlabel", IC_TRUE(ic)->key+100);
3133 emitLabel(nlbl->key+100);
3136 emit2("jp !tlabel", IC_FALSE(ic)->key+100);
3137 emitLabel(tlbl->key+100);
3142 /*-----------------------------------------------------------------*/
3143 /* genAnd - code for and */
3144 /*-----------------------------------------------------------------*/
3145 static void genAnd (iCode *ic, iCode *ifx)
3147 operand *left, *right, *result;
3149 unsigned long lit = 0L;
3152 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3153 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3154 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3157 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3159 AOP_TYPE(left), AOP_TYPE(right));
3160 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3162 AOP_SIZE(left), AOP_SIZE(right));
3165 /* if left is a literal & right is not then exchange them */
3166 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3167 AOP_NEEDSACC(left)) {
3168 operand *tmp = right ;
3173 /* if result = right then exchange them */
3174 if(sameRegs(AOP(result),AOP(right))){
3175 operand *tmp = right ;
3180 /* if right is bit then exchange them */
3181 if (AOP_TYPE(right) == AOP_CRY &&
3182 AOP_TYPE(left) != AOP_CRY){
3183 operand *tmp = right ;
3187 if(AOP_TYPE(right) == AOP_LIT)
3188 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3190 size = AOP_SIZE(result);
3192 if (AOP_TYPE(left) == AOP_CRY){
3197 // if(val & 0xZZ) - size = 0, ifx != FALSE -
3198 // bit = val & 0xZZ - size = 1, ifx = FALSE -
3199 if((AOP_TYPE(right) == AOP_LIT) &&
3200 (AOP_TYPE(result) == AOP_CRY) &&
3201 (AOP_TYPE(left) != AOP_CRY)) {
3202 int posbit = isLiteralBit(lit);
3206 MOVA(aopGet(AOP(left),posbit>>3,FALSE));
3210 emitcode("mov","c,acc.%d",posbit&0x07);
3215 sprintf(buffer, "%d", posbit&0x07);
3216 genIfxJump(ifx, buffer);
3224 symbol *tlbl = newiTempLabel(NULL);
3225 int sizel = AOP_SIZE(left);
3228 emitcode("setb","c");
3231 if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
3232 MOVA( aopGet(AOP(left),offset,FALSE));
3234 if((posbit = isLiteralBit(bytelit)) != 0) {
3236 emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
3239 if(bytelit != 0x0FFL)
3240 emitcode("and","a,%s",
3241 aopGet(AOP(right),offset,FALSE));
3245 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3250 // bit = left & literal
3252 emitcode("clr","c");
3253 emit2("!tlabeldef", tlbl->key+100);
3255 // if(left & literal)
3258 jmpTrueOrFalse(ifx, tlbl);
3266 /* if left is same as result */
3267 if(sameRegs(AOP(result),AOP(left))){
3268 for(;size--; offset++) {
3269 if(AOP_TYPE(right) == AOP_LIT){
3270 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
3274 aopPut(AOP(result),zero,offset);
3276 MOVA(aopGet(AOP(left),offset,FALSE));
3277 emitcode("and","a,%s",
3278 aopGet(AOP(right),offset,FALSE));
3279 aopPut(AOP(left), "a", offset);
3284 if (AOP_TYPE(left) == AOP_ACC) {
3288 MOVA(aopGet(AOP(left),offset,FALSE));
3289 emitcode("and","a,%s",
3290 aopGet(AOP(right),offset,FALSE));
3291 aopPut(AOP(left), "a", offset);
3296 // left & result in different registers
3297 if(AOP_TYPE(result) == AOP_CRY){
3300 for(;(size--);offset++) {
3302 // result = left & right
3303 if(AOP_TYPE(right) == AOP_LIT){
3304 if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
3306 aopGet(AOP(left),offset,FALSE),
3309 } else if(bytelit == 0){
3310 aopPut(AOP(result),zero,offset);
3314 // faster than result <- left, anl result,right
3315 // and better if result is SFR
3316 if (AOP_TYPE(left) == AOP_ACC)
3317 emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
3319 MOVA(aopGet(AOP(left),offset,FALSE));
3320 emitcode("and","a,%s",
3321 aopGet(AOP(right),offset,FALSE));
3323 aopPut(AOP(result),"a",offset);
3330 freeAsmop(left,NULL,ic);
3331 freeAsmop(right,NULL,ic);
3332 freeAsmop(result,NULL,ic);
3335 /*-----------------------------------------------------------------*/
3336 /* genOr - code for or */
3337 /*-----------------------------------------------------------------*/
3338 static void genOr (iCode *ic, iCode *ifx)
3340 operand *left, *right, *result;
3342 unsigned long lit = 0L;
3344 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3345 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3346 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3349 emitcode("","; Type res[%d] = l[%d]&r[%d]",
3351 AOP_TYPE(left), AOP_TYPE(right));
3352 emitcode("","; Size res[%d] = l[%d]&r[%d]",
3354 AOP_SIZE(left), AOP_SIZE(right));
3357 /* if left is a literal & right is not then exchange them */
3358 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3359 AOP_NEEDSACC(left)) {
3360 operand *tmp = right ;
3365 /* if result = right then exchange them */
3366 if(sameRegs(AOP(result),AOP(right))){
3367 operand *tmp = right ;
3372 /* if right is bit then exchange them */
3373 if (AOP_TYPE(right) == AOP_CRY &&
3374 AOP_TYPE(left) != AOP_CRY){
3375 operand *tmp = right ;
3379 if(AOP_TYPE(right) == AOP_LIT)
3380 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3382 size = AOP_SIZE(result);
3384 if (AOP_TYPE(left) == AOP_CRY){
3389 if((AOP_TYPE(right) == AOP_LIT) &&
3390 (AOP_TYPE(result) == AOP_CRY) &&
3391 (AOP_TYPE(left) != AOP_CRY)){
3396 /* if left is same as result */
3397 if(sameRegs(AOP(result),AOP(left))){
3398 for(;size--; offset++) {
3399 if(AOP_TYPE(right) == AOP_LIT){
3400 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3403 MOVA(aopGet(AOP(left),offset,FALSE));
3404 emitcode("or","a,%s",
3405 aopGet(AOP(right),offset,FALSE));
3406 aopPut(AOP(result),"a", offset);
3409 if (AOP_TYPE(left) == AOP_ACC)
3410 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3412 MOVA(aopGet(AOP(left),offset,FALSE));
3413 emitcode("or","a,%s",
3414 aopGet(AOP(right),offset,FALSE));
3415 aopPut(AOP(result),"a", offset);
3420 // left & result in different registers
3421 if(AOP_TYPE(result) == AOP_CRY){
3423 } else for(;(size--);offset++){
3425 // result = left & right
3426 if(AOP_TYPE(right) == AOP_LIT){
3427 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3429 aopGet(AOP(left),offset,FALSE),
3434 // faster than result <- left, anl result,right
3435 // and better if result is SFR
3436 if (AOP_TYPE(left) == AOP_ACC)
3437 emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
3439 MOVA(aopGet(AOP(left),offset,FALSE));
3440 emitcode("or","a,%s",
3441 aopGet(AOP(right),offset,FALSE));
3443 aopPut(AOP(result),"a",offset);
3444 /* PENDING: something weird is going on here. Add exception. */
3445 if (AOP_TYPE(result) == AOP_ACC)
3451 freeAsmop(left,NULL,ic);
3452 freeAsmop(right,NULL,ic);
3453 freeAsmop(result,NULL,ic);
3456 /*-----------------------------------------------------------------*/
3457 /* genXor - code for xclusive or */
3458 /*-----------------------------------------------------------------*/
3459 static void genXor (iCode *ic, iCode *ifx)
3461 operand *left, *right, *result;
3463 unsigned long lit = 0L;
3465 aopOp((left = IC_LEFT(ic)),ic,FALSE, FALSE);
3466 aopOp((right= IC_RIGHT(ic)),ic,FALSE, FALSE);
3467 aopOp((result=IC_RESULT(ic)),ic,TRUE, FALSE);
3469 /* if left is a literal & right is not then exchange them */
3470 if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
3471 AOP_NEEDSACC(left)) {
3472 operand *tmp = right ;
3477 /* if result = right then exchange them */
3478 if(sameRegs(AOP(result),AOP(right))){
3479 operand *tmp = right ;
3484 /* if right is bit then exchange them */
3485 if (AOP_TYPE(right) == AOP_CRY &&
3486 AOP_TYPE(left) != AOP_CRY){
3487 operand *tmp = right ;
3491 if(AOP_TYPE(right) == AOP_LIT)
3492 lit = (unsigned long)floatFromVal (AOP(right)->aopu.aop_lit);
3494 size = AOP_SIZE(result);
3496 if (AOP_TYPE(left) == AOP_CRY){
3501 if((AOP_TYPE(right) == AOP_LIT) &&
3502 (AOP_TYPE(result) == AOP_CRY) &&
3503 (AOP_TYPE(left) != AOP_CRY)){
3508 /* if left is same as result */
3509 if(sameRegs(AOP(result),AOP(left))){
3510 for(;size--; offset++) {
3511 if(AOP_TYPE(right) == AOP_LIT){
3512 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
3515 MOVA(aopGet(AOP(right),offset,FALSE));
3516 emitcode("xor","a,%s",
3517 aopGet(AOP(left),offset,FALSE));
3518 aopPut(AOP(result),"a",0);
3521 if (AOP_TYPE(left) == AOP_ACC)
3522 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3524 MOVA(aopGet(AOP(right),offset,FALSE));
3525 emitcode("xor","a,%s",
3526 aopGet(AOP(left),offset,FALSE));
3527 aopPut(AOP(result),"a",0);
3532 // left & result in different registers
3533 if(AOP_TYPE(result) == AOP_CRY){
3535 } else for(;(size--);offset++){
3537 // result = left & right
3538 if(AOP_TYPE(right) == AOP_LIT){
3539 if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
3541 aopGet(AOP(left),offset,FALSE),
3546 // faster than result <- left, anl result,right
3547 // and better if result is SFR
3548 if (AOP_TYPE(left) == AOP_ACC)
3549 emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
3551 MOVA(aopGet(AOP(right),offset,FALSE));
3552 emitcode("xor","a,%s",
3553 aopGet(AOP(left),offset,FALSE));
3554 aopPut(AOP(result),"a",0);
3556 aopPut(AOP(result),"a",offset);
3561 freeAsmop(left,NULL,ic);
3562 freeAsmop(right,NULL,ic);
3563 freeAsmop(result,NULL,ic);
3566 /*-----------------------------------------------------------------*/
3567 /* genInline - write the inline code out */
3568 /*-----------------------------------------------------------------*/
3569 static void genInline (iCode *ic)
3571 char buffer[MAX_INLINEASM];
3575 inLine += (!options.asmpeep);
3576 strcpy(buffer,IC_INLINE(ic));
3578 /* emit each line as a code */
3597 /* emitcode("",buffer); */
3598 inLine -= (!options.asmpeep);
3601 /*-----------------------------------------------------------------*/
3602 /* genRRC - rotate right with carry */
3603 /*-----------------------------------------------------------------*/
3604 static void genRRC (iCode *ic)
3609 /*-----------------------------------------------------------------*/
3610 /* genRLC - generate code for rotate left with carry */
3611 /*-----------------------------------------------------------------*/
3612 static void genRLC (iCode *ic)
3617 /*-----------------------------------------------------------------*/
3618 /* shiftR2Left2Result - shift right two bytes from left to result */
3619 /*-----------------------------------------------------------------*/
3620 static void shiftR2Left2Result (operand *left, int offl,
3621 operand *result, int offr,
3622 int shCount, int sign)
3624 movLeft2Result(left, offl, result, offr, 0);
3625 movLeft2Result(left, offl+1, result, offr+1, 0);
3631 /* if (AOP(result)->type == AOP_REG) {*/
3634 symbol *tlbl , *tlbl1;
3637 tlbl = newiTempLabel(NULL);
3638 tlbl1 = newiTempLabel(NULL);
3640 /* Left is already in result - so now do the shift */
3642 emit2("ld a,!immedbyte+1", shCount);
3643 emit2("!shortjp !tlabel", tlbl1->key+100);
3644 emitLabel(tlbl->key+100);
3647 emitcode("or", "a,a");
3650 l = aopGet(AOP(result), --offset, FALSE);
3651 emitcode("rr","%s", l);
3654 emitLabel(tlbl1->key+100);
3655 emitcode("dec", "a");
3656 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3661 /*-----------------------------------------------------------------*/
3662 /* shiftL2Left2Result - shift left two bytes from left to result */
3663 /*-----------------------------------------------------------------*/
3664 static void shiftL2Left2Result (operand *left, int offl,
3665 operand *result, int offr, int shCount)
3667 if(sameRegs(AOP(result), AOP(left)) &&
3668 ((offl + MSB16) == offr)){
3671 /* Copy left into result */
3672 movLeft2Result(left, offl, result, offr, 0);
3673 movLeft2Result(left, offl+1, result, offr+1, 0);
3675 /* PENDING: for now just see if it'll work. */
3676 /*if (AOP(result)->type == AOP_REG) { */
3680 symbol *tlbl , *tlbl1;
3683 tlbl = newiTempLabel(NULL);
3684 tlbl1 = newiTempLabel(NULL);
3686 /* Left is already in result - so now do the shift */
3688 emit2("ld a,!immedbyte+1", shCount);
3689 emit2("!shortjp !tlabel", tlbl1->key+100);
3690 emitLabel(tlbl->key+100);
3693 emitcode("or", "a,a");
3695 l = aopGet(AOP(result),offset++,FALSE);
3696 emitcode("rl","%s", l);
3699 emitLabel(tlbl1->key+100);
3700 emitcode("dec", "a");
3701 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3706 /*-----------------------------------------------------------------*/
3707 /* AccRol - rotate left accumulator by known count */
3708 /*-----------------------------------------------------------------*/
3709 static void AccRol (int shCount)
3711 shCount &= 0x0007; // shCount : 0..7
3748 /*-----------------------------------------------------------------*/
3749 /* AccLsh - left shift accumulator by known count */
3750 /*-----------------------------------------------------------------*/
3751 static void AccLsh (int shCount)
3755 emitcode("add","a,a");
3757 else if(shCount == 2) {
3758 emitcode("add","a,a");
3759 emitcode("add","a,a");
3761 /* rotate left accumulator */
3763 /* and kill the lower order bits */
3764 emit2("and a,!immedbyte", SLMask[shCount]);
3769 /*-----------------------------------------------------------------*/
3770 /* shiftL1Left2Result - shift left one byte from left to result */
3771 /*-----------------------------------------------------------------*/
3772 static void shiftL1Left2Result (operand *left, int offl,
3773 operand *result, int offr, int shCount)
3776 l = aopGet(AOP(left),offl,FALSE);
3778 /* shift left accumulator */
3780 aopPut(AOP(result),"a",offr);
3784 /*-----------------------------------------------------------------*/
3785 /* genlshTwo - left shift two bytes by known amount != 0 */
3786 /*-----------------------------------------------------------------*/
3787 static void genlshTwo (operand *result,operand *left, int shCount)
3789 int size = AOP_SIZE(result);
3793 /* if shCount >= 8 */
3798 movLeft2Result(left, LSB, result, MSB16, 0);
3799 aopPut(AOP(result),zero, 0);
3800 shiftL1Left2Result(left, MSB16, result, MSB16, shCount);
3803 movLeft2Result(left, LSB, result, MSB16, 0);
3804 aopPut(AOP(result),zero, 0);
3808 aopPut(AOP(result),zero,LSB);
3811 /* 1 <= shCount <= 7 */
3817 shiftL2Left2Result(left, LSB, result, LSB, shCount);
3822 /*-----------------------------------------------------------------*/
3823 /* genlshOne - left shift a one byte quantity by known count */
3824 /*-----------------------------------------------------------------*/
3825 static void genlshOne (operand *result, operand *left, int shCount)
3827 shiftL1Left2Result(left, LSB, result, LSB, shCount);
3830 /*-----------------------------------------------------------------*/
3831 /* genLeftShiftLiteral - left shifting by known count */
3832 /*-----------------------------------------------------------------*/
3833 static void genLeftShiftLiteral (operand *left,
3838 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
3841 freeAsmop(right,NULL,ic);
3843 aopOp(left,ic,FALSE, FALSE);
3844 aopOp(result,ic,FALSE, FALSE);
3846 size = getSize(operandType(result));
3849 emitcode("; shift left ","result %d, left %d",size,
3853 /* I suppose that the left size >= result size */
3858 else if(shCount >= (size * 8))
3860 aopPut(AOP(result),zero,size);
3864 genlshOne (result,left,shCount);
3867 genlshTwo (result,left,shCount);
3876 freeAsmop(left,NULL,ic);
3877 freeAsmop(result,NULL,ic);
3880 /*-----------------------------------------------------------------*/
3881 /* genLeftShift - generates code for left shifting */
3882 /*-----------------------------------------------------------------*/
3883 static void genLeftShift (iCode *ic)
3887 symbol *tlbl , *tlbl1;
3888 operand *left,*right, *result;
3890 right = IC_RIGHT(ic);
3892 result = IC_RESULT(ic);
3894 aopOp(right,ic,FALSE, FALSE);
3896 /* if the shift count is known then do it
3897 as efficiently as possible */
3898 if (AOP_TYPE(right) == AOP_LIT) {
3899 genLeftShiftLiteral (left,right,result,ic);
3903 /* shift count is unknown then we have to form a loop get the loop
3904 count in B : Note: we take only the lower order byte since
3905 shifting more that 32 bits make no sense anyway, ( the largest
3906 size of an object can be only 32 bits ) */
3907 emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
3908 emitcode("inc","a");
3909 freeAsmop (right,NULL,ic);
3910 aopOp(left,ic,FALSE, FALSE);
3911 aopOp(result,ic,FALSE, FALSE);
3913 /* now move the left to the result if they are not the
3916 if (!sameRegs(AOP(left),AOP(result))) {
3918 size = AOP_SIZE(result);
3921 l = aopGet(AOP(left),offset,FALSE);
3922 aopPut(AOP(result),l,offset);
3927 size = AOP_SIZE(result);
3930 l = aopGet(AOP(left),offset,FALSE);
3931 aopPut(AOP(result),l,offset);
3937 tlbl = newiTempLabel(NULL);
3938 size = AOP_SIZE(result);
3940 tlbl1 = newiTempLabel(NULL);
3942 emit2("!shortjp !tlabel", tlbl1->key+100);
3943 emitLabel(tlbl->key+100);
3944 l = aopGet(AOP(result),offset,FALSE);
3945 emitcode("or", "a,a");
3947 l = aopGet(AOP(result),offset++,FALSE);
3948 emitcode("rl","%s", l);
3950 emitLabel(tlbl1->key+100);
3951 emitcode("dec", "a");
3952 emit2("!shortjp nz,!tlabel", tlbl->key+100);
3954 freeAsmop(left,NULL,ic);
3955 freeAsmop(result,NULL,ic);
3958 /*-----------------------------------------------------------------*/
3959 /* genrshOne - left shift two bytes by known amount != 0 */
3960 /*-----------------------------------------------------------------*/
3961 static void genrshOne (operand *result,operand *left, int shCount)
3964 int size = AOP_SIZE(result);
3970 l = aopGet(AOP(left),0,FALSE);
3971 if (AOP(result)->type == AOP_REG) {
3972 aopPut(AOP(result), l, 0);
3973 l = aopGet(AOP(result), 0, FALSE);
3975 emitcode("srl", "%s", l);
3980 emitcode("srl", "a");
3982 aopPut(AOP(result),"a",0);
3986 /*-----------------------------------------------------------------*/
3987 /* AccRsh - right shift accumulator by known count */
3988 /*-----------------------------------------------------------------*/
3989 static void AccRsh (int shCount)
3992 /* rotate right accumulator */
3993 AccRol(8 - shCount);
3994 /* and kill the higher order bits */
3995 emit2("and a,!immedbyte", SRMask[shCount]);
3999 /*-----------------------------------------------------------------*/
4000 /* shiftR1Left2Result - shift right one byte from left to result */
4001 /*-----------------------------------------------------------------*/
4002 static void shiftR1Left2Result (operand *left, int offl,
4003 operand *result, int offr,
4004 int shCount, int sign)
4006 MOVA(aopGet(AOP(left),offl,FALSE));
4013 aopPut(AOP(result),"a",offr);
4016 /*-----------------------------------------------------------------*/
4017 /* genrshTwo - right shift two bytes by known amount != 0 */
4018 /*-----------------------------------------------------------------*/
4019 static void genrshTwo (operand *result,operand *left,
4020 int shCount, int sign)
4022 /* if shCount >= 8 */
4026 shiftR1Left2Result(left, MSB16, result, LSB,
4030 movLeft2Result(left, MSB16, result, LSB, sign);
4032 aopPut(AOP(result),zero,1);
4034 /* 1 <= shCount <= 7 */
4036 shiftR2Left2Result(left, LSB, result, LSB, shCount, sign);
4040 /*-----------------------------------------------------------------*/
4041 /* genRightShiftLiteral - left shifting by known count */
4042 /*-----------------------------------------------------------------*/
4043 static void genRightShiftLiteral (operand *left,
4048 int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
4051 freeAsmop(right,NULL,ic);
4053 aopOp(left,ic,FALSE, FALSE);
4054 aopOp(result,ic,FALSE, FALSE);
4056 size = getSize(operandType(result));
4058 emitcode("; shift right ","result %d, left %d",size,
4061 /* I suppose that the left size >= result size */
4066 else if(shCount >= (size * 8))
4068 aopPut(AOP(result),zero,size);
4072 genrshOne(result, left, shCount);
4075 /* PENDING: sign support */
4076 genrshTwo(result, left, shCount, FALSE);
4085 freeAsmop(left,NULL,ic);
4086 freeAsmop(result,NULL,ic);
4089 /*-----------------------------------------------------------------*/
4090 /* genRightShift - generate code for right shifting */
4091 /*-----------------------------------------------------------------*/
4092 static void genRightShift (iCode *ic)
4094 operand *right, *left, *result;
4096 int size, offset, first = 1;
4100 symbol *tlbl, *tlbl1 ;
4102 /* if signed then we do it the hard way preserve the
4103 sign bit moving it inwards */
4104 retype = getSpec(operandType(IC_RESULT(ic)));
4106 is_signed = !SPEC_USIGN(retype);
4108 /* signed & unsigned types are treated the same : i.e. the
4109 signed is NOT propagated inwards : quoting from the
4110 ANSI - standard : "for E1 >> E2, is equivalent to division
4111 by 2**E2 if unsigned or if it has a non-negative value,
4112 otherwise the result is implementation defined ", MY definition
4113 is that the sign does not get propagated */
4115 right = IC_RIGHT(ic);
4117 result = IC_RESULT(ic);
4119 aopOp(right,ic,FALSE, FALSE);
4121 /* if the shift count is known then do it
4122 as efficiently as possible */
4123 if (AOP_TYPE(right) == AOP_LIT) {
4124 genRightShiftLiteral(left,right,result,ic);
4128 aopOp(left,ic,FALSE, FALSE);
4129 aopOp(result,ic,FALSE, FALSE);
4131 /* now move the left to the result if they are not the
4133 if (!sameRegs(AOP(left),AOP(result)) &&
4134 AOP_SIZE(result) > 1) {
4136 size = AOP_SIZE(result);
4139 l = aopGet(AOP(left),offset,FALSE);
4140 aopPut(AOP(result),l,offset);
4145 emitcode("ld", "a,%s",aopGet(AOP(right),0,FALSE));
4146 emitcode("inc","a");
4147 freeAsmop (right, NULL, ic);
4149 tlbl = newiTempLabel(NULL);
4150 tlbl1= newiTempLabel(NULL);
4151 size = AOP_SIZE(result);
4154 emit2("!shortjp !tlabel", tlbl1->key+100);
4155 emitLabel(tlbl->key+100);
4157 l = aopGet(AOP(result),offset--,FALSE);
4160 emitcode("sra", "%s", l);
4162 emitcode("srl", "%s", l);
4166 emitcode("rr", "%s", l);
4168 emitLabel(tlbl1->key+100);
4169 emitcode("dec", "a");
4170 emit2("!shortjp nz,!tlabel", tlbl->key+100);
4172 freeAsmop(left,NULL,ic);
4173 freeAsmop(result,NULL,ic);
4176 /*-----------------------------------------------------------------*/
4177 /* genGenPointerGet - get value from generic pointer space */
4178 /*-----------------------------------------------------------------*/
4179 static void genGenPointerGet (operand *left,
4180 operand *result, iCode *ic)
4183 sym_link *retype = getSpec(operandType(result));
4189 aopOp(left,ic,FALSE, FALSE);
4190 aopOp(result,ic,FALSE, FALSE);
4192 if (isPair(AOP(left)) && AOP_SIZE(result)==1) {
4194 if (isPtrPair(AOP(left)))
4196 tsprintf(buffer, "!*pair", getPairName(AOP(left)));
4197 aopPut(AOP(result), buffer, 0);
4200 emit2("ld a,!*pair", getPairName(AOP(left)));
4201 aopPut(AOP(result),"a", 0);
4203 freeAsmop(left,NULL,ic);
4207 /* For now we always load into IY */
4208 /* if this is remateriazable */
4209 fetchPair(pair, AOP(left));
4211 /* so iy now contains the address */
4212 freeAsmop(left,NULL,ic);
4214 /* if bit then unpack */
4215 if (IS_BITVAR(retype)) {
4219 size = AOP_SIZE(result);
4223 /* PENDING: make this better */
4224 if (!IS_GB && AOP(result)->type == AOP_REG) {
4225 aopPut(AOP(result), "!*hl", offset++);
4228 emit2("ld a,!*pair", _pairs[pair].name);
4229 aopPut(AOP(result),"a",offset++);
4232 emit2("inc %s", _pairs[pair].name);
4233 _G.pairs[pair].offset++;
4239 freeAsmop(result,NULL,ic);
4242 /*-----------------------------------------------------------------*/
4243 /* genPointerGet - generate code for pointer get */
4244 /*-----------------------------------------------------------------*/
4245 static void genPointerGet (iCode *ic)
4247 operand *left, *result ;
4248 sym_link *type, *etype;
4251 result = IC_RESULT(ic) ;
4253 /* depending on the type of pointer we need to
4254 move it to the correct pointer register */
4255 type = operandType(left);
4256 etype = getSpec(type);
4258 genGenPointerGet (left,result,ic);
4261 bool isRegOrLit(asmop *aop)
4263 if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
4268 /*-----------------------------------------------------------------*/
4269 /* genGenPointerSet - stores the value into a pointer location */
4270 /*-----------------------------------------------------------------*/
4271 static void genGenPointerSet (operand *right,
4272 operand *result, iCode *ic)
4275 sym_link *retype = getSpec(operandType(right));
4276 PAIR_ID pairId = PAIR_HL;
4278 aopOp(result,ic,FALSE, FALSE);
4279 aopOp(right,ic,FALSE, FALSE);
4284 /* Handle the exceptions first */
4285 if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
4287 char *l = aopGet(AOP(right), 0, FALSE);
4288 const char *pair = getPairName(AOP(result));
4289 if (canAssignToPtr(l) && isPtr(pair)) {
4290 emit2("ld !*pair,%s", pair, l);
4294 emit2("ld !*pair,a", pair);
4299 /* if the operand is already in dptr
4300 then we do nothing else we move the value to dptr */
4301 if (AOP_TYPE(result) != AOP_STR) {
4302 fetchPair(pairId, AOP(result));
4304 /* so hl know contains the address */
4305 freeAsmop(result,NULL,ic);
4307 /* if bit then unpack */
4308 if (IS_BITVAR(retype)) {
4312 size = AOP_SIZE(right);
4316 char *l = aopGet(AOP(right),offset,FALSE);
4317 if (isRegOrLit(AOP(right)) && !IS_GB) {
4318 emit2("ld !*pair,%s", _pairs[pairId].name, l);
4322 emit2("ld !*pair,a", _pairs[pairId].name);
4325 emitcode("inc", _pairs[pairId].name);
4326 _G.pairs[pairId].offset++;
4332 freeAsmop(right,NULL,ic);
4335 /*-----------------------------------------------------------------*/
4336 /* genPointerSet - stores the value into a pointer location */
4337 /*-----------------------------------------------------------------*/
4338 static void genPointerSet (iCode *ic)
4340 operand *right, *result ;
4341 sym_link *type, *etype;
4343 right = IC_RIGHT(ic);
4344 result = IC_RESULT(ic) ;
4346 /* depending on the type of pointer we need to
4347 move it to the correct pointer register */
4348 type = operandType(result);
4349 etype = getSpec(type);
4351 genGenPointerSet (right,result,ic);
4354 /*-----------------------------------------------------------------*/
4355 /* genIfx - generate code for Ifx statement */
4356 /*-----------------------------------------------------------------*/
4357 static void genIfx (iCode *ic, iCode *popIc)
4359 operand *cond = IC_COND(ic);
4362 aopOp(cond,ic,FALSE, TRUE);
4364 /* get the value into acc */
4365 if (AOP_TYPE(cond) != AOP_CRY)
4369 /* the result is now in the accumulator */
4370 freeAsmop(cond,NULL,ic);
4372 /* if there was something to be popped then do it */
4376 /* if the condition is a bit variable */
4377 if (isbit && IS_ITEMP(cond) &&
4379 genIfxJump(ic,SPIL_LOC(cond)->rname);
4381 if (isbit && !IS_ITEMP(cond))
4382 genIfxJump(ic,OP_SYMBOL(cond)->rname);
4389 /*-----------------------------------------------------------------*/
4390 /* genAddrOf - generates code for address of */
4391 /*-----------------------------------------------------------------*/
4392 static void genAddrOf (iCode *ic)
4394 symbol *sym = OP_SYMBOL(IC_LEFT(ic));
4396 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4398 /* if the operand is on the stack then we
4399 need to get the stack offset of this
4404 if (sym->stack <= 0) {
4405 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset);
4408 emit2("!ldahlsp", sym->stack + _G.stack.pushed + _G.stack.offset + _G.stack.param_offset);
4410 emitcode("ld", "d,h");
4411 emitcode("ld", "e,l");
4414 emit2("ld de,!hashedstr", sym->rname);
4416 aopPut(AOP(IC_RESULT(ic)), "e", 0);
4417 aopPut(AOP(IC_RESULT(ic)), "d", 1);
4422 /* if it has an offset then we need to compute it */
4424 emitcode("ld", "hl,#%d+%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset, _G.stack.param_offset);
4426 emitcode("ld", "hl,#%d+%d+%d", sym->stack, _G.stack.pushed, _G.stack.offset);
4427 emitcode("add", "hl,sp");
4430 emitcode("ld", "hl,#%s", sym->rname);
4432 aopPut(AOP(IC_RESULT(ic)), "l", 0);
4433 aopPut(AOP(IC_RESULT(ic)), "h", 1);
4435 freeAsmop(IC_RESULT(ic),NULL,ic);
4438 /*-----------------------------------------------------------------*/
4439 /* genAssign - generate code for assignment */
4440 /*-----------------------------------------------------------------*/
4441 static void genAssign (iCode *ic)
4443 operand *result, *right;
4445 unsigned long lit = 0L;
4447 result = IC_RESULT(ic);
4448 right = IC_RIGHT(ic) ;
4451 /* Dont bother assigning if they are the same */
4452 if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
4453 emitcode("", "; (operands are equal %u)", operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)));
4458 aopOp(right,ic,FALSE, FALSE);
4459 aopOp(result,ic,TRUE, FALSE);
4461 /* if they are the same registers */
4462 if (sameRegs(AOP(right),AOP(result))) {
4463 emitcode("", "; (registers are the same)");
4467 /* if the result is a bit */
4468 if (AOP_TYPE(result) == AOP_CRY) {
4473 size = AOP_SIZE(result);
4476 if(AOP_TYPE(right) == AOP_LIT)
4477 lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
4478 if (isPair(AOP(result))) {
4479 fetchPair(getPairId(AOP(result)), AOP(right));
4481 else if((size > 1) &&
4482 (AOP_TYPE(result) != AOP_REG) &&
4483 (AOP_TYPE(right) == AOP_LIT) &&
4484 !IS_FLOAT(operandType(right)) &&
4486 bool fXored = FALSE;
4488 /* Work from the top down.
4489 Done this way so that we can use the cached copy of 0
4490 in A for a fast clear */
4492 if((unsigned int)((lit >> (offset*8)) & 0x0FFL)== 0) {
4493 if (!fXored && size>1) {
4494 emitcode("xor", "a,a");
4498 aopPut(AOP(result),"a",offset);
4501 aopPut(AOP(result), zero, offset);
4506 aopGet(AOP(right),offset,FALSE),
4511 else if (size == 2 && requiresHL(AOP(right)) && requiresHL(AOP(result)) && IS_GB) {
4512 /* Special case. Load into a and d, then load out. */
4513 MOVA(aopGet(AOP(right), 0, FALSE));
4514 emitcode("ld", "e,%s", aopGet(AOP(right), 1, FALSE));
4515 aopPut(AOP(result), "a", 0);
4516 aopPut(AOP(result), "e", 1);
4519 /* PENDING: do this check better */
4520 if (requiresHL(AOP(right)) && requiresHL(AOP(result))) {
4521 MOVA(aopGet(AOP(right), offset, FALSE));
4522 aopPut(AOP(result), "a", offset);
4526 aopGet(AOP(right),offset,FALSE),
4533 freeAsmop(right,NULL,ic);
4534 freeAsmop(result,NULL,ic);
4537 /*-----------------------------------------------------------------*/
4538 /* genJumpTab - genrates code for jump table */
4539 /*-----------------------------------------------------------------*/
4540 static void genJumpTab (iCode *ic)
4545 aopOp(IC_JTCOND(ic),ic,FALSE, FALSE);
4546 /* get the condition into accumulator */
4547 l = aopGet(AOP(IC_JTCOND(ic)),0,FALSE);
4549 emitcode("push", "de");
4550 emitcode("ld", "e,%s", l);
4551 emit2("ld d,!zero");
4552 jtab = newiTempLabel(NULL);
4554 emit2("ld hl,!immed!tlabel", jtab->key+100);
4555 emitcode("add", "hl,de");
4556 emitcode("add", "hl,de");
4557 emitcode("add", "hl,de");
4558 freeAsmop(IC_JTCOND(ic),NULL,ic);
4560 emitcode("pop", "de");
4562 emitLabel(jtab->key+100);
4563 /* now generate the jump labels */
4564 for (jtab = setFirstItem(IC_JTLABELS(ic)) ; jtab;
4565 jtab = setNextItem(IC_JTLABELS(ic)))
4566 emit2("jp !tlabel", jtab->key+100);
4569 /*-----------------------------------------------------------------*/
4570 /* genCast - gen code for casting */
4571 /*-----------------------------------------------------------------*/
4572 static void genCast (iCode *ic)
4574 operand *result = IC_RESULT(ic);
4575 sym_link *ctype = operandType(IC_LEFT(ic));
4576 operand *right = IC_RIGHT(ic);
4579 /* if they are equivalent then do nothing */
4580 if (operandsEqu(IC_RESULT(ic),IC_RIGHT(ic)))
4583 aopOp(right,ic,FALSE, FALSE);
4584 aopOp(result,ic,FALSE, FALSE);
4586 /* if the result is a bit */
4587 if (AOP_TYPE(result) == AOP_CRY) {
4591 /* if they are the same size : or less */
4592 if (AOP_SIZE(result) <= AOP_SIZE(right)) {
4594 /* if they are in the same place */
4595 if (sameRegs(AOP(right),AOP(result)))
4598 /* if they in different places then copy */
4599 size = AOP_SIZE(result);
4603 aopGet(AOP(right),offset,FALSE),
4610 /* PENDING: should be OK. */
4612 /* if the result is of type pointer */
4613 if (IS_PTR(ctype)) {
4618 /* so we now know that the size of destination is greater
4619 than the size of the source */
4620 /* we move to result for the size of source */
4621 size = AOP_SIZE(right);
4625 aopGet(AOP(right),offset,FALSE),
4630 /* now depending on the sign of the destination */
4631 size = AOP_SIZE(result) - AOP_SIZE(right);
4632 /* Unsigned or not an integral type - right fill with zeros */
4633 if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
4635 aopPut(AOP(result),zero,offset++);
4637 /* we need to extend the sign :{ */
4638 char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
4641 emitcode("", "; genCast: sign extend untested.");
4642 emitcode("rla", "");
4643 emitcode("sbc", "a,a");
4645 aopPut(AOP(result),"a",offset++);
4649 freeAsmop(right, NULL, ic);
4650 freeAsmop(result, NULL, ic);
4653 /*-----------------------------------------------------------------*/
4654 /* genReceive - generate code for a receive iCode */
4655 /*-----------------------------------------------------------------*/
4656 static void genReceive (iCode *ic)
4658 if (isOperandInFarSpace(IC_RESULT(ic)) &&
4659 ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
4660 IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
4664 aopOp(IC_RESULT(ic),ic,FALSE, FALSE);
4666 assignResultValue(IC_RESULT(ic));
4669 freeAsmop(IC_RESULT(ic),NULL,ic);
4672 /*-----------------------------------------------------------------*/
4673 /* genZ80Code - generate code for Z80 based controllers */
4674 /*-----------------------------------------------------------------*/
4675 void genZ80Code (iCode *lic)
4682 _fReturn = _gbz80_return;
4683 _fTmp = _gbz80_return;
4686 _fReturn = _z80_return;
4687 _fTmp = _z80_return;
4689 tsprintf(zero, "!zero");
4691 lineHead = lineCurr = NULL;
4693 /* if debug information required */
4694 if (options.debug && currFunc) {
4695 cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
4697 if (IS_STATIC(currFunc->etype))
4698 emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name);
4700 emitcode("","G$%s$0$0 ==.",currFunc->name);
4703 /* stack pointer name */
4707 for (ic = lic ; ic ; ic = ic->next ) {
4709 if ( cln != ic->lineno ) {
4710 if ( options.debug ) {
4712 emitcode("","C$%s$%d$%d$%d ==.",
4713 ic->filename,ic->lineno,
4714 ic->level,ic->block);
4717 emitcode(";","%s %d",ic->filename,ic->lineno);
4720 /* if the result is marked as
4721 spilt and rematerializable or code for
4722 this has already been generated then
4724 if (resultRemat(ic) || ic->generated )
4727 /* depending on the operation */
4730 emitcode("", "; genNot");
4735 emitcode("", "; genCpl");
4740 emitcode("", "; genUminus");
4745 emitcode("", "; genIpush");
4750 /* IPOP happens only when trying to restore a
4751 spilt live range, if there is an ifx statement
4752 following this pop then the if statement might
4753 be using some of the registers being popped which
4754 would destory the contents of the register so
4755 we need to check for this condition and handle it */
4757 ic->next->op == IFX &&
4758 regsInCommon(IC_LEFT(ic),IC_COND(ic->next))) {
4759 emitcode("", "; genIfx");
4760 genIfx (ic->next,ic);
4763 emitcode("", "; genIpop");
4769 emitcode("", "; genCall");
4774 emitcode("", "; genPcall");
4779 emitcode("", "; genFunction");
4784 emitcode("", "; genEndFunction");
4785 genEndFunction (ic);
4789 emitcode("", "; genRet");
4794 emitcode("", "; genLabel");
4799 emitcode("", "; genGoto");
4804 emitcode("", "; genPlus");
4809 emitcode("", "; genMinus");
4814 emitcode("", "; genMult");
4819 emitcode("", "; genDiv");
4824 emitcode("", "; genMod");
4829 emitcode("", "; genCmpGt");
4830 genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));
4834 emitcode("", "; genCmpLt");
4835 genCmpLt (ic,ifxForOp(IC_RESULT(ic),ic));
4842 /* note these two are xlated by algebraic equivalence
4843 during parsing SDCC.y */
4844 werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
4845 "got '>=' or '<=' shouldn't have come here");
4849 emitcode("", "; genCmpEq");
4850 genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
4854 emitcode("", "; genAndOp");
4859 emitcode("", "; genOrOp");
4864 emitcode("", "; genXor");
4865 genXor (ic,ifxForOp(IC_RESULT(ic),ic));
4869 emitcode("", "; genOr");
4870 genOr (ic,ifxForOp(IC_RESULT(ic),ic));
4874 emitcode("", "; genAnd");
4875 genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
4879 emitcode("", "; genInline");
4884 emitcode("", "; genRRC");
4889 emitcode("", "; genRLC");
4894 emitcode("", "; genHBIT");
4898 emitcode("", "; genLeftShift");
4903 emitcode("", "; genRightShift");
4907 case GET_VALUE_AT_ADDRESS:
4908 emitcode("", "; genPointerGet");
4914 if (POINTER_SET(ic)) {
4915 emitcode("", "; genAssign (pointer)");
4919 emitcode("", "; genAssign");
4925 emitcode("", "; genIfx");
4930 emitcode("", "; genAddrOf");
4935 emitcode("", "; genJumpTab");
4940 emitcode("", "; genCast");
4945 emitcode("", "; genReceive");
4950 emitcode("", "; addSet");
4951 addSet(&sendSet,ic);
4956 /* piCode(ic,stdout); */
4962 /* now we are ready to call the
4963 peep hole optimizer */
4964 if (!options.nopeep)
4965 peepHole (&lineHead);
4967 /* This is unfortunate */
4968 /* now do the actual printing */
4970 FILE *fp = codeOutFile;
4971 if (isInHome() && codeOutFile == code->oFile)
4972 codeOutFile = home->oFile;
4973 printLine (lineHead, codeOutFile);
4974 if (_G.flush_statics) {
4976 _G.flush_statics = 0;