void gencompactswitch(SNODE *stmt, struct cases *cs) { int tablab, size; AMODE *ap, *ap2; LLONG_TYPE i; tablab = nextlabel++; InitRegs(); size = natural_size(stmt->exp); if (size == BESZ_QWORD || size == - BESZ_QWORD) { ap = gen_expr_external(stmt->exp, FALSE, F_AXDX, BESZ_QWORD); if (cs->bottom) { gen_codes(op_sub, BESZ_DWORD, makedreg(EAX), make_immed(cs->bottom)); #if sizeof(LLONG_TYPE) == 4 gen_codes(op_sbb, BESZ_DWORD, makedreg(EDX), make_immed(cs->bottom < 0 ? - 1: 0)); #else gen_codes(op_sbb, BESZ_DWORD, makedreg(EDX), make_immed(cs->bottom >> 32)); #endif }
void genreturn(SNODE *stmt, int flag) /* * generate a return statement. */ { AMODE *ap,*ap1; int size; if( stmt != 0 && stmt->exp != 0 ) { initstack(); if (currentfunc->tp->btp && currentfunc->tp->btp->type != bt_void && (currentfunc->tp->btp->type == bt_struct || currentfunc->tp->btp->type == bt_union)) { size = currentfunc->tp->btp->size; ap = gen_expr(stmt->exp,F_ALL,4); if (!(save_mask & 0x40)) gen_push(ESI,am_dreg,0); if (!(save_mask & 0x80)) gen_push(EDI,am_dreg,0); if (prm_linkreg) { ap1 = xalloc(sizeof(AMODE)); ap1->preg = EBP; ap1->mode = am_indisp; if (currentfunc->pascaldefn && currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *) -1) ap1->offset = makenode(en_icon,(char *)(currentfunc->tp->lst.head->value.i+((currentfunc->tp->lst.head->tp->size+3) &0xFFFFFFFCL)),0); else ap1->offset = makenode(en_icon,(char *)8,0); } else if (currentfunc->pascaldefn && currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *) -1) ap1 = make_stack(-stackdepth-framedepth-currentfunc->tp->lst.head->value.i-((currentfunc->tp->lst.head->tp->size+3) & 0xfffffffcL)); else ap1 = make_stack(-stackdepth-framedepth); gen_code(op_mov,4,makedreg(ESI),ap); gen_code(op_mov,4,makedreg(EDI),ap1); gen_code(op_mov,4,makedreg(EAX),makedreg(EDI)); gen_code(op_mov,4,makedreg(ECX),make_immed(size)); gen_code(op_cld,0,0,0); gen_code(op_rep,1,0,0); gen_code(op_movsb,1,0,0); if (!(save_mask & 0x80)) gen_pop(EDI,am_dreg,0); if (!(save_mask & 0x40)) gen_pop(ESI,am_dreg,0); } else { size = currentfunc->tp->btp->size; ap = gen_expr(stmt->exp,F_DREG | F_FREG,size); if (size > 4) { if (ap->mode != am_freg) gen_code(op_fld,size,ap,0); } else if( ap->mode != am_dreg || ap->preg != 0 ) gen_code(op_mov,size,makedreg(0),ap); } freeop(ap); } if (flag) { if( retlab != -1 ) gen_label(retlab); if( fsave_mask != 0 ) diag("Float restore in return"); if (!prm_linkreg && lc_maxauto) gen_code(op_add,4,makedreg(ESP),make_immed(lc_maxauto)); if (currentfunc->intflag) { gen_code(op_popad,0,0,0); if (prm_linkreg && (lc_maxauto || currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1)) { gen_code(op_leave,0,0,0); } gen_code(op_iretd,0,0,0); } else { if( save_mask != 0 ) popregs(save_mask); if (prm_linkreg && (lc_maxauto || currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1)) { gen_code(op_leave,0,0,0); } if (currentfunc->pascaldefn) { long retsize = 0; if (currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1) { retsize = currentfunc->tp->lst.head->value.i+((currentfunc->tp->lst.head->tp->size + 3) & 0xfffffffcL); if (prm_linkreg) retsize -= 8; } if (currentfunc->tp->btp && currentfunc->tp->btp->type != bt_void && (currentfunc->tp->btp->type == bt_struct || currentfunc->tp->btp->type == bt_union)) retsize += 4; if (retsize) { gen_code(op_ret,0,make_immed(retsize),0); return; } } gen_code(op_ret,0,0,0); } } else { if (retlab == -1) retlab = nextlabel++; gen_code(op_jmp,0,make_label(retlab),0); } }
void loadregs(void) /* * initialize allocated registers */ { CSE *csp; ENODE *exptr; unsigned mask, rmask, i, fmask, frmask, size; AMODE *ap, *ap2; csp = olist; while (csp != 0) { int sz; if (csp->reg != - 1) { /* see if preload needed */ exptr = csp->exp; if (!lvalue(exptr) || ((SYM*)exptr->v.p[0]->v.p[0])->funcparm) { exptr = csp->exp; InitRegs(); sz = csp->size; ap = gen_expr_external(exptr, FALSE, F_MEM | F_DREG | F_IMMED, sz); if (csp->reg < 16) { if (ap->mode == am_dreg) peep_tail->oper1->preg = csp->reg; else { if (csp->reg > 3 && chksize(BESZ_WORD, sz)) DIAG("byte sized non-register in analyze"); ap2 = makedreg(csp->reg); ap2->length = BESZ_DWORD; if (ap->mode == am_immed || ap->length == BESZ_DWORD || ap ->length == - BESZ_DWORD) gen_codes(op_mov, BESZ_DWORD, ap2, ap); else if (sz < 0) gen_code(op_movsx, ap2, ap); else gen_code(op_movzx, ap2, ap); } } else if (csp->reg < 32) { if (ap->mode == am_dreg) peep_tail->oper1->preg = csp->reg - 12; else { if (csp->reg - 12 > 3 && chksize(BESZ_WORD, sz)) DIAG("byte sized non-register in analyze"); ap2 = makedreg(csp->reg - 12); ap2->length = BESZ_DWORD; if (ap->mode == am_immed || ap->length == BESZ_DWORD || ap ->length == - BESZ_DWORD) gen_codes(op_mov, BESZ_DWORD, ap2, ap); else if (sz < 0) gen_code(op_movsx, ap2, ap); else gen_code(op_movzx, ap2, ap); } } else { /* Should never get here */ DIAG("float reg assigned in analyze"); } if (lvalue(exptr) && ((SYM*)exptr->v.p[0]->v.p[0])->funcparm) { ((SYM*)exptr->v.p[0]->v.p[0])->mainsym->inreg = TRUE; ((SYM*)exptr->v.p[0]->v.p[0])->mainsym->value.i = - csp ->reg - (csp->size < 0 ? - csp->size: csp->size) *256; } } } csp = csp->next; } gen_label(startlab); }
void loadregs(void) /* * Initailze allocated regs * */ { CSE *csp; ENODE *exptr; unsigned mask, rmask,i,fmask,frmask,size; AMODE *ap, *ap2; csp = olist; while( csp != 0 ) { int sz; if( csp->reg != -1 ) { /* see if preload needed */ exptr = csp->exp; if( !lvalue(exptr) || ((SYM *)exptr->v.p[0]->v.p[0])->funcparm ) { exptr = csp->exp; initstack(); sz = csp->size; ap = gen_expr(exptr,F_ALL,sz); if (sz == 0 && ap->mode == am_immed) sz = 4; if( csp->reg < 16 ) { if (sz == 0 && ap->mode == am_immed) sz = 4; if (ap->mode == am_dreg) peep_tail->oper2->preg = csp->reg; else { ap2 = makedreg(csp->reg); gen_code(op_move,sz,ap,ap2); do_extend(ap2,sz,4,F_DREG); } } else if (csp->reg < 32) { if (sz == 0 && ap->mode == am_immed) sz = 4; if (ap->mode == am_areg) peep_tail->oper2->preg = csp->reg - 16; else { ap2 = makeareg(csp->reg - 16); gen_code(op_move,4,ap,ap2); } } else { if (sz == 0 && ap->mode == am_immed) sz = 8; if (ap->mode == am_freg) peep_tail->oper2->preg = csp->reg - 32; else { ap2 = makefreg(csp->reg - 32); size = 8; if (exptr->nodetype == en_floatref) size = 6; gen_code(op_fmove,size,ap,ap2); } } freeop(ap); if (lvalue(exptr) && ((SYM *)exptr->v.p[0]->v.p[0])->funcparm) { ((SYM *)exptr->v.p[0]->v.p[0])->inreg = TRUE; ((SYM *)exptr->v.p[0]->v.p[0])->value.i = -csp->reg; } } } csp = csp->next; } }
void allocate(int datareg, int addreg, int floatreg, SNODE *block) /* * allocate will allocate registers for the expressions that have * a high enough desirability. It also puts the function * header, consisting of saved registers and stack decrments for local * variables */ { CSE *csp; ENODE *exptr; unsigned mask, rmask, i, fmask, frmask, size; AMODE *ap, *ap2; mask = asmMask; rmask = asmRMask; fmask = frmask = 0; for (i = cf_freedata; i < datareg; i++) { rmask = rmask | (1 << (15-i)); mask = mask | (1 << i); } for (i = cf_freeaddress + 16; i < addreg; i++) { rmask = rmask | (1 << (23-i)); mask = mask | (1 << (i - 8)); } while (bsort(&olist)) ; /* sort the expression list */ csp = olist; while (csp != 0) { if (csp->reg == - 1 && !(csp->exp->cflags &DF_VOL) && !csp->voidf) { if (desire(csp) < 3) csp->reg = - 1; else { if (csp->exp->nodetype == en_rcon || csp->exp->nodetype == en_fcon || csp->exp->nodetype == en_lrcon || csp->exp ->nodetype == en_floatref || csp->exp->nodetype == en_doubleref || csp->exp->nodetype == en_longdoubleref || csp->exp->nodetype == en_fimaginarycon || csp->exp->nodetype == en_rimaginarycon || csp->exp->nodetype == en_lrimaginarycon || csp->exp->nodetype == en_fimaginaryref || csp->exp->nodetype == en_rimaginaryref || csp->exp->nodetype == en_lrimaginaryref) {} else if ((csp->duses <= csp->uses / 4) && (datareg < cf_maxdata) && dataregs) csp->reg = (datareg)++; else if (!(csp->size == 1 || csp->size == - 1 || csp->size == 5) && (addreg < cf_maxaddress) && addrregs) csp->reg = (addreg)++; else if ((datareg < cf_maxdata) && dataregs) csp->reg = (datareg)++; if (csp->reg != - 1) // if (lvalue(csp->exp)) // csp->seg = defseg(csp->exp->v.p[0]) ; // else if (!csp->seg) { csp->seg = defseg(csp->exp); if (csp->seg) csp->reg = -1; } } } if (csp->reg != - 1) { if (lvalue(csp->exp) && !((SYM*)csp->exp->v.p[0]->v.p[0])->funcparm) { ((SYM*)csp->exp->v.p[0]->v.p[0])->mainsym->inreg = TRUE; ((SYM*)csp->exp->v.p[0]->v.p[0])->mainsym->value.i = - csp ->reg - (csp->size < 0 ? - csp->size: csp->size) *256; } if (csp->reg < 16) { rmask = rmask | (1 << (15-csp->reg)); mask = mask | (1 << csp->reg); } if (csp->reg < 32) { rmask = rmask | (1 << (23-csp->reg)); mask = mask | (1 << (csp->reg - 8)); } else { frmask = frmask | (1 << (39-csp->reg)); fmask = fmask | (1 << (csp->reg - 32)); } } csp = csp->next; } allocstack(); /* Allocate stack space for the local vars */ floatstack_mode = 0; /* no space for floating point temps */ if (currentfunc->intflag || currentfunc->faultflag) { mask = 0; rmask = 0; if (currentfunc->loadds) loadds(); if (prm_farkeyword) { GenPush(ES + 24, am_dreg, 0); GenPush(FS + 24, am_dreg, 0); GenPush(GS + 24, am_dreg, 0); } gen_code(op_pushad, 0, 0); } if ((conscount || try_block_list || currentfunc->value.classdata.throwlist && currentfunc->value.classdata.throwlist->data) && prm_xcept) { xceptoffs = lc_maxauto += sizeof(XCEPTDATA); } if (prm_debug) { rmask = rmask | (1 << (15-EBX)); mask = mask | (1 << EBX); rmask = rmask | (1 << (15-ESI-4)); mask = mask | (1 << (ESI+4)); rmask = rmask | (1 << (15-EDI-4)); mask = mask | (1 << (EDI+4)); } if (prm_cplusplus && prm_xcept || (funcfloat || lc_maxauto || currentfunc ->tp->lst.head && currentfunc->tp->lst.head != (SYM*) - 1) || (currentfunc->value.classdata.cppflags &PF_MEMBER) && !(currentfunc ->value.classdata.cppflags &PF_STATIC) || !prm_smartframes || !stackframeoff) { /* enter is *really* inefficient so we will not use it */ if (!currentfunc->intflag) gen_codes(op_push, 4, makedreg(EBP), 0); gen_codes(op_mov, 4, makedreg(EBP), makedreg(ESP)); if (lc_maxauto) gen_code(op_sub, makedreg(ESP), make_immed(lc_maxauto)); // FIXME ... could auto-alloc an FP value when no frame! frame_ins = peep_tail; } else frame_ins = 0; if (mask != 0) PushRegs(rmask); save_mask = mask; if (fmask != 0) fsave_mask = fmask; if (currentfunc->loadds && !currentfunc->intflag) { loadds(); } if (prm_stackcheck && lc_maxauto) { AMODE *ap1; ap = set_symbol("__stackerror", 1); ap1 = set_symbol("__stackbottom", 0); ap1->mode = am_direct; gen_codes(op_cmp, 4, makedreg(ESP), ap1); gen_codes(op_jb, 0, ap, 0); } AddProfilerData(); if ((conscount || try_block_list || currentfunc->value.classdata.throwlist && currentfunc->value.classdata.throwlist->data) && prm_xcept) { currentfunc->value.classdata.conslabel = nextlabel++; currentfunc->value.classdata.destlabel = nextlabel++; gen_codes(op_mov, 4, makedreg(EAX), make_label(nextlabel - 2)); call_library("__InitExceptBlock"); gen_label(nextlabel - 1); } }