Newer
Older
emul / emul_inst_decipher.c
#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 24
emul_pseudo_t pseudo_dict[REG_COUNT] = {
    { DUMP    , ":DUMP"    },
    { DUMP    , ":dump"    },
    { MEMCAT  , ":MEMCAT"  },
    { MEMCAT  , ":memcat"  },
    { MEMCATW , ":MEMCATW" },
    { MEMCATW , ":memcatw" },
    { REGCAT  , ":REGCAT"  },
    { REGCAT  , ":regcat"  },
    { LABEL   , ":LABEL"   },
    { LABEL   , ":label"   },
    { RUN     , ":RUN"     },
    { RUN     , ":run"     },
    { STEP    , ":STEP"    },
    { STEP    , ":step"    },
    { INPUT   , ":INPUT"   },
    { INPUT   , ":input"   },
    { OUTPUT  , ":OUTPUT"  },
    { OUTPUT  , ":output"  },
    { CRLF    , ":CRLF"    },
    { CRLF    , ":crlf"    },
    { EXEC    , ":EXEC"    },
    { EXEC    , ":exec"    },
    { EXIT    , ":EXIT"    },
    { 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() {
    program_line_max = 0;
    program_line_current = 0;
}

void emul_inst_dec_set_pc(int pc) {
    program_line_current = pc;
}

void emul_inst_dec_update_pc() {
    int pc;
    // プログラムカウンタ取得
    pc = emul_reg_get(Spc);
    // 呼び出すアドレスにプログラムカウンタを設定
    emul_inst_dec_set_pc(pc);
    // プログラムカウンタをインクリメント
    emul_reg_set(Spc, pc+1);
}

void emul_inst_dec_reset_pc() {
    emul_reg_set(Spc, 0);
    emul_inst_dec_update_pc();
}

/* ファイルからデータをロードする,ファイルは自動的にクローズされる
 * Return:
 *   0 = 失敗
 *   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_loadline(const char *line) {
    int i;
    emul_out_std_debug("Now loading line %s...\n", line);
    // 読み込み
    strcpy(program[program_line_max], line);
    // 読み込んだ場所へPCをセット
    emul_reg_set(Spc, program_line_max);
    // 最大値をインクリメント
    program_line_max++;
    // デバック用
    for (i = 0; i < program_line_max; i++) {
        emul_out_std_debug("%s\n", program[i]);
    }
    emul_out_std_debug("Now program line max = %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;

    emul_out_std_debug("get_token: start\n");
    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]);
            emul_out_std_debug("get_token: program_line_current %d\n", program_line_current);
            emul_out_std_debug("get_token: program_line_current \"%s\"\n", program[program_line_current]);
            emul_out_std_debug("get_token: current = \"%s\"\n", current);
            // 読み込みを行った場合はシフトフラグをセット
            fShift = 1;
        }
    } while(fShift);	// 新しい行を読み込んだ場合もう一度シフトを行う

    // 次のスペース(もしくは'\0')が現れるまで読み込み
    i = 0;
    while ( !isspace(*current) && *current != '\0' ) {
        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);
}