diff options
Diffstat (limited to 'bcc/preserve.c')
-rw-r--r-- | bcc/preserve.c | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/bcc/preserve.c b/bcc/preserve.c new file mode 100644 index 0000000..74b0f34 --- /dev/null +++ b/bcc/preserve.c @@ -0,0 +1,216 @@ +/* preserve.c - preserve opererands or registers in use for bcc */ + +/* Copyright (C) 1992 Bruce Evans */ + +#include "const.h" +#include "types.h" +#include "gencode.h" +#include "reg.h" +#include "type.h" + +/* change stack ptr without changing condition codes */ + +PUBLIC void changesp(newsp, absflag) +offset_t newsp; +bool_pt absflag; +{ + if (newsp != sp || ((bool_t) absflag && switchnow != NULL)) + { +#ifdef FRAMEPOINTER + if (newsp != framep || (!(bool_t) absflag && switchnow != NULL)) + { + outleasp(); + if (!(bool_t) absflag && switchnow != NULL) + outswoffset(newsp); + else + outoffset(newsp - framep); + outindframereg(); + outnl(); + } + else + regtransfer(FRAMEREG, STACKREG); + sp = newsp; + if (framep == 0) + bugerror("no frame pointer"); +#else +# ifdef I8088 + outleasp(); + outoffset(newsp - sp); + outindstackreg(); + outnl(); +# else + modstk(newsp); /* this should preserve CC */ +# endif +#endif /* FRAMEPOINTER */ + } +} + +/* load source to any while preserving target */ + +PUBLIC void loadpres(source, target) +struct symstruct *source; +struct symstruct *target; +{ + store_t regmark; + + if (target->storage & ALLDATREGS) + { + if (source->type->scalar & CHAR) + { + push(target); + load(source, DREG); + } + else + load(source, getindexreg()); + } + else + { + regmark = reguse; + reguse |= target->storage; + loadany(source); + reguse = regmark; + } +} + +/* change stack ptr */ + +PUBLIC void modstk(newsp) +offset_t newsp; +{ + if (newsp != sp) + { +#ifdef FRAMEPOINTER + if (newsp != framep || framep == 0 || switchnow != NULL) + addconst(newsp - sp, STACKREG); + else + regtransfer(FRAMEREG, STACKREG); +#else +# ifdef I8088 + addconst(newsp - sp, STACKREG); +# else + outleasp(); + outoffset(newsp - sp); + outncspregname(); +# endif +#endif + sp = newsp; + } +} + +/* preserve target without changing source */ + +PUBLIC void pres2(source, target) +struct symstruct *source; +struct symstruct *target; +{ + if (target->storage & allregs) + { + if (target->storage & (allregs - allindregs) /* XXX */ || + (target->indcount == 0 && + target->type->scalar & (DLONG | RSCALAR))) + push(target); /* XXX - perhaps not float */ + else if (((target->storage | reguse) & allindregs) == allindregs) + { + loadpres(target, source); + push(target); + } + else + reguse |= target->storage; + } +} + +/* preserve source */ + +PUBLIC void preserve(source) +struct symstruct *source; +{ + if (source->storage & allregs) + { + if (source->storage & (allregs - allindregs) /* XXX */ || + ((source->storage | reguse) & allindregs) == allindregs) + push(source); + else + reguse |= source->storage; + } +} + +/* preserve lvalue target without changing source or target */ + +PUBLIC store_pt preslval(source, target) +struct symstruct *source; +struct symstruct *target; +{ + store_pt regpushed; + + if (target->indcount == 0) + reguse &= ~target->storage; + else + reguse = (target->storage | reguse) & allindregs; + if (!((source->type->scalar | target->type->scalar) & (DLONG | RSCALAR)) + || reguse != allindregs) + return 0; /* XXX - perhaps not float */ + reguse = source->storage | target->storage; /* free one other than s/t */ + pushreg(regpushed = getindexreg()); + reguse = ~(store_t) regpushed & allindregs; + return regpushed; +} + +PUBLIC void recovlist(reglist) +store_pt reglist; +{ + poplist(reglist); + reguse |= (store_t) reglist; +} + +#ifdef I8088 +PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 2, 3, 0, 0, 0, 4, 5}; + /* CONSTANT, BREG, ax = DREG, bx = INDREG0, si = INDREG1, di = INDREG2 */ + /* LOCAL, GLOBAL, STACKREG, cx = DATREG1, dx = DATREG2 */ +#endif +#ifdef MC6809 +PRIVATE smalin_t regoffset[] = {0, 0, 0, 1, 3, 2}; + /* CONSTANT, BREG, DREG, XREG = INDREG0, UREG = INDREG1, YREG = INDREG2 */ +#endif + +PUBLIC void savereturn(savelist, saveoffset) +store_pt savelist; +offset_t saveoffset; +{ + store_t reg; + smalin_t *regoffptr; + offset_t spoffset; + + if (savelist == 0) + return; +#ifdef MC6809 /* must check this */ + if (savelist == XREG || savelist == INDREG1) + saveoffset -= accregsize; /* patch for DREG/YREG not saved */ +#endif + for (reg = 1, regoffptr = regoffset; reg != 0; ++regoffptr, reg <<= 1) + if (reg & savelist) + { + outstore(); + spoffset = saveoffset + *regoffptr * maxregsize; +#ifdef I8088 +# ifdef FRAMEPOINTER + if (switchnow != NULL) + outswoffset(spoffset); + else + outoffset(spoffset - framep); + outindframereg(); +# else + outoffset(spoffset - sp); + outindstackreg(); +# endif + outncregname(reg); +#endif +#ifdef MC6809 + if (reg == YREG) + bumplc(); + outregname(reg); + outtab(); + outoffset(spoffset - sp); + outncspregname(); +#endif + } +} |