X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=src%2Fz80%2Fgen.c;h=281dc7baf33604390278b63dfe7b4cc5a983d4eb;hb=8b5bb80cd4be94a5da5af05c2abe67ab8c61939a;hp=263944333bdaaa71498bfe706485ceb4ab20ba9c;hpb=ed70c6e0de82527c2ee28c9c52a5eaf1b8f51650;p=fw%2Fsdcc diff --git a/src/z80/gen.c b/src/z80/gen.c index 26394433..281dc7ba 100644 --- a/src/z80/gen.c +++ b/src/z80/gen.c @@ -221,7 +221,8 @@ static struct bool in_home; const char *lastFunctionName; iCode *current_iCode; - + bool preserveCarry; + set *sendSet; struct @@ -235,6 +236,7 @@ static struct lineNode *head; lineNode *current; int isInline; + int isDebug; allocTrace trace; } lines; @@ -409,6 +411,7 @@ _vemit2 (const char *szFormat, va_list ap) (_G.lines.head = _newLineNode (buffer))); _G.lines.current->isInline = _G.lines.isInline; + _G.lines.current->isDebug = _G.lines.isDebug; _G.lines.current->ic = _G.current_iCode; } @@ -787,18 +790,34 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool requires_a) return aop; } - if (IS_GB) + if( IN_REGSP( space )) + { /*.p.t.20030716 minor restructure to add SFR support to the Z80 */ + if (IS_GB) { /* if it is in direct space */ - if (IN_REGSP (space) && !requires_a) - { - sym->aop = aop = newAsmop (AOP_SFR); - aop->aopu.aop_dir = sym->rname; - aop->size = getSize (sym->type); + if( !requires_a ) + { + sym->aop = aop = newAsmop (AOP_SFR); + aop->aopu.aop_dir = sym->rname; + aop->size = getSize (sym->type); emitDebug ("; AOP_SFR for %s", sym->rname); - return aop; - } + return aop; + } } + else + { /*.p.t.20030716 adding SFR support to the Z80 port */ + aop = newAsmop (AOP_SFR); + sym->aop = aop; + aop->aopu.aop_dir = sym->rname; + aop->size = getSize( sym->type ); + aop->paged = FUNC_REGBANK(sym->type); + aop->bcInUse = isPairInUse( PAIR_BC, ic ); + aop->deInUse = isPairInUse( PAIR_DE, ic ); + emitDebug( ";Z80 AOP_SFR for %s banked:%d bc:%d de:%d", sym->rname, FUNC_REGBANK(sym->type), aop->bcInUse, aop->deInUse ); + + return( aop ); + } + } /* only remaining is far space */ /* in which case DPTR gets the address */ @@ -991,6 +1010,11 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a) /* if already has a asmop then continue */ if (op->aop) { + if (op->aop->type == AOP_SFR) + { + op->aop->bcInUse = isPairInUse( PAIR_BC, ic ); + op->aop->deInUse = isPairInUse( PAIR_DE, ic ); + } return; } @@ -998,6 +1022,11 @@ aopOp (operand * op, iCode * ic, bool result, bool requires_a) if (IS_SYMOP (op) && OP_SYMBOL (op)->aop) { op->aop = OP_SYMBOL (op)->aop; + if (op->aop->type == AOP_SFR) + { + op->aop->bcInUse = isPairInUse( PAIR_BC, ic ); + op->aop->deInUse = isPairInUse( PAIR_DE, ic ); + } return; } @@ -1479,6 +1508,12 @@ setupPairFromSP (PAIR_ID id, int offset) { wassertl (id == PAIR_HL, "Setup relative to SP only implemented for HL"); + if (_G.preserveCarry) + { + _push (PAIR_AF); + offset += 2; + } + if (offset < INT8MIN || offset > INT8MAX) { emit2 ("ld hl,!immedword", offset); @@ -1486,7 +1521,13 @@ setupPairFromSP (PAIR_ID id, int offset) } else { - emit2 ("!ldahlsp", offset); + emit2 ("!ldahlsp", offset); + } + + if (_G.preserveCarry) + { + _pop (PAIR_AF); + offset -= 2; } } @@ -1522,11 +1563,15 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset) else { /* PENDING: Do this better. */ + if (_G.preserveCarry) + _push (PAIR_AF); sprintf (buffer, "%d", offset + _G.stack.pushed); emit2 ("ld %s,!hashedstr", _pairs[pairId].name, buffer); emit2 ("add %s,sp", _pairs[pairId].name); _G.pairs[pairId].last_type = aop->type; _G.pairs[pairId].offset = offset; + if (_G.preserveCarry) + _pop (PAIR_AF); } } break; @@ -1627,11 +1672,35 @@ aopGet (asmop * aop, int offset, bool bit16) return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); case AOP_SFR: - wassert (IS_GB); - emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset); - SNPRINTF (buffer, sizeof(buffer), "a"); + if( IS_GB ) + { + // wassert (IS_GB); + emit2 ("ldh a,(%s+%d)", aop->aopu.aop_dir, offset); + SNPRINTF (buffer, sizeof(buffer), "a"); - return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); + } + else + { /*.p.t.20030716 handling for i/o port read access for Z80 */ + if( aop->paged ) + { /* banked mode */ + /* reg A goes to address bits 15-8 during "in a,(x)" instruction */ + emit2( "ld a,!msbimmeds", aop->aopu.aop_dir); + emit2( "in a,(!lsbimmeds)", aop->aopu.aop_dir); + } + else if( z80_opts.port_mode == 180 ) + { /* z180 in0/out0 mode */ + emit2( "in0 a,(%s)", aop->aopu.aop_dir ); + } + else + { /* 8 bit mode */ + emit2( "in a,(%s)", aop->aopu.aop_dir ); + } + + SNPRINTF (buffer, sizeof(buffer), "a"); + + return traceAlloc(&_G.trace.aops, Safe_strdup(buffer)); + } case AOP_REG: return aop->aopu.aop_reg[offset]->name; @@ -1796,10 +1865,49 @@ aopPut (asmop * aop, const char *s, int offset) break; case AOP_SFR: - wassert (IS_GB); - if (strcmp (s, "a")) - emit2 ("ld a,%s", s); - emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset); + if( IS_GB ) + { + // wassert (IS_GB); + if (strcmp (s, "a")) + emit2 ("ld a,%s", s); + emit2 ("ldh (%s+%d),a", aop->aopu.aop_dir, offset); + } + else + { /*.p.t.20030716 handling for i/o port read access for Z80 */ + if( aop->paged ) + { /* banked mode */ + if( aop->bcInUse ) emit2( "push bc" ); + + emit2( "ld bc,#%s", aop->aopu.aop_dir ); + + if(( s[0] == '#' ) /* immediate number */ + ||( s[0] == '(' ) /* indirect register (ix or iy ??)*/ + ||( isdigit( s[0] )))/* indirect register with offset (ix or iy ??)*/ + { + emit2( "ld a,%s", s ); + emit2( "out (c),a" ); + } + else + { + emit2( "out (c),%s", s ); + } + + if( aop->bcInUse ) + emit2( "pop bc" ); + else + spillPair (PAIR_BC); + } + else if( z80_opts.port_mode == 180 ) + { /* z180 in0/out0 mode */ + emit2( "ld a,%s", s ); + emit2( "out0 (%s),a", aop->aopu.aop_dir ); + } + else + { /* 8 bit mode */ + emit2( "ld a,%s", s ); + emit2( "out (%s),a", aop->aopu.aop_dir ); + } + } break; case AOP_REG: @@ -1955,7 +2063,7 @@ aopPut (asmop * aop, const char *s, int offset) #define AOP(op) op->aop #define AOP_TYPE(op) AOP(op)->type #define AOP_SIZE(op) AOP(op)->size -#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY)) +#define AOP_NEEDSACC(x) (AOP(x) && ((AOP_TYPE(x) == AOP_CRY) || (AOP_TYPE(x) == AOP_SFR))) static void commitPair (asmop * aop, PAIR_ID id) @@ -3083,8 +3191,9 @@ genFunction (iCode * ic) emit2 ("!enterxl", sym->stack); else if (sym->stack) emit2 ("!enterx", sym->stack); - else + else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */ emit2 ("!enter"); + _G.stack.offset = sym->stack; } @@ -3120,7 +3229,7 @@ genEndFunction (iCode * ic) { emit2 ("!leavex", _G.stack.offset); } - else + else if( !FUNC_ISNAKED( sym->type )) /*.p.t.20030716 - now supporting Naked funcitons */ { emit2 ("!leave"); } @@ -3143,7 +3252,22 @@ genEndFunction (iCode * ic) } - /* Both baned and non-banked just ret */ + if (options.debug && currFunc) + { + _G.lines.isDebug = 1; + sprintf (buffer, "C$%s$%d$%d$%d", + FileBaseName (ic->filename), currFunc->lastLine, + ic->level, ic->block); + emit2 ("!labeldef", buffer); + if (IS_STATIC (currFunc->etype)) + sprintf (buffer, "XF%s$%s$0$0", moduleName, currFunc->name); + else + sprintf (buffer, "XG$%s$0$0", currFunc->name); + emit2 ("!labeldef", buffer); + _G.lines.isDebug = 0; + } + + /* Both banked and non-banked just ret */ emit2 ("ret"); sprintf (buffer, "%s_end", sym->rname); @@ -3464,7 +3588,10 @@ setupToPreserveCarry (asmop *result, asmop *left, asmop *right) } else if (couldDestroyCarry (right)) { - shiftIntoPair (0, right); + if (getPairId (result) == PAIR_HL) + _G.preserveCarry = TRUE; + else + shiftIntoPair (0, right); } else if (couldDestroyCarry (result)) { @@ -3498,7 +3625,7 @@ genPlus (iCode * ic) in ACC */ if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) || - (AOP_NEEDSACC (IC_LEFT (ic))) || + (AOP_NEEDSACC (IC_RIGHT (ic))) || AOP_TYPE (IC_RIGHT (ic)) == AOP_ACC) { operand *t = IC_RIGHT (ic); @@ -3695,6 +3822,7 @@ genPlus (iCode * ic) } release: + _G.preserveCarry = FALSE; freeAsmop (IC_LEFT (ic), NULL, ic); freeAsmop (IC_RIGHT (ic), NULL, ic); freeAsmop (IC_RESULT (ic), NULL, ic); @@ -3898,6 +4026,7 @@ genMinus (iCode * ic) } release: + _G.preserveCarry = FALSE; freeAsmop (IC_LEFT (ic), NULL, ic); freeAsmop (IC_RIGHT (ic), NULL, ic); freeAsmop (IC_RESULT (ic), NULL, ic); @@ -3913,11 +4042,14 @@ genMult (iCode * ic) int count, i; /* If true then the final operation should be a subtract */ bool active = FALSE; + bool byteResult; /* Shouldn't occur - all done through function calls */ aopOp (IC_LEFT (ic), ic, FALSE, FALSE); aopOp (IC_RIGHT (ic), ic, FALSE, FALSE); aopOp (IC_RESULT (ic), ic, TRUE, FALSE); + + byteResult = (AOP_SIZE (IC_RESULT (ic)) == 1); if (AOP_SIZE (IC_LEFT (ic)) > 2 || AOP_SIZE (IC_RIGHT (ic)) > 2 || @@ -3948,10 +4080,13 @@ genMult (iCode * ic) if ( AOP_SIZE (IC_LEFT (ic)) == 1 && !SPEC_USIGN (getSpec (operandType ( IC_LEFT (ic))))) { emit2 ("ld e,%s", aopGet (AOP (IC_LEFT (ic)), LSB, FALSE)); - emit2 ("ld a,e"); - emit2 ("rlc a"); - emit2 ("sbc a,a"); - emit2 ("ld d,a"); + if (!byteResult) + { + emit2 ("ld a,e"); + emit2 ("rlc a"); + emit2 ("sbc a,a"); + emit2 ("ld d,a"); + } } else { @@ -3973,7 +4108,8 @@ genMult (iCode * ic) if (active == FALSE) { emit2 ("ld l,e"); - emit2 ("ld h,d"); + if (!byteResult) + emit2 ("ld h,d"); } else { @@ -3992,7 +4128,10 @@ genMult (iCode * ic) _G.stack.pushedDE = FALSE; } - commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); + if (byteResult) + aopPut (AOP (IC_RESULT (ic)), _pairs[PAIR_HL].l, 0); + else + commitPair ( AOP (IC_RESULT (ic)), PAIR_HL); freeAsmop (IC_LEFT (ic), NULL, ic); freeAsmop (IC_RIGHT (ic), NULL, ic); @@ -4862,7 +5001,7 @@ genAnd (iCode * ic, iCode * ifx) /* if left is a literal & right is not then exchange them */ if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) || - AOP_NEEDSACC (left)) + (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left))) { operand *tmp = right; right = left; @@ -5052,7 +5191,7 @@ genOr (iCode * ic, iCode * ifx) /* if left is a literal & right is not then exchange them */ if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) || - AOP_NEEDSACC (left)) + (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left))) { operand *tmp = right; right = left; @@ -5210,7 +5349,7 @@ genXor (iCode * ic, iCode * ifx) /* if left is a literal & right is not then exchange them */ if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) || - AOP_NEEDSACC (left)) + (AOP_NEEDSACC (right) && !AOP_NEEDSACC (left))) { operand *tmp = right; right = left; @@ -5287,9 +5426,9 @@ genXor (iCode * ic, iCode * ifx) continue; else { - _moveA (aopGet (AOP (right), offset, FALSE)); + _moveA (aopGet (AOP (left), offset, FALSE)); emit2 ("xor a,%s", - aopGet (AOP (left), offset, FALSE)); + aopGet (AOP (right), offset, FALSE)); aopPut (AOP (result), "a", offset); } } @@ -5301,9 +5440,9 @@ genXor (iCode * ic, iCode * ifx) } else { - _moveA (aopGet (AOP (right), offset, FALSE)); + _moveA (aopGet (AOP (left), offset, FALSE)); emit2 ("xor a,%s", - aopGet (AOP (left), offset, FALSE)); + aopGet (AOP (right), offset, FALSE)); aopPut (AOP (result), "a", offset); } } @@ -5339,9 +5478,9 @@ genXor (iCode * ic, iCode * ifx) } else { - _moveA (aopGet (AOP (right), offset, FALSE)); + _moveA (aopGet (AOP (left), offset, FALSE)); emit2 ("xor a,%s", - aopGet (AOP (left), offset, FALSE)); + aopGet (AOP (right), offset, FALSE)); } aopPut (AOP (result), "a", offset); } @@ -7116,24 +7255,44 @@ genReceive (iCode * ic) static void genDummyRead (iCode * ic) { - operand *right; + operand *op; int size, offset; - right = IC_RIGHT (ic); - aopOp (right, ic, FALSE, FALSE); + op = IC_RIGHT (ic); + if (op && IS_SYMOP (op)) + { + aopOp (op, ic, FALSE, FALSE); - /* general case */ - size = AOP_SIZE (right); - offset = 0; + /* general case */ + size = AOP_SIZE (op); + offset = 0; - while (size--) - { - _moveA (aopGet (AOP (right), offset, FALSE)); - offset++; + while (size--) + { + _moveA (aopGet (AOP (op), offset, FALSE)); + offset++; + } + + freeAsmop (op, NULL, ic); } + + op = IC_LEFT (ic); + if (op && IS_SYMOP (op)) + { + aopOp (op, ic, FALSE, FALSE); + + /* general case */ + size = AOP_SIZE (op); + offset = 0; -release: - freeAsmop (right, NULL, ic); + while (size--) + { + _moveA (aopGet (AOP (op), offset, FALSE)); + offset++; + } + + freeAsmop (op, NULL, ic); + } } enum @@ -7672,13 +7831,36 @@ genZ80Code (iCode * lic) } _G.lines.head = _G.lines.current = NULL; + + /* if debug information required */ + if (options.debug && currFunc) + { + debugFile->writeFunction(currFunc); + _G.lines.isDebug = 1; + if (IS_STATIC (currFunc->etype)) + sprintf (buffer, "F%s$%s$0$0", moduleName, currFunc->name); + else + sprintf (buffer, "G$%s$0$0", currFunc->name); + emit2 ("!labeldef", buffer); + _G.lines.isDebug = 0; + } for (ic = lic; ic; ic = ic->next) { _G.current_iCode = ic; - if (cln != ic->lineno) + if (ic->lineno && cln != ic->lineno) { + if (options.debug) + { + _G.lines.isDebug = 1; + sprintf (buffer, "C$%s$%d$%d$%d", + FileBaseName (ic->filename), ic->lineno, + ic->level, ic->block); + emit2 ("%s !equ .", buffer); + emit2 ("!global", buffer); + _G.lines.isDebug = 0; + } if (!options.noCcodeInAsm) { emit2 (";%s:%d: %s", ic->filename, ic->lineno, printCLine(ic->filename, ic->lineno));