--- /dev/null
+TEST START
+ RET
+ END
#include <string.h>
#include <assert.h>
#include <stdbool.h>
+#include <limits.h>
/**
* @brief 配列のサイズを返すマクロ
#define FREE(ptr) {free(ptr); ptr = NULL;}
#endif
+/**
+ * @brief 数値文字列が特定の範囲の数値かチェックし、正の場合は変換した数値、不正の場合は0を返す
+ *
+ * @param str 数値文字列
+ * @param min 範囲最小値
+ * @param min 範囲最大値
+ * @param tag エラーメッセージなどで表示される名前
+ *
+ */
+long str2l_range(const char *str, long min, long max, const char *name);
+
/**
* @brief mallocを実行し、0で初期化する
*
INSIZE = 256 /**<IN命令の、入力領域 */
};
+/**
+ * @brief クロック周波数を表す文字列を正しいかチェックし、正の整数値に変換
+ *
+ * @return クロック周波数を表す正の整数値
+ *
+ * @param str クロック周波数を表す文字列
+ */
+CLOCK clock_str2clock(const char *str);
+
/**
* @brief 実行エラーをエラーリストに追加する
*/
#include "cmem.h"
#include "hash.h"
+typedef unsigned int CLOCK;
+
/**
* @brief COMET IIの規格値
*/
enum {
CMDSIZE = 4, /**<命令の最大文字数 */
- GRSIZE = 8, /**<汎用レジスタの数。COMET II規格では、8(0から7) */
- DEFAULT_MEMSIZE = 512, /**<デフォルトのメモリ容量。COMET II規格では、65535語(word) */
- DEFAULT_CLOCKS = 5000000, /**<デフォルトのクロック周波数。COMET II規格では、未定義 */
+ GRSIZE = 8, /**<汎用レジスタの数。COMET II規格で、GR0〜GR7までの8 */
+ MAX_MEMSIZE = 65536, /**<メモリ容量の最大値。COMET II規格で、アドレス0~65535の65536語(word) */
+ DEFAULT_MEMSIZE = 512, /**<メモリ容量の初期値。COMET II規格では、アドレス0~65535の65536語(word) */
+ MAX_CLOCKS = 1000000, /**<クロック周波数の最大値。POSIXのCLOCKS_PER_SECと同値 */
+ DEFAULT_CLOCKS = MAX_CLOCKS, /**<クロック周波数の初期値。最大値と同値 */
};
/**
typedef struct {
CPU *cpu; /**<CPU */
WORD *memory; /**<メモリ */
- int memsize; /**<メモリサイズ */
- clock_t clocks; /**<クロック周波数 */
+ WORD memsize; /**<メモリサイズ */
+ CLOCK clocks; /**<クロック周波数 */
} SYSTEM;
/**
char *grstr(WORD word);
/**
- * COMET II仮想マシンのリセット
+ * @brief メモリーサイズとして受け取った文字列をに変換。1から65536までの範囲の整数に変換できない場合はエラー
+ *
+ * @return メモリーサイズの数値。1から65536までの範囲の整数
+ *
+ * @param str メモリーサイズ文字列
*/
-void comet2_init(int memsize, int clocks);
+WORD memsize_str2word(const char *str);
/**
- * COMET II仮想マシンのCPUをリセット
+ * @brief COMET II仮想マシンの初期化
+ *
+ * @param memsize メモリーサイズ。1から65535までの範囲の整数
+ * @param clocks クロック数。1から1000000までの範囲の整数
*/
+void comet2_init(WORD memsize, CLOCK clocks);
+
+/**
+ * @brief COMET II仮想マシンのCPUをリセット
+ */
void comet2_reset();
/**
void comet2_resetall();
/**
- * COMET II仮想マシンのシャットダウン
+ * @brief COMET II仮想マシンのシャットダウン
*/
void comet2_shutdown();
*
* @param *str ファイル名
*/
-char *objfile_name(const char *str);
+char *objfile_name(const char *name);
/**
* @brief casl2コマンドのオプション
execmode.step = true;
break;
case 'M':
- memsize = atoi(optarg);
+ if((memsize = memsize_str2word(optarg)) == 0) {
+ goto casl2fin;
+ }
break;
case 'C':
- clocks = atoi(optarg);
+ if((clocks = clock_str2clock(optarg)) == 0) {
+ goto casl2fin;
+ }
break;
case 'v':
fprintf(stdout, cmdversion, version);
#include "cmem.h"
+long str2l_range(const char *str, long min, long max, const char *name) {
+ char *endptr = NULL;
+ long val = strtol(str, &endptr, 10);
+ if(endptr == str) {
+ fprintf(stderr, "%s: Not specified.\n", name);
+ return 0;
+ } else if(*endptr != '\0') {
+ fprintf(stderr, "%s: `%s' is not integer.\n", name, str);
+ return 0;
+ } else if(val < min || max < val) {
+ if(max == LONG_MAX) {
+ fprintf(stderr, "%s: %s out of range: %ld -\n", str, name, min);
+ } else {
+ fprintf(stderr, "%s: %s out of range: %ld - %ld\n", str, name, min, max);
+ }
+ return 0;
+ }
+ return val;
+}
+
void *malloc_chk(size_t size, const char *tag)
{
void *p = NULL;
execmode.monitor = true;
break;
case 'M':
- memsize = atoi(optarg);
+ if((memsize = memsize_str2word(optarg)) == 0) {
+ goto comet2fin;
+ }
break;
case 'C':
- clocks = atoi(optarg);
+ if((clocks = clock_str2clock(optarg)) == 0) {
+ goto comet2fin;
+ }
break;
case 'v':
fprintf(stdout, cmdversion, version);
while((opt = getopt_long(argc, argv, "M:C:vh", longopts, NULL)) != -1) {
switch(opt) {
case 'M':
- memsize = atoi(optarg);
+ if((memsize = memsize_str2word(optarg)) == 0) {
+ goto comet2monitorfin;
+ }
break;
case 'C':
- clocks = atoi(optarg);
+ if((clocks = clock_str2clock(optarg)) == 0) {
+ goto comet2monitorfin;
+ }
break;
case 'v':
fprintf(stdout, cmdversion, version);
{ 207, "address in word #2 - out of memory" },
{ 208, "SVC input - memory overflow" },
{ 209, "SVC output - memory overflow" },
+ { 214, "CPU Clocks - not positive integer" },
+ { 215, "Memory Size - not integer or out of range: 1 - 65536" },
};
/**
*/
EXECMODE execmode = {false, false, false, 0, 0xFFFF, false, false};
+CLOCK clock_str2clock(const char *str) {
+ long val = str2l_range(str, 1, LONG_MAX, "Clock");
+ if(val > MAX_CLOCKS) {
+ val = MAX_CLOCKS;
+ fprintf(stderr, "Info - %s: Clock frequency exceeds maximum. Set to %ld\n", str, val);
+ }
+ return (CLOCK)val;
+}
+
char *pr2str(WORD pr)
{
char *str = malloc_chk(CERRSTRSIZE + 1, "pr2str.pr");
break;
}
if(sys->cpu->gr[1] + i > execptr->end) {
- setcerr(208, ""); /* SVC input - memory overflow */
+ setcerr
+ (208, ""); /* SVC input - memory overflow */
break;
}
sys->memory[sys->cpu->gr[1] + i] = buf[i];
void exec()
{
- clock_t clock_begin = 0;
- clock_t clock_end = 0;
+ CLOCK clock_begin = 0;
+ CLOCK clock_end = 0;
void (*cmdptr)() = NULL;
char *s = NULL;
const char *monmsg = "COMET II machine code monitor. Type ? for help.\n";
end = start + fread(sys->memory + start, sizeof(WORD), sys->memsize - start, fp);
if(end == sys->memsize) {
setcerr(210, file); /* load - memory overflow */
+ fprintf(stderr, "Load error - %d: %s\n", cerr->num, cerr->msg);
}
fclose(fp);
return end;
+#include <errno.h>
#include "struct.h"
#include "exec.h"
*/
unsigned hash_code(WORD code);
+/**
+ * CPUのリセット
+ */
+void cpu_reset();
+
+/**
+ * メモリのリセット
+ */
+void memory_reset();
+
/**
* 命令の名前とタイプからハッシュ値を生成する
*/
return str;
}
-void cpu_reset() {
- sys->cpu = malloc_chk(sizeof(CPU), "cpu");
- for(int i = 0; i < GRSIZE; i++) { /* 汎用レジスタ */
- sys->cpu->gr[i] = 0x0;
- }
- sys->cpu->sp = sys->memsize; /* スタックポインタ */
- sys->cpu->pr = 0x0; /* プログラムレジスタ */
- sys->cpu->fr = 0x0; /* フラグレジスタ */
-}
-
-void memory_reset() {
+WORD memsize_str2word(const char *str) {
+ return (WORD)str2l_range(str, 1, MAX_MEMSIZE, "Memory Size");
}
-
/**
* COMET II仮想マシンの初期化
*/
-void comet2_init(int memsize, int clocks)
+void comet2_init(WORD memsize, CLOCK clocks)
{
sys = malloc_chk(sizeof(SYSTEM), "sys");
/* メモリサイズを設定 */
+ assert(0 < memsize && memsize <= MAX_MEMSIZE-1);
sys->memsize = memsize;
/* クロック周波数を設定 */
+ assert(0 < clocks && clocks <= MAX_CLOCKS);
sys->clocks = clocks;
- /* メモリ領域の確保 */
- sys->memory = calloc_chk(sys->memsize, sizeof(WORD), "memory");
- /* CPUã\82\92ã\82¯ã\83ªã\82¢ */
+ /* CPU領域の確保 */
+ sys->cpu = malloc_chk(sizeof(CPU), "comet2_init.cpu");
+ /* CPUã\82\92ã\83ªã\82»ã\83\83ã\83\88 */
cpu_reset();
+ /* メモリ領域の確保 */
+ sys->memory = calloc_chk(sys->memsize, sizeof(WORD), "comet2_init.memory");
+ /* メモリをリセット */
+ memory_reset();
/* CASL2プログラムの開始と終了のアドレスを初期化 */
execptr = malloc_chk(sizeof(EXECPTR), "execptr");
execptr->stop = false;
}
+
+void cpu_reset() {
+ /* 汎用レジスタ */
+ for(int i = 0; i < GRSIZE; i++) {
+ sys->cpu->gr[i] = 0x0;
+ }
+ sys->cpu->sp = sys->memsize; /* スタックポインタ */
+ sys->cpu->pr = 0x0; /* プログラムレジスタ */
+ sys->cpu->fr = 0x0; /* フラグレジスタ */
+}
+
+/**
+ * メモリのリセット
+ */
+void memory_reset() {
+ memset(sys->memory, 0, sys->memsize * sizeof(WORD));
+}
+
/**
* COMET II仮想マシンのCPUリセット
*/
/* CPUをリセット */
cpu_reset();
/* メモリをリセット */
- memset(sys->memory, 0, sys->memsize * sizeof(WORD));
+ memory_reset();
}
/**
--- /dev/null
+Execute error - 202: PR:#0000: Stack Pointer (SP) - stack overflow
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -M1 ../../../../as/sample/test.casl
--- /dev/null
+-1: Clock out of range: 1 -
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -C -1 ../../../../as/sample/test.casl
--- /dev/null
+0: Clock out of range: 1 -
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -C 0 ../../../../as/sample/test.casl
--- /dev/null
+Clock: `1.5' is not integer.
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -C 1.5 ../../../../as/sample/test.casl
--- /dev/null
+Clock: Not specified.
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -C abc ../../../../as/sample/test.casl
--- /dev/null
+-1: Memory Size out of range: 1 - 65536
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -M -1 ../../../../as/sample/test.casl
--- /dev/null
+0: Memory Size out of range: 1 - 65536
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -M 0 ../../../../as/sample/test.casl
--- /dev/null
+Memory Size: `1.5' is not integer.
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -M 1.5 ../../../../as/sample/test.casl
--- /dev/null
+65537: Memory Size out of range: 1 - 65536
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -M 65537 ../../../../as/sample/test.casl
--- /dev/null
+Memory Size: Not specified.
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -M abc ../../../../as/sample/test.casl
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -C 1 ../../../../as/sample/test.casl
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -C 1000 ../../../../as/sample/test.casl
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -M 65535 ../../../../as/sample/test.casl
--- /dev/null
+Info - 1000001: Clock frequency exceeds maximum. Set to 1000000
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -C 1000001 ../../../../as/sample/test.casl
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -M 2 ../../../../as/sample/test.casl
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -M 512 ../../../../as/sample/test.casl
--- /dev/null
+include ../Define.mk
+include ../Test.mk
--- /dev/null
+../../../../casl2 -M 65535 ../../../../as/sample/test.casl