📄 parser.y
字号:
/* SPIM S20 MIPS simulator. Parser for instructions and assembler directives. Copyright (C) 1990-2000 by James Larus (larus@cs.wisc.edu). ALL RIGHTS RESERVED. SPIM is distributed under the following conditions: You may make copies of SPIM for your own use and modify those copies. All copies of SPIM must retain my name and copyright notice. You may not sell SPIM or distributed SPIM in conjunction with a commerical product or service without the expressed written consent of James Larus. THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *//* $Header: $*/%start LINE%token Y_EOF%token Y_NL%token Y_INT%token Y_ID%token Y_REG%token Y_FP_REG%token Y_STR%token Y_FP/* MIPS instructions op codes: */%token Y_ABS_D_OP%token Y_ABS_S_OP%token Y_ADDIU_OP%token Y_ADDI_OP%token Y_ADDU_OP%token Y_ADD_D_OP%token Y_ADD_OP%token Y_ADD_S_OP%token Y_ANDI_OP%token Y_AND_OP%token Y_BC0F_OP%token Y_BC0T_OP%token Y_BC1F_OP%token Y_BC1T_OP%token Y_BC2F_OP%token Y_BC2T_OP%token Y_BC3F_OP%token Y_BC3T_OP%token Y_BEQ_OP%token Y_BGEZAL_OP%token Y_BGEZ_OP%token Y_BGTZ_OP%token Y_BLEZ_OP%token Y_BLTZAL_OP%token Y_BLTZ_OP%token Y_BNE_OP%token Y_BREAK_OP%token Y_CFC0_OP%token Y_CFC1_OP%token Y_CFC2_OP%token Y_CFC3_OP%token Y_COP0_OP%token Y_COP1_OP%token Y_COP2_OP%token Y_COP3_OP%token Y_CTC0_OP%token Y_CTC1_OP%token Y_CTC2_OP%token Y_CTC3_OP%token Y_CVT_D_S_OP%token Y_CVT_D_W_OP%token Y_CVT_S_D_OP%token Y_CVT_S_W_OP%token Y_CVT_W_D_OP%token Y_CVT_W_S_OP%token Y_C_EQ_D_OP%token Y_C_EQ_S_OP%token Y_C_F_D_OP%token Y_C_F_S_OP%token Y_C_LE_D_OP%token Y_C_LE_S_OP%token Y_C_LT_D_OP%token Y_C_LT_S_OP%token Y_C_NGE_D_OP%token Y_C_NGE_S_OP%token Y_C_NGLE_D_OP%token Y_C_NGLE_S_OP%token Y_C_NGL_D_OP%token Y_C_NGL_S_OP%token Y_C_NGT_D_OP%token Y_C_NGT_S_OP%token Y_C_OLT_D_OP%token Y_C_OLT_S_OP%token Y_C_OLE_D_OP%token Y_C_OLE_S_OP%token Y_C_SEQ_D_OP%token Y_C_SEQ_S_OP%token Y_C_SF_D_OP%token Y_C_SF_S_OP%token Y_C_UEQ_D_OP%token Y_C_UEQ_S_OP%token Y_C_ULT_D_OP%token Y_C_ULT_S_OP%token Y_C_ULE_D_OP%token Y_C_ULE_S_OP%token Y_C_UN_D_OP%token Y_C_UN_S_OP%token Y_DIVU_OP%token Y_DIV_D_OP%token Y_DIV_OP%token Y_DIV_S_OP%token Y_JALR_OP%token Y_JAL_OP%token Y_JR_OP%token Y_J_OP%token Y_LBU_OP%token Y_LB_OP%token Y_LHU_OP%token Y_LH_OP%token Y_LUI_OP%token Y_LWC0_OP%token Y_LWC1_OP%token Y_LWC2_OP%token Y_LWC3_OP%token Y_LWL_OP%token Y_LWR_OP%token Y_LW_OP%token Y_MFC0_OP%token Y_MFC1_OP%token Y_MFC2_OP%token Y_MFC3_OP%token Y_MFHI_OP%token Y_MFLO_OP%token Y_MOV_D_OP%token Y_MOV_S_OP%token Y_MTC0_OP%token Y_MTC1_OP%token Y_MTC2_OP%token Y_MTC3_OP%token Y_MTHI_OP%token Y_MTLO_OP%token Y_MULTU_OP%token Y_MULT_OP%token Y_MUL_D_OP%token Y_MUL_S_OP%token Y_NEG_D_OP%token Y_NEG_S_OP%token Y_NOR_OP%token Y_ORI_OP%token Y_OR_OP%token Y_PFW_OP%token Y_RFE_OP%token Y_SB_OP%token Y_SH_OP%token Y_SLLV_OP%token Y_SLL_OP%token Y_SLTIU_OP%token Y_SLTI_OP%token Y_SLTU_OP%token Y_SLT_OP%token Y_SRAV_OP%token Y_SRA_OP%token Y_SRLV_OP%token Y_SRL_OP%token Y_SUBU_OP%token Y_SUB_D_OP%token Y_SUB_OP%token Y_SUB_S_OP%token Y_SWC0_OP%token Y_SWC1_OP%token Y_SWC2_OP%token Y_SWC3_OP%token Y_SWL_OP%token Y_SWR_OP%token Y_SW_OP%token Y_SYSCALL_OP%token Y_TLBP_OP%token Y_TLBR_OP%token Y_TLBWI_OP%token Y_TLBWR_OP%token Y_XORI_OP%token Y_XOR_OP/* Assembler pseudo operations op codes: */%token Y_ABS_POP%token Y_BAL_POP%token Y_BEQZ_POP%token Y_BGEU_POP%token Y_BGE_POP%token Y_BGTU_POP%token Y_BGT_POP%token Y_BLEU_POP%token Y_BLE_POP%token Y_BLTU_POP%token Y_BLT_POP%token Y_BNEZ_POP%token Y_B_POP%token Y_LA_POP%token Y_LD_POP%token Y_LI_POP%token Y_LI_D_POP%token Y_LI_S_POP%token Y_L_D_POP%token Y_L_S_POP%token Y_MFC1_D_POP%token Y_MTC1_D_POP%token Y_MOVE_POP%token Y_MULOU_POP%token Y_MULO_POP%token Y_MUL_POP%token Y_NEGU_POP%token Y_NEG_POP%token Y_NOP_POP%token Y_NOT_POP%token Y_REMU_POP%token Y_REM_POP%token Y_ROL_POP%token Y_ROR_POP%token Y_SD_POP%token Y_SEQ_POP%token Y_SGEU_POP%token Y_SGE_POP%token Y_SGTU_POP%token Y_SGT_POP%token Y_SLEU_POP%token Y_SLE_POP%token Y_SNE_POP%token Y_S_D_POP%token Y_S_S_POP%token Y_ULHU_POP%token Y_ULH_POP%token Y_ULW_POP%token Y_USH_POP%token Y_USW_POP/* Assembler directives: */%token Y_ALIAS_DIR%token Y_ALIGN_DIR%token Y_ASCII_DIR%token Y_ASCIIZ_DIR%token Y_ASM0_DIR%token Y_BGNB_DIR%token Y_BYTE_DIR%token Y_COMM_DIR%token Y_DATA_DIR%token Y_DOUBLE_DIR%token Y_ENDB_DIR%token Y_ENDR_DIR%token Y_END_DIR%token Y_ENT_DIR%token Y_ERR_DIR%token Y_EXTERN_DIR%token Y_FILE_DIR%token Y_FLOAT_DIR%token Y_FMASK_DIR%token Y_FRAME_DIR%token Y_GLOBAL_DIR%token Y_HALF_DIR%token Y_K_TEXT_DIR%token Y_K_DATA_DIR%token Y_LABEL_DIR%token Y_LCOMM_DIR%token Y_LIVEREG_DIR%token Y_LOC_DIR%token Y_MASK_DIR%token Y_NOALIAS_DIR%token Y_OPTIONS_DIR%token Y_RDATA_DIR%token Y_REPEAT_DIR%token Y_SDATA_DIR%token Y_SET_DIR%token Y_SPACE_DIR%token Y_STRUCT_DIR%token Y_TEXT_DIR%token Y_VERSTAMP_DIR%token Y_VREG_DIR%token Y_WORD_DIR%{#include <stdio.h>#include "spim.h"#include "spim-utils.h"#include "inst.h"#include "mem.h"#include "reg.h"#include "sym-tbl.h"#include "data.h"#include "scanner.h"#include "parser.h"/* return (0) */#define LINE_PARSE_DONE YYACCEPT/* return (1) */#define FILE_PARSE_DONE YYABORTtypedef struct ll{ label *head; struct ll *tail;} label_list;/* Exported Variables: */int data_dir; /* Non-zero means item in data segment */int text_dir; /* Non-zero means item in text segment */int parse_error_occurred; /* Non-zero => parse resulted in error *//* Local functions: */#ifdef __STDC__static imm_expr *branch_offset (int n_inst);static void check_imm_range (imm_expr*, int32, int32);static void check_uimm_range (imm_expr*, uint32, uint32);static void clear_labels (void);static label_list *cons_label (label *head, label_list *tail);static void div_inst (int op, int rd, int rs, int rt, int const_divisor);static void mult_inst (int op, int rd, int rs, int rt);static void nop_inst (void);static void set_eq_inst (int op, int rd, int rs, int rt);static void set_ge_inst (int op, int rd, int rs, int rt);static void set_gt_inst (int op, int rd, int rs, int rt);static void set_le_inst (int op, int rd, int rs, int rt);static void store_word_data (int value);static void trap_inst (void);static void yywarn (char*);#elsestatic imm_expr *branch_offset ();static void check_imm_range();static void check_uimm_range();static void clear_labels ();static label_list *cons_label ();static void div_inst ();static void mult_inst ();static void nop_inst ();static void set_eq_inst ();static void set_ge_inst ();static void set_gt_inst ();static void set_le_inst ();static void store_word_data ();static void trap_inst ();static void yywarn ();#endif/* Local variables: */static int null_term; /* Non-zero means string terminate by \0 */static void (*store_op) (); /* Function to store items in an EXPR_LST */static label_list *this_line_labels = NULL; /* List of label for curent line */static int noat_flag = 0; /* Non-zero means program can use $1 */static char *input_file_name; /* Name of file being parsed */%}%%LINE: {parse_error_occurred = 0; scanner_start_line (); } LBL_CMD ;LBL_CMD: OPT_LBL CMD | CMD ;OPT_LBL: ID ':' { this_line_labels = cons_label (record_label ((char*)$1.p, text_dir ? current_text_pc () : current_data_pc (), 0), this_line_labels); if ($1.p) free($1.p); } | ID '=' Y_INT { label *l = record_label ((char*)$1.p, (mem_addr)$3.i, 1); if ($1.p) free($1.p); l->const_flag = 1; clear_labels (); } ;CMD: ASM_CODE { clear_labels (); } TERM | ASM_DIRECTIVE { clear_labels (); } TERM | TERM ;TERM: Y_NL { LINE_PARSE_DONE; } | Y_EOF { clear_labels (); FILE_PARSE_DONE; } ;ASM_CODE: LOAD_OP DEST_REG ADDRESS { i_type_inst ($1.i == Y_LD_POP ? Y_LW_OP : $1.i, $2.i, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p)); if ($1.i == Y_LD_POP) i_type_inst_free (Y_LW_OP, $2.i + 1, addr_expr_reg ((addr_expr *)$3.p), incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), 4)); free (((addr_expr *)$3.p)->imm); free ((addr_expr *)$3.p); } | LOAD_COP COP_REG ADDRESS { i_type_inst ($1.i, $2.i, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p)); free (((addr_expr *)$3.p)->imm); free ((addr_expr *)$3.p); } | LOAD_IMM_OP DEST_REG UIMM16 { i_type_inst_free ($1.i, $2.i, 0, (imm_expr *)$3.p); } | Y_LA_POP DEST_REG ADDRESS { if (addr_expr_reg ((addr_expr *)$3.p)) i_type_inst (Y_ADDI_OP, $2.i, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p)); else i_type_inst (Y_ORI_OP, $2.i, 0, addr_expr_imm ((addr_expr *)$3.p)); free (((addr_expr *)$3.p)->imm); free ((addr_expr *)$3.p); } | Y_LI_POP DEST_REG IMM32 { i_type_inst_free (Y_ORI_OP, $2.i, 0, (imm_expr *)$3.p); } | Y_LI_D_POP F_DEST Y_FP { int *x = (int *) $3.p; i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*x)); r_type_inst (Y_MTC1_OP, $2.i, 0, 1); i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*(x+1))); r_type_inst (Y_MTC1_OP, $2.i + 1, 0, 1); } | Y_LI_S_POP F_DEST Y_FP { float x = (float) *((double *) $3.p); int *y = (int *) &x; i_type_inst (Y_ORI_OP, 1, 0, const_imm_expr (*y)); r_type_inst (Y_MTC1_OP, $2.i, 0, 1); } | Y_ULW_POP DEST_REG ADDRESS {#ifdef BIGENDIAN i_type_inst (Y_LWL_OP, $2.i, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p)); i_type_inst_free (Y_LWR_OP, $2.i, addr_expr_reg ((addr_expr *)$3.p), incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), 3));#else i_type_inst_free (Y_LWL_OP, $2.i, addr_expr_reg ((addr_expr *)$3.p), incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), 3)); i_type_inst (Y_LWR_OP, $2.i, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p));#endif free (((addr_expr *)$3.p)->imm); free ((addr_expr *)$3.p); } | ULOADH_POP DEST_REG ADDRESS {#ifdef BIGENDIAN i_type_inst (($1.i == Y_ULH_POP ? Y_LB_OP : Y_LBU_OP), $2.i, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p)); i_type_inst_free (Y_LBU_OP, 1, addr_expr_reg ((addr_expr *)$3.p), incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), 1));#else i_type_inst_free (($1.i == Y_ULH_POP ? Y_LB_OP : Y_LBU_OP), $2.i, addr_expr_reg ((addr_expr *)$3.p), incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), 1)); i_type_inst (Y_LBU_OP, 1, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p));#endif r_sh_type_inst (Y_SLL_OP, $2.i, $2.i, 8); r_type_inst (Y_OR_OP, $2.i, $2.i, 1); free (((addr_expr *)$3.p)->imm); free ((addr_expr *)$3.p); } | LOADF_OP F_DEST ADDRESS { i_type_inst (Y_LWC1_OP, $2.i, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p)); if ($1.i == Y_L_D_POP) i_type_inst_free (Y_LWC1_OP, $2.i + 1, addr_expr_reg ((addr_expr *)$3.p), incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), 4)); free (((addr_expr *)$3.p)->imm); free ((addr_expr *)$3.p); } | STORE_OP SOURCE ADDRESS { i_type_inst ($1.i == Y_SD_POP ? Y_SW_OP : $1.i, $2.i, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p)); if ($1.i == Y_SD_POP) i_type_inst_free (Y_SW_OP, $2.i + 1, addr_expr_reg ((addr_expr *)$3.p), incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), 4)); free (((addr_expr *)$3.p)->imm); free ((addr_expr *)$3.p); } | STORE_COP COP_REG ADDRESS { i_type_inst ($1.i, $2.i, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p)); free (((addr_expr *)$3.p)->imm); free ((addr_expr *)$3.p); } | Y_USW_POP SOURCE ADDRESS {#ifdef BIGENDIAN i_type_inst (Y_SWL_OP, $2.i, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p)); i_type_inst_free (Y_SWR_OP, $2.i, addr_expr_reg ((addr_expr *)$3.p), incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), 3));#else i_type_inst_free (Y_SWL_OP, $2.i, addr_expr_reg ((addr_expr *)$3.p), incr_expr_offset (addr_expr_imm ((addr_expr *)$3.p), 3)); i_type_inst (Y_SWR_OP, $2.i, addr_expr_reg ((addr_expr *)$3.p), addr_expr_imm ((addr_expr *)$3.p));#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -