Newer
Older
emul / emul_inst_exec.c
#include "emul_inst_exec.h"
#include "emul_io_std.h"
#include <string.h>

int emul_inst_exec_load(char *filename) {
    return emul_inst_dec_load(filename);
}

/* オペコード解読処理群 - 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(int target) {
    emul_out_std_debug("       : j target[%d];\n", target);
    emul_reg_set(Spc, target);
    emul_out_std_debug("Execute: j target[%d];\n", target);
}

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, "DEBUG0") == 0 ) emul_std_debug(0);
    if ( strcmp(option, "DEBUG1") == 0 ) emul_std_debug(1);
    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() {}

/* :STEP
* SUMMARY:
*   現在の状態からステップ実行に切り替える */
void emul_inst_exec_pseudo_step() {}

/* :INPUT <REGISTER>
* SUMMARY:
*   キーボート入力を待機し,結果をレジスタへ格納する */
void emul_inst_exec_pseudo_input() {}

/* :OUTPUT <REGISTER>
*   レジスタの値をASCII文字として画面に出力する,改行はない*/
void emul_inst_exec_pseudo_output() {}

/* :CRLF
*   画面へ改行コードを送信する,改行コードについて決まりはない */
void emul_inst_exec_pseudo_crlf() {}

/* 疑似コード解読処理群 - END */


/* Execute pseudocode
 * RETURN:
 *   seccsess: 1
 *   failed  : 0 */
int emul_inst_exec_pseudo(char token[LOAD_TOKEN_MAX]) {
    char label[LABEL_NAME_LENGTH_MAX];
    char temp[LOAD_TOKEN_MAX];
    // execute pseudocode.
    EMUL_PSEUDO ps_id;

    // 疑似コードIDを取得
    ps_id = emul_inst_dec_get_pseudo(token);

    // 例外処理:疑似コードが見つからない
    if ( ps_id == PSEUDO_DECODE_ERROR ) {
        return 0;
    }

    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:
    //    break;
    //case STEP:
    //    break;
    //case INPUT:
    //    break;
    //case OUTPUT:
    //    break;
    //case CRLF:
    //    break;
    //case EXIT:
    //    break;
	default:
	    emul_out_std_debug("[疑似コード]まだ実装してないので待って!\n");
    }

    return 1;
}

/* Execute Step
 * RETURN:
 *   seccsess: 1
 *   failed  : 0 */
int 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;

    emul_out_std_debug(">>START STEP!>>\n");

    // 読みだす命令のアドレスをPCの値とし,PCをインクリメント
    //emul_inst_dec_update_pc();

    // トークンを取得
    if ( emul_inst_dec_get_token(token) == 0 ) {
        emul_out_std_err("Non exist next token\n");
        // 次のトークンが見つからない場合終了
        return 0;
    }
    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 0;
        } else {
            // 疑似コードを実行
            emul_inst_exec_pseudo(token);
            return 1;
        }
    }

    int temp_op[3];
    char label[LABEL_NAME_LENGTH_MAX];
    // オペコード実行
    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(token);
        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   :
        temp_op[0] = emul_inst_dec_get_next_immediate();
        emul_inst_exec_j(temp_op[0]);
	    break;
	case LW  :
        temp_op[0] = emul_inst_dec_get_next_operand();
        temp_op[1] = emul_inst_dec_get_next_operand();
        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_operand();
        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 1;
}

/* Execute Run All
 * RETURN:
 *   seccsess: 1
 *   failed  : 0 */
int emul_inst_exec_run() {
    // step関数を終わるまで呼び出せばよい
    int exit_code;
    while ( (exit_code = emul_inst_exec_step()) );
    return exit_code;
}

int main(void) {
    emul_inst_exec_load("test_asm/test.asm");
    emul_reg_init();
    while ( emul_inst_exec_step() ) {
        puts("...Wait for step, please input key enter.");
        getchar();
    }
    //emul_inst_exec_run();
}