root/src/struct.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hash_cmdtype
  2. create_cmdtable
  3. free_cmdtable
  4. getcmdcode
  5. hash_code
  6. getcmdptr
  7. getcmdtype
  8. getcmdname
  9. grstr
  10. memsize_str2word
  11. comet2_init
  12. cpu_reset
  13. memory_reset
  14. comet2_reset
  15. comet2_resetall
  16. comet2_shutdown

   1 #include <errno.h>
   2 #include "struct.h"
   3 #include "exec.h"
   4 
   5 /**
   6  * COMET IIの仮想実行マシンシステム
   7  */
   8 SYSTEM *sys = NULL;
   9 
  10 /**
  11  * プログラム実行時の開始と終了のアドレス
  12  */
  13 EXECPTR *execptr = NULL;
  14 
  15 /**
  16  * システムCOMET IIの命令表
  17  */
  18 static const COMET2CMD comet2cmd[] = {
  19     { "NOP", NONE, 0x0, nop },
  20     { "LD", R_ADR_X, 0x1000, ld_r_adr_x },
  21     { "ST", R_ADR_X, 0x1100, st },
  22     { "LAD", R_ADR_X, 0x1200, lad },
  23     { "LD", R1_R2, 0x1400, ld_r1_r2 },
  24     { "ADDA", R_ADR_X, 0x2000, adda_r_adr_x },
  25     { "SUBA", R_ADR_X, 0x2100, suba_r_adr_x },
  26     { "ADDL", R_ADR_X, 0x2200, addl_r_adr_x },
  27     { "SUBL", R_ADR_X, 0x2300, subl_r_adr_x },
  28     { "ADDA", R1_R2, 0x2400, adda_r1_r2 },
  29     { "SUBA", R1_R2, 0x2500, suba_r1_r2 },
  30     { "ADDL", R1_R2, 0x2600, addl_r1_r2 },
  31     { "SUBL", R1_R2, 0x2700, subl_r1_r2 },
  32     { "AND", R_ADR_X, 0x3000, and_r_adr_x },
  33     { "OR", R_ADR_X, 0x3100, or_r_adr_x },
  34     { "XOR", R_ADR_X, 0x3200, xor_r_adr_x },
  35     { "AND", R1_R2, 0x3400, and_r1_r2 },
  36     { "OR", R1_R2, 0x3500, or_r1_r2 },
  37     { "XOR", R1_R2, 0x3600, xor_r1_r2 },
  38     { "CPA", R_ADR_X, 0x4000, cpa_r_adr_x },
  39     { "CPL", R_ADR_X, 0x4100, cpl_r_adr_x },
  40     { "CPA", R1_R2, 0x4400, cpa_r1_r2 },
  41     { "CPL", R1_R2, 0x4500, cpl_r1_r2 },
  42     { "SLA", R_ADR_X, 0x5000, sla },
  43     { "SRA", R_ADR_X, 0x5100, sra },
  44     { "SLL", R_ADR_X, 0x5200, sll },
  45     { "SRL", R_ADR_X, 0x5300, srl },
  46     { "JMI", ADR_X, 0x6100, jmi },
  47     { "JNZ", ADR_X, 0x6200, jnz },
  48     { "JZE", ADR_X, 0x6300, jze },
  49     { "JUMP", ADR_X, 0x6400, jump },
  50     { "JPL", ADR_X, 0x6500, jpl },
  51     { "JOV", ADR_X, 0x6600, jov },
  52     { "PUSH", ADR_X, 0x7000, push },
  53     { "POP", R_, 0x7100, pop },
  54     { "CALL", ADR_X, 0x8000, call },
  55     { "SVC", ADR_X, 0xF000, svc },
  56     { "RET", NONE, 0x8100, ret },
  57 };
  58 
  59 /**
  60  * 命令表のサイズ
  61  */
  62 static int comet2cmdsize = ARRAYSIZE(comet2cmd);
  63 
  64 /**
  65  * ハッシュ表のサイズ
  66  */
  67 enum {
  68     CMDTABSIZE = 41,
  69 };
  70 
  71 /**
  72  * ハッシュ表
  73  */
  74 static CMDTAB *cmdtab[HASH_MAX][CMDTABSIZE] = {{NULL}};
  75 
  76 /**
  77  * 命令の名前とタイプからハッシュ値を生成する
  78  */
  79 unsigned hash_cmdtype(const char *cmd, CMDTYPE type);
  80 
  81 /**
  82  * 命令コードからハッシュ値を生成する
  83  */
  84 unsigned hash_code(WORD code);
  85 
  86 /**
  87  * CPUのリセット
  88  */
  89 void cpu_reset();
  90 
  91 /**
  92  * メモリのリセット
  93  */
  94 void memory_reset();
  95 
  96 /**
  97  * 命令の名前とタイプからハッシュ値を生成する
  98  */
  99 unsigned hash_cmdtype(const char *cmd, CMDTYPE type)
 100 {
 101     HKEY *keys[2] = {NULL};
 102     unsigned hashval = 0;
 103 
 104     /* 命令名を設定 */
 105     keys[0] = malloc_chk(sizeof(HKEY), "hash_cmdtype.keys[0]");
 106     keys[0]->type = CHARS;
 107     keys[0]->val.s = strdup_chk(cmd, "keys[0].val.s");
 108     /* 命令タイプを設定 */
 109     keys[1] = malloc_chk(sizeof(HKEY), "hash_cmdtype.keys[1]");
 110     keys[1]->type = INT;
 111     keys[1]->val.i = (int)(type & 070);
 112     /* ハッシュ値の計算 */
 113     hashval = hash(2, keys, CMDTABSIZE);
 114     FREE(keys[0]->val.s);
 115     FREE(keys[0]);
 116     FREE(keys[1]);
 117     /* ハッシュ値を返す */
 118     return hashval;
 119 }
 120 
 121 /**
 122  * 命令ハッシュ表を作成する
 123  */
 124 bool create_cmdtable(CMDTAB_HASH hash)
 125 {
 126     CMDTAB *p = NULL;
 127     unsigned hashval;
 128 
 129     for(int i = 0; i < comet2cmdsize; i++) {
 130         p = malloc_chk(sizeof(CMDTAB), "create_cmdtable.p");
 131         p->cmd = &comet2cmd[i];
 132         if(hash == HASH_CMDTYPE) {
 133             hashval = hash_cmdtype(comet2cmd[i].name, comet2cmd[i].type);
 134         } else if(hash == HASH_CODE) {
 135             hashval = hash_code(comet2cmd[i].code);
 136         }
 137         p->next = cmdtab[hash][hashval];
 138         cmdtab[hash][hashval] = p;
 139     }
 140     return true;
 141 }
 142 
 143 /**
 144  * 命令ハッシュ表を解放する
 145  */
 146 void free_cmdtable(CMDTAB_HASH hash)
 147 {
 148     CMDTAB *p = NULL;
 149     CMDTAB *q = NULL;
 150 
 151     for(int i = 0; i < CMDTABSIZE; i++) {
 152         for(p = cmdtab[hash][i]; p != NULL; p = q) {
 153             q = p->next;
 154             FREE(p);
 155         }
 156         cmdtab[hash][i] = NULL;
 157     }
 158 }
 159 
 160 /**
 161  * 命令の名前とタイプから、命令コードを返す\n
 162  * 無効な場合は0xFFFFを返す
 163  */
 164 WORD getcmdcode(const char *cmd, CMDTYPE type)
 165 {
 166     CMDTAB *p = NULL;
 167     WORD w = 0xFFFF;
 168 
 169     assert(cmd != NULL);
 170     for(p = cmdtab[HASH_CMDTYPE][hash_cmdtype(cmd, type)]; p != NULL; p = p->next) {
 171         if(strcmp(cmd, p->cmd->name) == 0 && type == p->cmd->type) {
 172             w = p->cmd->code;
 173             break;
 174         }
 175     }
 176     return w;
 177 }
 178 
 179 /**
 180  * 命令コードからハッシュ値を生成する
 181  */
 182 unsigned hash_code(WORD code)
 183 {
 184     HKEY *keys[1] = {NULL};
 185     unsigned h = 0;
 186 
 187     /* 命令コードを設定 */
 188     keys[0] = malloc_chk(sizeof(HKEY), "hash_code.key");
 189     keys[0]->type = INT;
 190     keys[0]->val.i = (int)(code >> 8);
 191     h = hash(1, keys, CMDTABSIZE);
 192     FREE(keys[0]);
 193     return h;
 194 }
 195 
 196 /**
 197  * 命令コードから命令の関数ポインタを返す
 198  */
 199 const void (*getcmdptr(WORD code))
 200 {
 201     CMDTAB *t = NULL;
 202     const void *ptr = NULL;
 203 
 204     for(t = cmdtab[HASH_CODE][hash_code(code)]; t != NULL; t = t->next) {
 205         if(code == t->cmd->code) {
 206             ptr = t->cmd->ptr;
 207             break;
 208         }
 209     }
 210     return ptr;
 211 }
 212 
 213 /**
 214  * 命令コードから命令のタイプを返す
 215  */
 216 CMDTYPE getcmdtype(WORD code)
 217 {
 218     CMDTAB *t = NULL;
 219     CMDTYPE type = NONE;
 220 
 221     for(t = cmdtab[HASH_CODE][hash_code(code)]; t != NULL; t = t->next) {
 222         if(code == t->cmd->code) {
 223             type = t->cmd->type;
 224             break;
 225         }
 226     }
 227     return type;
 228 }
 229 
 230 /**
 231  * 命令コードから命令の名前を返す
 232  */
 233 char *getcmdname(WORD code)
 234 {
 235     CMDTAB *t = NULL;
 236     char *cmd = NULL;
 237 
 238     for(t = cmdtab[HASH_CODE][hash_code(code)]; t != NULL; t = t->next) {
 239         if(code == t->cmd->code) {
 240             cmd = t->cmd->name;
 241             break;
 242         }
 243     }
 244     return cmd;
 245 }
 246 
 247 /**
 248  * 汎用レジスタの番号からレジスタを表す文字列を返す
 249  */
 250 
 251 char *grstr(WORD word)
 252 {
 253     assert(word <= 7);
 254     char *str = NULL;
 255 
 256     str = malloc_chk(3 + 1, "grstr.str");
 257     sprintf(str, "GR%d", word);
 258     return str;
 259 }
 260 
 261 WORD memsize_str2word(const char *str) {
 262     return (WORD)str2l_range(str, 1, MAX_MEMSIZE, "Memory Size");
 263 }
 264 
 265 /**
 266  * COMET II仮想マシンの初期化
 267  */
 268 void comet2_init(WORD memsize, CLOCK clocks)
 269 {
 270     sys = malloc_chk(sizeof(SYSTEM), "sys");
 271     /* メモリサイズを設定 */
 272     assert(0 < memsize && memsize <= MAX_MEMSIZE-1);
 273     sys->memsize = memsize;
 274     /* クロック周波数を設定 */
 275     assert(0 < clocks && clocks <= MAX_CLOCKS);
 276     sys->clocks = clocks;
 277     /* CPU領域の確保 */
 278     sys->cpu = malloc_chk(sizeof(CPU), "comet2_init.cpu");
 279     /* CPUをリセット */
 280     cpu_reset();
 281     /* メモリ領域の確保 */
 282     sys->memory = calloc_chk(sys->memsize, sizeof(WORD), "comet2_init.memory");
 283     /* メモリをリセット */
 284     memory_reset();
 285     /* CASL2プログラムの開始と終了のアドレスを初期化 */
 286     execptr = malloc_chk(sizeof(EXECPTR), "execptr");
 287     execptr->stop = false;
 288 }
 289 
 290 
 291 void cpu_reset() {
 292     /* 汎用レジスタ  */
 293     for(int i = 0; i < GRSIZE; i++) {
 294         sys->cpu->gr[i] = 0x0;
 295     }
 296     sys->cpu->sp = sys->memsize;   /* スタックポインタ */
 297     sys->cpu->pr = 0x0;            /* プログラムレジスタ */
 298     sys->cpu->fr = 0x0;            /* フラグレジスタ */
 299 }
 300 
 301 /**
 302  * メモリのリセット
 303  */
 304 void memory_reset() {
 305     memset(sys->memory, 0, sys->memsize * sizeof(WORD));
 306 }
 307 
 308 /**
 309  * COMET II仮想マシンのCPUリセット
 310  */
 311 void comet2_reset()
 312 {
 313     /* CPUをリセット */
 314     cpu_reset();
 315 }
 316 
 317 /**
 318  * COMET II仮想マシンのCPUとメモリをリセット
 319  */
 320 void comet2_resetall()
 321 {
 322     /* CPUをリセット */
 323     cpu_reset();
 324     /* メモリをリセット */
 325     memory_reset();
 326 }
 327 
 328 /**
 329  * COMET II仮想マシンのシャットダウン
 330  */
 331 void comet2_shutdown()
 332 {
 333     FREE(execptr);
 334     FREE(sys->memory);
 335     FREE(sys->cpu);
 336     FREE(sys);
 337 }

/* [<][>][^][v][top][bottom][index][help] */