* acl4のページ0023
-(by [[K]], 2026.04.26)
** (1) 概要
-a4_0023 は、 acl4v1 にとっての8番目のライブラリプログラムになります。
-提供される主な機能は、以下の通りです。
--(1-1)あとでまとめて解放できる BufFree クラス
--(1-2)簡易な仮想マシン関数 A4vm_exec0
-以下、それぞれについてもう少し詳しく説明します。
~
-(1-1)あとでまとめて解放できる BufFree クラス
--プログラムで比較的不規則に malloc 処理が発生するような場合、あとでそれらをきれいに片付けるのはちょっと面倒です。そういう時に BufFree_malloc でメモリ確保をして、使い終わったタイミングで BufFree_flush すれば、きれいに片付けてくれます。
-(1-2)簡易な仮想マシン関数 A4vm_exec0
--レジスタマシン型の仮想マシンのインタプリタです。インタプリタ型にしてはまあまあ高速に動作します。
** (2) デモ
** (3) ライブラリプログラム
#if (a_Version >= 1)
#define BufFree a_BufFree
#define BufFree_ini a_BufFree_ini
#define BufFree_din a_BufFree_din
#define BufFree_add a_BufFree_add
#define BufFree_malloc a_BufFree_malloc
#define BufFree_flush a_BufFree_flush
#define double2intptr a_double2intptr
#define A4vm_exec0 a_A4vm_exec0
#endif
a_class(a_BufFree) { a_VecChr stk[1]; a_DbgLv1( a_DbgObjInf doi[1]; ) };
a_static void a_BufFree_ini(_aDef_ a_BufFree *w) { a_VecChr_ini(_a_ w->stk); a_DbgLv2( a_DbgObjInf_ini(_aThr, w->doi, "BufFree"); ) }
a_static void a_BufFree_din(_aDef_ a_BufFree *w) { a_DbgLv2( a_DbgObjInf_din(_aThr, w->doi); ) a_VecChr_din(_a_ w->stk); }
a_static void a_BufFree_add(a_BufFree *w, void *p, intptr_t sz)
{
a_parseArgs_Arg *paa = a_VecChr_stkAdd(w->stk, sizeof (a_parseArgs_Arg));
paa->s = p; paa->n = sz;
}
a_static void *a_BufFree_malloc(_aDef_ a_BufFree *w, intptr_t sz)
{
void *p = a_malloc(_aThr_ sz); a_BufFree_add(w, p, sz); return p;
}
a_static void a_BufFree_flush(_aDef_ a_BufFree *w)
{
while (a_VecChr_N(w->stk) > 0) {
a_parseArgs_Arg *paa = a_VecChr_stkRmv(w->stk, sizeof (a_parseArgs_Arg));
a_free(_aThr_ (char *) paa->s, paa->n);
}
}
// 切り捨てではなく四捨五入.
a_static intptr_t a_double2intptr(double x) { if (x >= 0.0) { x += 0.5; } else { x -= 0.5; } return (intptr_t) x; }
a_class(a_A4vm_exec0_funcInfo) {
intptr_t prv, reg, frg, subArg, pc, arg;
};
a_static intptr_t a_A4vm_exec0(intptr_t *bp, intptr_t bn, intptr_t argc, intptr_t *argv)
{
a_VecChr vcLbl[1], vcInf[1], vcStk[1]; a_VecChr_ini4(_a_ vcLbl, vcInf, vcStk, 0);
a_VecChr_reserve(vcLbl, 256 * sizeof (intptr_t));
intptr_t argc1 = (argc + 1) & -2; // 2の倍数に切り上げる.
a_VecChr_reserve(vcStk, argc1 * sizeof (intptr_t));
if (argc > 0) { memcpy(vcStk->p, argv, argc * sizeof (intptr_t)); a_VecChr_N(vcStk) = argc1 * sizeof (intptr_t); }
intptr_t *lab, pc, *reg = NULL, *subArg = NULL, *arg = (intptr_t *) vcStk->p, retVal = 0, argIdx = 0;
intptr_t *lab = NULL, pc, *reg = NULL, *subArg = NULL, *arg = (intptr_t *) vcStk->p, retVal = 0, argIdx = 0;
double *frg = NULL;
a_A4vm_exec0_funcInfo *inf;
for (pc = 0; pc < bn; pc += 4) {
if (bp[pc] == 0x03) {
a_VecChr_reserve(vcLbl, (bp[pc + 1] + 1) * sizeof (intptr_t));
lab = (intptr_t *) vcLbl->p;
lab[bp[pc + 1]] = pc + 4; // Lbl_T(t)命令の次の命令を指す.
}
}
for (pc = 0;;) {
intptr_t op = bp[pc], a = bp[pc + 1], b = bp[pc + 2], c = bp[pc + 3], d; pc += 4;
switch (op) {
case 0x00: continue;
case 0x01: pc = lab[a]; continue;
case 0x02: retVal = a; goto err;
case 0x03: continue;
case 0x04: reg[a] = b; continue;
case 0x05: reg[a] = reg[b]; continue;
case 0x06: reg[a] = reg[b] | c; continue;
case 0x07: reg[a] = reg[b] | reg[c]; continue;
case 0x08: reg[a] = reg[b] ^ c; continue;
case 0x09: reg[a] = reg[b] ^ reg[c]; continue;
case 0x0a: reg[a] = reg[b] & c; continue;
case 0x0b: reg[a] = reg[b] & reg[c]; continue;
case 0x0c: reg[a] = reg[b] << c; continue;
case 0x0d: reg[a] = reg[b] << reg[c]; continue;
case 0x0e: reg[a] = reg[b] >> c; continue;
case 0x0f: reg[a] = reg[b] >> reg[c]; continue;
case 0x10: reg[a] = reg[b] + c; continue;
case 0x11: reg[a] = reg[b] + reg[c]; continue;
case 0x12: reg[a] = reg[b] - c; continue;
case 0x13: reg[a] = reg[b] - reg[c]; continue;
case 0x14: reg[a] = reg[b] * c; continue;
case 0x15: reg[a] = reg[b] * reg[c]; continue;
case 0x16: reg[a] = reg[b] / c; continue;
case 0x17: reg[a] = reg[b] / reg[c]; continue;
case 0x18: reg[a] = reg[b] % c; continue;
case 0x19: reg[a] = reg[b] % reg[c]; continue;
case 0x1a: reg[a] = c - reg[b]; continue;
case 0x1b: reg[a] = c / reg[b]; continue;
case 0x1c: reg[a] = c % reg[b]; continue;
case 0x1d: d = bp[pc + 1]; pc += 4; reg[a] = (intptr_t)(((int64_t)reg[b]*(int64_t)reg[c])>>d); continue;
case 0x1e: reg[a] = a_double2intptr(cos(reg[b] * (2 * 3.14159265358979323 / 65536)) * 65536); continue;
case 0x1f: reg[a] = a_double2intptr(sin(reg[b] * (2 * 3.14159265358979323 / 65536)) * 65536); continue;
case 0x20: reg[a] = (reg[b] < c); continue;
case 0x21: reg[a] = (reg[b] < reg[c]); continue;
case 0x22: reg[a] = (reg[b] >= c); continue;
case 0x23: reg[a] = (reg[b] >= reg[c]); continue;
case 0x24: reg[a] = (reg[b] <= c); continue;
case 0x25: reg[a] = (reg[b] <= reg[c]); continue;
case 0x26: reg[a] = (reg[b] > c); continue;
case 0x27: reg[a] = (reg[b] > reg[c]); continue;
case 0x28: reg[a] = (reg[b] == c); continue;
case 0x29: reg[a] = (reg[b] == reg[c]); continue;
case 0x2a: reg[a] = (reg[b] != c); continue;
case 0x2b: reg[a] = (reg[b] != reg[c]); continue;
case 0x2c: if (b >= 256) { reg[a] = arg[b - 256]; } else { reg[a] = subArg[b]; } continue; // Lod_RA
case 0x2d: if (a >= 256) { arg[a - 256] = reg[b]; } else { subArg[a] = reg[b]; } continue; // Lod_AR
case 0x2e: if (a >= 256) { arg[a - 256] = b; } else { subArg[a] = b; } continue; // Lod_AI
case 0x2f: inf = (a_A4vm_exec0_funcInfo *) (vcInf->p + a_VecChr_N(vcInf) - sizeof (a_A4vm_exec0_funcInfo)); // call
inf->pc = pc; inf->arg = argIdx; arg = subArg; argIdx = inf->subArg; pc = lab[a]; continue;
case 0x30: if (reg[b] < c) { pc = lab[a]; } continue;
case 0x31: if (reg[b] < reg[c]) { pc = lab[a]; } continue;
case 0x32: if (reg[b] >= c) { pc = lab[a]; } continue;
case 0x33: if (reg[b] >= reg[c]) { pc = lab[a]; } continue;
case 0x34: if (reg[b] <= c) { pc = lab[a]; } continue;
case 0x35: if (reg[b] <= reg[c]) { pc = lab[a]; } continue;
case 0x36: if (reg[b] > c) { pc = lab[a]; } continue;
case 0x37: if (reg[b] > reg[c]) { pc = lab[a]; } continue;
case 0x38: if (reg[b] == c) { pc = lab[a]; } continue;
case 0x39: if (reg[b] == reg[c]) { pc = lab[a]; } continue;
case 0x3a: if (reg[b] != c) { pc = lab[a]; } continue;
case 0x3b: if (reg[b] != reg[c]) { pc = lab[a]; } continue;
case 0x3c: reg[a] = a_double2intptr(sqrt(reg[b] * (1.0 / 65536)) * 65536); continue;
case 0x3d:
if (b == 0) { intptr_t (*fn)() = (void *) a; reg[c] = fn(); continue; }
if (b <= 3) { intptr_t (*fn)(intptr_t, intptr_t, intptr_t) = (void *) a; reg[c] = fn(reg[bp[pc+1]], reg[bp[pc+2]], reg[bp[pc+3]]); pc += 4; continue; }
if (b <= 6) { intptr_t (*fn)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t) = (void *) a;
reg[c] = fn(reg[bp[pc+1]], reg[bp[pc+2]], reg[bp[pc+3]], reg[bp[pc+5]], reg[bp[pc+6]], reg[bp[pc+7]]); pc += 8; continue; }
if (b <= 9) { intptr_t (*fn)(intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t, intptr_t) = (void *) a;
reg[c] = fn(reg[bp[pc+1]], reg[bp[pc+2]], reg[bp[pc+3]], reg[bp[pc+5]], reg[bp[pc+6]], reg[bp[pc+7]], reg[bp[pc+9]], reg[bp[pc+10]], reg[bp[pc+11]]); pc += 12; continue; }
case 0x3e: // enter
pc += 4; inf = a_VecChr_stkAdd(vcInf, sizeof (a_A4vm_exec0_funcInfo)); a = (a + 1) & -2; c = (c + 1) & -2;
inf->prv = a_VecChr_N(vcStk); a_VecChr_resizeDiff(vcStk, (a + b * 2 + c) * sizeof (intptr_t));
inf->reg = inf->prv; inf->frg = inf->reg + a * sizeof (intptr_t); inf->subArg = inf->frg + b * 2 * sizeof (intptr_t);
reg = (intptr_t *) (vcStk->p + inf->reg); frg = (double *) (vcStk->p + inf->frg); subArg = (intptr_t *) (vcStk->p + inf->subArg);
arg = (intptr_t *) (vcStk->p + argIdx); continue;
case 0x3f: // leave/return
inf = a_VecChr_stkRmv(vcInf, sizeof (a_A4vm_exec0_funcInfo));
a_VecChr_N(vcStk) = inf->prv; if (a_VecChr_N(vcInf) == 0) goto fin;
inf--; reg = (intptr_t *) (vcStk->p + inf->reg); frg = (double *) (vcStk->p + inf->frg); subArg = (intptr_t *) (vcStk->p + inf->subArg);
argIdx = inf->arg; arg = (intptr_t *) (vcStk->p + argIdx); pc = inf->pc; continue;
case 0x40: frg[a] = (double) *(float *) &bp[pc - 2]; continue;
case 0x41: frg[a] = frg[b]; continue;
case 0x42: frg[a] = (double) reg[b]; continue;
case 0x43: reg[a] = (intptr_t) frg[b]; continue;
case 0x44: frg[a] = *(double *) &bp[pc - 2]; continue;
case 0x45: if (a >= 256) { *(double *) &arg[a - 256] = *(double *) &bp[pc - 2]; } else { *(double *) &subArg[a] = *(double *) &bp[pc - 2]; } continue;// lod_AJ
case 0x46: frg[a] = (double) *(float *) &bp[pc - 1] - frg[b]; continue;
case 0x47: frg[a] = (double) *(float *) &bp[pc - 1] / frg[b]; continue;
case 0x48: frg[a] = frg[b] + (double) *(float *) &bp[pc - 1]; continue;
case 0x49: frg[a] = frg[b] + frg[c]; continue;
case 0x4a: frg[a] = frg[b] - (double) *(float *) &bp[pc - 1]; continue;
case 0x4b: frg[a] = frg[b] - frg[c]; continue;
case 0x4c: frg[a] = frg[b] * (double) *(float *) &bp[pc - 1]; continue;
case 0x4d: frg[a] = frg[b] * frg[c]; continue;
case 0x4e: frg[a] = frg[b] / (double) *(float *) &bp[pc - 1]; continue;
case 0x4f: frg[a] = frg[b] / frg[c]; continue;
case 0x50: frg[a] = fabs(frg[b]); continue;
case 0x51: frg[a] = sqrt(frg[b]); continue;
case 0x52: frg[a] = exp(frg[b]); continue;
case 0x53: frg[a] = log(frg[b]); continue;
case 0x54: frg[a] = cos(frg[b]); continue;
case 0x55: frg[a] = sin(frg[b]); continue;
case 0x56: frg[a] = tan(frg[b]); continue;
case 0x57: frg[a] = pow(frg[b], frg[c]); continue;
case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: case 0x5d:
case 0x5e: frg[a] = floor(frg[b]); continue;
case 0x5f: frg[a] = ceil(frg[b]); continue;
case 0x60: reg[a] = (frg[b] < (double) *(float *) &bp[pc - 1]); continue;
case 0x61: reg[a] = (frg[b] < frg[c]); continue;
case 0x62: reg[a] = (frg[b] >= (double) *(float *) &bp[pc - 1]); continue;
case 0x63: reg[a] = (frg[b] >= frg[c]); continue;
case 0x64: reg[a] = (frg[b] <= (double) *(float *) &bp[pc - 1]); continue;
case 0x65: reg[a] = (frg[b] <= frg[c]); continue;
case 0x66: reg[a] = (frg[b] > (double) *(float *) &bp[pc - 1]); continue;
case 0x67: reg[a] = (frg[b] > frg[c]); continue;
case 0x68: reg[a] = (frg[b] == (double) *(float *) &bp[pc - 1]); continue;
case 0x69: reg[a] = (frg[b] == frg[c]); continue;
case 0x6a: reg[a] = (frg[b] != (double) *(float *) &bp[pc - 1]); continue;
case 0x6b: reg[a] = (frg[b] != frg[c]); continue;
case 0x6c: if (b >= 256) { frg[a] = *(double *) &arg[b - 256]; } else { frg[a] = *(double *) &subArg[b]; } continue; // Lod_FA
case 0x6d: if (a >= 256) { *(double *) &arg[a - 256] = frg[b]; } else { *(double *) &subArg[a] = frg[b]; } continue; // Lod_AF
case 0x6e:
case 0x6f:
case 0x70: if (frg[b] < (double) *(float *) &bp[pc - 1]) { pc = lab[a]; } continue;
case 0x71: if (frg[b] < frg[c]) { pc = lab[a]; } continue;
case 0x72: if (frg[b] >= (double) *(float *) &bp[pc - 1]) { pc = lab[a]; } continue;
case 0x73: if (frg[b] >= frg[c]) { pc = lab[a]; } continue;
case 0x74: if (frg[b] <= (double) *(float *) &bp[pc - 1]) { pc = lab[a]; } continue;
case 0x75: if (frg[b] <= frg[c]) { pc = lab[a]; } continue;
case 0x76: if (frg[b] > (double) *(float *) &bp[pc - 1]) { pc = lab[a]; } continue;
case 0x77: if (frg[b] > frg[c]) { pc = lab[a]; } continue;
case 0x78: if (frg[b] == (double) *(float *) &bp[pc - 1]) { pc = lab[a]; } continue;
case 0x79: if (frg[b] == frg[c]) { pc = lab[a]; } continue;
case 0x7a: if (frg[b] != (double) *(float *) &bp[pc - 1]) { pc = lab[a]; } continue;
case 0x7b: if (frg[b] != frg[c]) { pc = lab[a]; } continue;
case 0x7c:
case 0x7d:
case 0x7e:
case 0x7f:
;
}
}
fin:
retVal = arg[0];
a_memcpy(argv, vcStk->p, argc * sizeof (intptr_t));
err:
a_VecChr_din4(_a_ vcLbl, vcInf, vcStk, 0);
return retVal;
}
** (99) 更新履歴
-2026.04.26(日) 初版