From d1f82970bf7d41db2fea11b08cd8e308f6cb8138 Mon Sep 17 00:00:00 2001 From: j8takagi Date: Mon, 27 Dec 2010 08:12:53 +0900 Subject: [PATCH] =?utf8?q?=E4=BE=9D=E5=AD=98=E9=96=A2=E4=BF=82=E3=82=92?= =?utf8?q?=E6=95=B4=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- include/assemble.h | 164 +++++++--------- include/cerr.h | 44 +++-- include/cmem.h | 5 - include/exec.h | 40 ++-- include/hash.h | 17 +- include/struct.h | 158 ++++++++++++++++ include/word.h | 14 -- src/.gitignore | 1 + src/Makefile | 30 ++- src/assemble.c | 453 ++++++++++++++++++++++++++++++++++----------- src/casl2.c | 57 +++--- src/cerr.c | 33 +++- src/cmd.c | 80 +++++--- src/cmem.c | 30 ++- src/comet2.c | 54 ++---- src/dump.c | 10 +- src/dumpword.c | 8 +- src/exec.c | 158 +++++++++++----- src/hash.c | 21 +-- src/label.c | 44 ++++- src/struct.c | 3 +- src/token.c | 9 +- src/word.c | 24 ++- 23 files changed, 984 insertions(+), 473 deletions(-) create mode 100644 include/struct.h diff --git a/include/assemble.h b/include/assemble.h index eb0ab28..15d314c 100644 --- a/include/assemble.h +++ b/include/assemble.h @@ -1,19 +1,29 @@ #ifndef YACASL2_ASSEMBLE_INCLUDED #define YACASL2_ASSEMBLE_INCLUDED -/* CASL IIの仕様 */ +#include +#include "struct.h" +#include "word.h" + +/** + * CASL IIの仕様 + */ enum { - LABELSIZE = 8, /* ラベルの最大文字数 */ - OPDSIZE = 40, /* オペラントの最大数。CASL IIシミュレータの制限 */ + LABELSIZE = 8, /** ラベルの最大文字数 */ + OPDSIZE = 40, /** オペラントの最大数。CASL IIシミュレータの制限 */ }; -/* YACASL2の制限 */ +/** + * YACASL2の制限 + */ enum { LINESIZE = 1024, /* 行の最大文字数 */ TOKENSIZE = 256, /* トークンの最大文字数 */ }; -/* アセンブルモード */ +/** + * アセンブルモード + */ typedef struct { bool src; /* ソースを表示する場合はtrue */ bool label; /* ラベル表を表示する場合はtrue */ @@ -24,7 +34,9 @@ typedef struct { extern ASMODE asmode; -/* アセンブル時のプロパティ */ +/** + * アセンブルのプロパティ + */ typedef struct { WORD ptr; /* 現在のポインタ */ WORD lptr; /* リテラル(=付きの値)を格納するポインタ */ @@ -33,7 +45,9 @@ typedef struct { extern ASPROP *asprop; -/* アセンブラ命令を表す番号 */ +/** + * アセンブラ命令を表す番号 + */ typedef enum { START = 01, END = 02, @@ -41,7 +55,9 @@ typedef enum { DC = 04, } ASCMDID; -/* アセンブラ命令を表す配列 */ +/** + * アセンブラ命令を表す配列 + */ typedef struct { ASCMDID cmdid; int opdc_min; @@ -49,7 +65,9 @@ typedef struct { char *cmd; } ASCMD; -/* マクロ命令を表す番号 */ +/** + * マクロ命令を表す番号 + */ typedef enum { IN = 011, OUT = 012, @@ -57,7 +75,9 @@ typedef enum { RPOP = 014, } MACROCMDID; -/* マクロ命令を表す配列 */ +/** + * マクロ命令を表す配列 + */ typedef struct { MACROCMDID cmdid; int opdc_min; @@ -65,14 +85,18 @@ typedef struct { char *cmd; } MACROCMD; -/* ラベル配列 */ +/** + * ラベル配列 + */ typedef struct { char *prog; char *label; WORD adr; } LABELARRAY; -/* ラベル表 */ +/** + * ラベル表 + */ typedef struct _LABELTAB { struct _LABELTAB *next; char *prog; @@ -81,115 +105,71 @@ typedef struct _LABELTAB { } LABELTAB; enum { - LABELTABSIZE = 251, /* ラベル表のサイズ */ + /** + * ラベル表のサイズ + */ + LABELTABSIZE = 251, }; -/* アセンブラが、1回目か、2回目か、を表す */ +/** + * アセンブラが、1回目か、2回目か、を表す + */ typedef enum { FIRST = 0, SECOND = 1, } PASS; -/* アセンブルのエラー定義 */ -bool addcerrlist_assemble(); - -/* プログラム名とラベルに対応するハッシュ値を返す */ -unsigned labelhash(const char *prog, const char *label); - -/* プログラム名とラベルに対応するアドレスをラベル表から検索する */ +/** + * プログラム名とラベルに対応するアドレスをラベル表から検索する + */ WORD getlabel(const char *prog, const char *label); -/* ラベルを表に追加する */ +/** + * ラベルを表に追加する + */ bool addlabel(const char *prog, const char *label, WORD word); -/* ラベル表を表示する */ +/** + * ラベル表を表示する + */ void printlabel(); -/* ラベル表を解放する */ +/** + * ラベル表を解放する + */ void freelabel(); -/* オペランド */ +/** + * オペランド + */ typedef struct { int opdc; char *opdv[OPDSIZE]; } OPD; -/* 命令行 */ +/** + * 命令行 + */ typedef struct { char *label; char *cmd; OPD *opd; } CMDLINE; -/* 命令がマクロ命令の場合はメモリに書込 - 書込に成功した場合TRUE、それ以外の場合はFALSEを返す */ -bool macrocmd(const CMDLINE *cmdl, PASS pass); - -/* 「,」区切りの文字列から、オペランドを取得する */ -OPD *opdtok(const char *str); - -/* 1行を解析する */ +/** + * 1行を解析する + */ CMDLINE *linetok(const char *line); -/* 汎用レジスタを表す文字列「GR[0-7]」から、レジスタ番号[0-7]をWORD値で返す */ -/* 文字列が汎用レジスタを表さない場合は、0xFFFFを返す */ -/* is_xがtrueの場合は指標レジスタ。GR0は、COMET IIの仕様により、エラー発生 */ -WORD getgr(const char *str, bool is_x); - -/* 10進定数をWORDに変換 */ -WORD getint(const char *str); - -/* 16進定数をWORDに変換 */ -WORD gethex(const char *str); - -/* アドレスを返す */ -/* アドレスには、リテラル/10進定数/16進定数/アドレス定数が含まれる */ -WORD getadr(const char *prog, const char *str, PASS pass); - -/* 定数の前に等号(=)をつけて記述される、リテラルを返す */ -/* リテラルには、10進定数/16進定数/文字定数が含まれる */ -WORD getliteral(const char *str, PASS pass); - -/* COMET IIのメモリにアドレス値を書き込む */ -bool writememory(WORD word, WORD adr, PASS pass); - -/* ' 'で囲まれた、文字定数をメモリに書込 */ -/* DC命令とリテラルで使い、リテラルの場合はリテラル領域に書込 */ -void writestr(const char *str, bool literal, PASS pass); - -/* アセンブラ命令DCをメモリに書込 */ -void writeDC(const char *str, PASS pass); - -/* 命令がアセンブラ命令の場合は処理を実行する。 */ -/* 実行に成功した場合TRUE、それ以外の場合はFALSEを返す */ -bool assemblecmd(const CMDLINE *cmdl, PASS pass); - -/* 命令のコードを返す - 命令が無効な場合は0xFFFF */ -WORD getcmd(CMDTYPE type, const char *cmd); - -/* 命令が機械語命令の場合は処理を実行 */ -/* 実行に成功した場合TRUE、それ以外の場合はFALSEを返す */ -bool cometcmd(const CMDLINE *cmdl, PASS pass); - -/* 1行のアセンブル */ -/* アセンブル完了時はTRUE、未完了時はFALSEを返す */ -bool assembleline(const CMDLINE *cmdl, PASS pass); - -/* 指定された名前のファイルをアセンブル */ -/* 2回実行される */ +/** + * 指定された名前のファイルをアセンブル + * 2回実行される + */ bool assemble(const char *file, PASS pass); -/* マクロ命令「IN IBUF,LEN」をメモリに書込 */ -bool writeIN(const char *ibuf, const char *len, PASS pass); - -/* マクロ命令「OUT OBUF,LEN」をメモリに書込 */ -bool writeOUT(const char *obuf, const char *len, PASS pass); - -/* マクロ命令「RPUSH」をメモリに書込 */ -bool writeRPUSH(PASS pass); - -/* マクロ命令「RPOP」をメモリに書込 */ -bool writeRPOP(PASS pass); +/** + * 指定されたファイルにアセンブル結果を書込 + */ +void outassemble(const char *file); #endif /* YACASL2_ASSEMBLE_INCLUDEDの終端 */ diff --git a/include/cerr.h b/include/cerr.h index 08532da..db9adbe 100644 --- a/include/cerr.h +++ b/include/cerr.h @@ -1,48 +1,62 @@ #ifndef YACASL2_CERR_H_INCLUDED #define YACASL2_CERR_H_INCLUDED -#include -#include -#include -#include #include - #include "cmem.h" -/* エラーの構造体 */ +/** + * エラーの構造体 + */ typedef struct { int num; /* エラー番号 */ char *msg; /* エラーメッセージ */ } CERR; -/* 現在のエラー */ +/** + * 現在のエラー + */ extern CERR *cerr; -/* エラーリスト */ +/** + * エラーリスト型 + */ typedef struct _CERRLIST { struct _CERRLIST *next; CERR *cerr; } CERRLIST; +/** + * エラーリスト + */ extern CERRLIST *cerrlist; enum { - CERRSTRSIZE = 10, /* エラーメッセージ中に挿入できる文字列のサイズ */ - CERRMSGSIZE = 70, /* エラーメッセージのサイズ */ + CERRSTRSIZE = 10, /**<エラーメッセージ中に挿入できる文字列のサイズ */ + CERRMSGSIZE = 70, /**<エラーメッセージのサイズ */ }; -/* エラーの初期化 */ +/** + * エラーの初期化 + */ void cerr_init(); -/* エラーリストを作成・追加する */ +/** + * エラーリストを作成・追加する + */ bool addcerrlist(int cerrc, CERR cerrv[]); -/* エラー番号とエラーメッセージを設定 */ +/** + * 現在のエラーを設定する + */ void setcerr(int num, const char *str); -/* エラー番号からメッセージを返す */ +/** + * エラーリストから、エラー番号に対応するメッセージを返す + */ char *getcerrmsg(int num); -/* エラーを解放する */ +/** + * エラーリストと現在のエラーを解放する + */ void freecerr(); #endif diff --git a/include/cmem.h b/include/cmem.h index 50a29ec..a8629ab 100644 --- a/include/cmem.h +++ b/include/cmem.h @@ -1,11 +1,6 @@ #ifndef YACASL2_CMEM_H_INCLUDED #define YACASL2_CMEM_H_INCLUDED - -#include #include -#include -#include -#include #ifndef ARRAYSIZE #define ARRAYSIZE(array) (sizeof(array)/sizeof(array[0])) diff --git a/include/exec.h b/include/exec.h index 9afde5b..073e576 100644 --- a/include/exec.h +++ b/include/exec.h @@ -1,35 +1,49 @@ #ifndef YACASL2_EXEC_INCLUDED #define YACASL2_EXEC_INCLUDED +#include +#include "struct.h" +#include "word.h" + enum { - INSIZE = 256 /* CASL IIの、IN命令入力領域 */ + INSIZE = 256 /** -#include -#include -#include -#include #include -/* wordのエラー定義 */ -bool addcerrlist_word(); - /* WORD - 16ビットデータ型 */ typedef unsigned short WORD; -/* 10進数の文字列をWORD値に変換 */ -WORD n2word(const char *str); - -/* 16進数の文字列をWORD値に変換 */ -WORD h2word(const char *str); - /* 10進数または16進数の文字列をWORD値に変換 */ WORD nh2word(const char *str); diff --git a/src/.gitignore b/src/.gitignore index 63d8a21..2477ac1 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,2 +1,3 @@ +*.d *.o TAGS diff --git a/src/Makefile b/src/Makefile index ca967d9..187a690 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,41 +1,35 @@ INCLUDE = ../include CC = gcc CFLAGS = -g -Wall -I $(INCLUDE) -WORDOBJ = word.o -HASHOBJ = hash.o -CMEMOBJ = cmem.o -CERROBJ = cerr.o -COMMONOBJ = $(WORDOBJ) $(HASHOBJ) $(CMEMOBJ) $(CERROBJ) struct.o cmd.o -ASOBJ = assemble.o token.o label.o macro.o -EXECOBJ = exec.o dump.o -COMMONHEAD = $(INCLUDE)/casl2.h $(INCLUDE)/word.h $(INCLUDE)/hash.h $(INCLUDE)/cmem.h $(INCLUDE)/cerr.h -ASHEAD = $(INCLUDE)/assemble.h -EXECHEAD = $(INCLUDE)/exec.h + +COMMONSRC = word.c cmem.c cerr.c +CASL2SRC = struct.c cmd.c hash.c +ASSRC = assemble.c token.c label.c +EXECSRC = exec.c dump.c .PHONY: all clean all: ../casl2 ../comet2 ../dumpword -../casl2: casl2.o $(COMMONOBJ) $(ASOBJ) $(EXECOBJ) +../casl2: casl2.o $(subst .c,.o,$(COMMONSRC) $(CASL2SRC) $(ASSRC) $(EXECSRC)) $(CC) $(CFLAGS) -o $@ $^ -../comet2: comet2.o $(COMMONOBJ) $(EXECOBJ) +../comet2: comet2.o $(subst .c,.o,$(COMMONSRC) $(CASL2SRC) $(EXECSRC)) $(CC) $(CFLAGS) -o $@ $^ -../dumpword: dumpword.o $(WORDOBJ) $(CMEMOBJ) $(CERROBJ) +../dumpword: dumpword.o $(subst .c,.o,$(COMMONSRC)) $(CC) $(CFLAGS) -o $@ $^ %.o: %.c $(CC) -c $(CFLAGS) $< -casl2.o comet2.o $(COMMONOBJ) $(ASOBJ) $(EXECOBJ): $(COMMONHEAD) - -casl2.o $(ASOBJ): $(ASHEAD) +%.d: %.c + @$(CC) -MM -I $(INCLUDE) $< | sed 's/\($*\.o\):/\1 $@:/g' >$@ -comet2.o $(EXECOBJ): $(EXECHEAD) +-include $(subst .c,.d,casl2.c comet2.c dumpword.c $(COMMONSRC) $(CASL2SRC) $(ASSRC) $(EXECSRC)) TAGS: $(INCLUDE)/*.h *.c @if test `which etags`; then etags $^; fi clean: - @rm -f *.o + @rm -f ../casl2 ../comet2 ../dumpword *.o *.d diff --git a/src/assemble.c b/src/assemble.c index 6d67955..272f2f8 100644 --- a/src/assemble.c +++ b/src/assemble.c @@ -1,14 +1,26 @@ -#include "casl2.h" +#include +#include +#include +#include +#include + #include "assemble.h" +#include "cerr.h" -/* アセンブルモード: src, label, onlylabel, asdetail, onlyassemble */ +/** + * アセンブルモード: src, label, onlylabel, asdetail, onlyassemble + */ ASMODE asmode = {false, false, false, false, false}; -/* アセンブル時のプロパティ */ +/** + * アセンブルのプロパティ + */ ASPROP *asprop; -/* アセンブルのエラー定義 */ -CERR cerr_assemble[] = { +/** + * アセンブルのエラー定義 + */ +static CERR cerr_assemble[] = { { 101, "label already defined" }, { 102, "label table is full" }, { 103, "label not found" }, @@ -33,14 +45,43 @@ CERR cerr_assemble[] = { { 125, "not GR in operand x" }, }; -bool addcerrlist_assemble() -{ - return addcerrlist(ARRAYSIZE(cerr_assemble), cerr_assemble); -} +#ifndef UNITTEST +static WORD getadr(const char *prog, const char *str, PASS pass); + +static WORD getgr(const char *str, bool is_x); + +static WORD getliteral(const char *str, PASS pass); + +static bool assemblecmd(const CMDLINE *cmdl, PASS pass); + +static bool macrocmd(const CMDLINE *cmdl, PASS pass); + +static bool writeIN(const char *ibuf, const char *len, PASS pass); + +static bool writeOUT(const char *obuf, const char *len, PASS pass); + +static bool writeRPUSH(PASS pass); + +static bool writeRPOP(PASS pass); + +static bool cometcmd(const CMDLINE *cmdl, PASS pass); + +static bool writememory(WORD word, WORD adr, PASS pass); + +static void writestr(const char *str, bool literal, PASS pass); + +static void writeDC(const char *str, PASS pass); -/* 汎用レジスタを表す文字列「GR[0-7]」から、レジスタ番号[0-7]をWORD値で返す */ -/* 文字列が汎用レジスタを表さない場合は、0xFFFFを返す */ -/* is_xがtrueの場合は指標レジスタ。GR0は、COMET IIの仕様により、エラー発生 */ +static bool assembleline(const CMDLINE *cmdl, PASS pass); + +static void printline(FILE *stream, const char *filename, int lineno, char *line); +#endif + +/** + * 汎用レジスタを表す文字列「GR[0-7]」から、レジスタ番号[0-7]をWORD値で返す + * 文字列が汎用レジスタを表さない場合は、0xFFFFを返す + * is_xがtrueの場合は指標レジスタ。GR0が指定された場合は、COMET IIの仕様によりエラー発生 + */ WORD getgr(const char *str, bool is_x) { assert(str != NULL); @@ -60,47 +101,10 @@ WORD getgr(const char *str, bool is_x) return r; } -/* アドレスを返す */ -/* アドレスには、リテラル/10進定数/16進定数/アドレス定数が含まれる */ -WORD getadr(const char *prog, const char *str, PASS pass) -{ - WORD adr = 0x0; - if(*str == '=') { - adr = getliteral(str, pass); - } else if(isdigit(*str) || *str == '-' || *str == '#') { - adr = nh2word(str); - } else { - if(pass == SECOND && (adr = getlabel(prog, str)) == 0xFFFF) { - if(prog != NULL) { - setcerr(103, str); /* label not found */ - } - } - } - return adr; -} - -/* WORD値wordをアドレスadrに書込 */ -/* 書込に成功した場合はtrue、失敗した場合はfalseを返す */ -bool writememory(WORD word, WORD adr, PASS pass) -{ - bool status = false; - - /* COMET IIメモリオーバーの場合 */ - if(adr >= sys->memsize) { - setcerr(119, word2n(adr)); /* out of COMET II memory */ - } - if(cerr->num == 0) { - (sys->memory)[adr] = word; - if(pass == SECOND && asmode.asdetail == true) { - fprintf(stdout, "\t#%04X\t#%04X\n", adr, word); - } - status = true; - } - return status; -} - -/* 定数の前に等号(=)をつけて記述されるリテラルを返す */ -/* リテラルには、10進定数/16進定数/文字定数が含まれる */ +/** + * 定数の前に等号(=)をつけて記述されるリテラルを返す + * リテラルには、10進定数/16進定数/文字定数が含まれる + */ WORD getliteral(const char *str, PASS pass) { WORD adr = asprop->lptr; @@ -113,57 +117,10 @@ WORD getliteral(const char *str, PASS pass) return adr; } -/* ' 'で囲まれた文字定数をメモリに書込 */ -/* DC命令とリテラルで使い、リテラルの場合はリテラル領域に書込 */ -void writestr(const char *str, bool literal, PASS pass) -{ - assert(cerr->num == 0 && *str == '\''); - const char *p = str + 1; - bool lw = false; - - for(; ;) { - /* 閉じ「'」がないまま文字列が終了した場合 */ - if(*p == '\0') { - setcerr(123, str); /* unclosed quote */ - break; - } - /* 「'」の場合、次の文字が「'」でない場合は正常終了 */ - if(*p == '\'' && *(++p) != '\'') { - break; - } else if(literal == true && lw == true) { - setcerr(124, str); /* more than one character in literal */ - break; - } - /*リテラルの場合はリテラル領域に書込 */ - if(literal == true) { - writememory(*(p++), (asprop->lptr)++, pass); - lw = true; - } else { - writememory(*(p++), (asprop->ptr)++, pass); - } - } -} - -/* アセンブラ命令DCをメモリに書込 */ -void writeDC(const char *str, PASS pass) -{ - WORD adr = 0x0; - if(*str == '\'') { - writestr(str, false, pass); - } else { - if(*str == '#' || isdigit(*str) || *str == '-') { - adr = nh2word(str); - } else { - if(pass == SECOND && (adr = getlabel(asprop->prog, str)) == 0xFFFF) { - setcerr(103, str); /* label not found */ - } - } - writememory(adr, (asprop->ptr)++, pass); - } -} - -/* 命令がアセンブラ命令の場合は処理を実行 */ -/* 実行に成功した場合はtrue、それ以外の場合はfalseを返す */ +/** + * アセンブラ命令をメモリに書込 + * 実行に成功した場合はtrue、それ以外の場合はfalseを返す + */ bool assemblecmd(const CMDLINE *cmdl, PASS pass) { int i = 0; @@ -244,8 +201,11 @@ bool assemblecmd(const CMDLINE *cmdl, PASS pass) return status; } -/* 命令がマクロ命令の場合はメモリに書込 */ -/* 書込に成功した場合はtrue、それ以外の場合はfalseを返す */ +/** + * macrocmd + * マクロ命令をメモリに書込 + * 書込に成功した場合はtrue、それ以外の場合はfalseを返す + */ bool macrocmd(const CMDLINE *cmdl, PASS pass) { int i = 0; @@ -291,8 +251,158 @@ bool macrocmd(const CMDLINE *cmdl, PASS pass) return status; } -/* 機械語命令の書込 */ -/* 書込に成功した場合はtrue、それ以外の場合はfalseを返す */ +/** + * マクロ命令「IN IBUF,LEN」をメモリに書込 + * PUSH 0,GR1 + * PUSH 0,GR2 + * LAD GR1,IBUF + * LAD GR2,LEN + * SVC 1 + * POP GR2 + * POP GR1 + */ +bool writeIN(const char *ibuf, const char *len, PASS pass) +{ + bool status = false; + + /* PUSH 0,GR1 */ + writememory(0x7001, (asprop->ptr)++, pass); + writememory(0x0, (asprop->ptr)++, pass); + /* PUSH 0,GR2 */ + writememory(0x7002, (asprop->ptr)++, pass); + writememory(0x0, (asprop->ptr)++, pass); + /* LAD GR1,IBUF */ + writememory(0x1210, (asprop->ptr)++, pass); + writememory(getadr(asprop->prog, ibuf, pass), (asprop->ptr)++, pass); + /* LAD GR2,LEN */ + writememory(0x1220, (asprop->ptr)++, pass); + writememory(getadr(asprop->prog, len, pass), (asprop->ptr)++, pass); + /* SVC 1 */ + writememory(0xF000, (asprop->ptr)++, pass); + writememory(0x0001, (asprop->ptr)++, pass); + /* POP GR2 */ + writememory(0x7120, (asprop->ptr)++, pass); + /* POP GR1 */ + writememory(0x7110, (asprop->ptr)++, pass); + if(cerr->num == 0) { + status = true; + } + return status; +} + +/** + * マクロ命令「OUT OBUF,LEN」をメモリに書込 + * PUSH 0,GR1 + * PUSH 0,GR2 + * LAD GR1,OBUF + * LAD GR2,LEN + * SVC 2 + * LAD GR1,=#A + * LAD GR2,1 + * SVC 2 + * POP GR2 + * POP GR1 + */ +bool writeOUT(const char *obuf, const char *len, PASS pass) +{ + bool status = false; + + /* PUSH 0,GR1 */ + writememory(0x7001, (asprop->ptr)++, pass); + writememory(0x0, (asprop->ptr)++, pass); + /* PUSH 0,GR2 */ + writememory(0x7002, (asprop->ptr)++, pass); + writememory(0x0, (asprop->ptr)++, pass); + /* LAD GR1,OBUF */ + writememory(0x1210, (asprop->ptr)++, pass); + writememory(getadr(asprop->prog, obuf, pass), (asprop->ptr)++, pass); + /* LAD GR2,OLEN */ + writememory(0x1220, (asprop->ptr)++, pass); + writememory(getadr(asprop->prog, len, pass), (asprop->ptr)++, pass); + /* SVC 2 */ + writememory(0xF000, (asprop->ptr)++, pass); + writememory(0x0002, (asprop->ptr)++, pass); + /* LAD GR1,=#A */ + writememory(0x1210, (asprop->ptr)++, pass); + if(pass == FIRST) { + (asprop->ptr)++; + } else { + writememory(asprop->lptr, (asprop->ptr)++, pass); /* リテラルのアドレスを書込 */ + } + writememory(0xA, (asprop->lptr)++, pass); + /* LAD GR2,=1 */ + writememory(0x1220, (asprop->ptr)++, pass); + if(pass == FIRST) { + (asprop->ptr)++; + } else { + writememory(asprop->lptr, (asprop->ptr)++, pass); /* リテラルのアドレスを書込 */ + } + writememory(0x1, (asprop->lptr)++, pass); + /* SVC 2 */ + writememory(0xF000, (asprop->ptr)++, pass); + writememory(0x0002, (asprop->ptr)++, pass); + /* POP GR2 */ + writememory(0x7120, (asprop->ptr)++, pass); + /* POP GR1 */ + writememory(0x7110, (asprop->ptr)++, pass); + if(cerr->num == 0) { + status = true; + } + return status; +} + +/** マクロ命令「RPUSH」をメモリに書き込む + * PUSH 0,GR1 + * PUSH 0,GR2 + * PUSH 0,GR3 + * PUSH 0,GR4 + * PUSH 0,GR5 + * PUSH 0,GR6 + * PUSH 0,GR7 + */ +bool writeRPUSH(PASS pass) +{ + int i; + bool status = false; + + for(i = 1; i <= 7; i++) { + writememory(0x7000 + i, (asprop->ptr)++, pass); /* PUSH GRn */ + writememory(0x0, (asprop->ptr)++, pass); + } + if(cerr->num == 0) { + status = true; + } + return status; +} + +/** + * マクロ命令「RPOP」をメモリに書き込む + * POP GR7 + * POP GR6 + * POP GR5 + * POP GR4 + * POP GR3 + * POP GR3 + * POP GR2 + * POP GR1 + */ +bool writeRPOP(PASS pass) +{ + int i; + bool status = false; + for(i = 7; i >= 1; i--) { + writememory((0x7100 + (i << 4)), (asprop->ptr)++, pass); /* POP GRn */ + } + if(cerr->num == 0) { + status = true; + } + return status; +} + +/** + * 機械語命令をメモリに書込 + * 書込に成功した場合はtrue、それ以外の場合はfalseを返す + */ bool cometcmd(const CMDLINE *cmdl, PASS pass) { WORD cmd, adr, r1, r2, x; @@ -393,7 +503,82 @@ bool cometcmd(const CMDLINE *cmdl, PASS pass) return status; } -/* 命令行を1行アセンブルする */ +/** + * COMET IIのメモリにアドレス値を書き込む + */ +bool writememory(WORD word, WORD adr, PASS pass) +{ + bool status = false; + + /* COMET IIメモリオーバーの場合 */ + if(adr >= sys->memsize) { + setcerr(119, word2n(adr)); /* out of COMET II memory */ + } + if(cerr->num == 0) { + (sys->memory)[adr] = word; + if(pass == SECOND && asmode.asdetail == true) { + fprintf(stdout, "\t#%04X\t#%04X\n", adr, word); + } + status = true; + } + return status; +} + +/** + * 文字をメモリに書き込む + */ +void writestr(const char *str, bool literal, PASS pass) +{ + assert(cerr->num == 0 && *str == '\''); + const char *p = str + 1; + bool lw = false; + + for(; ;) { + /* 閉じ「'」がないまま文字列が終了した場合 */ + if(*p == '\0') { + setcerr(123, str); /* unclosed quote */ + break; + } + /* 「'」の場合、次の文字が「'」でない場合は正常終了 */ + if(*p == '\'' && *(++p) != '\'') { + break; + } else if(literal == true && lw == true) { + setcerr(124, str); /* more than one character in literal */ + break; + } + /*リテラルの場合はリテラル領域に書込 */ + if(literal == true) { + writememory(*(p++), (asprop->lptr)++, pass); + lw = true; + } else { + writememory(*(p++), (asprop->ptr)++, pass); + } + } +} + +/** + * DC命令の内容を書き込む + */ +void writeDC(const char *str, PASS pass) +{ + WORD adr = 0x0; + if(*str == '\'') { + writestr(str, false, pass); + } else { + if(*str == '#' || isdigit(*str) || *str == '-') { + adr = nh2word(str); + } else { + if(pass == SECOND && (adr = getlabel(asprop->prog, str)) == 0xFFFF) { + setcerr(103, str); /* label not found */ + } + } + writememory(adr, (asprop->ptr)++, pass); + } +} + +/** + * 1行をアセンブル + */ bool assembleline(const CMDLINE *cmdl, PASS pass) { bool status = false; @@ -426,12 +611,39 @@ bool assembleline(const CMDLINE *cmdl, PASS pass) return status; } -void printline(FILE *stream, const char *filename, int lineno, char *line) { +/** + * ファイルストリームの現在行を番号付きで表示する + */ +void printline(FILE *stream, const char *filename, int lineno, char *line) +{ fprintf(stream, "%s:%5d:%s", filename, lineno, line); } -/* 指定された名前のファイルをアセンブル */ -/* 2回実行される */ +/** + * アドレスを返す + * アドレスには、リテラル/10進定数/16進定数/アドレス定数が含まれる + */ +WORD getadr(const char *prog, const char *str, PASS pass) +{ + WORD adr = 0x0; + if(*str == '=') { + adr = getliteral(str, pass); + } else if(isdigit(*str) || *str == '-' || *str == '#') { + adr = nh2word(str); + } else { + if(pass == SECOND && (adr = getlabel(prog, str)) == 0xFFFF) { + if(prog != NULL) { + setcerr(103, str); /* label not found */ + } + } + } + return adr; +} + +/** + * 指定された名前のファイルをアセンブル + * 2回実行される + */ bool assemble(const char *file, PASS pass) { int lineno = 0; @@ -440,7 +652,7 @@ bool assemble(const char *file, PASS pass) char *line; FILE *fp; - addcerrlist_assemble(); + addcerrlist(ARRAYSIZE(cerr_assemble), cerr_assemble); if((fp = fopen(file, "r")) == NULL) { perror(file); return false; @@ -481,3 +693,18 @@ bool assemble(const char *file, PASS pass) fclose(fp); return status; } + +/** + * 引数で指定したファイルにアセンブル結果を書込 + */ +void outassemble(const char *file) +{ + FILE *fp; + + if((fp = fopen(file, "w")) == NULL) { + perror(file); + exit(-1); + } + fwrite(sys->memory, sizeof(WORD), prog->end, fp); + fclose(fp); +} diff --git a/src/casl2.c b/src/casl2.c index 7569f92..d17922c 100644 --- a/src/casl2.c +++ b/src/casl2.c @@ -1,10 +1,17 @@ -#include "casl2.h" -#include "assemble.h" -#include "exec.h" +#include +#include + #define _GNU_SOURCE #include -/* casl2コマンドのオプション */ +#include "assemble.h" +#include "exec.h" +#include "cerr.h" +#include "cmem.h" + +/** + * casl2コマンドのオプション + */ static struct option longopts[] = { { "source", no_argument, NULL, 's' }, { "label", no_argument, NULL, 'l' }, @@ -23,35 +30,25 @@ static struct option longopts[] = { { 0, 0, 0, 0 }, }; -/* casl2のエラー定義 */ -CERR cerr_casl2[] = { +/** + * casl2のエラー定義 + */ +static CERR cerr_casl2[] = { { 126, "no source file" }, }; -bool addcerrlist_casl2() -{ - return addcerrlist(sizeof(cerr_casl2), cerr_casl2); -} - -/* 指定されたファイルにアセンブル結果を書込 */ -void outassemble(const char *file) { - FILE *fp; - - if((fp = fopen(file, "w")) == NULL) { - perror(file); - exit(-1); - } - fwrite(sys->memory, sizeof(WORD), prog->end, fp); - fclose(fp); -} -/* アセンブル結果を書き込むファイルの名前 */ -const char *objfile_name(const char *str) +/** + * アセンブル結果を書き込むファイルの名前 + */ +static const char *objfile_name(const char *str) { const char *default_name = "a.o"; return (str == NULL) ? default_name : str; } -/* casl2コマンドのメイン */ +/** + * casl2コマンドのメイン + */ int main(int argc, char *argv[]) { int memsize = DEFAULT_MEMSIZE, clocks = DEFAULT_CLOCKS; @@ -64,7 +61,7 @@ int main(int argc, char *argv[]) "Usage: %s [-slLaAtTdh] [-oO[]] [-M ] [-C ] FILE1[ FILE2 ...]\n"; cerr_init(); - addcerrlist_casl2(); + addcerrlist(sizeof(cerr_casl2), cerr_casl2); /* オプションの処理 */ while((opt = getopt_long(argc, argv, "tTdslLao::O::AM:C:h", longopts, NULL)) != -1) { switch(opt) { @@ -127,7 +124,7 @@ int main(int argc, char *argv[]) /* アセンブル。ラベル表作成のため、2回行う */ for(pass = FIRST; pass <= SECOND; pass++) { if(pass == FIRST) { - create_cmdtype_code(); /* 命令と命令タイプがキーのハッシュ表を作成 */ + create_cmdtype_code(); /* 命令の名前とタイプがキーのハッシュ表を作成 */ asprop = malloc_chk(sizeof(ASPROP), "asprop"); /* アセンブル時のプロパティ用の領域確保 */ } for(i = optind; i < argc; i++) { @@ -158,7 +155,7 @@ int main(int argc, char *argv[]) freelabel(); /* ラベルハッシュ表を解放 */ free_chk(asprop->prog, "asprop.prog"); /* プログラム名を解放 */ free_chk(asprop, "asprop"); /* アセンブル時のプロパティを解放 */ - free_cmdtype_code(); /* 命令と命令タイプがキーのハッシュ表を解放 */ + free_cmdtype_code(); /* 命令の名前とタイプがキーのハッシュ表を解放 */ } } if(res == true) { @@ -166,9 +163,9 @@ int main(int argc, char *argv[]) outassemble(objfile); } if(asmode.onlyassemble == false) { - create_code_type(); /* 命令と命令タイプがキーのハッシュ表を作成 */ + create_code_type(); /* 命令のコードとタイプがキーのハッシュ表を作成 */ res = exec(); /* プログラム実行 */ - free_code_type(); /* 命令と命令タイプがキーのハッシュ表を解放 */ + free_code_type(); /* 命令のコードとタイプがキーのハッシュ表を解放 */ } } /* COMET II仮想マシンのシャットダウン */ diff --git a/src/cerr.c b/src/cerr.c index 02b6a3b..36b33a4 100644 --- a/src/cerr.c +++ b/src/cerr.c @@ -1,19 +1,32 @@ +#include +#include +#include +#include +#include #include "cerr.h" -/* エラーの初期化 */ +/** + * エラーの初期化 + */ void cerr_init() { cerr = malloc_chk(sizeof(CERR), "cerr"); cerr->num = 0; } -/* 現在のエラー */ +/** + * 現在のエラー + */ CERR *cerr; -/* エラーリスト */ +/** + * エラーリスト + */ CERRLIST *cerrlist; -/* エラーリストを作成・追加する */ +/** + * エラーリストを作成・追加する + */ bool addcerrlist(int newerrc, CERR newerrv[]) { int i; @@ -38,7 +51,9 @@ bool addcerrlist(int newerrc, CERR newerrv[]) return true; } -/* 現在のエラーを設定する */ +/** + * 現在のエラーを設定する + */ void setcerr(int num, const char *str) { /* 現在のエラー番号を設定 */ @@ -52,7 +67,9 @@ void setcerr(int num, const char *str) } } -/* エラーリストから、エラー番号に対応するメッセージを返す */ +/** + * エラーリストから、エラー番号に対応するメッセージを返す + */ char *getcerrmsg(int num) { CERRLIST *p; @@ -65,7 +82,9 @@ char *getcerrmsg(int num) return "unknown error"; } -/* エラーリストと現在のエラーを解放する */ +/** + * エラーリストと現在のエラーを解放する + */ void freecerr() { CERRLIST *p = cerrlist, *q; diff --git a/src/cmd.c b/src/cmd.c index 6c2c63f..258c491 100644 --- a/src/cmd.c +++ b/src/cmd.c @@ -1,9 +1,13 @@ -#include "cmem.h" -#include "cerr.h" +#include +#include +#include #include "hash.h" -#include "word.h" -#include "casl2.h" +#include "struct.h" +#include "cmem.h" +/** + * 機械語命令のリスト + */ CMD comet2cmd[] = { { "NOP", NONE, 0x0 }, { "LD", R_ADR_X_, 0x1000 }, @@ -45,20 +49,40 @@ CMD comet2cmd[] = { { "RET", NONE, 0x8100 }, }; -int comet2cmdsize = ARRAYSIZE(comet2cmd); -int cmdtabsize; -CMDTAB **cmdtype_code, **code_type; +/** + * 命令コード配列のサイズ + */ +static int comet2cmdsize = ARRAYSIZE(comet2cmd); + +/** + * 命令表のサイズ + */ +static int cmdtabsize; + +/** + * ハッシュ表 + */ +static CMDTAB **cmdtype_code, **code_type; -/* 命令と命令タイプからハッシュ値を生成する */ -unsigned hash_cmdtype(const char *cmd, CMDTYPE type) { +#ifndef UNITTEST +static unsigned hash_cmdtype(const char *cmd, CMDTYPE type); + +static unsigned hash_code(WORD code); +#endif + +/** + * 命令の名前とタイプからハッシュ値を生成する + */ +unsigned hash_cmdtype(const char *cmd, CMDTYPE type) +{ HKEY *keys[2]; unsigned hashval; - /* 命令をセット */ + /* 命令名を設定 */ keys[0] = malloc_chk(sizeof(HKEY), "hash_cmdtype.keys[0]"); keys[0]->type = CHARS; keys[0]->val.s = strdup_chk(cmd, "keys[0].val.s"); - /* 命令タイプをセット */ + /* 命令タイプを設定 */ keys[1] = malloc_chk(sizeof(HKEY), "hash_cmdtype.keys[1]"); keys[1]->type = INT; keys[1]->val.i = (int)(type & 070); @@ -71,7 +95,9 @@ unsigned hash_cmdtype(const char *cmd, CMDTYPE type) { return hashval; } -/* 命令と命令タイプがキーのハッシュ表を作成する */ +/** + * 名前とタイプがキーの命令ハッシュ表を作成する + */ bool create_cmdtype_code() { CMDTAB *np; @@ -97,8 +123,10 @@ bool create_cmdtype_code() return true; } -/* 命令と命令タイプから、命令コードを取得する */ -/* 無効な場合は0xFFFFを返す */ +/** + * 命令の名前とタイプから、命令コードを返す + * 無効な場合は0xFFFFを返す + */ WORD getcmdcode(const char *cmd, CMDTYPE type) { CMDTAB *np; @@ -112,7 +140,9 @@ WORD getcmdcode(const char *cmd, CMDTYPE type) return 0xFFFF; } -/* 命令と命令タイプがキーのハッシュ表を解放する */ +/** + * 名前とタイプがキーの命令ハッシュ表を解放する + */ void free_cmdtype_code() { int i; @@ -129,12 +159,14 @@ void free_cmdtype_code() free_chk(cmdtype_code, "cmdtype_code"); } -/* 命令コードからハッシュ値を生成する */ +/** + * 命令コードからハッシュ値を生成する + */ unsigned hash_code(WORD code) { HKEY *keys[1]; - /* 命令コードをセット */ + /* 命令コードを設定 */ keys[0] = malloc_chk(sizeof(HKEY), "hash_code.key"); keys[0]->type = INT; keys[0]->val.i = (int)(code >> 8); @@ -142,7 +174,9 @@ unsigned hash_code(WORD code) return hash(1, keys, cmdtabsize); } -/* 命令コードがキーのハッシュ表を作成する */ +/** + * コードがキーの命令ハッシュ表を作成する + */ bool create_code_type() { CMDTAB *np; @@ -168,8 +202,10 @@ bool create_code_type() return true; } -/* 命令コードから命令タイプを取得する */ -/* 無効な場合はNONEを返す */ +/** + * 命令コードから命令タイプを返す + * 無効な場合はNONEを返す + */ CMDTYPE getcmdtype(WORD code) { CMDTAB *np; @@ -181,7 +217,9 @@ CMDTYPE getcmdtype(WORD code) return NONE; } -/* 命令コードがキーのハッシュ表を解放する */ +/** + * コードがキーの命令ハッシュ表を解放する + */ void free_code_type() { int i; diff --git a/src/cmem.c b/src/cmem.c index b83c79c..0be54c4 100644 --- a/src/cmem.c +++ b/src/cmem.c @@ -1,7 +1,14 @@ +#include +#include +#include +#include +#include #include "cmem.h" -/* mallocを実行し、0で初期化 */ -/* メモリを確保できない場合はエラーを出力して終了 */ +/** + * mallocを実行し、0で初期化 + * メモリを確保できない場合はエラーを出力して終了 + */ void *malloc_chk(size_t size, char *tag) { void *p; @@ -13,8 +20,10 @@ void *malloc_chk(size_t size, char *tag) return memset(p, 0, size); } -/* callocを実行 */ -/* メモリを確保できない場合はエラーを出力して終了 */ +/** + * callocを実行 + * メモリを確保できない場合はエラーを出力して終了 + */ void *calloc_chk(size_t nmemb, size_t size, char *tag) { void *p; @@ -26,8 +35,9 @@ void *calloc_chk(size_t nmemb, size_t size, char *tag) return p; } -/* malloc_chkを実行してメモリを確保してから、 */ -/* コピーした文字列を返す */ +/** + * malloc_chkを実行してメモリを確保してから、コピーした文字列を返す + */ char *strdup_chk(const char *s, char *tag) { assert(s != NULL); @@ -38,10 +48,10 @@ char *strdup_chk(const char *s, char *tag) return t; } -/* メモリがNULLの場合は解放 */ +/** + * メモリを解放 + */ void free_chk(void *ptr, char *tag) { - if(ptr != NULL) { - free(ptr); - } + free(ptr); } diff --git a/src/comet2.c b/src/comet2.c index fedf895..138382a 100644 --- a/src/comet2.c +++ b/src/comet2.c @@ -1,9 +1,15 @@ -#include "casl2.h" -#include "exec.h" +#include +#include #define _GNU_SOURCE #include -/* comet2コマンドのオプション */ +#include "exec.h" +#include "cmem.h" +#include "cerr.h" + +/** + * comet2コマンドのオプション + */ static struct option longopts[] = { {"trace", no_argument, NULL, 't'}, {"tracearithmetic", no_argument, NULL, 't'}, @@ -15,37 +21,16 @@ static struct option longopts[] = { {0, 0, 0, 0} }; -/* comet2のエラー定義 */ -CERR cerr_comet2[] = { - { 201, "load object file - full of COMET II memory" }, +/** + * comet2コマンドのエラー + */ +static CERR cerr_comet2[] = { { 208, "object file is not specified" }, }; -bool addcerrlist_comet2() -{ - return addcerrlist(ARRAYSIZE(cerr_comet2), cerr_comet2); -} - -/* 指定されたファイルからアセンブル結果を読込 */ -bool loadassemble(char *file) { - FILE *fp; - bool status = true; - 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, NULL); /* Load object file - full of COMET II memory */ - fprintf(stderr, "Execute error - %d: %s\n", cerr->num, cerr->msg); - status = false; - } - fclose(fp); - return status; -} - -/* comet2コマンド */ +/** + * comet2コマンドのメイン + */ int main(int argc, char *argv[]) { int memsize = DEFAULT_MEMSIZE, clocks = DEFAULT_CLOCKS; @@ -53,7 +38,8 @@ int main(int argc, char *argv[]) const char *usage = "Usage: %s [-tTdh] [-M ] [-C ] FILE\n"; cerr_init(); - addcerrlist_comet2(); + addcerrlist(ARRAYSIZE(cerr_comet2), cerr_comet2); /* エラーリスト作成 */ + /* オプションの処理 */ while((opt = getopt_long(argc, argv, "tTdM:C:h", longopts, NULL)) != -1) { switch(opt) { @@ -90,9 +76,9 @@ int main(int argc, char *argv[]) reset(memsize, clocks); prog->start = 0; if(loadassemble(argv[optind]) == true) { - create_code_type(); /* 命令と命令タイプがキーのハッシュ表を作成 */ + create_code_type(); /* タイプがキーの命令ハッシュ表を作成 */ exec(); /* プログラム実行 */ - free_code_type(); /* 命令と命令タイプがキーのハッシュ表を解放 */ + free_code_type(); /* タイプがキーの命令ハッシュ表を解放 */ } /* COMET II仮想マシンのシャットダウン */ shutdown(); diff --git a/src/dump.c b/src/dump.c index 17ff7bc..857b3de 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1,7 +1,9 @@ -#include "casl2.h" +#include #include "exec.h" -/* COMET IIのメモリを表示 */ +/** + * COMET IIのメモリを表示 + */ void dumpmemory() { const int col = 16; @@ -26,7 +28,9 @@ void dumpmemory() } } -/* COMET IIのレジスタを表示 */ +/** + * COMET IIのレジスタを表示 + */ void dspregister() { int i; diff --git a/src/dumpword.c b/src/dumpword.c index 7e7d00a..d0afa9f 100644 --- a/src/dumpword.c +++ b/src/dumpword.c @@ -1,8 +1,9 @@ #define _GNU_SOURCE +#include +#include #include #include "word.h" #include "cerr.h" -#include "cmem.h" static struct option longopts[] = { { "arithmetic", no_argument, NULL, 'a' }, @@ -11,9 +12,12 @@ static struct option longopts[] = { { 0, 0, 0, 0 }, }; +/** + * dumpwordコマンドのメイン + */ int main(int argc, char *argv[]) { - bool logicalmode = false; /* レジストリの内容を論理値(0〜65535)で表示する場合はtrue */ + bool logicalmode = false; /* レジストリの内容を論理値(0から65535)で表示する場合はtrue */ int opt; WORD word; const char *usage = "Usage: %s [-alh] WORD\n"; diff --git a/src/exec.c b/src/exec.c index 35aec47..e19b415 100644 --- a/src/exec.c +++ b/src/exec.c @@ -1,8 +1,16 @@ -#include "casl2.h" +#include +#include +#include + #include "exec.h" +#include "cerr.h" + +/* 実行エラーの定義 */ +static CERR cerr_loadassemble[] = { + { 201, "Loading - full of COMET II memory" }, +}; -/* 実行のエラー定義 */ -CERR cerr_exec[] = { +static CERR cerr_exec[] = { { 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 +19,39 @@ CERR cerr_exec[] = { { 207, "Stack Pointer (SP) - out of COMET II memory" }, }; -bool addcerrlist_exec() -{ - return addcerrlist(ARRAYSIZE(cerr_exec), cerr_exec); -} - -/* 実行モード: trace, logical, dump */ +/** + * 実行モード: trace, logical, dump + */ EXECMODE execmode = {false, false, false}; -/* 標準入力から文字データを読込(SVC 1) */ -void svcin() +/** + * 指定されたファイルからアセンブル結果を読み込む + */ +bool loadassemble(char *file) { + FILE *fp; + bool status = true; + + addcerrlist(ARRAYSIZE(cerr_exec), cerr_loadassemble); /* エラーリスト作成 */ + 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 +75,10 @@ void svcin() free_chk(buffer, "buffer"); } -/* 標準出力へ文字データを書出(SVC 2) */ -void svcout() +/** + * 標準出力へ文字データを書出(SVC 2) + */ +static void svcout() { int i; WORD w; @@ -65,12 +98,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 +114,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 +138,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 +166,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 +187,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 +200,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 +232,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 +268,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 +296,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 +324,9 @@ WORD srl(WORD val0, WORD val1) return res; } -/* 仮想マシンCOMET IIでの実行 */ +/** + * 仮想マシンCOMET IIの実行 + */ bool exec() { WORD op, r_r1, x_r2, val; @@ -274,7 +334,7 @@ bool exec() char *errpr = malloc_chk(CERRSTRSIZE + 1, "exec.errpr"); clock_t clock_begin, clock_end; - addcerrlist_exec(); + addcerrlist(ARRAYSIZE(cerr_exec), cerr_exec); /* エラーリスト作成 */ if(execmode.trace == true) { fprintf(stdout, "\nExecuting machine codes\n"); } diff --git a/src/hash.c b/src/hash.c index f63b3f5..3da13dc 100644 --- a/src/hash.c +++ b/src/hash.c @@ -1,23 +1,8 @@ #include "hash.h" -/* ハッシュ表のサイズを決めるため、引数の数値より大きい最小の素数を返す */ -int hashtabsize(int size) -{ - int i; - const int prime[] = - {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, - 31, 37, 41, 43, 47, 53, 59, 61, 67, - 71, 73, 79, 83, 89, 97, - }; - for(i = 0; i < ARRAYSIZE(prime); i++) { - if(i > 0 && prime[i] >= size) { - break; - } - } - return prime[i]; -} - -/* ハッシュ値を取得する */ +/** + * ハッシュ値を取得する + */ unsigned hash(int keyc, HKEY *keyv[], int tabsize) { int i; diff --git a/src/label.c b/src/label.c index 1b9b806..2c4214e 100644 --- a/src/label.c +++ b/src/label.c @@ -1,10 +1,25 @@ -#include "casl2.h" +#include +#include +#include +#include + +#include "cerr.h" +#include "cmem.h" +#include "hash.h" #include "assemble.h" -int labelcnt = 0; /* ラベル数 */ -LABELTAB *labels[LABELTABSIZE]; /* ラベル表 */ +static int labelcnt = 0; /* ラベル数 */ +static LABELTAB *labels[LABELTABSIZE]; /* ラベル表 */ + +#ifndef UNITTEST +static unsigned labelhash(const char *prog, const char *label); + +static int compare_adr(const void *a, const void *b); +#endif -/* プログラム名とラベルに対応するハッシュ値を返す */ +/** + * プログラム名とラベルに対応するハッシュ値を返す + */ unsigned labelhash(const char *prog, const char *label) { HKEY *keys[2]; @@ -22,7 +37,9 @@ unsigned labelhash(const char *prog, const char *label) return hash(i+1, keys, LABELTABSIZE); } -/* ラベル表からアドレスを検索する */ +/** + * ラベル表からアドレスを検索する + */ WORD getlabel(const char *prog, const char *label) { assert(label != NULL); @@ -38,7 +55,9 @@ WORD getlabel(const char *prog, const char *label) return 0xFFFF; } -/* プログラム名、ラベル、アドレスをラベル表に追加する */ +/** + * プログラム名、ラベル、アドレスをラベル表に追加する + */ bool addlabel(const char *prog, const char *label, WORD adr) { assert(label != NULL); @@ -71,12 +90,17 @@ bool addlabel(const char *prog, const char *label, WORD adr) return true; } +/** + * ラベルを比較した結果を返す + */ int compare_adr(const void *a, const void *b) { return (**(LABELARRAY **)a).adr - (**(LABELARRAY **)b).adr; } -/* ラベル表を表示する */ +/** + * ラベル表を表示する + */ void printlabel() { int i, asize = 0; @@ -105,7 +129,9 @@ void printlabel() } } -/* ラベル表を解放する */ +/** + * ラベル表を解放する + */ void freelabel() { int i; @@ -115,7 +141,7 @@ void freelabel() for(np = labels[i]; np != NULL; np = nq) { nq = np->next; if(np->prog != NULL) { - free(np->prog); + free_chk(np->prog, "np.prog"); } free_chk(np->label, "np.label"); free_chk(np, "np"); diff --git a/src/struct.c b/src/struct.c index 9e3d256..7ac58e5 100644 --- a/src/struct.c +++ b/src/struct.c @@ -1,4 +1,5 @@ -#include "casl2.h" +#include "struct.h" +#include "cmem.h" /* COMET IIの仮装実行マシンシステム */ SYSTEM *sys; diff --git a/src/token.c b/src/token.c index 02e304d..3972d51 100644 --- a/src/token.c +++ b/src/token.c @@ -1,6 +1,13 @@ -#include "casl2.h" +#include +#include +#include "cerr.h" +#include "cmem.h" #include "assemble.h" +#ifndef UNITTEST +static OPD *opdtok(const char *str); +#endif + /* 「,」区切りの文字列から、オペランドのトークンを取得 */ OPD *opdtok(const char *str) { diff --git a/src/word.c b/src/word.c index 6e9fb17..3e9d305 100644 --- a/src/word.c +++ b/src/word.c @@ -1,20 +1,21 @@ +#include +#include +#include +#include +#include + #include "word.h" #include "cerr.h" /* wordのエラー定義 */ -CERR cerr_word[] = { +static CERR cerr_word[] = { { 114, "not integer" }, { 115, "not hex" }, { 116, "out of hex range" }, }; -bool addcerrlist_word() -{ - return addcerrlist(ARRAYSIZE(cerr_word), cerr_word); -} - /* 10進数の文字列をWORD値に変換 */ -WORD n2word(const char *str) +static WORD n2word(const char *str) { assert(isdigit(*str) || *str == '-'); @@ -26,7 +27,7 @@ WORD n2word(const char *str) setcerr(114, str); /* not integer */ return 0x0; } - /* nが-32768〜32767の範囲にないときは、その下位16ビットを格納 */ + /* nが-32768から32767の範囲にないときは、その下位16ビットを格納 */ if(n < -32768 || n > 32767) { n = n & 0xFFFF; } @@ -34,7 +35,7 @@ WORD n2word(const char *str) } /* 16進数の文字列をWORD値に変換 */ -WORD h2word(const char *str) +static WORD h2word(const char *str) { assert(*str == '#'); @@ -57,8 +58,11 @@ WORD h2word(const char *str) /* 10進数または16進数の文字列をWORD値に変換 */ WORD nh2word(const char *str) { - addcerrlist_word(); + assert(sizeof(WORD)*8 == 16); /* WORD型のサイズが16ビットであることを確認 */ + addcerrlist(ARRAYSIZE(cerr_word), cerr_word); /* エラーの設定 */ + WORD word; + if(!isdigit(*str) && *str != '-' && *str != '#') { setcerr(114, str); /* not integer */ return 0x0; -- 2.18.0