#include "emul_inst_decipher.h" #include <string.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include "emul_io_std.h" /* typedef struct { int opecode; int string; } emul_isa_t; */ #define ISA_COUNT 23 emul_isa_t isa_dict[ISA_COUNT] = { { ADD , "add" }, { ADDI, "addi" }, { SUB , "sub" }, { SLT , "slt" }, { SLTI, "slti" }, { SEQ , "seq" }, { SGE , "sge" }, { SGT , "sgt" }, { SLE , "sle" }, { SNE , "sne" }, { B , "b" }, { BEQ , "beq" }, { BNE , "bne" }, { J , "j" }, { LW , "lw" }, { SW , "sw" }, { MOVE, "move" } }; #define REG_COUNT 31 emul_reg_t reg_dict[REG_COUNT] = { { Szero, "$zero" }, // Zero register { Sat , "$at" }, // using asem { Sv0 , "$v0" }, // return { Sv1 , "$v1" }, { Sa0 , "$a0" }, // argment { Sa1 , "$a1" }, { Sa2 , "$a2" }, { Sa3 , "$a3" }, { St0 , "$t0" }, // temp { St1 , "$t1" }, { St2 , "$t2" }, { St3 , "$t3" }, { St4 , "$t4" }, { St5 , "$t5" }, { St6 , "$t6" }, { St7 , "$t7" }, { Ss0 , "$s0" }, // var { Ss1 , "$s1" }, { Ss2 , "$s2" }, { Ss3 , "$s3" }, { Ss4 , "$s4" }, { Ss5 , "$s5" }, { Ss6 , "$s6" }, { Ss7 , "$s7" }, { Sk0 , "$k0" }, // kernel { Sk1 , "$k1" }, { Sgp , "$gp" }, // grobal { Ssp , "$sp" }, // stack { Sfp , "$fp" }, // frame { Sra , "$ra" }, // return address { Spc , "$pc" } // return address }; #define PSEUDO_COUNT 11 emul_pseudo_t pseudo_dict[REG_COUNT] = { { DUMP , ":DUMP" }, { MEMCAT , ":MEMCAT" }, { MEMCATW , ":MEMCATW" }, { REGCAT , ":REGCAT" }, { LABEL , ":LABEL" }, { RUN , ":RUN" }, { STEP , ":STEP" }, { INPUT , ":INPUT" }, { OUTPUT , ":OUTPUT" }, { CRLF , ":CRLF" }, { EXIT , ":EXIT" } }; static char program[LOAD_LINE_HEIGHT_MAX][LOAD_LINE_WIDTH_MAX]; static int program_line_current; // *_update_pc()により更新される static int program_line_max; // *_load()を呼び出したときにのみ更新 void emul_inst_dec_init() { } void emul_inst_dec_set_pc(int pc) { program_line_current = pc; } void emul_inst_dec_update_pc() { int pc; // プログラムカウンタ取得 pc = emul_reg_get(emul_inst_dec_get_operand("$pc\0")); // 呼び出すアドレスにプログラムカウンタを設定 emul_inst_dec_set_pc(pc); // プログラムカウンタをインクリメント emul_reg_set(emul_inst_dec_get_operand("$pc\0"), pc+1); } int emul_inst_dec_load(const char *filename) { FILE *fp; int line; emul_out_std_debug("Now opening file $s...\n", filename); if ((fp = fopen(filename, "r")) == NULL) { emul_out_std_err("%s is can not open\n", filename); return 0; } emul_out_std_debug("Now loading file $s...\n", filename); program_line_current = 0; line = 0; while ( fgets(program[line], LOAD_LINE_WIDTH_MAX, fp) != NULL ) { emul_out_std_debug("Now loading file line %d\n", line); emul_out_std_debug(">>%s\n", program[line]); line++; } program_line_max = line; fclose(fp); emul_out_std_debug("Finish loading! line=%d\n", program_line_max); return 1; } int emul_inst_dec_get_token(char *token) { static char line[LOAD_LINE_WIDTH_MAX] = {0}; static char *current = line; int fShift; int i; do { fShift = 0; // 読み込んだ行の先頭が印字可能文字になるようにシフト while ( *current != '\0' && isspace(*current) ) current++; // 読み込みを開始する先頭がヌルなら新しい行を読み込む if ( *current == '\0' ) { // 読み込める行がない場合終了 if ( !(program_line_current < program_line_max) ) return 0; // 次の行を読み込むためPCを更新 emul_inst_dec_update_pc(); // 次の行を読み込むためcurrentのポインタをリセット current = line; // currentにセット strcpy(current, program[program_line_current]); // 読み込みを行った場合はシフトフラグをセット fShift = 1; } } while(fShift); // 新しい行を読み込んだ場合もう一度シフトを行う // 次のスペース(もしくは'\0')が現れるまで読み込み i = 0; while ( !isspace(*current) ) { token[i] = *current; i++, current++; // インクリメントに注意する } token[i] = '\0'; return 1; } // Example: // ASM: add St0, Ss0, Ss1 // RETURN: add int emul_inst_dec_get_opecode(const char *token) { int i; for (i = 0; i < ISA_COUNT; i++) { if ( strcmp(isa_dict[i].string, token) == 0 ) { return isa_dict[i].opecode; } } return OPECODE_DECODE_ERROR; } // Example: // ASM: add St0, Ss0, Ss1 // RETURN: St0 // RETURN: Ss0 // RETURN: Ss1 int emul_inst_dec_get_operand(const char *token) { int i; for (i = 0; i < REG_COUNT; i++) { if ( strcmp(reg_dict[i].string, token) == 0 ) { return reg_dict[i].operand; } } return OPERAND_DECODE_ERROR; } int emul_inst_dec_get_next_opecode() { char token[LOAD_TOKEN_MAX]; emul_inst_dec_get_token(token); return emul_inst_dec_get_opecode(token); } int emul_inst_dec_get_next_operand() { char token[LOAD_TOKEN_MAX]; emul_inst_dec_get_token(token); return emul_inst_dec_get_operand(token); } // immediate int emul_inst_dec_get_next_immediate() { char token[LOAD_TOKEN_MAX]; emul_inst_dec_get_token(token); return atoi(token); } // 疑似コード int emul_inst_dec_get_pseudo(const char *token) { int i; for (i = 0; i < PSEUDO_COUNT; i++) { if ( strcmp(pseudo_dict[i].string, token) == 0 ) { return pseudo_dict[i].pseudo; } } return PSEUDO_DECODE_ERROR; } int emul_inst_dec_get_next_pseudo() { char token[LOAD_TOKEN_MAX]; emul_inst_dec_get_token(token); return emul_inst_dec_get_pseudo(token); }