#include "cerr.h"
/**
- * 実行エラーの定義
+ * @brief プログラムレジスタ(PR)を表すWORD値を文字列に変換
+ *
+ * @return 文字列「PR:XXXX」(Xは16進数の数字)
+ *
+ * @param pr プログラムレジスタ(PR)を表すWORD値
+ */
+char *pr2str(WORD pr);
+
+/**
+ * @brief 標準入力から文字データを読込(SVC 1)
+ *
+ * @return なし
+ */
+void svcin();
+
+/**
+ * @brief 標準出力へ文字データを書出(SVC 2)
+ *
+ * @return なし
+ */
+void svcout();
+
+/**
+ * @brief ロード/論理積/論理和/排他的論理和のフラグ設定。OFは常に0
+ *
+ * @return なし
+ *
+ * @param adr アドレス
+ */
+void setfr(WORD adr);
+
+/**
+ * @brief WORD値からr/r1を取得
+ *
+ * @return r/r1を表すWORD値
+ *
+ * @param oprx オペランドを表すWORD値
+ */
+WORD get_r_r1(WORD oprx);
+
+/**
+ * @brief WORD値からx/r2を取得
+ *
+ * @return x/r2を表すWORD値
+ *
+ * @param oprx オペランドを表すWORD値
+ */
+WORD get_x_r2(WORD oprx);
+
+/**
+ * @brief 2つのWORD値からadr[,x]を取得
+ *
+ * @return adr[,x]を表すWORD値
+ *
+ * @param adr アドレスを表すWORD値
+ * @param oprx オペランドを表すWORD値
+ */
+WORD get_adr_x(WORD adr, WORD oprx);
+
+/**
+ * @brief 2つのWORD値からadr[,x]のアドレスに格納されている値を取得
+ *
+ * @return adr[,x]のアドレスに格納されている値を表すWORD値
+ *
+ * @param adr アドレスを表すWORD値
+ * @param oprx オペランドを表すWORD値
+ */
+WORD get_val_adr_x(WORD adr, WORD oprx);
+
+/**
+ * @brief 実行エラーの定義
*/
static CERR cerr_exec[] = {
{ 201, "Program Register (PR) - memory overflow" },
};
/**
- * アセンブル結果読み込みエラーの定義
+ * @brief アセンブル結果読み込みエラーの定義
*/
static CERR cerr_load[] = {
{ 210, "load - memory overflow" },
};
/**
- * 実行モード: trace, logical, dump
+ * @brief 実行モード: trace, logical, dump
*/
EXECMODE execmode = {false, false, false};
-/**
- * アセンブル結果読み込みエラーをエラーリストに追加
- */
-void addcerrlist_load()
+char *pr2str(WORD pr)
{
- addcerrlist(ARRAYSIZE(cerr_load), cerr_load);
-}
-
-/**
- * 実行エラーをエラーリストに追加
- */
-void addcerrlist_exec()
-{
- addcerrlist(ARRAYSIZE(cerr_exec), cerr_exec);
-}
-/**
- * 指定されたファイルからアセンブル結果を読み込む
- */
-bool loadassemble(const char *file)
-{
- FILE *fp;
- bool stat = true;
-
- assert(file != NULL);
- if((fp = fopen(file, "r")) == NULL) {
- perror(file);
- return false;
- }
- execptr->end = execptr->start +
- fread(sys->memory, sizeof(WORD), sys->memsize - execptr->start, fp);
- if(execptr->end == sys->memsize) {
- setcerr(210, file); /* load - memory overflow */
- fprintf(stderr, "Load error - %d: %s\n", cerr->num, cerr->msg);
- stat = false;
- }
- fclose(fp);
- return stat;
-}
-
-/**
- * プログラムレジスタ(PR)を表す文字列を返す
- */
-char *pr2str(WORD pr) {
char *str = malloc_chk(CERRSTRSIZE + 1, "pr2str.pr");
sprintf(str, "PR:#%04X", pr);
return str;
}
-/**
- * 標準入力から文字データを読込(SVC 1)
- */
void svcin()
{
int i;
FREE(buffer);
}
-/**
- * 標準出力へ文字データを書出(SVC 2)
- */
void svcout()
{
int i;
}
}
-/**
- * ロード/論理積/論理和/排他的論理和のフラグ設定。OFは常に0
- */
void setfr(WORD adr)
{
sys->cpu->fr = 0x0;
}
}
-/**
- * WORD値からr/r1を取得
- */
WORD get_r_r1(WORD oprx)
{
WORD r;
return r;
}
-/**
- * WORD値からx/r2を取得
- */
WORD get_x_r2(WORD oprx)
{
WORD x;
return x;
}
-/**
- * 2つのWORD値からadr[,x]を取得
- */
WORD get_adr_x(WORD adr, WORD oprx)
{
WORD a = adr, x;
return a;
}
-
-/**
- * 2つのWORD値からadr[,x]のアドレスに格納されている内容を取得
- */
WORD get_val_adr_x(WORD adr, WORD oprx)
{
WORD a;
return sys->memory[a];
}
-/**
- * NOP命令。語長1(OPのみ)
- * \relates exec
- */
+/* exec.hで定義された関数群 */
+void addcerrlist_load()
+{
+ addcerrlist(ARRAYSIZE(cerr_load), cerr_load);
+}
+
+void addcerrlist_exec()
+{
+ addcerrlist(ARRAYSIZE(cerr_exec), cerr_exec);
+}
+
+bool loadassemble(const char *file)
+{
+ FILE *fp;
+ bool stat = true;
+
+ assert(file != NULL);
+ if((fp = fopen(file, "rb")) == NULL) {
+ perror(file);
+ return false;
+ }
+ execptr->end = execptr->start +
+ fread(sys->memory, sizeof(WORD), sys->memsize - execptr->start, fp);
+ if(execptr->end == sys->memsize) {
+ setcerr(210, file); /* load - memory overflow */
+ fprintf(stderr, "Load error - %d: %s\n", cerr->num, cerr->msg);
+ stat = false;
+ }
+ fclose(fp);
+ return stat;
+}
+
void nop()
{
sys->cpu->pr += 1;
}
-/**
- * LD命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void ld_r_adr_x()
{
WORD w[2];
sys->cpu->pr += 2;
}
-/**
- * LD命令 - オペランドr1,r2。語長1
- * \relates exec
- */
void ld_r1_r2()
{
WORD w[1];
sys->cpu->pr += 1;
}
-/**
- * ST命令。語長2
- * \relates exec
- */
void st()
{
WORD w[2];
sys->cpu->pr += 2;
}
-/**
- * LAD命令。語長2
- * \relates exec
- */
void lad()
{
WORD w[2];
sys->cpu->pr += 2;
}
-/**
- * ADDA命令のテンプレート\n
- * 汎用レジスタrに値valを算術加算
- */
void adda(WORD r, WORD val)
{
long tmp;
}
}
-/**
- * ADDA命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void adda_r_adr_x()
{
WORD w[2];
sys->cpu->pr += 2;
}
-/**
- * ADDA命令 - オペランドr1,r2。語長1
- * \relates exec
- */
void adda_r1_r2()
{
WORD w[1];
sys->cpu->pr += 1;
}
-/**
- * SUBA命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void suba_r_adr_x()
{
WORD w[2];
sys->cpu->pr += 2;
}
-/**
- * SUBA命令 - オペランドr1,r2。語長1
- * \relates exec
- */
void suba_r1_r2()
{
WORD w[1];
sys->cpu->pr += 1;
}
-/**
- * ADDL命令のテンプレート\n
- * 汎用レジスタrに値valを論理加算
- */
-void addl(WORD r, WORD val)
+void addl_gr(WORD r, WORD val, bool add)
{
- long tmp;
- sys->cpu->fr = 0x0;
+ unsigned long o, s;
- if((tmp = sys->cpu->gr[r] + val) < 0 || tmp > 65535) {
- sys->cpu->fr += OF;
+ o = sys->cpu->gr[r];
+ sys->cpu->fr = 0x0; /* flag initialize */
+
+ if(add == true) {
+ s = o + val;
+ if(s > 0xFFFF) {
+ sys->cpu->fr += OF;
+ }
+ } else {
+ if(o < val) {
+ sys->cpu->fr += OF;
+ }
+ s = o + (~val + 1);
+ if(s > 0xFFFF) {
+ s &= 0xFFFF;
+ }
}
- if(((sys->cpu->gr[r] = (WORD)(tmp & 0xFFFF)) & 0x8000) == 0x8000) {
+ sys->cpu->gr[r] = (WORD)s;
+
+ if((s & 0x8000) == 0x8000) {
sys->cpu->fr += SF;
- } else if(sys->cpu->gr[r] == 0x0) {
+ }
+ else if(s == 0x0) {
sys->cpu->fr += ZF;
}
}
-/**
- * ADDL命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void addl_r_adr_x()
{
WORD w[2];
w[0] = sys->memory[sys->cpu->pr];
w[1] = sys->memory[sys->cpu->pr + 1];
- addl(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]));
+ addl_gr(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]), true);
sys->cpu->pr += 2;
}
-/**
- * ADDL命令 - オペランドr1,r2。語長1
- * \relates exec
- */
void addl_r1_r2()
{
WORD w[1];
w[0] = sys->memory[sys->cpu->pr];
- addl(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])]);
+ addl_gr(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])], true);
sys->cpu->pr += 1;
}
-/**
- * SUBL命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void subl_r_adr_x()
{
WORD w[2];
w[0] = sys->memory[sys->cpu->pr];
w[1] = sys->memory[sys->cpu->pr + 1];
- addl(get_r_r1(w[0]), ~(get_val_adr_x(w[1], w[0])) + 1);
+ addl_gr(get_r_r1(w[0]), get_val_adr_x(w[1], w[0]), false);
sys->cpu->pr += 2;
}
-
-/**
- * SUBL命令 - オペランドr1,r2。語長1
- * \relates exec
- */
void subl_r1_r2()
{
WORD w[1];
w[0] = sys->memory[sys->cpu->pr];
- addl(get_r_r1(w[0]), ~(sys->cpu->gr[get_x_r2(w[0])]) + 1);
+ addl_gr(get_r_r1(w[0]), sys->cpu->gr[get_x_r2(w[0])], false);
sys->cpu->pr += 1;
}
-/**
- * AND命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void and_r_adr_x()
{
WORD w[2];
sys->cpu->pr += 2;
}
-/**
- * AND命令 - オペランドr1,r2。語長1
- * \relates exec
- */
void and_r1_r2()
{
WORD w[1];
sys->cpu->pr += 1;
}
-/**
- * OR命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void or_r_adr_x()
{
WORD w[2];
sys->cpu->pr += 2;
}
-/**
- * OR命令 - オペランドr1,r2。語長1
- * \relates exec
- */
void or_r1_r2()
{
WORD w[1];
sys->cpu->pr += 1;
}
-/**
- * XOR命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void xor_r_adr_x()
{
WORD w[2];
sys->cpu->pr += 2;
}
-/**
- * XOR命令 - オペランドr1,r2。語長1
- * \relates exec
- */
void xor_r1_r2()
{
WORD w[1];
sys->cpu->pr += 1;
}
-/**
- * CPA命令のテンプレート\n
- * 汎用レジスタrの内容と値valを算術比較
- */
void cpa(WORD r, WORD val)
{
sys->cpu->fr = 0x0;
}
}
-/**
- * CPA命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void cpa_r_adr_x()
{
WORD w[2];
sys->cpu->pr += 2;
}
-/**
- * CPA命令 - オペランドr1,r2。語長1
- * \relates exec
- */
void cpa_r1_r2()
{
WORD w[1];
sys->cpu->pr += 1;
}
-/**
- * CPL命令のテンプレート\n
- * 汎用レジスタrの内容と値valを論理比較
- */
void cpl(WORD r, WORD val)
{
sys->cpu->fr = 0x0;
}
}
-
-/**
- * CPL命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void cpl_r_adr_x()
{
WORD w[2];
sys->cpu->pr += 2;
}
-/**
- * CPL命令 - オペランドr1,r2。語長1
- * \relates exec
- */
void cpl_r1_r2()
{
WORD w[1];
sys->cpu->pr += 1;
}
-/**
- * SLA命令 - オペランドr,adr,x。語長2\n
- * 算術演算なので、第15ビットは送り出されない
- * \relates exec
- */
void sla()
{
WORD w[2], sign, last = 0x0, r;
sys->cpu->pr += 2;
}
-/**
- * SRA命令 - オペランドr,adr,x。語長2\n
- * 算術演算なので、第15ビットは送り出されない\n
- * 空いたビット位置には符号と同じものが入る
- * \relates exec
- */
void sra()
{
WORD w[2], sign, last = 0x0, r;
sys->cpu->pr += 2;
}
-/**
- * SLL命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void sll()
{
WORD w[2], last = 0x0, r;
sys->cpu->pr += 2;
}
-/**
- * SRL命令 - オペランドr,adr,x。語長2
- * \relates exec
- */
void srl()
{
WORD w[2], last = 0x0, r;
sys->cpu->pr += 2;
}
-/**
- * JPL命令。語長2
- * \relates exec
- */
void jpl()
{
WORD w[2];
}
}
-/**
- * JMI命令。語長2
- * \relates exec
- */
void jmi()
{
WORD w[2];
}
}
-/**
- * JNZ命令。語長2
- * \relates exec
- */
void jnz()
{
WORD w[2];
}
}
-/**
- * JZE命令。語長2
- * \relates exec
- */
void jze()
{
WORD w[2];
}
}
-/**
- * JOV命令。語長2
- * \relates exec
- */
void jov()
{
WORD w[2];
}
}
-/**
- * JUMP命令。語長2
- * \relates exec
- */
void jump()
{
WORD w[2];
sys->cpu->pr = get_adr_x(w[1], w[0]);
}
-/**
- * PUSH命令。語長2
- * \relates exec
- */
void push()
{
assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
sys->cpu->pr += 2;
}
-/**
- * POP命令。語長1
- * \relates exec
- */
void pop()
{
assert(sys->cpu->sp > execptr->end);
}
}
-/**
- * CALL命令。語長2
- * \relates exec
- */
void call()
{
assert(sys->cpu->sp > execptr->end && sys->cpu->sp <= sys->memsize);
sys->cpu->pr = get_adr_x(w[1], w[0]);
}
-/**
- * RET命令。語長1(OPのみ)
- * \relates exec
- */
void ret()
{
assert(sys->cpu->sp <= sys->memsize);
}
}
-/**
- * SVC命令。語長2
- * \relates exec
- */
void svc()
{
WORD w[2];
sys->cpu->pr += 2;
}
-/**
- * 仮想マシンCOMET IIの実行
- * \class exec
- */
void exec()
{
clock_t clock_begin, clock_end;
void (*cmdptr)();
char *s;
- create_code_type(); /* 命令のコードとタイプがキーのハッシュ表を作成 */
+ create_code_cmdtype(); /* 命令のコードとタイプがキーのハッシュ表を作成 */
if(execmode.trace == true) {
fprintf(stdout, "\nExecuting machine codes\n");
}
} while(clock_end - clock_begin < CLOCKS_PER_SEC / sys->clocks);
}
execfin:
- free_code_type(); /* 命令のコードとタイプがキーのハッシュ表を解放 */
+ free_code_cmdtype(); /* 命令のコードとタイプがキーのハッシュ表を解放 */
if(cerr->num > 0) {
fprintf(stderr, "Execute error - %d: %s\n", cerr->num, cerr->msg);
}