#ifndef YACASL2_ASSEMBLE_INCLUDED
#define YACASL2_ASSEMBLE_INCLUDED
-/* CASL IIの仕様 */
+#include <stdbool.h>
+#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 */
extern ASMODE asmode;
-/* アセンブル時のプロパティ */
+/**
+ * アセンブルのプロパティ
+ */
typedef struct {
WORD ptr; /* 現在のポインタ */
WORD lptr; /* リテラル(=付きの値)を格納するポインタ */
extern ASPROP *asprop;
-/* アセンブラ命令を表す番号 */
+/**
+ * アセンブラ命令を表す番号
+ */
typedef enum {
START = 01,
END = 02,
DC = 04,
} ASCMDID;
-/* アセンブラ命令を表す配列 */
+/**
+ * アセンブラ命令を表す配列
+ */
typedef struct {
ASCMDID cmdid;
int opdc_min;
char *cmd;
} ASCMD;
-/* マクロ命令を表す番号 */
+/**
+ * マクロ命令を表す番号
+ */
typedef enum {
IN = 011,
OUT = 012,
RPOP = 014,
} MACROCMDID;
-/* マクロ命令を表す配列 */
+/**
+ * マクロ命令を表す配列
+ */
typedef struct {
MACROCMDID cmdid;
int opdc_min;
char *cmd;
} MACROCMD;
-/* ラベル配列 */
+/**
+ * ラベル配列
+ */
typedef struct {
char *prog;
char *label;
WORD adr;
} LABELARRAY;
-/* ラベル表 */
+/**
+ * ラベル表
+ */
typedef struct _LABELTAB {
struct _LABELTAB *next;
char *prog;
} 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の終端 */
#ifndef YACASL2_CERR_H_INCLUDED
#define YACASL2_CERR_H_INCLUDED
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
#include <stdbool.h>
-
#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
#ifndef YACASL2_CMEM_H_INCLUDED
#define YACASL2_CMEM_H_INCLUDED
-
-#include <stdio.h>
#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdbool.h>
#ifndef ARRAYSIZE
#define ARRAYSIZE(array) (sizeof(array)/sizeof(array[0]))
#ifndef YACASL2_EXEC_INCLUDED
#define YACASL2_EXEC_INCLUDED
+#include <stdbool.h>
+#include "struct.h"
+#include "word.h"
+
enum {
- INSIZE = 256 /* CASL IIの、IN命令入力領域 */
+ INSIZE = 256 /**<IN命令の、入力領域 */
};
-/* 実行モード */
+/**
+ * 実行モード型
+ */
typedef struct {
- bool trace; /* レジストリの内容を表示する場合はtrue */
- bool logical; /* レジストリの内容を論理値(0〜65535)で表示する場合はtrue */
- bool dump; /* メモリの内容を表示する場合はtrue */
+ bool trace; /**<レジストリの内容を表示する場合はtrue */
+ bool logical; /**<レジストリの内容を論理値(0から65535)で表示する場合はtrue */
+ bool dump; /**<メモリの内容を表示する場合はtrue */
} EXECMODE;
+/**
+ * 実行モード: trace, logical, dump
+ */
extern EXECMODE execmode;
-/* コードから命令のパターンを取得 */
-CMDTYPE getcmdtype(WORD code);
-
-/* 実行のエラー定義 */
-bool addcerrlist_exec();
+/**
+ * 指定されたファイルからアセンブル結果を読み込む
+ */
+bool loadassemble(char *file);
/* COMET II仮想マシンのリセット */
void reset();
-/* コードの実行 */
+/**
+ * COMET II仮想マシンの実行
+ */
bool exec();
-/* COMET IIのメモリを表示 */
+/**
+ * COMET IIのメモリを表示
+ */
void dumpmemory();
-/* COMET IIのレジスタを表示 */
+/**
+ * COMET IIのレジスタを表示
+ */
void dspregister();
#endif /* YACASL2_EXEC_INCLUDEDの終端 */
#ifndef YACASL2_HASH_INCLUDED
#define YACASL2_HASH_INCLUDED
-#include "cmem.h"
-
-/* ハッシュ共用体の型 */
+/**
+ * ハッシュ共用体の型
+ */
typedef enum {
CHARS = 0,
INT = 1,
} UTYPE;
-/* ハッシュ共用体 */
+/**
+ * ハッシュ共用体
+ */
typedef struct {
UTYPE type;
union {
} val;
} HKEY;
-/* ハッシュ表のサイズを決めるため、引数の数値未満で最大の素数を返す */
-int hashtabsize(int size);
-
-/* ハッシュ値を取得する */
+/**
+ * ハッシュ値を取得する
+ */
unsigned hash(int keyc, HKEY *keyv[], int tabsize);
#endif
--- /dev/null
+#ifndef YACASL2_CASL2_INCLUDED
+#define YACASL2_CASL2_INCLUDED
+
+#include "word.h"
+
+/**
+ * COMET IIの規格
+ */
+enum {
+ CMDSIZE = 4, /**<命令の最大文字数 */
+ GRSIZE = 8, /**<汎用レジスタの数。COMET II規格により0から7までの8つ */
+ DEFAULT_MEMSIZE = 512, /**<デフォルトのメモリ容量。COMET II規格では、65535語(word) */
+ DEFAULT_CLOCKS = 5000000, /**<デフォルトのクロック周波数。COMET II規格では、未定義 */
+};
+
+/**
+ * COMET II フラグのマスク値
+ */
+enum {
+ OF = 0x4, /**<Overflow Flag */
+ SF = 0x2, /**<Sign Flag */
+ ZF = 0x1, /**<Zero Flag */
+};
+
+/**
+ * COMET IIのCPU
+ */
+typedef struct {
+ WORD gr[GRSIZE]; /**<汎用レジスタ */
+ WORD sp; /**<スタックポインタ */
+ WORD pr; /**<プログラムレジスタ */
+ WORD fr; /**<フラグレジスタ */
+} CPU;
+
+/**
+ * COMET IIの仮想実行マシンシステム
+ */
+typedef struct {
+ CPU *cpu; /**<CPU */
+ WORD *memory; /**<メモリ */
+ int memsize; /**<メモリサイズ */
+ int clocks; /**<クロック周波数 */
+} SYSTEM;
+
+extern SYSTEM *sys;
+
+/**
+ * COMET II 命令
+ * 命令タイプは、オペランドにより6種類に分類
+ */
+typedef enum {
+ /**
+ * オペランド数2または3
+ * 第1オペランド: 汎用レジスタ
+ * 第2オペランド: アドレス
+ * 第3オペランド: 指標レジスタ
+ */
+ R_ADR_X = 010,
+ /**
+ * オペランド数2または3
+ * 第1オペランド: 汎用レジスタ、
+ * 第2オペランド: アドレスに格納されている内容
+ * 第3オペランド: 指標レジスタ
+ */
+ R_ADR_X_ = 011,
+ /**
+ * オペランド数2
+ * 第1オペランド: 汎用レジスタ
+ * 第2オペランド: 汎用レジスタ
+ */
+ R1_R2 = 020,
+ /**
+ * オペランド数1または2
+ * 第1オペランド: アドレス
+ * 第2オペランド: 指標レジスタ
+ */
+ ADR_X = 030,
+ /**
+ * オペランド数1
+ * 第1オペランド: 汎用レジスタ
+ */
+ R_ = 040,
+ /**
+ * オペランドなし
+ */
+ NONE = 0,
+} CMDTYPE;
+
+/**
+ * 命令コード配列
+ */
+typedef struct {
+ char *name;
+ CMDTYPE type;
+ WORD code;
+} CMD;
+
+/**
+ * 命令コードのハッシュ表
+ */
+typedef struct _CMDTAB {
+ struct _CMDTAB *next;
+ CMD *cmd;
+} CMDTAB;
+
+/**
+ * CASL2プログラムのプロパティ
+ */
+typedef struct {
+ WORD start; /**<プログラムの開始番地 */
+ WORD end; /**<プログラムの終了番地 */
+} PROGPROP;
+
+extern PROGPROP *prog;
+
+/**
+ * COMET II仮想マシンのリセット
+ */
+void reset(int memsize, int clocks);
+
+/**
+ * COMET II仮想マシンのシャットダウン
+ */
+void shutdown();
+
+/**
+ * 名前とタイプがキーの命令ハッシュ表を作成する
+ */
+bool create_cmdtype_code();
+
+/**
+ * 命令の名前とタイプから、命令コードを返す
+ * 無効な場合は0xFFFFを返す
+ */
+WORD getcmdcode(const char *cmd, CMDTYPE type);
+
+/**
+ * 名前とタイプがキーの命令ハッシュ表を解放する
+ */
+void free_cmdtype_code();
+
+/**
+ * コードがキーの命令ハッシュ表を作成する
+ */
+bool create_code_type();
+
+/**
+ * 命令コードから命令タイプを返す
+ * 無効な場合はNONEを返す
+ */
+CMDTYPE getcmdtype(WORD code);
+
+/**
+ * コードがキーの命令ハッシュ表を解放する
+ */
+void free_code_type();
+
+#endif /* YACASL2_CASL2_INCLUDEDの終端 */
#ifndef YACASL2_WORD_H_INCLUDED
#define YACASL2_WORD_H_INCLUDED
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <ctype.h>
#include <stdbool.h>
-/* 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);
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
-#include "casl2.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
#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" },
{ 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);
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;
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;
return status;
}
-/* 命令がマクロ命令の場合はメモリに書込 */
-/* 書込に成功した場合はtrue、それ以外の場合はfalseを返す */
+/**
+ * macrocmd
+ * マクロ命令をメモリに書込
+ * 書込に成功した場合はtrue、それ以外の場合はfalseを返す
+ */
bool macrocmd(const CMDLINE *cmdl, PASS pass)
{
int i = 0;
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;
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;
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;
char *line;
FILE *fp;
- addcerrlist_assemble();
+ addcerrlist(ARRAYSIZE(cerr_assemble), cerr_assemble);
if((fp = fopen(file, "r")) == NULL) {
perror(file);
return false;
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);
+}
-#include "casl2.h"
-#include "assemble.h"
-#include "exec.h"
+#include <stdio.h>
+#include <stdlib.h>
+
#define _GNU_SOURCE
#include <getopt.h>
-/* 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' },
{ 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;
"Usage: %s [-slLaAtTdh] [-oO[<OBJECTFILE>]] [-M <MEMORYSIZE>] [-C <CLOCKS>] 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) {
/* アセンブル。ラベル表作成のため、2回行う */
for(pass = FIRST; pass <= SECOND; pass++) {
if(pass == FIRST) {
- create_cmdtype_code(); /* å\91½ä»¤ã\81¨å\91½ä»¤タイプがキーのハッシュ表を作成 */
+ create_cmdtype_code(); /* å\91½ä»¤ã\81®å\90\8då\89\8dã\81¨タイプがキーのハッシュ表を作成 */
asprop = malloc_chk(sizeof(ASPROP), "asprop"); /* アセンブル時のプロパティ用の領域確保 */
}
for(i = optind; i < argc; i++) {
freelabel(); /* ラベルハッシュ表を解放 */
free_chk(asprop->prog, "asprop.prog"); /* プログラム名を解放 */
free_chk(asprop, "asprop"); /* アセンブル時のプロパティを解放 */
- free_cmdtype_code(); /* å\91½ä»¤ã\81¨å\91½ä»¤タイプがキーのハッシュ表を解放 */
+ free_cmdtype_code(); /* å\91½ä»¤ã\81®å\90\8då\89\8dã\81¨タイプがキーのハッシュ表を解放 */
}
}
if(res == true) {
outassemble(objfile);
}
if(asmode.onlyassemble == false) {
- create_code_type(); /* å\91½ä»¤ã\81¨å\91½ä»¤タイプがキーのハッシュ表を作成 */
+ create_code_type(); /* å\91½ä»¤ã\81®ã\82³ã\83¼ã\83\89ã\81¨タイプがキーのハッシュ表を作成 */
res = exec(); /* プログラム実行 */
- free_code_type(); /* å\91½ä»¤ã\81¨å\91½ä»¤タイプがキーのハッシュ表を解放 */
+ free_code_type(); /* å\91½ä»¤ã\81®ã\82³ã\83¼ã\83\89ã\81¨タイプがキーのハッシュ表を解放 */
}
}
/* COMET II仮想マシンのシャットダウン */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdbool.h>
#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;
return true;
}
-/* 現在のエラーを設定する */
+/**
+ * 現在のエラーを設定する
+ */
void setcerr(int num, const char *str)
{
/* 現在のエラー番号を設定 */
}
}
-/* エラーリストから、エラー番号に対応するメッセージを返す */
+/**
+ * エラーリストから、エラー番号に対応するメッセージを返す
+ */
char *getcerrmsg(int num)
{
CERRLIST *p;
return "unknown error";
}
-/* エラーリストと現在のエラーを解放する */
+/**
+ * エラーリストと現在のエラーを解放する
+ */
void freecerr()
{
CERRLIST *p = cerrlist, *q;
-#include "cmem.h"
-#include "cerr.h"
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
#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 },
{ "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);
return hashval;
}
-/* 命令と命令タイプがキーのハッシュ表を作成する */
+/**
+ * 名前とタイプがキーの命令ハッシュ表を作成する
+ */
bool create_cmdtype_code()
{
CMDTAB *np;
return true;
}
-/* 命令と命令タイプから、命令コードを取得する */
-/* 無効な場合は0xFFFFを返す */
+/**
+ * 命令の名前とタイプから、命令コードを返す
+ * 無効な場合は0xFFFFを返す
+ */
WORD getcmdcode(const char *cmd, CMDTYPE type)
{
CMDTAB *np;
return 0xFFFF;
}
-/* 命令と命令タイプがキーのハッシュ表を解放する */
+/**
+ * 名前とタイプがキーの命令ハッシュ表を解放する
+ */
void free_cmdtype_code()
{
int i;
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);
return hash(1, keys, cmdtabsize);
}
-/* 命令コードがキーのハッシュ表を作成する */
+/**
+ * コードがキーの命令ハッシュ表を作成する
+ */
bool create_code_type()
{
CMDTAB *np;
return true;
}
-/* 命令コードから命令タイプを取得する */
-/* 無効な場合はNONEを返す */
+/**
+ * 命令コードから命令タイプを返す
+ * 無効な場合はNONEを返す
+ */
CMDTYPE getcmdtype(WORD code)
{
CMDTAB *np;
return NONE;
}
-/* 命令コードがキーのハッシュ表を解放する */
+/**
+ * コードがキーの命令ハッシュ表を解放する
+ */
void free_code_type()
{
int i;
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <stdbool.h>
#include "cmem.h"
-/* mallocを実行し、0で初期化 */
-/* メモリを確保できない場合はエラーを出力して終了 */
+/**
+ * mallocを実行し、0で初期化
+ * メモリを確保できない場合はエラーを出力して終了
+ */
void *malloc_chk(size_t size, char *tag)
{
void *p;
return memset(p, 0, size);
}
-/* callocを実行 */
-/* メモリを確保できない場合はエラーを出力して終了 */
+/**
+ * callocを実行
+ * メモリを確保できない場合はエラーを出力して終了
+ */
void *calloc_chk(size_t nmemb, size_t size, char *tag)
{
void *p;
return p;
}
-/* malloc_chkを実行してメモリを確保してから、 */
-/* コピーした文字列を返す */
+/**
+ * malloc_chkを実行してメモリを確保してから、コピーした文字列を返す
+ */
char *strdup_chk(const char *s, char *tag)
{
assert(s != NULL);
return t;
}
-/* メモリがNULLの場合は解放 */
+/**
+ * メモリを解放
+ */
void free_chk(void *ptr, char *tag)
{
- if(ptr != NULL) {
- free(ptr);
- }
+ free(ptr);
}
-#include "casl2.h"
-#include "exec.h"
+#include <stdio.h>
+#include <stdlib.h>
#define _GNU_SOURCE
#include <getopt.h>
-/* 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'},
{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;
const char *usage = "Usage: %s [-tTdh] [-M <MEMORYSIZE>] [-C <CLOCKS>] 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) {
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();
-#include "casl2.h"
+#include <stdio.h>
#include "exec.h"
-/* COMET IIのメモリを表示 */
+/**
+ * COMET IIのメモリを表示
+ */
void dumpmemory()
{
const int col = 16;
}
}
-/* COMET IIのレジスタを表示 */
+/**
+ * COMET IIのレジスタを表示
+ */
void dspregister()
{
int i;
#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
#include <getopt.h>
#include "word.h"
#include "cerr.h"
-#include "cmem.h"
static struct option longopts[] = {
{ "arithmetic", no_argument, NULL, 'a' },
{ 0, 0, 0, 0 },
};
+/**
+ * dumpwordコマンドのメイン
+ */
int main(int argc, char *argv[])
{
- bool logicalmode = false; /* ã\83¬ã\82¸ã\82¹ã\83\88ã\83ªã\81®å\86\85容ã\82\92è«\96ç\90\86å\80¤ï¼\880ã\80\9c65535)で表示する場合はtrue */
+ bool logicalmode = false; /* ã\83¬ã\82¸ã\82¹ã\83\88ã\83ªã\81®å\86\85容ã\82\92è«\96ç\90\86å\80¤ï¼\880ã\81\8bã\82\8965535)で表示する場合はtrue */
int opt;
WORD word;
const char *usage = "Usage: %s [-alh] WORD\n";
-#include "casl2.h"
+#include <stdio.h>
+#include <assert.h>
+#include <time.h>
+
#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" },
{ 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");
free_chk(buffer, "buffer");
}
-/* 標準出力へ文字データを書出(SVC 2) */
-void svcout()
+/**
+ * 標準出力へ文字データを書出(SVC 2)
+ */
+static void svcout()
{
int i;
WORD w;
}
}
-/* ロード/論理積/論理和/排他的論理和のフラグ設定。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 */
}
}
-/* 算術加算。フラグを設定して値を返す */
-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;
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;
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) {
}
}
-/* 論理比較のフラグ設定。OFは常に0 */
-void cpl(WORD val0, WORD val1)
+/**
+ * 論理比較のフラグ設定。OFは常に0
+ */
+static void cpl(WORD val0, WORD val1)
{
sys->cpu->fr = 0x0;
if(val0 < val1) {
}
}
-/* 算術左シフト。フラグを設定して値を返す。 */
-/* 算術演算なので、第15ビットは送り出されない */
-WORD sla(WORD val0, WORD val1)
+/**
+ * 算術左シフト。フラグを設定して値を返す
+ * 算術演算なので、第15ビットは送り出されない
+ */
+static WORD sla(WORD val0, WORD val1)
{
WORD sign, res, last = 0x0;
int i;
return res;
}
-/* 算術右シフト。フラグを設定して値を返す */
-/* 算術演算なので、第15ビットは送り出されない */
-/* 空いたビット位置には符号と同じものが入る */
-WORD sra(WORD val0, WORD val1)
+/**
+ * 算術右シフト。フラグを設定して値を返す
+ * 算術演算なので、第15ビットは送り出されない
+ * 空いたビット位置には符号と同じものが入る
+ */
+static WORD sra(WORD val0, WORD val1)
{
WORD sign, res, last = 0x0;
int i;
return res;
}
-/* 論理左シフト。フラグを設定して値を返す */
-WORD sll(WORD val0, WORD val1)
+/**
+ * 論理左シフト。フラグを設定して値を返す
+ */
+static WORD sll(WORD val0, WORD val1)
{
WORD res = val0, last = 0x0;
int i;
return res;
}
-/* 論理右シフト。フラグを設定して値を返す */
-WORD srl(WORD val0, WORD val1)
+/**
+ * 論理右シフト。フラグを設定して値を返す
+ */
+static WORD srl(WORD val0, WORD val1)
{
WORD res = val0, last = 0x0;
int i;
return res;
}
-/* 仮想マシンCOMET IIでの実行 */
+/**
+ * 仮想マシンCOMET IIの実行
+ */
bool exec()
{
WORD op, r_r1, x_r2, val;
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");
}
#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;
-#include "casl2.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#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];
return hash(i+1, keys, LABELTABSIZE);
}
-/* ラベル表からアドレスを検索する */
+/**
+ * ラベル表からアドレスを検索する
+ */
WORD getlabel(const char *prog, const char *label)
{
assert(label != NULL);
return 0xFFFF;
}
-/* プログラム名、ラベル、アドレスをラベル表に追加する */
+/**
+ * プログラム名、ラベル、アドレスをラベル表に追加する
+ */
bool addlabel(const char *prog, const char *label, WORD adr)
{
assert(label != NULL);
return true;
}
+/**
+ * ラベルを比較した結果を返す
+ */
int compare_adr(const void *a, const void *b)
{
return (**(LABELARRAY **)a).adr - (**(LABELARRAY **)b).adr;
}
-/* ラベル表を表示する */
+/**
+ * ラベル表を表示する
+ */
void printlabel()
{
int i, asize = 0;
}
}
-/* ラベル表を解放する */
+/**
+ * ラベル表を解放する
+ */
void freelabel()
{
int i;
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");
-#include "casl2.h"
+#include "struct.h"
+#include "cmem.h"
/* COMET IIの仮装実行マシンシステム */
SYSTEM *sys;
-#include "casl2.h"
+#include <stdio.h>
+#include <string.h>
+#include "cerr.h"
+#include "cmem.h"
#include "assemble.h"
+#ifndef UNITTEST
+static OPD *opdtok(const char *str);
+#endif
+
/* 「,」区切りの文字列から、オペランドのトークンを取得 */
OPD *opdtok(const char *str)
{
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <ctype.h>
+
#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 == '-');
setcerr(114, str); /* not integer */
return 0x0;
}
- /* nã\81\8c-32768ã\80\9c32767の範囲にないときは、その下位16ビットを格納 */
+ /* nã\81\8c-32768ã\81\8bã\82\8932767の範囲にないときは、その下位16ビットを格納 */
if(n < -32768 || n > 32767) {
n = n & 0xFFFF;
}
}
/* 16進数の文字列をWORD値に変換 */
-WORD h2word(const char *str)
+static WORD h2word(const char *str)
{
assert(*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;