void GenerateThrow(Statement *stmt) { AMODE *ap; if( stmt != NULL && stmt->exp != NULL ) { initstack(); ap = GenerateExpression(stmt->exp,F_ALL,8); if (ap->mode==am_immed) { if (isFISA64) FISA64_GenLdi(makereg(1),ap,8); else GenerateTriadic(op_ori,0,makereg(1),makereg(0),ap); } else if( ap->mode != am_reg) GenerateDiadic(op_lw,0,makereg(1),ap); else if (ap->preg != 1 ) GenerateTriadic(op_or,0,makereg(1),ap,makereg(0)); ReleaseTempRegister(ap); if (isFISA64) FISA64_GenLdi(makereg(2),make_immed((int64_t)stmt->label),8); else GenerateTriadic(op_ori,0,makereg(2),makereg(0),make_immed((int64_t)stmt->label)); } GenerateMonadic(isThor?op_br:op_bra,0,make_clabel(throwlab)); }
SYMBOL *gen_mp_virtual_thunk(SYMBOL *vsp) { QUAD *oi = intermed_head, *ot = intermed_tail; LIST *v = mpthunklist; SYMBOL *sp; IMODE *ap1, *ap2; char buf[256]; while (v) { sp = (SYMBOL*)v->data; if (sp->value.i == vsp->value.classdata.vtabindex) if (isstructured(vsp->tp->btp) == isstructured(sp->tp->btp)) return sp; v = v->link; } intermed_head = intermed_tail = NULL; blockMax = 0; blockCount = tempCount = 0; exitBlock = 0; IncGlobalFlag(); sp = Alloc(sizeof(SYMBOL)); sp->storage_class = sc_static; sp->tp = vsp->tp; sp->value.i = vsp->value.classdata.vtabindex; //sprintf(buf, "@$mpt$%d$%d", sp->value.i, isstructured(sp->tp->btp)); sp->name = sp->decoratedName = litlate(buf); sp->errname = sp->decoratedName; sp->staticlabel = FALSE; sp->gennedvirtfunc = TRUE; v = (LIST *)Alloc(sizeof(LIST)); v->data = sp; v->link = mpthunklist; mpthunklist = v; DecGlobalFlag(); gen_virtual(sp, FALSE); addblock(i_goto); gen_icode(i_substack, NULL, ap2 = tempreg(ISZ_ADDR, 0), NULL); gen_icode(i_add, ap2, ap2 , make_immed(ISZ_NONE, isstructured(sp->tp->btp) ? ISZ_ADDR * 2 : ISZ_ADDR)); ap1 = indnode(ap2, ISZ_ADDR); gen_icode(i_assn, ap2 = tempreg(ISZ_ADDR, 0), ap1, 0); if (sp->value.classdata.baseofs) gen_icode(i_add, ap2, ap2, make_immed(ISZ_NONE, sp->value.classdata.baseofs)); ap1 = indnode(ap2, ISZ_ADDR); gen_icode(i_assn, ap2 = tempreg(ISZ_ADDR, 0), ap1, 0); gen_icode(i_add, ap2, ap2, make_immed(ISZ_NONE, sp->value.i)); ap1 = indnode(ap2, ISZ_ADDR); gen_icode(i_directbranch, 0, ap1, 0); addblock(i_ret); optimize(); rewrite_icode(); /* Translate to machine code & dump */ if (chosenAssembler->gen->post_function_gen) chosenAssembler->gen->post_function_gen(intermed_head); gen_endvirtual(sp); intermed_head = oi; intermed_tail = ot; return sp; }
void gencompactswitch(SNODE *stmt, int deflab) { int tablab,curlab,i, size = natural_size(stmt->exp); AMODE *ap,*ap2; long switchbottom=gswitchbottom, switchcount=gswitchcount; long switchtop=gswitchtop; int *switchlabels=0; tablab = nextlabel++; curlab = nextlabel++; initstack(); ap = gen_expr(stmt->exp,F_DREG | F_VOL,4); initstack(); if (switchbottom) gen_code(op_sub,4,ap,make_immed(switchbottom)); if (size < 0) gen_code(op_jl,0,make_label(deflab),0); else gen_code(op_jb,0,make_label(deflab),0); gen_code(op_cmp,4,ap,make_immed(switchtop-switchbottom)); if (size < 0) gen_code(op_jge,0,make_label(deflab),0); else gen_code(op_jnc,0,make_label(deflab),0); gen_code(op_shl,4,ap,make_immed(2)); ap2 = xalloc(sizeof(AMODE)); ap->mode = am_indisp; ap2->preg = ap->preg; ap->offset = makenode(en_labcon,(char *)tablab,0); gen_code(op_jmp,4,ap,0); initstack(); align(4); gen_label(tablab); switchlabels = xalloc((switchtop-switchbottom) * sizeof(int)); for (i=switchbottom; i < switchtop; i++) { switchlabels[i-switchbottom] = deflab; } stmt = stmt->s1; while (stmt) { if( stmt->s2 ) /* default case ? */ { stmt->label = (SNODE *)deflab; diddef = TRUE; } else { switchlabels[(int)stmt->label-switchbottom] = curlab; stmt->label = (SNODE *)curlab; } if(stmt->next != 0 ) curlab = nextlabel++; stmt = stmt->next; } for (i=0; i < switchtop-switchbottom; i++) gen_code(op_dd,4,make_label(switchlabels[i]),0); }
void genxswitch(STATEMENT *stmt, SYMBOL *funcsp) /* * analyze and generate best switch statement. */ { int oldbreak, i; struct cases cs; IMODE *ap, *ap3; #ifdef USE_LONGLONG ULLONG_TYPE a = 1; #endif oldbreak = breaklab; breaklab = stmt->breaklabel; memset(&cs,0,sizeof(cs)); #ifndef USE_LONGLONG cs.top = INT_MIN; cs.bottom = INT_MAX; #else cs.top = (a << 63); /* LLONG_MIN*/ cs.bottom = cs.top - 1; /* LLONG_MAX*/ #endif count_cases(stmt->cases,&cs) ; cs.top++; ap3 = gen_expr(funcsp, stmt->select, F_VOL | F_NOVALUE, ISZ_UINT); ap = LookupLoadTemp(NULL, ap3); if (ap != ap3) { IMODE *barrier; if (stmt->select->isatomic) { barrier = doatomicFence(funcsp, stmt->select, NULL); } gen_icode(i_assn, ap, ap3, NULL); if (stmt->select->isatomic) { doatomicFence(funcsp, stmt->select, barrier); } } gen_icode2(i_coswitch, make_immed(ISZ_NONE,cs.count), ap, make_immed(ISZ_NONE,cs.top - cs.bottom), stmt->label); gather_cases(stmt->cases,&cs); qsort(cs.ptrs, cs.count, sizeof(cs.ptrs[0]), gcs_compare); for (i = 0; i < cs.count; i++) { gen_icode2(i_swbranch,0,make_immed(ISZ_NONE,cs.ptrs[i].id),0,cs.ptrs[i].label); } breaklab = oldbreak; }
// Generate a function body. // void GenerateFunction(SYM *sym, Statement *stmt) { char buf[20]; char *bl; throwlab = retlab = contlab = breaklab = -1; lastsph = 0; memset(semaphores,0,sizeof(semaphores)); throwlab = nextlabel++; while( lc_auto & 7 ) /* round frame size to word */ ++lc_auto; if (sym->IsInterrupt) { //GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(30*8)); //GenerateDiadic(op_sm,0,make_indirect(30), make_mask(0x9FFFFFFE)); } if (!sym->IsNocall) { GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(24)); // For a leaf routine don't bother to store the link register or exception link register. if (sym->IsLeaf) GenerateDiadic(op_sw,0,makereg(27),make_indirect(30)); else { GenerateDiadic(op_sw, 0, makereg(27), make_indexed(0,30)); GenerateDiadic(op_sw, 0, makereg(28), make_indexed(8,30)); GenerateDiadic(op_sw, 0, makereg(31), make_indexed(16,30)); GenerateDiadic(op_lea,0,makereg(28),make_label(throwlab)); } GenerateDiadic(op_mov,0,makereg(27),makereg(30)); if (lc_auto) GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(lc_auto)); } if (optimize) opt1(stmt); GenerateStatement(stmt); GenerateReturn(sym,0); // Generate code for the hidden default catch GenerateLabel(throwlab); if (sym->IsLeaf){ if (sym->DoesThrow) { GenerateDiadic(op_mov,0,makereg(31),makereg(28)); GenerateDiadic(op_bra,0,make_label(retlab),NULL); // goto regular return cleanup code } } else { GenerateDiadic(op_lw,0,makereg(31),make_indexed(8,27)); // load throw return address from stack into LR GenerateDiadic(op_sw,0,makereg(31),make_indexed(16,27)); // and store it back (so it can be loaded with the lm) GenerateDiadic(op_bra,0,make_label(retlab),NULL); // goto regular return cleanup code } }
/* * generate shift equals operators. */ AMODE *GenerateAssignShift(ENODE *node,int flags,int size,int op) { struct amode *ap1, *ap2, *ap3; ap1 = GetTempRegister(); //size = GetNaturalSize(node->p[0]); ap3 = GenerateExpression(node->p[0],F_ALL,size); ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,size); if (ap3->mode==am_reg) GenerateDiadic(op_mov,0,ap1,ap3); else if (ap3->mode == am_immed) { error(ERR_LVALUE); if (isFISA64) FISA64_GenLdi(ap1,ap2); else GenerateDiadic(op_ldi,0,ap1,ap3); } else GenLoad(ap1,ap3,size); MaskShift(op, ap1, size); if (ap2->mode==am_immed) GenerateTriadic(op,0,ap1,ap1,make_immed(ap2->offset->i)); else GenerateTriadic(op,0,ap1,ap1,ap2); if (ap3->mode != am_reg) GenStore(ap1,ap3,size); ReleaseTempRegister(ap2); ReleaseTempRegister(ap3); MakeLegalAmode(ap1,flags,size); return ap1; }
AMODE *GenerateShift(ENODE *node,int flags, int size, int op) { AMODE *ap1, *ap2, *ap3; ap3 = GetTempRegister(); ap1 = GenerateExpression(node->p[0],F_REG,size); ap2 = GenerateExpression(node->p[1],F_REG | F_IMMED,8); MaskShift(op, ap1, GetNaturalSize(node->p[0])); if (ap2->mode==am_immed) { switch(op) { case op_asl: op = op_asli; break; case op_sll: op = op_slli; break; case op_shl: op = op_shli; break; case op_shlu: op = op_shlui; break; case op_asr: op = isThor?op_shri:op_asri; break; case op_sra: op = op_srai; break; case op_shr: op = op_shri; break; case op_shru: op = op_shrui; break; case op_srl: op = op_srli; break; case op_lsr: op = op_lsri; break; } GenerateTriadic(op,0,ap3,ap1,make_immed(ap2->offset->i)); } else GenerateTriadic(op,0,ap3,ap1,ap2); ReleaseTempRegister(ap2); ReleaseTempRegister(ap1); MakeLegalAmode(ap3,flags,size); return ap3; }
/* Assums the dseg is the next higher seg value from the cseg */ void loadds(void) { gen_code(op_push, makesegreg(DS), 0); gen_code(op_push, makesegreg(CS), 0); gen_codes(op_add, 2, make_stack(0), make_immed(8)); gen_code(op_pop, makesegreg(DS), 0); }
void bingen(int lower, int avg, int higher,AMODE *ap1, int deflab, int size,long * switchids,int * switchlabels,int *switchbinlabels) { AMODE *ap2 = make_immed(switchids[avg]); AMODE *ap3 = make_label(switchlabels[avg]); if (switchbinlabels[avg] != -1) gen_label(switchbinlabels[avg]); gen_code(op_cmp,4,ap1,ap2); gen_code(op_je,0,ap3,0); if (avg == lower) { ap3 = make_label(deflab); gen_code(op_jmp,0,ap3,0); } else { int avg1 = (lower + avg)/2; int avg2 = (higher + avg+1)/2; if (avg+1 < higher) ap3 = make_label(switchbinlabels[avg2]=nextlabel++); else ap3 = make_label(deflab); if (size < 0) gen_code(op_jg,0,ap3,0); else gen_code(op_ja,0,ap3,0); bingen(lower,avg1,avg,ap1,deflab,size,switchids,switchlabels,switchbinlabels); if (avg+1 < higher) bingen(avg+1,avg2,higher,ap1,deflab,size,switchids,switchlabels,switchbinlabels); } }
void bingen(int lower, int avg, int higher, AMODE *ap1, struct cases *cs, int size) { AMODE *ap2 = make_immed(cs->ptrs[avg].id); AMODE *ap3 = make_label(cs->ptrs[avg].label); if (cs->ptrs[avg].binlabel != - 1) gen_label(cs->ptrs[avg].binlabel); gen_coden(op_cmp, size, ap1, ap2); gen_code(op_je, ap3, 0); if (avg == lower) { if (cs->deflab < 0) cs->deflab = nextlabel++; ap3 = make_label(cs->deflab); gen_code(op_jmp, ap3, 0); } else { int avg1 = (lower + avg) / 2; int avg2 = (higher + avg + 1) / 2; if (avg + 1 < higher) ap3 = make_label(cs->ptrs[avg2].binlabel = nextlabel++); else ap3 = make_label(cs->deflab); if (size < 0) gen_code(op_jg, ap3, 0); else gen_code(op_ja, ap3, 0); bingen(lower, avg1, avg, ap1, cs, size); if (avg + 1 < higher) bingen(avg + 1, avg2, higher, ap1, cs, size); } }
void gen_genword(STATEMENT *stmt, SYMBOL *funcsp) /* * generate data in the code seg */ { (void)funcsp; gen_icode(i_genword, 0, make_immed(ISZ_NONE,(int)stmt->select), 0); }
AMODE *GenerateFunctionCall(ENODE *node, int flags) { AMODE *ap, *result; SYM *sym; int i; int msk; msk = SaveTempRegs(); sym = NULL; i = GeneratePushParameterList(node->p[1]); // Call the function if( node->p[0]->nodetype == en_nacon ) { GenerateDiadic(op_call,0,make_offset(node->p[0]),NULL); sym = gsearch(node->p[0]->sp); } else { ap = GenerateExpression(node->p[0],F_REG,8); ap->mode = am_ind; GenerateDiadic(op_jal,0,makereg(31),ap); ReleaseTempRegister(ap); } // Pop parameters off the stack if (i!=0) { if (sym) { if (!sym->IsPascal) GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(i * 8)); } else GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(i * 8)); } RestoreTempRegs(msk); result = GetTempRegister(); if( result->preg != 1 || (flags & F_REG) == 0 ) if (sym) { if (sym->tp->btp->type==bt_void) ; else GenerateDiadic(op_mov,0,result,makereg(1)); } else GenerateDiadic(op_mov,0,result,makereg(1)); return result; }
SYMBOL *gen_vsn_virtual_thunk(SYMBOL *func, int ofs) { QUAD *oi = intermed_head, *ot = intermed_tail; SYMBOL *sp; IMODE *ap1, *ap2; char buf[256]; //sprintf(buf, "@$vsn%s$%d", func->decoratedName, ofs); sp = search(buf, gsyms); if (sp) return sp; intermed_head = intermed_tail = NULL; blockMax = 0; blockCount = tempCount = 0; exitBlock = 0; IncGlobalFlag(); sp = Alloc(sizeof(SYMBOL)); sp->storage_class = sc_static; sp->value.i = ofs; sp->name = sp->decoratedName = litlate(buf); sp->errname = sp->decoratedName; sp->staticlabel = FALSE; sp->tp = func->tp; sp->gennedvirtfunc = TRUE; insert(sp, gsyms); DecGlobalFlag(); gen_virtual(sp, FALSE); addblock(i_goto); gen_icode(i_substack, NULL, ap2 = tempreg(ISZ_ADDR, 0), NULL ); gen_icode(i_add, ap1 = tempreg(ISZ_ADDR, 0), ap2, make_immed(ISZ_NONE, getSize(bt_pointer))); ap1 = indnode(ap1, ISZ_ADDR); gen_icode(i_add, ap1, ap1 , make_immed(ISZ_NONE, - ofs)); ap1 = make_imaddress(varNode(en_napccon, func), ISZ_ADDR); gen_icode(i_directbranch, 0, ap1, 0); addblock(i_ret); optimize(); rewrite_icode(); /* Translate to machine code & dump */ if (chosenAssembler->gen->post_function_gen) chosenAssembler->gen->post_function_gen(intermed_head); gen_endvirtual(sp); intermed_head = oi; intermed_tail = ot; return sp; }
AMODE *GenerateFunctionCall(ENODE *node, int flags) { AMODE *ap, *result; SYM *sym; int i; int msk; int sp; //msk = SaveTempRegs(); sp = TempInvalidate(); sym = (SYM*)NULL; i = GeneratePushParameterList(node->p[1]); // Call the function if( node->p[0]->nodetype == en_cnacon ) { GenerateMonadic(op_jsr,0,make_offset(node->p[0])); sym = gsearch(node->p[0]->sp); } else { ap = GenerateExpression(node->p[0],F_BREG,8); ap->mode = am_brind; GenerateDiadic(op_jsr,0,makebreg(LR),ap); ReleaseTempRegister(ap); } // Pop parameters off the stack if (i!=0) { if (sym) { if (!sym->IsPascal) GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(i * 8)); } else GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(i * 8)); } //RestoreTempRegs(msk); TempRevalidate(sp); ap = GetTempRegister(); GenerateDiadic(op_mov,0,ap,makereg(1)); return ap; }
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 }
static void MaskShift(int op, AMODE *ap1, int size) { switch(op) { case op_shru: j1: switch (size) { case 1: GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xff)); break; case 2: GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xffff)); break; case 4: GenerateTriadic(op_andi,0,ap1,ap1,make_immed(0xffffffff)); break; default: ; } break; case op_srl: case op_sra: case op_asr: case op_shr: if (isTable888|isFISA64|isThor) { if (ap1->isUnsigned) goto j1; switch (size) { case 1: GenerateDiadic(op_sxb,0,ap1,ap1); break; case 2: GenerateDiadic(op_sxc,0,ap1,ap1); break; case 4: GenerateDiadic(op_sxh,0,ap1,ap1); break; default: ; } } else { switch (size) { case 1: GenerateDiadic(op_sext8,0,ap1,ap1); break; case 2: GenerateDiadic(op_sext16,0,ap1,ap1); break; case 4: GenerateDiadic(op_sext32,0,ap1,ap1); break; default: ; } } break; } }
// push entire parameter list onto stack // static int GeneratePushParameterList(ENODE *plist) { ENODE *st = plist; int i,n; // count the number of parameters for(n = 0; plist != NULL; n++ ) plist = plist->p[1]; // move stack pointer down by number of parameters if (st) GenerateTriadic(op_subui,0,makereg(regSP),makereg(regSP),make_immed(n*8)); plist = st; for(i = 0; plist != NULL; i++ ) { GeneratePushParameter(plist->p[0],i,n); plist = plist->p[1]; } return i; }
void scppinit(void) { if (!strcmp(currentfunc->name,"_main")) { AMODE *ap1,*ap2,*ap3,*ap4; int lbl = nextlabel++; initstack(); ap1 = temp_data(); ap4 = xalloc(sizeof(AMODE)); ap4->preg = ap1->preg; ap4->mode = am_indisp; ap4->offset = makenode(en_icon,0,0); ap2 = set_symbol("cppistart",0); ap3 = set_symbol("cppiend",0); gen_code(op_mov,4,ap1,ap2); gen_label(lbl); gen_code(op_push,4,ap1,0); gen_code(op_call,4,ap4,0); gen_code(op_pop,4,ap1,0); gen_code(op_add,4,ap1,make_immed(4)); gen_code(op_cmp,4,ap1,ap3); gen_code(op_jb,0,make_label(lbl),0); freeop(ap1); } }
void genreturn(STATEMENT *stmt, SYMBOL *funcsp, int flag, int noepilogue, IMODE *allocaAP) /* * generate a return statement. */ { IMODE *ap, *ap1, *ap3; EXPRESSION ep; /* returns a value? */ if (stmt != 0 && stmt->select != 0) { if (basetype(funcsp->tp)->btp && (isstructured(basetype(funcsp->tp)->btp) || basetype(basetype(funcsp->tp)->btp)->type == bt_memberptr)) { SYMBOL *sp = anonymousVar(sc_parameter, &stdpointer); EXPRESSION *en = varNode(en_auto, sp); IMODE *ap3 = gen_expr(funcsp, stmt->select, 0, ISZ_ADDR), *ap2, *ap1; DumpIncDec(funcsp); if (!ap3->retval) { ap1 = LookupLoadTemp(NULL, ap3); if (ap1 != ap3) { IMODE *barrier; if (stmt->select->isatomic) { barrier = doatomicFence(funcsp, stmt->select, NULL); } gen_icode(i_assn, ap1, ap3, NULL); if (stmt->select->isatomic) { doatomicFence(funcsp, stmt->select, barrier); } } } else { ap1 = ap3; } if ((funcsp->linkage == lk_pascal) && basetype(funcsp->tp)->syms->table[0] && ((SYMBOL *)basetype(funcsp->tp)->syms->table[0])->tp->type != bt_void) { sp->offset = funcsp->paramsize; } else { sp->offset = chosenAssembler->arch->retblocksize+(funcsp->farproc *getSize(bt_pointer)); if (funcsp->storage_class == sc_member || funcsp->storage_class == sc_virtual) sp->offset += getSize(bt_pointer); } en = exprNode(en_l_p, en, NULL); ap3 = gen_expr(funcsp, en, 0, ISZ_ADDR); ap = LookupLoadTemp(NULL, ap3); if (ap != ap3) { IMODE *barrier; if (en->isatomic) { barrier = doatomicFence(funcsp, en, NULL); } gen_icode(i_assn, ap, ap3, NULL); if (en->isatomic) { doatomicFence(funcsp, en, barrier); } } gen_icode(i_assnblock, make_immed(ISZ_NONE, basetype(funcsp->tp)->btp->size), ap, ap1); ap1 = tempreg(ISZ_ADDR, 0); ap1->retval = TRUE; gen_icode(i_assn, ap1, ap, NULL); } else if (basetype(funcsp->tp)->btp && basetype(funcsp->tp)->btp->type == bt_memberptr) { ap3 = gen_expr(funcsp, stmt->select, F_VOL, ISZ_ADDR); DumpIncDec(funcsp); ap = LookupLoadTemp(NULL, ap3); if (ap != ap3) { IMODE *barrier; if (stmt->select->isatomic) { barrier = doatomicFence(funcsp, stmt->select, NULL); } gen_icode(i_assn, ap, ap3, NULL); if (stmt->select->isatomic) { doatomicFence(funcsp, stmt->select, barrier); } } ap1 = tempreg(ISZ_ADDR, 0); ap1->retval = TRUE; gen_icode(i_assn, ap1, ap, 0); } else { int size = natural_size(stmt->select); ap3 = gen_expr(funcsp, stmt->select, 0, size); DumpIncDec(funcsp); ap = LookupLoadTemp(NULL, ap3); if (ap != ap3) { IMODE *barrier; if (stmt->select->isatomic) { barrier = doatomicFence(funcsp, stmt->select, NULL); } gen_icode(i_assn, ap, ap3, NULL); if (stmt->select->isatomic) { doatomicFence(funcsp, stmt->select, barrier); } } if (abs(size) < ISZ_UINT) size = -ISZ_UINT; ap1 = tempreg(size, 0); ap1->retval = TRUE; gen_icode(i_assn, ap1, ap, 0); } } else { DumpIncDec(funcsp); } /* create the return or a branch to the return * return is put at end of function... */ if (flag) { int retsize = 0; if (funcsp->linkage == lk_pascal || funcsp->linkage == lk_stdcall) { retsize = funcsp->paramsize ; } gen_label(retlab); if (!noepilogue) { if (allocaAP) { gen_icode(i_loadstack, 0, allocaAP, 0); } /* if (funcsp->loadds && funcsp->farproc) gen_icode(i_unloadcontext,0,0,0); */ gen_icode(i_epilogue,0,0,0); if (funcsp->linkage == lk_interrupt || funcsp->linkage == lk_fault) { /* if (funcsp->loadds) gen_icode(i_unloadcontext,0,0,0); */ gen_icode(i_popcontext, 0,0,0); gen_icode(i_rett, 0, make_immed(ISZ_NONE,funcsp->linkage == lk_interrupt), 0); } else { gen_icode(i_ret, 0, make_immed(ISZ_NONE,retsize), 0); } } } else { /* not using gen_igoto because it will make a new block */ gen_icode(i_goto, NULL, NULL, NULL); intermed_tail->dc.v.label = retlab; } }
// Generate a function body. // void GenerateFunction(SYM *sym, Statement *stmt) { char buf[20]; char *bl; int cnt, nn; AMODE *ap; ENODE *ep; SYM *sp; throwlab = retlab = contlab = breaklab = -1; lastsph = 0; memset(semaphores,0,sizeof(semaphores)); throwlab = nextlabel++; while( lc_auto & 7 ) /* round frame size to word */ ++lc_auto; if (sym->IsInterrupt) { //GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(30*8)); //GenerateDiadic(op_sm,0,make_indirect(30), make_mask(0x9FFFFFFE)); } if (!sym->IsNocall) { GenerateTriadic(op_subui,0,makereg(SP),makereg(SP),make_immed(32)); if (lc_auto || sym->NumParms > 0) { GenerateDiadic(op_ss|op_sw,0,makereg(regBP),make_indirect(SP)); } // if (sym->UsesPredicate) GenerateDiadic(op_ss|op_sws, 0, make_string("pregs"), make_indexed(24,SP)); // For a leaf routine don't bother to store the link register or exception link register. if (!sym->IsLeaf) { if (exceptions) { GenerateDiadic(op_ss|op_sws, 0, makebreg(CLR), make_indexed(8,SP)); } GenerateDiadic(op_ss|op_sws, 0, makebreg(LR), make_indexed(16,SP)); if (exceptions) { ep = allocEnode(); ep->nodetype = en_clabcon; ep->i = throwlab; ap = allocAmode(); ap->mode = am_immed; ap->offset = ep; GenerateDiadic(op_ldis,0, makebreg(CLR), ap); } } if (lc_auto || sym->NumParms > 0) { GenerateDiadic(op_mov,0,makereg(regBP),makereg(regSP)); if (lc_auto) GenerateTriadic(op_subui,0,makereg(regSP),makereg(regSP),make_immed(lc_auto)); } // Save registers used as register variables. // **** Done in Analyze.c **** //if( save_mask != 0 ) { // GenerateTriadic(op_subui,0,makereg(SP),makereg(SP),make_immed(popcnt(save_mask)*8)); // cnt = (bitsset(save_mask)-1)*8; // for (nn = 31; nn >=1 ; nn--) { // if (save_mask & (1 << nn)) { // GenerateTriadic(op_sw,0,makereg(nn),make_indexed(cnt,SP),NULL); // cnt -= 8; // } // } //} } if (optimize) sym->NumRegisterVars = opt1(stmt); GenerateStatement(stmt); GenerateReturn(sym,0); // Generate code for the hidden default catch if (exceptions) { if (sym->IsLeaf){ if (sym->DoesThrow) { GenerateLabel(throwlab); ap = GetTempRegister(); GenerateDiadic(op_mfspr,0,ap,makebreg(CLR)); GenerateDiadic(op_mtspr,0,makebreg(LR),ap); ReleaseTempRegister(ap); GenerateMonadic(op_bra,0,make_clabel(retlab)); // goto regular return cleanup code } } else { GenerateLabel(throwlab); GenerateDiadic(op_lws,0,makebreg(regLR),make_indexed(8,regBP)); // load throw return address from stack into LR GenerateDiadic(op_sws,0,makebreg(regLR),make_indexed(16,regBP)); // and store it back (so it can be loaded with the lm) GenerateMonadic(op_bra,0,make_clabel(retlab)); // goto regular return cleanup code } } }
// Generate a return statement. // void GenerateReturn(SYM *sym, Statement *stmt) { AMODE *ap; int nn; int lab1; int cnt; // Generate code to evaluate the return expression. if( stmt != NULL && stmt->exp != NULL ) { initstack(); ap = GenerateExpression(stmt->exp,F_ALL & ~F_BREG,8); // Force return value into register 1 if( ap->preg != 1 ) { if (ap->mode == am_immed) GenerateDiadic(op_ldi, 0, makereg(1),ap); else if (ap->mode == am_reg) GenerateDiadic(op_mov, 0, makereg(1),ap); else GenerateDiadic(op_lw,0,makereg(1),ap); } } // Generate the return code only once. Branch to the return code for all returns. if( retlab == -1 ) { retlab = nextlabel++; GenerateLabel(retlab); // Unlock any semaphores that may have been set for (nn = lastsph - 1; nn >= 0; nn--) GenerateDiadic(op_sb,0,makereg(0),make_string(semaphores[nn])); if (sym->IsNocall) // nothing to do for nocall convention return; // Restore registers used as register variables. if( bsave_mask != 0 ) { cnt = (bitsset(bsave_mask)-1)*8; for (nn = 15; nn >=1 ; nn--) { if (bsave_mask & (1 << nn)) { GenerateDiadic(op_ss|op_lws,0,makebreg(nn),make_indexed(cnt,SP)); cnt -= 8; } } GenerateTriadic(op_addui,0,makereg(SP),makereg(SP),make_immed(popcnt(bsave_mask)*8)); } if( save_mask != 0 ) { cnt = (bitsset(save_mask)-1)*8; for (nn = 31; nn >=1 ; nn--) { if (save_mask & (1 << nn)) { GenerateDiadic(op_ss|op_lw,0,makereg(nn),make_indexed(cnt,SP)); cnt -= 8; } } GenerateTriadic(op_addui,0,makereg(SP),makereg(SP),make_immed(popcnt(save_mask)*8)); } // Unlink the stack // For a leaf routine the link register and exception link register doesn't need to be saved/restored. if (lc_auto || sym->NumParms > 0) { GenerateDiadic(op_mov,0,makereg(SP),makereg(regBP)); GenerateDiadic(op_ss|op_lw,0,makereg(regBP),make_indirect(regSP)); } if (!sym->IsLeaf) { if (exceptions) GenerateDiadic(op_ss|op_lws,0,makebreg(CLR),make_indexed(8,regSP)); GenerateDiadic(op_ss|op_lws,0,makebreg(LR),make_indexed(16,regSP)); // if (sym->UsesPredicate) } GenerateDiadic(op_ss|op_lws,0,make_string("pregs"),make_indexed(24,regSP)); //if (isOscall) { // GenerateDiadic(op_move,0,makereg(0),make_string("_TCBregsave")); // gen_regrestore(); //} // Generate the return instruction. For the Pascal calling convention pop the parameters // from the stack. if (sym->IsInterrupt) { //GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(24)); //GenerateDiadic(op_lm,0,make_indirect(30),make_mask(0x9FFFFFFE)); //GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(popcnt(0x9FFFFFFE)*8)); GenerateMonadic(op_rti,0,(AMODE *)NULL); return; } if (sym->IsPascal) { GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(32+sym->NumParms * 8)); GenerateMonadic(op_rts,0,(AMODE *)NULL); } else { GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(32)); GenerateMonadic(op_rts,0,(AMODE*)NULL); } } // Just branch to the already generated stack cleanup code. else { GenerateMonadic(op_bra,0,make_clabel(retlab)); } }
// Generate a function body. // void GenerateFunction(SYM *sym, Statement *stmt) { char buf[20]; char *bl; int cnt, nn; AMODE *ap; ENODE *ep; SYM *sp; std::string vep; throwlab = retlab = contlab = breaklab = -1; lastsph = 0; memset(semaphores,0,sizeof(semaphores)); throwlab = nextlabel++; retlab = nextlabel++; while( lc_auto & 7 ) /* round frame size to word */ ++lc_auto; if (sym->IsInterrupt) { //GenerateTriadic(op_subui,0,makereg(30),makereg(30),make_immed(30*8)); //GenerateDiadic(op_sm,0,make_indirect(30), make_mask(0x9FFFFFFE)); } if (sym->prolog) { if (optimize) opt1(sym->prolog); GenerateStatement(sym->prolog); } if (!sym->IsNocall) { GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(-GetReturnBlockSize())); if (lc_auto || sym->NumParms > 0) { GenerateDiadic(op_sw,0,makereg(regBP),make_indirect(regSP)); } // if (sym->UsesPredicate) GenerateDiadic(op_sws, 0, make_string("pregs"), make_indexed(24,regSP)); GenerateDiadic(op_sw, 0, makereg(regCLP),make_indexed(32,regSP)); // For a leaf routine don't bother to store the link register or exception link register. // Since virtual functions call other functions, they can't be leaf // routines. if (!sym->IsLeaf || sym->IsVirtual) { if (exceptions) { GenerateDiadic(op_sws, 0, makebreg(regXLR), make_indexed(8,regSP)); } GenerateDiadic(op_sws, 0, makebreg(regLR), make_indexed(16,regSP)); if (exceptions) { ep = allocEnode(); ep->nodetype = en_clabcon; ep->i = throwlab; ap = allocAmode(); ap->mode = am_immed; ap->offset = ep; GenerateDiadic(op_ldis,0, makebreg(regXLR), ap); } } GenerateDiadic(op_lw,0,makereg(regCLP),make_indexed(GetReturnBlockSize(),regSP)); vep = *sym->mangledName; vep += "_VEP"; GenerateMonadic(op_fnname,0,make_string((char *)vep.c_str())); // Generate switch to call derived methods if (sym->IsVirtual || sym->derivitives) { char buf[20]; char *buf2; DerivedMethod *mthd; dfs.printf("VirtualFunction Switch"); GenerateDiadic(op_lcu,0,makereg(24),make_indirect(regCLP)); mthd = sym->derivitives; while (mthd) { sprintf(buf, "p%d", 7); buf2 = my_strdup(buf); GenerateTriadic(op_cmpi,0,make_string(buf2),makereg(24),make_immed(mthd->typeno)); vep = *(mthd->name); vep += "_VEP"; // Virtual Entry Point GeneratePredicatedMonadic(7,PredOp(op_eq),op_jmp,0, make_string((char *)vep.c_str())); // jump to the method mthd = mthd->next; } } if (lc_auto || sym->NumParms > 0) { GenerateDiadic(op_mov,0,makereg(regBP),makereg(regSP)); if (lc_auto) GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(-lc_auto)); } // Save registers used as register variables. // **** Done in Analyze.c **** //if( save_mask != 0 ) { // GenerateTriadic(op_subui,0,makereg(SP),makereg(SP),make_immed(popcnt(save_mask)*8)); // cnt = (bitsset(save_mask)-1)*8; // for (nn = 31; nn >=1 ; nn--) { // if (save_mask & (1 << nn)) { // GenerateTriadic(op_sw,0,makereg(nn),make_indexed(cnt,SP),NULL); // cnt -= 8; // } // } //} } if (optimize) sym->NumRegisterVars = opt1(stmt); GenerateStatement(stmt); GenerateEpilog(sym); // Generate code for the hidden default catch if (exceptions) { if (sym->IsLeaf){ if (sym->DoesThrow) { GenerateLabel(throwlab); ap = GetTempRegister(); GenerateDiadic(op_mfspr,0,ap,makebreg(regXLR)); GenerateDiadic(op_mtspr,0,makebreg(regLR),ap); ReleaseTempRegister(ap); GenerateMonadic(op_br,0,make_clabel(retlab)); // goto regular return cleanup code } } else { GenerateLabel(throwlab); GenerateDiadic(op_lws,0,makebreg(regLR),make_indexed(8,regBP)); // load throw return address from stack into LR GenerateDiadic(op_sws,0,makebreg(regLR),make_indexed(16,regBP)); // and store it back (so it can be loaded with the lm) GenerateMonadic(op_br,0,make_clabel(retlab)); // goto regular return cleanup code } } }
AMODE *GenerateFunctionCall(ENODE *node, int flags) { AMODE *ap, *result; SYM *sym; int i; int msk; int sp; int isPascal = FALSE; dfs.puts("<GenerateFunctionCall>"); //msk = SaveTempRegs(); if (node->p[0] < (ENODE *)0x0FLL) { error(ERR_NULLPOINTER); goto xit1; } sp = TempInvalidate(); sym = (SYM*)NULL; i = GeneratePushParameterList(node->p[1]); // Call the function if( node->p[0]->nodetype == en_cnacon ) { dfs.printf("cnacon node:%s|\n",(char *)node->p[0]->sp->c_str()); // if (node->p[0]->i==25) // GenerateDiadic(op_sw,0,makereg(regCLP),make_indexed(0,regSP)); if (node->p[0]->sp < (std::string *)0x0FLL) node->p[0]->sp = new std::string("<null>"); GenerateMonadic(op_jsr,0,make_offset(node->p[0])); sym = gsearch(*node->p[0]->sp); dfs.puts((char*)(node->p[0]->sp->c_str())); if (sym) { dfs.puts("<found></found>"); } else { dfs.printf("<notfound>%s</notfound>",(char*)(node->p[0]->sp->c_str())); } } else { ap = GenerateExpression(node->p[0],F_BREG,8); ap->mode = am_brind; isPascal = node->p[0]->isPascal; GenerateDiadic(op_jsr,0,makebreg(1),ap); ReleaseTempRegister(ap); } // Pop parameters off the stack if (i!=0) { if (sym) { if (!sym->IsPascal) GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(i * 8)); } else if (!isPascal) GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(i * 8)); } //RestoreTempRegs(msk); TempRevalidate(sp); xit1: ap = GetTempRegister(); if (flags & F_NOVALUE) ; else GenerateDiadic(op_mov,0,ap,makereg(1)); dfs.puts("</GenerateFunctionCall>"); return ap; }
// Generate function epilog code. // void GenerateEpilog(SYM *sym) { AMODE *ap; int nn; int lab1; int cnt; // Generate the return code only once. Branch to the return code for all returns. GenerateLabel(retlab); // Unlock any semaphores that may have been set for (nn = lastsph - 1; nn >= 0; nn--) GenerateDiadic(op_sb,0,makereg(0),make_string(semaphores[nn])); if (sym->IsNocall) // nothing to do for nocall convention return; // Restore registers used as register variables. if( bsave_mask != 0 ) { cnt = (bitsset(bsave_mask)-1)*8; for (nn = 15; nn >=1 ; nn--) { if (bsave_mask & (1 << nn)) { GenerateDiadic(op_lws,0,makebreg(nn),make_indexed(cnt,regSP)); cnt -= 8; } } GenerateTriadic(op_addui,0,makereg(SP),makereg(regSP),make_immed(popcnt(bsave_mask)*8)); } if( save_mask != 0 ) { cnt = (bitsset(save_mask)-1)*8; for (nn = 31; nn >=1 ; nn--) { if (save_mask & (1 << nn)) { GenerateDiadic(op_lw,0,makereg(nn),make_indexed(cnt,regSP)); cnt -= 8; } } GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(popcnt(save_mask)*8)); } // Unlink the stack // For a leaf routine the link register and exception link register doesn't need to be saved/restored. if (lc_auto || sym->NumParms > 0) { GenerateDiadic(op_mov,0,makereg(regSP),makereg(regBP)); GenerateDiadic(op_lw,0,makereg(regBP),make_indirect(regSP)); } if (!sym->IsLeaf) { if (exceptions) GenerateDiadic(op_lws,0,makebreg(regXLR),make_indexed(8,regSP)); // 11=CLR GenerateDiadic(op_lws,0,makebreg(regLR),make_indexed(16,regSP)); // 1 = LR // if (sym->UsesPredicate) } GenerateDiadic(op_lws,0,make_string("pregs"),make_indexed(24,regSP)); GenerateDiadic(op_lw,0,makereg(regCLP),make_indexed(32,regSP)); if (sym->epilog) { if (optimize) opt1(sym->epilog); GenerateStatement(sym->epilog); return; } //if (isOscall) { // GenerateDiadic(op_move,0,makereg(0),make_string("_TCBregsave")); // gen_regrestore(); //} // Generate the return instruction. For the Pascal calling convention pop the parameters // from the stack. if (sym->IsInterrupt) { //GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(24)); //GenerateDiadic(op_lm,0,make_indirect(30),make_mask(0x9FFFFFFE)); //GenerateTriadic(op_addui,0,makereg(30),makereg(30),make_immed(popcnt(0x9FFFFFFE)*8)); GenerateMonadic(op_rti,0,(AMODE *)NULL); return; } if (sym->IsPascal) { GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(GetReturnBlockSize()+sym->NumParms * 8)); GenerateMonadic(op_rts,0,(AMODE *)NULL); } else { GenerateTriadic(op_addui,0,makereg(regSP),makereg(regSP),make_immed(GetReturnBlockSize())); GenerateMonadic(op_rts,0,(AMODE*)NULL); } }
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); } }
void genreturn(STATEMENT *stmt, SYMBOL *funcsp, int flag, int noepilogue, IMODE *allocaAP) /* * generate a return statement. */ { IMODE *ap = NULL, *ap1, *ap3; EXPRESSION ep; int size; /* returns a value? */ if (stmt != 0 && stmt->select != 0) { if (basetype(funcsp->tp)->btp && (isstructured(basetype(funcsp->tp)->btp) || basetype(basetype(funcsp->tp)->btp)->type == bt_memberptr)) { EXPRESSION *en = anonymousVar(sc_parameter, &stdpointer); SYMBOL *sp = en->v.sp; gen_expr(funcsp, stmt->select, 0, ISZ_ADDR); DumpIncDec(funcsp); sp->offset = chosenAssembler->arch->retblocksize; sp->allocate = FALSE; if ((funcsp->linkage == lk_pascal) && basetype(funcsp->tp)->syms->table[0] && ((SYMBOL *)basetype(funcsp->tp)->syms->table[0])->tp->type != bt_void) sp->offset = funcsp->paramsize; deref(&stdpointer, &en); ap = gen_expr(funcsp, en, 0, ISZ_ADDR); size = ISZ_ADDR; } else { size = natural_size(stmt->select); ap3 = gen_expr(funcsp, stmt->select, 0, size); DumpIncDec(funcsp); ap = LookupLoadTemp(NULL, ap3); if (ap != ap3) { IMODE *barrier; if (stmt->select->isatomic) { barrier = doatomicFence(funcsp, stmt->select, NULL); } gen_icode(i_assn, ap, ap3, NULL); if (stmt->select->isatomic) { doatomicFence(funcsp, stmt->select, barrier); } } if (abs(size) < ISZ_UINT) size = -ISZ_UINT; } } else { DumpIncDec(funcsp); } if (ap) { ap1 = tempreg(size, 0); ap1->retval = TRUE; gen_icode(i_assn, ap1, ap, 0); } if (stmt && stmt->destexp) { gen_expr(funcsp, stmt->destexp, F_NOVALUE, ISZ_ADDR); } /* create the return or a branch to the return * return is put at end of function... */ if (flag) { int retsize = 0; if (funcsp->linkage == lk_pascal || funcsp->linkage == lk_stdcall) { retsize = funcsp->paramsize ; } gen_label(retlab); if (!noepilogue) { if (allocaAP) { gen_icode(i_loadstack, 0, allocaAP, 0); } /* if (funcsp->loadds && funcsp->farproc) gen_icode(i_unloadcontext,0,0,0); */ if (cparams.prm_xcept && funcsp->xc && funcsp->xc->xcRundownFunc) gen_expr(funcsp, funcsp->xc->xcRundownFunc, F_NOVALUE, ISZ_UINT); gen_icode(i_epilogue,0,0,0); if (funcsp->linkage == lk_interrupt || funcsp->linkage == lk_fault) { /* if (funcsp->loadds) gen_icode(i_unloadcontext,0,0,0); */ gen_icode(i_popcontext, 0,0,0); gen_icode(i_rett, 0, make_immed(ISZ_UINT,funcsp->linkage == lk_interrupt), 0); } else { gen_icode(i_ret, 0, make_immed(ISZ_UINT,retsize), 0); } } } else { /* not using gen_igoto because it will make a new block */ gen_icode(i_goto, NULL, NULL, NULL); intermed_tail->dc.v.label = retlab; } }
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 genstmt(SNODE *stmt) /* * genstmt will generate a statement and follow the next pointer * until the block is generated. */ { while( stmt != 0 ) { switch( stmt->stype ) { case st_block: genstmt(stmt->exp); break; case st_label: gen_label((int)stmt->label); break; case st_goto: gen_code(op_jmp,0,make_label((int)stmt->label),0); break; case st_expr: initstack(); gen_expr(stmt->exp,F_ALL | F_NOVALUE, natural_size(stmt->exp)); break; case st_return: genreturn(stmt,0); break; case st_if: genif(stmt); break; case st_while: genwhile(stmt); break; case st_do: gendo(stmt); break; case st_for: gen_for(stmt); break; case st_continue: gen_code(op_jmp,0,make_label(contlab),0); break; case st_break: gen_code(op_jmp,0,make_label(breaklab),0); break; case st_switch: genxswitch(stmt); break; case st_line: gen_line(stmt); break; case st_asm: if (stmt->exp) add_peep(stmt->exp); break; case st__genword: gen_code(op_genword,0,make_immed((int)stmt->exp),0); break; default: diag("unknown statement."); break; } stmt = stmt->next; } }
/*-------------------------------------------------------------------------*/ void gen_tryblock(void *val) { /* xceptoffs will be put in the label field later */ gen_icode(i_tryblock, 0, make_immed(ISZ_NONE, (int)val), 0); }
void allocate(int datareg, int addreg, int floatreg, SNODE *block ) /* * allocate will allocate registers for the expressions that have * a high enough desirability. */ { CSE *csp; ENODE *exptr; unsigned mask, rmask,i,fmask,frmask,size; AMODE *ap, *ap2; framedepth = 4+lc_maxauto; mask = 0; rmask = 0; fmask = frmask = 0; for (i=cf_freedata; i < datareg; i++) { framedepth+=4; rmask = rmask | (1 << (15 - i)); mask = mask | (1 << i); } for (i=cf_freeaddress+16; i < addreg; i++) { framedepth+=4; 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) { if (floatreg <24 && floatregs) csp->reg = floatreg++; } else if( (datareg < cf_maxdata) && (csp->duses <= csp->uses/4) && dataregs) csp->reg = (datareg)++; else if( !(csp->size == 1 || csp->size == -1) && (addreg < cf_maxaddress) &&addrregs) csp->reg = (addreg)++; } } 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])->inreg = TRUE; ((SYM *)csp->exp->v.p[0]->v.p[0])->value.i = -csp->reg; } if (csp->reg < 16) { framedepth+=4; rmask = rmask | (1 << (15 - csp->reg)); mask = mask | (1 << csp->reg); } else if (csp->reg < 32) { framedepth+=4; rmask = rmask | (1 << (23 - csp->reg)); mask = mask | (1 << (csp->reg-8)); } else { framedepth+=12; frmask = frmask | (1 << (39 - csp->reg)); fmask = fmask | (1 << (csp->reg-32)); } } csp = csp->next; } allocstack(); /* Allocate stack space for the local vars */ if (currentfunc->tp->lst.head !=0 && currentfunc->tp->lst.head != (SYM *)-1) { if (prm_phiform || currentfunc->intflag) { mask |= (1 << (linkreg +8)); rmask |= (1 << (15 - linkreg -8)); framedepth+=4; } if (currentfunc->intflag) { mask |= 0xffff; rmask |= 0xffff; framedepth = lc_maxauto; } } if (prm_linkreg && !currentfunc->intflag && (currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *)-1 || lc_maxauto)) { gen_code(op_link,0,makeareg(linkreg),make_immed(-lc_maxauto)); } if( mask != 0 ) gen_code(op_movem,4,make_mask(rmask,0,0),push); save_mask = mask; if (fmask!=0) gen_code(op_fmovem,10,make_mask(frmask,0,1),push); fsave_mask = fmask; if ((prm_phiform || currentfunc->intflag) && currentfunc->tp->lst.head && currentfunc->tp->lst.head != (SYM *) -1) { gen_code(op_move,4,makeareg(0), makeareg(linkreg)); } if ((!prm_linkreg || currentfunc->intflag) && lc_maxauto) { AMODE *ap = xalloc(sizeof(AMODE)); ap->mode = am_indx; ap->offset = makenode(en_icon,(char *)-lc_maxauto,0); ap->preg = 7; gen_code(op_lea,0,ap,makeareg(7)); } if (prm_stackcheck) { AMODE *ap1; ap = set_symbol("_stackerror",1); ap1 = set_symbol("_stackbottom",0); if (prm_rel) { ap1->mode = am_indx; ap1->preg = basereg; } else { ap1->mode = am_adirect; if (prm_smalldata) ap1->preg = 2; else ap1->preg = 4; } gen_code(op_cmp,4,ap1,makeareg(7)); gen_code(op_bhi,0,ap,0); } }