COMETII命令実行部分を、switch文から関数ポインタへ変更
authorj8takagi <j8takagi@nifty.com>
Wed, 30 Mar 2011 15:39:57 +0000 (00:39 +0900)
committerj8takagi <j8takagi@nifty.com>
Wed, 30 Mar 2011 15:39:57 +0000 (00:39 +0900)
include/exec.h
include/struct.h
src/cmd.c
src/exec.c

index f0788df..dbf2c49 100644 (file)
@@ -38,9 +38,152 @@ void addcerrlist_load();
  */
 bool loadassemble(char *file);
 
-/* COMET II仮想マシンのリセット */
+/**
+ * COMET II仮想マシンのリセット
+ */
 void reset();
 
+/**
+ * NOP命令
+ */
+void nop(const WORD r, const WORD v);
+
+/**
+ * LD命令
+ */
+void ld(const WORD r, const WORD v);
+
+/**
+ * ST命令
+ */
+void st(const WORD r, const WORD v);
+
+/**
+ * LAD命令
+ */
+void lad(const WORD r, const WORD v);
+
+/**
+ * ADDA命令
+ */
+void adda(const WORD r, const WORD v);
+
+/**
+ * SUBA命令
+ */
+void suba(const WORD r, const WORD v);
+
+/**
+ * ADDL命令
+ */
+void addl(const WORD r, const WORD v);
+
+/**
+ * SUBL命令
+ */
+void subl(const WORD r, const WORD v);
+
+/**
+ * AND命令
+ */
+void and(const WORD r, const WORD v);
+
+/**
+ * OR命令
+ */
+void or(const WORD r, const WORD v);
+
+/**
+ * XOR命令
+ */
+void xor(const WORD r, const WORD v);
+
+/**
+ * CPA命令
+ */
+void cpa(const WORD r, const WORD v);
+
+/**
+ * CPL命令
+ */
+void cpl(const WORD r, const WORD v);
+
+/**
+ * SLA命令
+ */
+void sla(const WORD r, const WORD v);
+
+/**
+ * SRA命令
+ */
+void sra(const WORD r, const WORD v);
+
+/**
+ * SLL命令
+ */
+void sll(const WORD r, const WORD v);
+
+/**
+ * SRL命令
+ */
+void srl(const WORD r, const WORD v);
+
+/**
+ * JMI命令
+ */
+void jmi(const WORD r, const WORD v);
+
+/**
+ * JNZ命令
+ */
+void jnz(const WORD r, const WORD v);
+
+/**
+ * JZE命令
+ */
+void jze(const WORD r, const WORD v);
+
+/**
+ * JUMP命令
+ */
+void jump(const WORD r, const WORD v);
+
+/**
+ * JPL命令
+ */
+void jpl(const WORD r, const WORD v);
+
+/**
+ * JOV命令
+ */
+void jov(const WORD r, const WORD v);
+
+/**
+ * PUSH命令
+ */
+void push(const WORD r, const WORD v);
+
+/**
+ * POP命令
+ */
+void pop(const WORD r, const WORD v);
+
+/**
+ * CALL命令
+ */
+void call(const WORD r, const WORD v);
+
+/**
+ * RET命令
+ */
+void ret(const WORD r, const WORD v);
+
+/**
+ * SVC命令
+ */
+void svc(const WORD r, const WORD v);
+
+
 /**
  * COMET II仮想マシンの実行
  */
index 39f874b..de1aa4b 100644 (file)
@@ -97,6 +97,7 @@ typedef struct {
     char *name;                 /**<命令名 */
     CMDTYPE type;               /**<命令タイプ */
     WORD code;                  /**<命令コード */
+    const void (*ptr);                   /**<命令の関数ポインタ */
 } CMD;
 
 /**
@@ -154,6 +155,11 @@ bool create_code_type();
  */
 CMDTYPE getcmdtype(WORD code);
 
+/**
+ * 命令コードから命令の関数ポインタを返す
+ */
+const void (*getcmdptr(WORD code));
+
 /**
  * コードがキーの命令ハッシュ表を解放する
  */
index 04acd32..aa435b9 100644 (file)
--- a/src/cmd.c
+++ b/src/cmd.c
@@ -4,49 +4,50 @@
 #include "hash.h"
 #include "struct.h"
 #include "cmem.h"
+#include "exec.h"
 
 /**
  * 機械語命令のリスト
  */
 static CMD comet2cmd[] = {
-    { "NOP", NONE, 0x0 },
-    { "LD", R_ADR_X_, 0x1000 },
-    { "ST", R_ADR_X, 0x1100 },
-    { "LAD", R_ADR_X, 0x1200 },
-    { "LD", R1_R2, 0x1400 },
-    { "ADDA", R_ADR_X_, 0x2000 },
-    { "SUBA", R_ADR_X_, 0x2100 },
-    { "ADDL", R_ADR_X_, 0x2200 },
-    { "SUBL", R_ADR_X_, 0x2300 },
-    { "ADDA", R1_R2, 0x2400 },
-    { "SUBA", R1_R2, 0x2500 },
-    { "ADDL", R1_R2, 0x2600 },
-    { "SUBL", R1_R2, 0x2700 },
-    { "AND", R_ADR_X_, 0x3000 },
-    { "OR", R_ADR_X_, 0x3100 },
-    { "XOR", R_ADR_X_, 0x3200 },
-    { "AND", R1_R2, 0x3400 },
-    { "OR", R1_R2, 0x3500 },
-    { "XOR", R1_R2, 0x3600 },
-    { "CPA", R_ADR_X_, 0x4000 },
-    { "CPL", R_ADR_X_, 0x4100 },
-    { "CPA", R1_R2, 0x4400 },
-    { "CPL", R1_R2, 0x4500 },
-    { "SLA", R_ADR_X, 0x5000 },
-    { "SRA", R_ADR_X, 0x5100 },
-    { "SLL", R_ADR_X, 0x5200 },
-    { "SRL", R_ADR_X, 0x5300 },
-    { "JMI", ADR_X, 0x6100 },
-    { "JNZ", ADR_X, 0x6200 },
-    { "JZE", ADR_X, 0x6300 },
-    { "JUMP", ADR_X, 0x6400 },
-    { "JPL", ADR_X, 0x6500 },
-    { "JOV", ADR_X, 0x6600 },
-    { "PUSH", ADR_X, 0x7000 },
-    { "POP", R_, 0x7100 },
-    { "CALL", ADR_X, 0x8000 },
-    { "SVC", ADR_X, 0xF000 },
-    { "RET", NONE, 0x8100 },
+    { "NOP", NONE, 0x0, nop },
+    { "LD", R_ADR_X_, 0x1000, ld },
+    { "ST", R_ADR_X, 0x1100, st },
+    { "LAD", R_ADR_X, 0x1200, lad },
+    { "LD", R1_R2, 0x1400, ld },
+    { "ADDA", R_ADR_X_, 0x2000, adda },
+    { "SUBA", R_ADR_X_, 0x2100, suba },
+    { "ADDL", R_ADR_X_, 0x2200, addl },
+    { "SUBL", R_ADR_X_, 0x2300, subl },
+    { "ADDA", R1_R2, 0x2400, adda },
+    { "SUBA", R1_R2, 0x2500, suba },
+    { "ADDL", R1_R2, 0x2600, addl },
+    { "SUBL", R1_R2, 0x2700, subl },
+    { "AND", R_ADR_X_, 0x3000, and },
+    { "OR", R_ADR_X_, 0x3100, or },
+    { "XOR", R_ADR_X_, 0x3200, xor },
+    { "AND", R1_R2, 0x3400, and },
+    { "OR", R1_R2, 0x3500, or },
+    { "XOR", R1_R2, 0x3600, xor },
+    { "CPA", R_ADR_X_, 0x4000, cpa },
+    { "CPL", R_ADR_X_, 0x4100, cpl },
+    { "CPA", R1_R2, 0x4400, cpa },
+    { "CPL", R1_R2, 0x4500, cpl },
+    { "SLA", R_ADR_X, 0x5000, sla },
+    { "SRA", R_ADR_X, 0x5100, sra },
+    { "SLL", R_ADR_X, 0x5200, sll },
+    { "SRL", R_ADR_X, 0x5300, srl },
+    { "JMI", ADR_X, 0x6100, jmi },
+    { "JNZ", ADR_X, 0x6200, jnz },
+    { "JZE", ADR_X, 0x6300, jze },
+    { "JUMP", ADR_X, 0x6400, jump },
+    { "JPL", ADR_X, 0x6500, jpl },
+    { "JOV", ADR_X, 0x6600, jov },
+    { "PUSH", ADR_X, 0x7000, push },
+    { "POP", R_, 0x7100, pop },
+    { "CALL", ADR_X, 0x8000, call },
+    { "SVC", ADR_X, 0xF000, svc },
+    { "RET", NONE, 0x8100, ret },
 };
 
 /**
@@ -199,6 +200,23 @@ CMDTYPE getcmdtype(WORD code)
     return t;
 }
 
+/**
+ * 命令コードから命令の関数ポインタを返す
+ */
+const void (*getcmdptr(WORD code))
+{
+    CMDTAB *t;
+    const void (*ptr);
+
+    for(t = code_type[hash_code(code)]; t != NULL; t = t->next) {
+        if(code == t->cmd->code) {
+            ptr = t->cmd->ptr;
+            break;
+        }
+    }
+    return ptr;
+}
+
 /**
  * コードがキーの命令ハッシュ表を解放する
  */
index 5d8f62f..62d0b13 100644 (file)
@@ -71,6 +71,16 @@ bool loadassemble(char *file)
     return status;
 }
 
+/**
+ * プログラムレジスタ(PR)を表す文字列を返す
+ **/
+static char *pr2str(WORD pr) {
+    char *str = malloc_chk(CERRSTRSIZE + 1, "pr2str.pr");
+
+    sprintf(str, "PR:#%04X", pr);
+    return str;
+}
+
 /**
  * 標準入力から文字データを読込(SVC 1)
  */
@@ -138,108 +148,160 @@ static void setfr(WORD val)
 }
 
 /**
- * 算術加算。フラグを設定して値を返す
+ * NOP命令
  */
-static WORD adda(WORD val0, WORD val1)
+void nop(const WORD r, const WORD v)
+{
+
+}
+
+/**
+ * LD命令
+ */
+void ld(const WORD r, const WORD v)
+{
+    setfr(sys->cpu->gr[r] = v);
+}
+
+/**
+ * ST命令
+ */
+void st(const WORD r, const WORD v)
+{
+    sys->memory[v] = sys->cpu->gr[r];
+}
+
+/**
+ * LAD命令
+ */
+void lad(const WORD r, const WORD v)
+{
+    sys->cpu->gr[r] = v;
+}
+
+/**
+ * ADDA命令
+ */
+void adda(const WORD r, const WORD v)
 {
-    WORD res;
     long tmp;
 
     sys->cpu->fr = 0x0;
     /* 引数の値を16ビット符号付整数として加算し、オーバーフローをチェック */
     assert(sizeof(short) * 8 == 16 && (short)0xFFFF == -1);
-    if((tmp = (short)val0 + (short)val1) > 32767 || tmp < -32768) {
+    if((tmp = (short)(sys->cpu->gr[r]) + (short)v) > 32767 || tmp < -32768) {
         sys->cpu->fr += OF;
     }
     /* 加算した結果を、WORD値に戻す */
-    res = (WORD)(tmp & 0xFFFF);
-    if((res & 0x8000) == 0x8000) {
+    sys->cpu->gr[r] = (WORD)(tmp & 0xFFFF);
+    if((sys->cpu->gr[r] & 0x8000) == 0x8000) {
         sys->cpu->fr += SF;
-    } else if(res == 0x0) {
+    } else if(sys->cpu->gr[r] == 0x0) {
         sys->cpu->fr += ZF;
     }
-    return res;
 }
 
 /**
- * 算術減算。フラグを設定して値を返す
+ * SUBA命令
  */
-static WORD suba(WORD val0, WORD val1)
+void suba(const WORD r, const WORD v)
 {
-    return adda(val0, (~val1 + 1));
+    adda(r, (~v + 1));
 }
 
 /**
- * 論理加算。フラグを設定して値を返す
+ * ADDL命令
  */
-static WORD addl(WORD val0, WORD val1)
+void addl(const WORD r, const WORD v)
 {
     long tmp;
-    WORD res;
     sys->cpu->fr = 0x0;
 
-    if((tmp = val0 + val1) < 0 || tmp > 65535) {
+    if((tmp = sys->cpu->gr[r] + v) < 0 || tmp > 65535) {
         sys->cpu->fr += OF;
     }
-    if(((res = (WORD)(tmp & 0xFFFF)) & 0x8000) == 0x8000) {
+    if(((sys->cpu->gr[r] = (WORD)(tmp & 0xFFFF)) & 0x8000) == 0x8000) {
         sys->cpu->fr += SF;
-    } else if(res == 0x0) {
+    } else if(sys->cpu->gr[r] == 0x0) {
         sys->cpu->fr += ZF;
     }
-    return res;
 }
 
 /**
- * 論理減算。フラグを設定して値を返す
+ * SUBL命令
+ */
+void subl(const WORD r, const WORD v)
+{
+    addl(r, (~v + 1));
+}
+
+/**
+ * AND命令
+ */
+void and(const WORD r, const WORD v)
+{
+    setfr(sys->cpu->gr[r] &= v);
+}
+
+/**
+ * OR命令
+ */
+void or(const WORD r, const WORD v)
+{
+    setfr(sys->cpu->gr[r] |= v);
+}
+
+/**
+ * XOR命令
  */
-static WORD subl(WORD val0, WORD val1)
+void xor(const WORD r, const WORD v)
 {
-    return addl(val0, (~val1 + 1));
+    setfr(sys->cpu->gr[r] ^= v);
 }
 
 /**
- * 算術比較のフラグ設定。OFは常に0
+ * CPA命令
  */
-static void cpa(WORD val0, WORD val1)
+void cpa(const WORD r, const WORD v)
 {
     sys->cpu->fr = 0x0;
-    if((short)val0 < (short)val1) {
+    if((short)sys->cpu->gr[r] < (short)v) {
         sys->cpu->fr = SF;
-    } else if(val0 == val1) {
+    } else if(sys->cpu->gr[r] == v) {
         sys->cpu->fr = ZF;
     }
 }
 
 /**
- * 論理比較のフラグ設定。OFは常に0
+ * CPL命令
  */
-static void cpl(WORD val0, WORD val1)
+void cpl(const WORD r, const WORD v)
 {
     sys->cpu->fr = 0x0;
-    if(val0 < val1) {
+    if(sys->cpu->gr[r] < v) {
         sys->cpu->fr = SF;
-    } else if(val0 == val1) {
+    } else if(sys->cpu->gr[r] == v) {
         sys->cpu->fr = ZF;
     }
 }
 
+
 /**
- * 算術左シフト。フラグを設定して値を返す
- * 算術演算なので、第15ビットは送り出されない
+ * SLA命令。算術演算なので、第15ビットは送り出されない
  */
-static WORD sla(WORD val0, WORD val1)
+void sla(const WORD r, const WORD v)
 {
-    WORD sign, res, last = 0x0;
+    WORD sign, last = 0x0;
     int i;
 
     sys->cpu->fr = 0x0;
-    sign = val0 & 0x8000;
-    res = val0 & 0x7FFF;
-    for(i = 0; i < val1; i++) {
-        last = res & 0x4000;
-        res <<= 1;
+    sign = sys->cpu->gr[r] & 0x8000;
+    sys->cpu->gr[r] &= 0x7FFF;
+    for(i = 0; i < v; i++) {
+        last = sys->cpu->gr[r] & 0x4000;
+        sys->cpu->gr[r] <<= 1;
     }
-    res = sign | (res & 0x7FFF);
+    sys->cpu->gr[r] = sign | (sys->cpu->gr[r] & 0x7FFF);
     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
     if(last > 0x0) {
         sys->cpu->fr += OF;
@@ -249,33 +311,32 @@ static WORD sla(WORD val0, WORD val1)
         sys->cpu->fr += SF;
     }
     /* 演算結果が0のとき、ZFは1 */
-    if(res == 0x0) {
+    if(sys->cpu->gr[r] == 0x0) {
         sys->cpu->fr += ZF;
     }
-    return res;
 }
 
 /**
- * 算術右シフト。フラグを設定して値を返す
+ * SRA命令
  * 算術演算なので、第15ビットは送り出されない
  * 空いたビット位置には符号と同じものが入る
  */
-static WORD sra(WORD val0, WORD val1)
+void sra(const WORD r, const WORD v)
 {
-    WORD sign, res, last = 0x0;
+    WORD sign, last = 0x0;
     int i;
 
     sys->cpu->fr = 0x0;
-    sign = val0 & 0x8000;
-    res = val0 & 0x7FFF;
-    for(i = 0; i < val1; i++) {
-        last = res & 0x1;
-        res >>= 1;
+    sign = sys->cpu->gr[r] & 0x8000;
+    sys->cpu->gr[r] &= 0x7FFF;
+    for(i = 0; i < v; i++) {
+        last = sys->cpu->gr[r] & 0x1;
+        sys->cpu->gr[r] >>= 1;
         if(sign > 0) {
-            res |= 0x4000;
+            sys->cpu->gr[r] |= 0x4000;
         }
     }
-    res = sign | res;
+    sys->cpu->gr[r] = sign | sys->cpu->gr[r];
     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
     if(last > 0x0) {
         sys->cpu->fr += OF;
@@ -285,76 +346,175 @@ static WORD sra(WORD val0, WORD val1)
         sys->cpu->fr += SF;
     }
     /* 演算結果が0のとき、ZFは1 */
-    if(res == 0x0) {
+    if(sys->cpu->gr[r] == 0x0) {
         sys->cpu->fr += ZF;
     }
-    return res;
 }
 
 /**
- * 論理左シフト。フラグを設定して値を返す
+ * SLL命令
  */
-static WORD sll(WORD val0, WORD val1)
+void sll(const WORD r, const WORD v)
 {
-    WORD res = val0, last = 0x0;
+    WORD last = 0x0;
     int i;
 
     sys->cpu->fr = 0x0;
-    for(i = 0; i < val1; i++) {
-        last = res & 0x8000;
-        res <<= 1;
+    for(i = 0; i < v; i++) {
+        last = sys->cpu->gr[r] & 0x8000;
+        sys->cpu->gr[r] <<= 1;
     }
     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
     if(last > 0x0) {
         sys->cpu->fr += OF;
     }
     /* 第15ビットが1のとき、SFは1 */
-    if((res & 0x8000) > 0x0) {
+    if((sys->cpu->gr[r] & 0x8000) > 0x0) {
         sys->cpu->fr += SF;
     }
     /* 演算結果が0のとき、ZFは1 */
-    if(res == 0x0) {
+    if(sys->cpu->gr[r] == 0x0) {
         sys->cpu->fr += ZF;
     }
-    return res;
 }
 
 /**
- * 論理右シフト。フラグを設定して値を返す
+ * SRL命令
  */
-static WORD srl(WORD val0, WORD val1)
+void srl(const WORD r, const WORD v)
 {
-    WORD res = val0, last = 0x0;
+    WORD last = 0x0;
     int i;
 
     sys->cpu->fr = 0x0;
-    for(i = 0; i < val1; i++) {
-        last = res & 0x0001;
-        res >>= 1;
+    for(i = 0; i < v; i++) {
+        last = sys->cpu->gr[r] & 0x0001;
+        sys->cpu->gr[r] >>= 1;
     }
     /* OFに、レジスタから最後に送り出されたビットの値を設定 */
     if(last > 0x0) {
         sys->cpu->fr += OF;
     }
     /* 第15ビットが1のとき、SFは1 */
-    if((res & 0x8000) > 0x0) {
+    if((sys->cpu->gr[r] & 0x8000) > 0x0) {
         sys->cpu->fr += SF;
     }
     /* 演算結果が0のとき、ZFは1 */
-    if(res == 0x0) {
+    if(sys->cpu->gr[r] == 0x0) {
         sys->cpu->fr += ZF;
     }
-    return res;
 }
 
 /**
- * プログラムレジスタ(PR)を表す文字列を返す
- **/
-static char *pr2str(WORD pr) {
-    char *str = malloc_chk(CERRSTRSIZE + 1, "pr2str.pr");
+ * JMI命令
+ */
+void jmi(const WORD r, const WORD v)
+{
+    if((sys->cpu->fr & SF) > 0) {
+        sys->cpu->pr = v;
+    }
+}
 
-    sprintf(str, "PR:#%04X", pr);
-    return str;
+/**
+ * JNZ命令
+ */
+void jnz(const WORD r, const WORD v)
+{
+    if((sys->cpu->fr & ZF) == 0) {
+        sys->cpu->pr = v;
+    }
+}
+
+/**
+ * JZE命令
+ */
+void jze(const WORD r, const WORD v)
+{
+    if((sys->cpu->fr & ZF) > 0) {
+        sys->cpu->pr = v;
+    }
+}
+
+/**
+ * JUMP命令
+ */
+void jump(const WORD r, const WORD v)
+{
+    sys->cpu->pr = v;
+}
+
+/**
+ * JPL命令
+ */
+void jpl(const WORD r, const WORD v)
+{
+    if((sys->cpu->fr & (SF | ZF)) == 0) {
+        sys->cpu->pr = v;
+    }
+}
+
+/**
+ * JOV命令
+ */
+void jov(const WORD r, const WORD v)
+{
+    if((sys->cpu->fr & OF) > 0) {
+        sys->cpu->pr = v;
+    }
+}
+
+/**
+ * PUSH命令
+ */
+void push(const WORD r, const WORD v)
+{
+    assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
+    sys->memory[--(sys->cpu->sp)] = v;
+}
+
+/**
+ * POP命令
+ */
+void pop(const WORD r, const WORD v)
+{
+    assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
+    sys->cpu->gr[r] = sys->memory[(sys->cpu->sp)++];
+}
+
+/**
+ * CALL命令
+ */
+void call(const WORD r, const WORD v)
+{
+    assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
+    sys->memory[--(sys->cpu->sp)] = sys->cpu->pr;
+    sys->cpu->pr = v;
+}
+
+/**
+ * RET命令
+ */
+void ret(const WORD r, const WORD v)
+{
+    if(sys->cpu->sp < sys->memsize) {
+        sys->cpu->pr = sys->memory[(sys->cpu->sp)++];
+    }
+}
+
+/**
+ * SVC命令
+ */
+void svc(const WORD r, const WORD v)
+{
+    switch(v)
+    {
+    case 0x1:                   /* IN */
+        svcin();
+        break;
+    case 0x2:                   /* OUT */
+        svcout();
+        break;
+    }
 }
 
 /**
@@ -364,6 +524,7 @@ bool exec()
 {
     WORD op, r_r1, x_r2, val;
     CMDTYPE cmdtype;
+    void (*cmdptr)();
     clock_t clock_begin, clock_end;
 
     if(execmode.trace == true) {
@@ -388,16 +549,16 @@ bool exec()
         else if(sys->cpu->sp > sys->memsize) {
             setcerr(207, pr2str(sys->cpu->pr));    /* Stack Pointer (SP) - out of COMET II memory */
         }
-        /* エラー発生時は終了 */
-        if(cerr->num > 0) {
-            goto execerr;
-        }
         /* 命令の取り出し */
         op = sys->memory[sys->cpu->pr] & 0xFF00;
         /* 命令の解読 */
         if((cmdtype = getcmdtype(op)) == NOTCMD) {
             setcerr(210, pr2str(sys->cpu->pr));          /* not command code of COMET II */
         }
+        /* エラー発生時は終了 */
+        if(cerr->num > 0) {
+            goto execerr;
+        }
         r_r1 = (sys->memory[sys->cpu->pr] >> 4) & 0xF;
         x_r2 = sys->memory[sys->cpu->pr] & 0xF;
         /* traceオプション指定時、レジスタを出力 */
@@ -450,121 +611,11 @@ bool exec()
             op &= 0xFB00;
         }
         /* 命令の実行 */
-        switch(op)
-        {
-        case 0x0:       /* NOP */
-            break;
-        case 0x1000:    /* LD */
-            setfr(sys->cpu->gr[r_r1] = val);
-            break;
-        case 0x1100:    /* ST */
-            sys->memory[val] = sys->cpu->gr[r_r1];
-            break;
-        case 0x1200:    /* LAD */
-            sys->cpu->gr[r_r1] = val;
-            break;
-        case 0x2000:    /* ADDA */
-            sys->cpu->gr[r_r1] = adda(sys->cpu->gr[r_r1], val);
-            break;
-        case 0x2100:    /* SUBA */
-            sys->cpu->gr[r_r1] = suba(sys->cpu->gr[r_r1], val);
-            break;
-        case 0x2200:    /* ADDL */
-            sys->cpu->gr[r_r1] = addl(sys->cpu->gr[r_r1], val);
-            break;
-        case 0x2300:    /* SUBL */
-            sys->cpu->gr[r_r1] = subl(sys->cpu->gr[r_r1], val);
-            break;
-        case 0x3000:    /* AND */
-            setfr(sys->cpu->gr[r_r1] &= val);
-            break;
-        case 0x3100:    /* OR */
-            setfr(sys->cpu->gr[r_r1] |= val);
-            break;
-        case 0x3200:    /* XOR */
-            setfr(sys->cpu->gr[r_r1] ^= val);
-            break;
-        case 0x4000:    /* CPA */
-            cpa(sys->cpu->gr[r_r1], val);
-            break;
-        case 0x4100:    /* CPL */
-            cpl(sys->cpu->gr[r_r1], val);
-            break;
-        case 0x5000:    /* SLA */
-            sys->cpu->gr[r_r1] = sla(sys->cpu->gr[r_r1], val);
-            break;
-        case 0x5100:    /* SRA */
-            sys->cpu->gr[r_r1] = sra(sys->cpu->gr[r_r1], val);
-            break;
-        case 0x5200:    /* SLL */
-            sys->cpu->gr[r_r1] = sll(sys->cpu->gr[r_r1], val);
-            break;
-        case 0x5300:    /* SRL */
-            sys->cpu->gr[r_r1] = srl(sys->cpu->gr[r_r1], val);
-            break;
-        case 0x6100:    /* JMI */
-            if((sys->cpu->fr & SF) > 0) {
-                sys->cpu->pr = val;
-            }
-            break;
-        case 0x6200:    /* JNZ */
-            if((sys->cpu->fr & ZF) == 0) {
-                sys->cpu->pr = val;
-            }
-            break;
-        case 0x6300:    /* JZE */
-            if((sys->cpu->fr & ZF) > 0) {
-                sys->cpu->pr = val;
-            }
-            break;
-        case 0x6400:    /* JUMP */
-            sys->cpu->pr = val;
-            break;
-        case 0x6500:    /* JPL */
-            if((sys->cpu->fr & (SF | ZF)) == 0) {
-                sys->cpu->pr = val;
-            }
-            break;
-        case 0x6600:    /* JOV */
-            if((sys->cpu->fr & OF) > 0) {
-                sys->cpu->pr = val;
-            }
-            break;
-        case 0x7000:    /* PUSH */
-            assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
-            sys->memory[--(sys->cpu->sp)] = val;
-            break;
-        case 0x7100:    /* POP */
-            assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
-            sys->cpu->gr[r_r1] = sys->memory[(sys->cpu->sp)++];
-            break;
-        case 0x8000:    /* CALL */
-            assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
-            sys->memory[--(sys->cpu->sp)] = sys->cpu->pr;
-            sys->cpu->pr = val;
-            break;
-        case 0x8100:    /* RET */
-            assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
-            if(sys->cpu->sp == sys->memsize) {
-                return true;
-            } else {
-                sys->cpu->pr = sys->memory[(sys->cpu->sp)++];
-                break;
-            }
-        case 0xF000:    /* SVC */
-            switch(val)
-            {
-            case 0x0: /* EXIT */
-                return true;
-            case 0x1: /* IN */
-                svcin();
-                break;
-            case 0x2: /* OUT */
-                svcout();
-                break;
-            }
-        default:
-            break;
+        if((op == 0x8100 && sys->cpu->sp == sys->memsize) || (op == 0xF000 && val == 0x0)) {
+            return true;
+        } else {
+            cmdptr = getcmdptr(op);
+            (*cmdptr)(r_r1, val);
         }
         /* クロック周波数の設定 */
         do {