/* * generate code to evaluate an if statement. */ void GenerateIf(Statement *stmt) { int lab1, lab2, oldbreak; lab1 = nextlabel++; /* else label */ lab2 = nextlabel++; /* exit label */ oldbreak = breaklab; /* save break label */ initstack(); /* clear temps */ if (gCpu!=888) if (stmt->predreg==70) GenerateFalseJump(stmt->exp,lab1,stmt->predreg); GenerateFalseJump(stmt->exp,lab1,stmt->predreg); //if( stmt->s1 != 0 && stmt->s1->next != 0 ) // if( stmt->s2 != 0 ) // breaklab = lab2; // else // breaklab = lab1; GenerateStatement(stmt->s1); if( stmt->s2 != 0 ) /* else part exists */ { GenerateDiadic(isThor ? op_br:op_bra,0,make_clabel(lab2),0); if (mixedSource) GenerateMonadic(op_rem,0,make_string("; else")); GenerateLabel(lab1); //if( stmt->s2 == 0 || stmt->s2->next == 0 ) // breaklab = oldbreak; //else // breaklab = lab2; GenerateStatement(stmt->s2); GenerateLabel(lab2); } else /* no else code */ GenerateLabel(lab1); breaklab = oldbreak; }
// generate code to evaluate a for loop // void GenerateFor(struct snode *stmt) { int old_break, old_cont, exit_label, loop_label; AMODE *ap; old_break = breaklab; old_cont = contlab; loop_label = nextlabel++; exit_label = nextlabel++; contlab = nextlabel++; initstack(); if( stmt->initExpr != NULL ) ReleaseTempRegister(GenerateExpression(stmt->initExpr,F_ALL | F_NOVALUE ,GetNaturalSize(stmt->initExpr))); GenerateLabel(loop_label); initstack(); if( stmt->exp != NULL ) GenerateFalseJump(stmt->exp,exit_label,stmt->predreg); if( stmt->s1 != NULL ) { breaklab = exit_label; GenerateStatement(stmt->s1); } GenerateLabel(contlab); initstack(); if( stmt->incrExpr != NULL ) ReleaseTempRegister(GenerateExpression(stmt->incrExpr,F_ALL | F_NOVALUE,GetNaturalSize(stmt->incrExpr))); GenerateMonadic(isThor ? op_br:op_bra,0,make_clabel(loop_label)); breaklab = old_break; contlab = old_cont; GenerateLabel(exit_label); }
/* * generate code to evaluate an until statement. */ void GenerateUntil(Statement *stmt) { int lab1, lab2; initstack(); /* initialize temp registers */ lab1 = contlab; /* save old continue label */ lab2 = breaklab; /* save old break label */ contlab = nextlabel++; /* new continue label */ GenerateLabel(contlab); if( stmt->s1 != NULL ) /* has block */ { breaklab = nextlabel++; initstack(); GenerateTrueJump(stmt->exp,breaklab,stmt->predreg); GenerateStatement(stmt->s1); GenerateMonadic(isThor ? op_br:op_bra,0,make_clabel(contlab)); GenerateLabel(breaklab); breaklab = lab2; /* restore old break label */ } else /* no loop code */ { initstack(); GenerateFalseJump(stmt->exp,contlab,stmt->predreg); } contlab = lab1; /* restore old continue label */ }
// generate all cases for a switch statement. // void GenerateCase(Statement *stmt) { while( stmt != (Statement *)NULL ) { if( stmt->s1 != (Statement *)NULL ) { GenerateLabel((int64_t)stmt->label); GenerateStatement(stmt->s1); } else if( stmt->next == (Statement *)NULL ) GenerateLabel((int64_t)stmt->label); stmt = stmt->next; } }
/* * generate code for a do - while loop. */ void GenerateDoUntil(struct snode *stmt) { int oldcont, oldbreak; oldcont = contlab; oldbreak = breaklab; contlab = nextlabel++; GenerateLabel(contlab); breaklab = nextlabel++; GenerateStatement(stmt->s1); /* generate body */ initstack(); GenerateFalseJump(stmt->exp,contlab,stmt->predreg); GenerateLabel(breaklab); breaklab = oldbreak; contlab = oldcont; }
void GenerateFirstcall(Statement *stmt) { int lab1, lab2; char buf[20]; AMODE *ap1,*ap2; lab1 = contlab; /* save old continue label */ lab2 = breaklab; /* save old break label */ contlab = nextlabel++; /* new continue label */ if( stmt->s1 != NULL ) /* has block */ { breaklab = nextlabel++; ap1 = GetTempRegister(); GenerateDiadic(op_lb,0,ap1,make_string(stmt->fcname)); if (isThor) { GenerateDiadic(op_tst,0,make_string("p0"), ap1); GeneratePredicatedMonadic(0,PredOp(op_eq),op_br,0,make_clabel(breaklab)); } else GenerateDiadic(op_beq,0,ap1,make_clabel(breaklab)); ReleaseTempRegister(ap1); GenerateDiadic(op_sb,0,makereg(0),make_string(stmt->fcname)); GenerateStatement(stmt->s1); GenerateLabel(breaklab); breaklab = lab2; /* restore old break label */ } contlab = lab1; /* restore old continue label */ }
/* * analyze and generate best switch statement. */ void genxswitch(Statement *stmt) { int oldbreak; oldbreak = breaklab; breaklab = nextlabel++; GenerateSwitch(stmt); GenerateCase(stmt->s1); GenerateLabel(breaklab); breaklab = oldbreak; }
// generate code to evaluate a forever loop // void GenerateForever(Statement *stmt) { int old_break, old_cont, exit_label, loop_label; old_break = breaklab; old_cont = contlab; loop_label = nextlabel++; exit_label = nextlabel++; contlab = loop_label; GenerateLabel(loop_label); if( stmt->s1 != NULL ) { breaklab = exit_label; GenerateStatement(stmt->s1); } GenerateMonadic(isThor ? op_br:op_bra,0,make_clabel(loop_label)); breaklab = old_break; contlab = old_cont; GenerateLabel(exit_label); }
//--------------------------------------------------------------------------- TList * __fastcall TAuthenticateForm::GeneratePrompt(UnicodeString Instructions, TStrings * Prompts) { while (FPromptParent->ControlCount > 0) { delete FPromptParent->Controls[0]; } TList * Result = new TList; int Current = FPromptTop; if (!Instructions.IsEmpty()) { TLabel * Label = GenerateLabel(Current, Instructions); Current += Label->Height + FPromptsGap; } for (int Index = 0; Index < Prompts->Count; Index++) { if (Index > 0) { Current += FPromptEditGap; } TLabel * Label = GenerateLabel(Current, Prompts->Strings[Index]); Current += Label->Height + FPromptEditGap; bool Echo = FLAGSET(int(Prompts->Objects[Index]), pupEcho); TCustomEdit * Edit = GenerateEdit(Current, Echo); Result->Add(Edit); Label->FocusControl = Edit; Current += Edit->Height; } FPromptParent->ClientHeight = Current; return Result; }
// 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 } }
void NCluster::AsJson(string &json,vector<NameMap*>&nm){ //get the generate id json += "\"cluster_id\": \""; string labelString; GenerateLabel(labelString); json += labelString; json += "\","; //get the element names for(int i=0; i < n; i++){ bool found=false; for(int j=0; j < nm.size(); j++){ //cerr<<"\nHERE JSON FIRST! "<<j<<"\t"<<nm[j]->GetId()<<"\t"<<sets[i]->Id(); if (nm[j]->GetId() == sets[i]->Id()){ string idStr = to_string(nm[j]->GetId()); json += "\""; json += idStr; json +="\": ["; for(int k=0; k < sets[i]->Size(); k++){ json += "\""; json += nm[j]->GetName(sets[i]->At(k)); json += "\","; } json += "],"; found = true; break; } } // if(!found){ // json += to_string(i); // json += "\": ["; // cerr<<"\nHERE JSON FIRST! "<<<<"\t"<<nm[i]->GetId()<<"\t"<<sets[i]->Id(); // for(int k=0; k < sets[i]->Size(); k++){ // json += "\""; // json += nm[i]->GetName(sets[i]->At(k)); // json += "\","; // } // json += "],"; // } } }
void GenerateSpinlock(Statement *stmt) { int lab1, lab2, lab3, lab4; AMODE *ap1, *ap2; AMODE *ap; int sp = 0; lab1 = nextlabel++; lab2 = nextlabel++; lab3 = nextlabel++; if( stmt != (Statement *)NULL && stmt->exp != (ENODE *)NULL ) { initstack(); ap1 = GetTempRegister(); ap2 = GetTempRegister(); ap = GenerateExpression(stmt->exp,F_REG,8); GenerateDiadic(op_mov,0,makereg(1),ap); if (stmt->initExpr) { if (isFISA64) FISA64_GenLdi(makereg(2),make_immed((int64_t)stmt->initExpr)); else GenerateTriadic(op_ori, 0, makereg(2),makereg(0),make_immed((int64_t)stmt->initExpr)); } else { GenerateDiadic(op_ldi,0,makereg(2),make_immed(-1)); } GenerateMonadic(op_bsr,0,make_string("_LockSema")); if (stmt->initExpr) GenerateDiadic(op_beq,0,makereg(1),make_clabel(lab2)); ReleaseTempRegister(ap); ReleaseTempRegister(ap2); ReleaseTempRegister(ap1); // We treat this statement generation like a function call and save // the used temporary beforehand. The statement might reinitialize // the expression vars. There aren't any other cases where temporaries // are needed after statements are generated. GenerateMonadic(op_push,0,ap); GenerateStatement(stmt->s1); GenerateMonadic(op_pop,0,ap); // unlock if (isRaptor64) GenerateDiadic(op_outb, 0, makereg(0), make_indexed((int64_t)stmt->incrExpr,ap->preg)); else if (isFISA64) { GenerateDiadic(op_mov, 0, makereg(1), makereg(ap->preg)); GenerateMonadic(op_bsr, 0, make_string("_UnlockSema")); } else GenerateDiadic(op_sw, 0, makereg(0), make_indexed((int64_t)stmt->incrExpr,ap->preg)); if (stmt->initExpr) { GenerateMonadic(isThor?op_br:op_bra,0,make_clabel(lab3)); GenerateLabel(lab2); GenerateStatement(stmt->s2); GenerateLabel(lab3); } else { printf("Warning: The lockfail code is unreachable because spinlock tries are infinite.\r\n"); } } //ap1 = GetTempRegister(); //ap2 = GetTempRegister(); //if (stmt->exp) { // lab2 = nextlabel++; // GenerateTriadic(op_ori,0,ap2,makereg(0),make_immed(stmt->exp)); // GenerateLabel(lab1); // GenerateTriadic(op_beq,0,ap2,makereg(0),make_label(lab2)); // GenerateTriadic(op_subui,0,ap2,ap2,make_immed(1)); // GenerateTriadic(op_lwr,0,ap1,make_string(stmt->label),NULL); // GenerateTriadic(op_bne,0,ap1,makereg(0),make_label(lab1),NULL); // GenerateTriadic(op_not,0,ap1,ap1,NULL); // GenerateTriadic(op_swc,0,ap1,make_string(stmt->label),NULL); // GenerateTriadic(op_bnr,0,make_label(lab1),NULL,NULL); //} //else { // GenerateLabel(lab1); // GenerateTriadic(op_lwr,0,ap1,make_string(stmt->label),NULL); // GenerateTriadic(op_bne,0,ap1,makereg(0),make_label(lab1),NULL); // GenerateTriadic(op_not,0,ap1,ap1,NULL); // GenerateTriadic(op_swc,0,ap1,make_string(stmt->label),NULL); // GenerateTriadic(op_bnr,0,make_label(lab1),NULL,NULL); //} //ReleaseTempRegister(ap1); //ReleaseTempRegister(ap2); //GenerateStatement(stmt->s1); //GenerateDiadic(op_sb,0,makereg(0),make_string(stmt->label)); //if (stmt->exp) { // lab3 = nextlabel++; // GenerateTriadic(op_bra,0,make_label(lab3),NULL,NULL); // GenerateLabel(lab2); // GenerateStatement(stmt->s2); // GenerateLabel(lab3); //} //else { // printf("Warning: The lockfail code is unreachable because spinlock tries are infinite.\r\n"); //} }
// 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 } } }
// 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); } }
/* * genstmt will generate a statement and follow the next pointer * until the block is generated. */ void GenerateStatement(Statement *stmt) { AMODE *ap; while( stmt != NULL ) { GenMixedSource(stmt); switch( stmt->stype ) { //case st_vortex: // gen_vortex(stmt); // break; case st_funcbody: GenerateFuncbody(stmt); break; case st_compound: GenerateCompound(stmt); break; case st_try: GenerateTry(stmt); break; case st_throw: GenerateThrow(stmt); break; case st_intoff: GenerateIntoff(stmt); break; case st_stop: GenerateStop(stmt); break; case st_inton: GenerateInton(stmt); break; case st_asm: GenerateAsm(stmt); break; case st_label: GenerateLabel((int64_t)stmt->label); break; case st_goto: GenerateMonadic(isThor?op_br:op_bra,0,make_clabel((int64_t)stmt->label)); break; //case st_critical: // GenerateCritical(stmt); // break; case st_spinlock: GenerateSpinlock(stmt); break; case st_spinunlock: GenerateSpinUnlock(stmt); break; case st_check: GenerateCheck(stmt); break; case st_expr: initstack(); ap = GenerateExpression(stmt->exp,F_ALL | F_NOVALUE, GetNaturalSize(stmt->exp)); ReleaseTempRegister(ap); tmpFreeAll(); break; case st_return: if (isFISA64) GenerateFISA64Return(currentFn,stmt); else if (is816) Generate816Return(currentFn,stmt); else if (isTable888) GenerateTable888Return(currentFn,stmt); else if (isRaptor64) GenerateRaptor64Return(currentFn,stmt); else GenerateReturn(currentFn,stmt); break; case st_if: GenerateIf(stmt); break; case st_do: GenerateDo(stmt); break; case st_dountil: GenerateDoUntil(stmt); break; case st_doloop: GenerateForever(stmt); break; case st_while: GenerateWhile(stmt); break; case st_until: GenerateUntil(stmt); break; case st_for: GenerateFor(stmt); break; case st_forever: GenerateForever(stmt); break; case st_firstcall: GenerateFirstcall(stmt); break; case st_continue: if (contlab==-1) error(ERR_NOT_IN_LOOP); GenerateDiadic(isThor?op_br:op_bra,0,make_clabel(contlab),0); break; case st_break: if (breaklab==-1) error(ERR_NOT_IN_LOOP); GenerateDiadic(isThor?op_br:op_bra,0,make_clabel(breaklab),0); break; case st_switch: genxswitch(stmt); break; case st_empty: break; default: printf("DIAG - unknown statement.\n"); break; } stmt = stmt->next; } }
void GenerateTry(Statement *stmt) { int lab1,curlab; int oldthrow; char buf[20]; AMODE *ap, *a, *ap2; ENODE *node; SYM *sym; lab1 = nextlabel++; oldthrow = throwlab; throwlab = nextlabel++; if (isTable888|isRaptor64) GenerateDiadic(op_lea,0,makereg(regXLR),make_clabel(throwlab)); else if (isFISA64) { a = make_clabel(throwlab); a->mode = am_immed; FISA64_GenLdi(makereg(regXLR),a,8); } else GenerateDiadic(op_ldi,0,makebreg(CLR),make_clabel(throwlab)); GenerateStatement(stmt->s1); GenerateMonadic(isThor?op_br:op_bra,0,make_clabel(lab1)); GenerateLabel(throwlab); stmt = stmt->s2; // Generate catch statements // r1 holds the value to be assigned to the catch variable // r2 holds the type number while (stmt) { GenMixedSource(stmt); throwlab = oldthrow; curlab = nextlabel++; GenerateLabel(curlab); if (stmt->s2==(Statement *)99999) ; else { if (isRaptor64) GenerateTriadic(op_bnei,0,makereg(2),make_immed((int64_t)stmt->s2),make_clabel(nextlabel)); else if (isFISA64) { ap = GetTempRegister(); GenerateTriadic(op_cmp, 0, ap, makereg(2), make_immed((int64_t)stmt->s2)); GenerateDiadic(op_bne, 0, ap, make_clabel(nextlabel)); ReleaseTempRegister(ap); } else if (isTable888) { GenerateTriadic(op_cmp, 0, makereg(244), makereg(2), make_immed((int64_t)stmt->s2)); GenerateDiadic(op_bne, 0, makereg(244), make_clabel(nextlabel)); } else { // ToDo: fix Thor GenerateTriadic(op_cmpi, 0, make_string("p0"), makereg(2), make_immed((int64_t)stmt->s2)); GeneratePredicatedMonadic(0,PredOp(op_ne),op_br,0,make_clabel(nextlabel)); } } // move the throw expression result in 'r1' into the catch variable. node = (ENODE *)stmt->label; { ap2 = GenerateExpression(node,F_REG|F_MEM,GetNaturalSize(node)); if (ap2->mode==am_reg) GenerateDiadic(op_mov,0,ap2,makereg(1)); else GenStore(makereg(1),ap2,GetNaturalSize(node)); ReleaseTempRegister(ap2); } // GenStore(makereg(1),make_indexed(sym->value.i,regBP),sym->tp->size); GenerateStatement(stmt->s1); stmt=stmt->next; } GenerateLabel(lab1); if (isTable888|isRaptor64) GenerateDiadic(op_lea,0,makereg(regXLR),make_clabel(oldthrow)); else if (isFISA64) { a = make_clabel(oldthrow); a->mode = am_immed; FISA64_GenLdi(makereg(regXLR),a,8); } else GenerateDiadic(op_ldi,0,makebreg(CLR),make_clabel(oldthrow)); }