// 仮想スタックの一番奥の Acc を実スタックに移す static void outStk() { int idx = srchAcc(); // 一番奥の Acc を探す int sta = stkSta[idx]; // Acc, FLAG か間接アドレス int acc = stkAux[idx]; // レジスタ番号 if (sta!=ACC) // FLAG か間接アドレスなら loadReg(acc, idx); // 値を Acc にロードし printf("\tPUSH\t%s\n", regs[acc]); // PUSH Acc relAcc(acc); // Acc を解放する stkSta[idx] = STK; // データが実スタックにある }
// 仮想スタックの任意の位置のロード待ちを Acc にロードする // 通常 offs は 0 か 1 static void loadStk(int offs) { // offs はスタックトップ int p = stkPtr - offs; // からの距離 BUG(p<0 || stkPtr<p, "loadStk"); if (stkSta[p]!=ACC) { // スタックがロード待ちなら int acc = stkAux[p]; // ロードする Acc を決める if (!isAcc(p)) { // もし Acc が未割り当てなら if (accCnt>=AccSIZ) outStk(); // 空きがなければつくり acc = allocAcc(); // 新しく割り当てる } loadReg(acc, p); // Acc にロード待ちをロードする stkSta[p] = ACC; // スタックの状態を stkAux[p] = acc; // (ACC, acc) に変更 } }
// スタックトップの値をn番目のローカル変数にストアする(POPはしない) void vmStLoc(int n) { // n はローカル変数番号(n>=1) if (n<=RVarSIZ) { // レジスタ変数なら int reg = n-1+AccSIZ; // レジスタの番号 if (topSta!=RVAR || topAux!=reg) // 必要があれば loadReg(reg, stkPtr); // 値をレジスタ変数に格納 if (topSta!=ACC) { // もともとAcc以外に値があった if (isAcc(stkPtr)) relAcc(topAux); // Acc を開放(間接アドレス) topSta = RVAR; // 今後は、 topAux = reg; // 今回レジスタ変数に } // ロードした値を使用する } else { // メモリ上のローカル変数なら if (topSta!=RVAR) loadStk(0); // レジスタにロードし printf("\tST\t%s,-%d,FP\n", // ローカル変数へストア regs[topAux], (n-RVarSIZ)*2); // ST Acc,-n,FP } }
// 関数の返り値をハードウェアレジスタ(G0)に移動 void vmMReg() { if (topSta!=ACC || topAux!=0) // 返す値が G0 以外にあるなら loadReg(0, stkPtr); // G0 にロードする if (isAcc(stkPtr)) relAcc(topAux); // Acc を使用中なら解放する popStk(1); // 仮想スタックが 1 縮小 }
void Tpreset::loadDefault(void) { ff_strncpy(presetName, FFPRESET_DEFAULT, countof(presetName)); loadReg(); }