X-Git-Url: http://j8takagi.net/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fexec.c;h=4bbe3509fb51885e3c6d1397f63b20184e9e2d1a;hb=refs%2Ftags%2Fv0.1p19;hp=35aec47abe17a5e9b4b64ab2810f8957bde5d2d7;hpb=bf31ea99380e3ee2198f61f6510ebe6e4a3961f5;p=YACASL2.git diff --git a/src/exec.c b/src/exec.c index 35aec47..4bbe350 100644 --- a/src/exec.c +++ b/src/exec.c @@ -1,8 +1,15 @@ -#include "casl2.h" +#include +#include +#include + #include "exec.h" +#include "cerr.h" -/* 実行のエラー定義 */ -CERR cerr_exec[] = { +/** + * 実行エラーの定義 + */ +static CERR cerr_exec[] = { + { 201, "Loading - full of COMET II memory" }, { 202, "SVC input - out of Input memory" }, { 203, "SVC output - out of COMET II memory" }, { 204, "Program Register (PR) - out of COMET II memory" }, @@ -11,16 +18,47 @@ CERR cerr_exec[] = { { 207, "Stack Pointer (SP) - out of COMET II memory" }, }; +/** + * 実行モード: trace, logical, dump + */ +EXECMODE execmode = {false, false, false}; + +/** + * 実行エラーをエラーリストに追加 + */ bool addcerrlist_exec() { return addcerrlist(ARRAYSIZE(cerr_exec), cerr_exec); } -/* 実行モード: trace, logical, dump */ -EXECMODE execmode = {false, false, false}; +/** + * 指定されたファイルからアセンブル結果を読み込む + */ +bool loadassemble(char *file) +{ + FILE *fp; + bool status = true; -/* 標準入力から文字データを読込(SVC 1) */ -void svcin() + assert(file != NULL); + if((fp = fopen(file, "r")) == NULL) { + perror(file); + return false; + } + prog->end = prog->start + + fread(sys->memory, sizeof(WORD), sys->memsize - prog->start, fp); + if(prog->end == sys->memsize) { + setcerr(201, file); /* Loading - full of COMET II memory */ + fprintf(stderr, "Load error - %d: %s\n", cerr->num, cerr->msg); + status = false; + } + fclose(fp); + return status; +} + +/** + * 標準入力から文字データを読込(SVC 1) + */ +static void svcin() { int i; char *buffer = malloc_chk(INSIZE + 1, "svcin.buffer"); @@ -44,8 +82,10 @@ void svcin() free_chk(buffer, "buffer"); } -/* 標準出力へ文字データを書出(SVC 2) */ -void svcout() +/** + * 標準出力へ文字データを書出(SVC 2) + */ +static void svcout() { int i; WORD w; @@ -65,12 +105,14 @@ void svcout() } } -/* ロード/論理積/論理和/排他的論理和のフラグ設定。OFは常に0 */ -void setfr(WORD val) +/** + * ロード/論理積/論理和/排他的論理和のフラグ設定。OFは常に0 + */ +static void setfr(WORD val) { sys->cpu->fr = 0x0; /* 第15ビットが1のとき、SFは1 */ - if((val & 0x8000) > 0x0) { + if((val & 0x8000) == 0x8000) { sys->cpu->fr += SF; } /* 演算結果が0のとき、ZFは1 */ @@ -79,18 +121,23 @@ void setfr(WORD val) } } -/* 算術加算。フラグを設定して値を返す */ -WORD adda(WORD val0, WORD val1) +/** + * 算術加算。フラグを設定して値を返す + */ +static WORD adda(WORD val0, WORD val1) { WORD res; - long temp; - sys->cpu->fr = 0x0; + long tmp; - temp = (signed short)val0 + (signed short)val1; - if(temp > 32767 || temp < -32768) { + sys->cpu->fr = 0x0; + /* 引数の値を16ビット符号付整数として加算し、オーバーフローをチェック */ + assert(sizeof(short)*8 == 16 && (short)0xFFFF == -1); + if((tmp = (short)val0 + (short)val1) > 32767 || tmp < -32768) { sys->cpu->fr += OF; } - if(((res = (WORD)(temp & 0xFFFF)) & 0x8000) == 0x8000) { + /* 加算した結果を、WORD値に戻す */ + res = (WORD)(tmp & 0xFFFF); + if((res & 0x8000) == 0x8000) { sys->cpu->fr += SF; } else if(res == 0x0) { sys->cpu->fr += ZF; @@ -98,23 +145,27 @@ WORD adda(WORD val0, WORD val1) return res; } -/* 算術減算。フラグを設定して値を返す */ -WORD suba(WORD val0, WORD val1) +/** + * 算術減算。フラグを設定して値を返す + */ +static WORD suba(WORD val0, WORD val1) { return adda(val0, (~val1 + 1)); } -/* 論理加算。フラグを設定して値を返す */ -WORD addl(WORD val0, WORD val1) +/** + * 論理加算。フラグを設定して値を返す + */ +static WORD addl(WORD val0, WORD val1) { - long temp; + long tmp; WORD res; sys->cpu->fr = 0x0; - if((temp = val0 + val1) < 0 || temp > 65535) { + if((tmp = val0 + val1) < 0 || tmp > 65535) { sys->cpu->fr += OF; } - if(((res = (WORD)(temp & 0xFFFF)) & 0x8000) == 0x8000) { + if(((res = (WORD)(tmp & 0xFFFF)) & 0x8000) == 0x8000) { sys->cpu->fr += SF; } else if(res == 0x0) { sys->cpu->fr += ZF; @@ -122,14 +173,18 @@ WORD addl(WORD val0, WORD val1) return res; } -/* 論理減算。フラグを設定して値を返す */ -WORD subl(WORD val0, WORD val1) +/** + * 論理減算。フラグを設定して値を返す + */ +static WORD subl(WORD val0, WORD val1) { return addl(val0, (~val1 + 1)); } -/* 算術比較のフラグ設定。OFは常に0 */ -void cpa(WORD val0, WORD val1) +/** + * 算術比較のフラグ設定。OFは常に0 + */ +static void cpa(WORD val0, WORD val1) { sys->cpu->fr = 0x0; if((short)val0 < (short)val1) { @@ -139,8 +194,10 @@ void cpa(WORD val0, WORD val1) } } -/* 論理比較のフラグ設定。OFは常に0 */ -void cpl(WORD val0, WORD val1) +/** + * 論理比較のフラグ設定。OFは常に0 + */ +static void cpl(WORD val0, WORD val1) { sys->cpu->fr = 0x0; if(val0 < val1) { @@ -150,9 +207,11 @@ void cpl(WORD val0, WORD val1) } } -/* 算術左シフト。フラグを設定して値を返す。 */ -/* 算術演算なので、第15ビットは送り出されない */ -WORD sla(WORD val0, WORD val1) +/** + * 算術左シフト。フラグを設定して値を返す + * 算術演算なので、第15ビットは送り出されない + */ +static WORD sla(WORD val0, WORD val1) { WORD sign, res, last = 0x0; int i; @@ -180,10 +239,12 @@ WORD sla(WORD val0, WORD val1) return res; } -/* 算術右シフト。フラグを設定して値を返す */ -/* 算術演算なので、第15ビットは送り出されない */ -/* 空いたビット位置には符号と同じものが入る */ -WORD sra(WORD val0, WORD val1) +/** + * 算術右シフト。フラグを設定して値を返す + * 算術演算なので、第15ビットは送り出されない + * 空いたビット位置には符号と同じものが入る + */ +static WORD sra(WORD val0, WORD val1) { WORD sign, res, last = 0x0; int i; @@ -214,8 +275,10 @@ WORD sra(WORD val0, WORD val1) return res; } -/* 論理左シフト。フラグを設定して値を返す */ -WORD sll(WORD val0, WORD val1) +/** + * 論理左シフト。フラグを設定して値を返す + */ +static WORD sll(WORD val0, WORD val1) { WORD res = val0, last = 0x0; int i; @@ -240,8 +303,10 @@ WORD sll(WORD val0, WORD val1) return res; } -/* 論理右シフト。フラグを設定して値を返す */ -WORD srl(WORD val0, WORD val1) +/** + * 論理右シフト。フラグを設定して値を返す + */ +static WORD srl(WORD val0, WORD val1) { WORD res = val0, last = 0x0; int i; @@ -266,7 +331,9 @@ WORD srl(WORD val0, WORD val1) return res; } -/* 仮想マシンCOMET IIでの実行 */ +/** + * 仮想マシンCOMET IIの実行 + */ bool exec() { WORD op, r_r1, x_r2, val; @@ -274,7 +341,6 @@ bool exec() char *errpr = malloc_chk(CERRSTRSIZE + 1, "exec.errpr"); clock_t clock_begin, clock_end; - addcerrlist_exec(); if(execmode.trace == true) { fprintf(stdout, "\nExecuting machine codes\n"); } @@ -349,7 +415,7 @@ bool exec() } } free_chk(errpr, "errpr"); - /* 主オペランドが1〜4の場合、第2ビットを無視 */ + /* 主オペランドが1から4の場合、第2ビットを無視 */ if(op >= 0x1000 && op <= 0x4FFF) { op &= 0xFB00; } @@ -470,6 +536,7 @@ bool exec() default: break; } + /* クロック周波数の設定 */ do { clock_end = clock(); } while(clock_end - clock_begin < CLOCKS_PER_SEC / sys->clocks);