#include "emul_inst_exec.h" #include "emul_io_std.h" #include <string.h> // exit message static char faild_message(); #define EXIT_MESSAGE_LENGTH 128 void emul_inst_exec_get_faild_message(char *msg); // propaty static RUNMODE RunMode; void emul_inst_exec_set_runmode(RUNMODE mode) { RunMode = mode; } RUNMODE emul_inst_exec_get_runmode() { return RunMode; } // プロトタイプ exitcode_t emul_inst_exec_pseudo(char token[LOAD_TOKEN_MAX]); // load label void emul_inst_exec_load_label() { char token[LOAD_TOKEN_MAX]; int ps_id; // トークンを取得 if ( emul_inst_dec_get_token(token) == 0 ) { emul_out_std_err("Non exist next token\n"); // 次のトークンが見つからない場合終了, pcのアドレスを初期化 emul_inst_dec_reset_pc(); return ; } emul_out_std_debug("[label] load token: %s\n", token); // 疑似コードを取得 ps_id = emul_inst_dec_get_pseudo(token); // 疑似コードがLABELなら if ( ps_id == LABEL ) { // 疑似コードを実行 emul_inst_exec_pseudo(token); } // 読み込めるトークンがなくなるまで実行 emul_inst_exec_load_label(); } void emul_inst_exec_init() { emul_std_init(); emul_reg_init(); emul_inst_dec_init(); } void emul_inst_exec_end() { emul_std_end(); } int emul_inst_exec_load(char *filename) { // ロードできないなら終了 if ( emul_inst_dec_load(filename) == 0 ) return 0; // できたらラベルも読み込み emul_inst_exec_load_label(); return 1; } int emul_inst_exec_loadline(char *line) { // ロードできないなら終了 if ( emul_inst_dec_loadline(line) == 0 ) return 0; // できたらラベルも読み込み //emul_inst_exec_load_label(); return 1; } /* オペコード解読処理群 - START */ void emul_inst_exec_add(int r0, int r1, int r2) { emul_out_std_debug(" : add r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); emul_reg_set(r0, emul_reg_get(r1) + emul_reg_get(r2)); emul_out_std_debug("Execute: add r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); } void emul_inst_exec_addi(int r0, int r1, int im) { emul_out_std_debug(" : addi r0[%d], r1[%d], im[%d];\n", emul_reg_get(r0), emul_reg_get(r1), im); emul_reg_set(r0, emul_reg_get(r1) + im); emul_out_std_debug("Execute: addi r0[%d], r1[%d], im[%d];\n", emul_reg_get(r0), emul_reg_get(r1), im); } void emul_inst_exec_sub(int r0, int r1, int r2) { emul_out_std_debug(" : sub r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); emul_reg_set(r0, emul_reg_get(r1) - emul_reg_get(r2)); emul_out_std_debug("Execute: sub r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); } void emul_inst_exec_slt(int r0, int r1, int r2) { emul_out_std_debug(" : slt r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); if (emul_reg_get(r1) < emul_reg_get(r2)) emul_reg_set(r0, 1); else emul_reg_set(r0, 0); emul_out_std_debug("Execute: slt r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); } void emul_inst_exec_slti(int r0, int r1, int im) { emul_out_std_debug(" : slti r0[%d], r1[%d], im[%d];\n", emul_reg_get(r0), emul_reg_get(r1), im); if (emul_reg_get(r1) < im) emul_reg_set(r0, 1); else emul_reg_set(r0, 0); emul_out_std_debug("Execute: slti r0[%d], r1[%d], im[%d];\n", emul_reg_get(r0), emul_reg_get(r1), im); } void emul_inst_exec_seq(int r0, int r1, int r2) { emul_out_std_debug(" : seq r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); if (emul_reg_get(r1) == emul_reg_get(r2)) emul_reg_set(r0, 1); else emul_reg_set(r0, 0); emul_out_std_debug("Execute: seq r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); } void emul_inst_exec_sge(int r0, int r1, int r2) { emul_out_std_debug(" : sge r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); if (emul_reg_get(r1) >= emul_reg_get(r2)) emul_reg_set(r0, 1); else emul_reg_set(r0, 0); emul_out_std_debug("Execute: sge r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); } void emul_inst_exec_sgt(int r0, int r1, int r2) { emul_out_std_debug(" : sgt r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); if (emul_reg_get(r1) >= emul_reg_get(r2)) emul_reg_set(r0, 1); else emul_reg_set(r0, 0); emul_out_std_debug("Execute: sgt r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); } void emul_inst_exec_sle(int r0, int r1, int r2) { emul_out_std_debug(" : sle r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); if (emul_reg_get(r1) <= emul_reg_get(r2)) emul_reg_set(r0, 1); else emul_reg_set(r0, 0); emul_out_std_debug("Execute: sle r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); } void emul_inst_exec_sne(int r0, int r1, int r2) { emul_out_std_debug(" : sne r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); if (emul_reg_get(r1) != emul_reg_get(r2)) emul_reg_set(r0, 1); else emul_reg_set(r0, 0); emul_out_std_debug("Execute: sne r0[%d], r1[%d], r2[%d];\n", emul_reg_get(r0), emul_reg_get(r1), emul_reg_get(r2)); } void emul_inst_exec_j(char *label) { int getted_address; emul_out_std_debug(" : j label[%s];\n", label); getted_address = emul_label_resolve(label); emul_reg_set( Spc, getted_address ); emul_out_std_debug("Execute: j label[%s];\n", label); } void emul_inst_exec_beq(int r0, int r1, char *label) { emul_out_std_debug(" : beq r0[%d] r1[%d] label[%d];\n", emul_reg_get(r0), emul_reg_get(r1), label); if (emul_reg_get(r0) == emul_reg_get(r1)) { emul_reg_set( Spc, emul_label_resolve(label) ); } emul_out_std_debug("Execute: beq r0[%d] r1[%d] label[%d];\n", emul_reg_get(r0), emul_reg_get(r1), label); } void emul_inst_exec_bne(int r0, int r1, char *label) { int getted_address = -1; emul_out_std_debug(" : bne r0[%d] r1[%d] label[%s]>>PC(%d);\n", emul_reg_get(r0), emul_reg_get(r1), label, getted_address); if (emul_reg_get(r0) != emul_reg_get(r1)) { getted_address = emul_label_resolve(label); emul_reg_set( Spc, getted_address ); } else { getted_address = -1; } emul_out_std_debug("Execute: bne r0[%d] r1[%d] label[%s]>>PC(%d);\n", emul_reg_get(r0), emul_reg_get(r1), label, getted_address); } void emul_inst_exec_lw(int r0, int address) { emul_out_std_debug(" : lw r0[%d] address[%d];\n", emul_reg_get(r0), address); emul_reg_set(r0, emul_mem_get_word(address)); emul_out_std_debug("Execute: lw r0[%d] address[%d];\n", emul_reg_get(r0), address); } void emul_inst_exec_sw(int r0, int address) { emul_out_std_debug(" : sw r0[%d] address[%d];\n", emul_reg_get(r0), address); emul_mem_set_word(address, emul_reg_get(r0)); emul_out_std_debug("Execute: sw r0[%d] address[%d];\n", emul_reg_get(r0), address); } /* オペコード解読処理群 - END */ /* 疑似コード解読処理群 - START */ /* :DUMP <OPTION> * OPTION: * LAST: 最後に実行した命令を表示 * NONE: デバックなし(通常モード)へ切り替え * DEBUG<NUM>: デバックあり * NUM: デバックレベル[0-2] (0はデバックなし) * OUTPUT: * LAST_CMD [OPTION] */ void emul_inst_exec_pseudo_dump(const char *option) { if ( strcmp(option, "NONE") == 0 ) emul_std_debug(0); if ( strcmp(option, "none") == 0 ) emul_std_debug(0); if ( strcmp(option, "DEBUG0") == 0 ) emul_std_debug(0); if ( strcmp(option, "debug0") == 0 ) emul_std_debug(0); if ( strcmp(option, "DEBUG1") == 0 ) emul_std_debug(1); if ( strcmp(option, "debug1") == 0 ) emul_std_debug(1); if ( strcmp(option, "DEBUG2") == 0 ) emul_std_debug(2); if ( strcmp(option, "debug2") == 0 ) emul_std_debug(2); emul_out_std_debug("PseudoExec: DUMP option[%s];\n", option); } /* :MEMCAT <ADDRESS> * OUTPUT: * ADDRESS = <0xVALUE(8bit)> */ void emul_inst_exec_pseudo_memcat(int address) { emul_out_std("0x%02X\n", emul_mem_get(address)); emul_out_std_debug("PseudoExec: MEMCAT address[%d];\n", address); } /* :MEMCATW <ADDRESS> * OUTPUT: * ADDRESS = <0xVALUE(32bit)> */ void emul_inst_exec_pseudo_memcatw(int address) { emul_out_std("0x%08X\n", emul_mem_get(address)); emul_out_std_debug("PseudoExec: MEMCATW address[%d];\n", address); } /* :REGCAT <REGISTER> * OUTPUT: * ADDRESS = <0xVALUE(32bit)> */ void emul_inst_exec_pseudo_regcat(int reg) { emul_out_std("0x%08X\n", emul_reg_get(reg)); emul_out_std_debug("PseudoExec: REGCAT address[%d];\n", reg); } /* :LABEL <LABELNAME> * INPUT: * LABELNAME = <ラベル名>*/ void emul_inst_exec_pseudo_label(const char *labelname, int address) { emul_label_add(labelname, address); emul_out_std_debug("PseudoExec: LABEL labelname[%s] address[%d];\n", labelname, address); } /* :RUN * SUMMARY: * 現在の状態から逐次実行に切り替える */ void emul_inst_exec_pseudo_run() { emul_inst_exec_set_runmode(Run); } /* :STEP * SUMMARY: * 現在の状態からステップ実行に切り替える */ void emul_inst_exec_pseudo_step() { emul_inst_exec_set_runmode(Step); } /* :INPUT <REGISTER> * SUMMARY: * キーボート入力を待機し,結果をレジスタへ格納する */ void emul_inst_exec_pseudo_input(int reg) { int c; emul_out_std_debug("wait to be inputed...\n"); while ( (c = getchar()) == '\n' ); emul_reg_set(reg, c); } /* :OUTPUT <REGISTER> * レジスタの値をASCII文字として画面に出力する,改行はない*/ void emul_inst_exec_pseudo_output(int reg) { emul_out_std("%c", (char)emul_reg_get(reg)); } /* :CRLF * 画面へ改行コードを送信する,改行コードについて決まりはない */ void emul_inst_exec_pseudo_crlf() { emul_out_std("\n"); } void emul_inst_exec_pseudo_exec(char *filename) { emul_inst_exec_load(filename); } /* :Exit * プログラムを正常終了 */ void emul_inst_exec_pseudo_exit() { emul_inst_exec_set_runmode(Exit); } /* 疑似コード解読処理群 - END */ /* Execute pseudocode * RETURN: * succsess: 1 * failed : 0 */ exitcode_t emul_inst_exec_pseudo(char token[LOAD_TOKEN_MAX]) { char label[LABEL_NAME_LENGTH_MAX]; char temp[LOAD_TOKEN_MAX]; // execute pseudocode. int ps_id; // 疑似コードIDを取得 ps_id = emul_inst_dec_get_pseudo(token); // 例外処理:疑似コードが見つからない if ( ps_id == PSEUDO_DECODE_ERROR ) { return Failed; } switch( ps_id ) { case DUMP: emul_inst_dec_get_token(temp); emul_inst_exec_pseudo_dump(temp); break; case MEMCAT: emul_inst_exec_pseudo_memcat( emul_inst_dec_get_next_immediate() ); break; case MEMCATW: emul_inst_exec_pseudo_memcatw( emul_inst_dec_get_next_immediate() ); break; case REGCAT: emul_inst_exec_pseudo_regcat( emul_inst_dec_get_next_operand() ); break; case LABEL: emul_inst_dec_get_token(label); emul_inst_exec_pseudo_label( label, emul_reg_get(Spc) ); break; case RUN: emul_inst_exec_pseudo_run(); break; case STEP: emul_inst_exec_pseudo_step(); break; case INPUT: emul_inst_exec_pseudo_input( emul_inst_dec_get_next_operand() ); break; case OUTPUT: emul_inst_exec_pseudo_output( emul_inst_dec_get_next_operand() ); break; case CRLF: emul_inst_exec_pseudo_crlf(); break; case EXEC: emul_inst_dec_get_token(label); emul_inst_exec_pseudo_exec( label ); break; case EXIT: emul_inst_exec_pseudo_exit(); break; default: emul_out_std_debug("[疑似コード]まだ実装してないので待って!\n"); } return Success; } /* Execute Step * RETURN: * succsess: 1 * failed : 0 */ exitcode_t emul_inst_exec_step() #define COUNT_OPERAND_MAX 3 { char token[LOAD_TOKEN_MAX]; int op_id, oprs[COUNT_OPERAND_MAX]; int ps_id; int pc; int temp_op[3]; char label[LABEL_NAME_LENGTH_MAX]; emul_out_std_debug(">>>Start step\n"); // トークンを取得 if ( emul_inst_dec_get_token(token) == 0 ) { emul_out_std_err("Non exist next token\n"); // 次のトークンが見つからない場合終了 return Failed; } emul_out_std_debug("token: %s\n", token); // オペコードIDを取得 op_id = emul_inst_dec_get_opecode(token); // 例外処理: オペコードが見つからない if ( op_id == OPECODE_DECODE_ERROR ) { emul_out_std_err("Non exist next operand\n"); ps_id = emul_inst_dec_get_pseudo(token); // 例外処理:疑似コードが見つからない if ( ps_id == PSEUDO_DECODE_ERROR ) { emul_out_std_err("Non exist next pseudocode\n"); return Continue; } else { // 疑似コードを実行 return emul_inst_exec_pseudo(token); } } // オペコード実行 switch (op_id) { case ADD : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); temp_op[2] = emul_inst_dec_get_next_operand(); emul_inst_exec_add(temp_op[0], temp_op[1], temp_op[2]); break; case ADDI: temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); temp_op[2] = emul_inst_dec_get_next_immediate(); emul_inst_exec_addi(temp_op[0], temp_op[1], temp_op[2]); break; case SUB : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); temp_op[2] = emul_inst_dec_get_next_operand(); emul_inst_exec_sub(temp_op[0], temp_op[1], temp_op[2]); break; case SLT : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); temp_op[2] = emul_inst_dec_get_next_operand(); emul_inst_exec_slt(temp_op[0], temp_op[1], temp_op[2]); break; case SLTI: temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); temp_op[2] = emul_inst_dec_get_next_immediate(); emul_inst_exec_slti(temp_op[0], temp_op[1], temp_op[2]); break; case SEQ : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); temp_op[2] = emul_inst_dec_get_next_operand(); emul_inst_exec_seq(temp_op[0], temp_op[1], temp_op[2]); break; case SGE : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); temp_op[2] = emul_inst_dec_get_next_operand(); emul_inst_exec_sge(temp_op[0], temp_op[1], temp_op[2]); break; case SGT : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); temp_op[2] = emul_inst_dec_get_next_operand(); emul_inst_exec_sgt(temp_op[0], temp_op[1], temp_op[2]); break; case SLE : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); temp_op[2] = emul_inst_dec_get_next_operand(); emul_inst_exec_sle(temp_op[0], temp_op[1], temp_op[2]); break; case SNE : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); temp_op[2] = emul_inst_dec_get_next_operand(); emul_inst_exec_sne(temp_op[0], temp_op[1], temp_op[2]); break; //case B : // break; case BEQ : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); emul_inst_dec_get_token(label); emul_inst_exec_beq(temp_op[0], temp_op[1], label); break; case BNE : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_operand(); emul_inst_dec_get_token(label); emul_inst_exec_bne(temp_op[0], temp_op[1], label); break; case J : emul_inst_dec_get_token(label); emul_inst_exec_j(label); break; case LW : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_immediate(); emul_inst_exec_lw(temp_op[0], temp_op[1]); break; case SW : temp_op[0] = emul_inst_dec_get_next_operand(); temp_op[1] = emul_inst_dec_get_next_immediate(); emul_inst_exec_sw(temp_op[0], temp_op[1]); break; //case MOVE: //break; default: emul_out_std_debug("[オペコード]まだ実装してないので待って!\n"); } //emul_inst_dec_get_operand(token); return Success; } /* Execute Run All * RETURN: * succsess: 1 * failed : 0 */ exitcode_t emul_inst_exec_run() { // step関数を終わるまで呼び出せばよい exitcode_t exit_code; emul_out_std_debug(">>>Start run\n"); while ( (exit_code = emul_inst_exec_step()) == Success ) { if (RunMode == Step) { emul_out_std("...Wait for step, please input key enter.\n"); getchar(); } else if (RunMode == Exit) { emul_out_std_debug("Program Exit...\n"); return Success; } } emul_out_std_debug("<<<Stop run\n"); return exit_code; }