📄 parser.y
字号:
| Y_ID '(' REGISTER ')' { $$.p = make_addr_expr (0, (char*)$1.p, $3.i); if ($1.p) free ((char*)$1.p); } | Y_ID '+' ABS_ADDR { $$.p = make_addr_expr ($3.i, (char*)$1.p, 0); if ($1.p) free ((char*)$1.p); } | ABS_ADDR '+' ID { $$.p = make_addr_expr ($1.i, (char*)$3.p, 0); } | Y_ID '-' ABS_ADDR { $$.p = make_addr_expr (- $3.i, (char*)$1.p, 0); if ($1.p) free ((char*)$1.p); } | Y_ID '+' ABS_ADDR '(' REGISTER ')' { $$.p = make_addr_expr ($3.i, (char*)$1.p, $5.i); if ($1.p) free ((char*)$1.p); } | Y_ID '-' ABS_ADDR '(' REGISTER ')' { $$.p = make_addr_expr (- $3.i, (char*)$1.p, $5.i); if ($1.p) free ((char*)$1.p); } ;BR_IMM32: {only_id = 1;} IMM32 {only_id = 0; $$ = $2;}IMM16: IMM32 { check_imm_range($1.p, IMM_MIN, IMM_MAX); $$ = $1; }UIMM16: IMM32 { check_uimm_range($1.p, UIMM_MIN, UIMM_MAX); $$ = $1; }IMM32: ABS_ADDR { $$.p = make_imm_expr ($1.i, NULL, 0); } | '(' ABS_ADDR ')' '>' '>' Y_INT { $$.p = make_imm_expr ($2.i >> $6.i, NULL, 0); } | ID { $$.p = make_imm_expr (0, (char*)$1.p, 0); } | Y_ID '+' ABS_ADDR { $$.p = make_imm_expr ($3.i, (char*)$1.p, 0); free ((char*)$1.p); } | Y_ID '-' ABS_ADDR { $$.p = make_imm_expr (- $3.i, (char*)$1.p, 0); free ((char*)$1.p); } ;ABS_ADDR: Y_INT | Y_INT '+' Y_INT {$$.i = $1.i + $3.i;} | Y_INT Y_INT { /* Y_INT '-' Y_INT */ if ($2.i >= 0) yyerror ("Syntax error"); $$.i = $1.i - $2.i; } ;DEST_REG: REGISTER ;SRC1: REGISTER ;SRC2: REGISTER ;DEST: REGISTER ;REG: REGISTER ;SOURCE: REGISTER ;REGISTER: Y_REG { if ($1.i < 0 || $1.i > 31) yyerror ("Register number out of range"); if ($1.i == 1 && !bare_machine && !noat_flag) yyerror ("Register 1 is reserved for assembler"); $$ = $1; }F_DEST: FP_REGISTER ;F_SRC1: FP_REGISTER ;F_SRC2: FP_REGISTER ;FP_REGISTER: Y_FP_REG { if ($1.i < 0 || $1.i > 31) yyerror ("FP register number out of range"); $$ = $1; }COP_REG: Y_REG | Y_FP_REG ;LABEL: ID { $$.p = make_imm_expr (-(int)current_text_pc (), (char*)$1.p, 1); }STR_LST: STR_LST STR | STR ;STR: Y_STR { store_string ((char*)$1.p, y_str_length, null_term); free ((char*)$1.p); } | Y_STR ':' Y_INT { int i; for (i = 0; i < $3.i; i ++) store_string ((char*)$1.p, y_str_length, null_term); free ((char*)$1.p); } ;EXPRESSION: {only_id = 1;} EXPR {only_id = 0; $$ = $2;}EXPR: Y_INT | ID { label *l = lookup_label ((char*)$1.p); if (l->addr == 0) { record_data_uses_symbol (current_data_pc (), l); $$.p = NULL; } else $$.i = l->addr; }EXPR_LST: EXPR_LST EXPRESSION { store_op ($2.p); } | EXPRESSION { store_op ($1.p); } | EXPRESSION ':' Y_INT { int i; for (i = 0; i < $3.i; i ++) store_op ($1.p); } ;FP_EXPR_LST: FP_EXPR_LST Y_FP { store_op ($2.p); } | Y_FP { store_op ($1.p); } ;OPTIONAL_ID: {only_id = 1;} OPT_ID {only_id = 0; $$ = $2;}OPT_ID: ID | {$$.p = (void*)NULL;} ;ID: {only_id = 1;} Y_ID {only_id = 0; $$ = $2;}%%/* Maintain and update the address of labels for the current line. */#ifdef __STDC__voidfix_current_label_address (mem_addr new_addr)#elsevoidfix_current_label_address (new_addr) mem_addr new_addr;#endif{ label_list *l; for (l = this_line_labels; l != NULL; l = l->tail) { l->head->addr = new_addr; } clear_labels ();}#ifdef __STDC__static label_list *cons_label (label *head, label_list *tail)#elsestatic label_list *cons_label (head, tail) label *head; label_list *tail;#endif{ label_list *c = (label_list *) malloc (sizeof (label_list)); c->head = head; c->tail = tail; return (c);}#ifdef __STDC__static voidclear_labels (void)#elsestatic voidclear_labels ()#endif{ label_list *n; for ( ; this_line_labels != NULL; this_line_labels = n) { resolve_label_uses(this_line_labels->head); n = this_line_labels->tail; free (this_line_labels); }}/* Operations on op codes. */#ifdef __STDC__intop_to_imm_op (int opcode)#elseintop_to_imm_op (opcode) int opcode;#endif{ switch (opcode) { case Y_ADD_OP: return (Y_ADDI_OP); case Y_ADDU_OP: return (Y_ADDIU_OP); case Y_AND_OP: return (Y_ANDI_OP); case Y_OR_OP: return (Y_ORI_OP); case Y_XOR_OP: return (Y_XORI_OP); case Y_SLT_OP: return (Y_SLTI_OP); case Y_SLTU_OP: return (Y_SLTIU_OP); case Y_SLLV_OP: return (Y_SLL_OP); case Y_SRAV_OP: return (Y_SRA_OP); case Y_SRLV_OP: return (Y_SRL_OP); default: fatal_error ("Can't convert op to immediate op\n"); return (0); }}#ifdef __STDC__intimm_op_to_op (int opcode)#elseintimm_op_to_op (opcode) int opcode;#endif{ switch (opcode) { case Y_ADDI_OP: return (Y_ADD_OP); case Y_ADDIU_OP: return (Y_ADDU_OP); case Y_ANDI_OP: return (Y_AND_OP); case Y_ORI_OP: return (Y_OR_OP); case Y_XORI_OP: return (Y_XOR_OP); case Y_SLTI_OP: return (Y_SLT_OP); case Y_SLTIU_OP: return (Y_SLTU_OP); case Y_J_OP: return (Y_JR_OP); case Y_LUI_OP: return (Y_ADDU_OP); case Y_SLL_OP: return (Y_SLLV_OP); case Y_SRA_OP: return (Y_SRAV_OP); case Y_SRL_OP: return (Y_SRLV_OP); default: fatal_error ("Can't convert immediate op to op\n"); return (0); }}#ifdef __STDC__static voidnop_inst (void)#elsestatic voidnop_inst ()#endif{ r_type_inst (Y_SLL_OP, 0, 0, 0); /* = 0 */}#ifdef __STDC__static voidtrap_inst (void)#elsestatic voidtrap_inst ()#endif{ r_type_inst (Y_BREAK_OP, 0, 0, 0);}#ifdef __STDC__static imm_expr *branch_offset (int n_inst)#elsestatic imm_expr *branch_offset (n_inst) int n_inst;#endif{ return (const_imm_expr (n_inst << 2)); /* Later shifted right 2 places */}#ifdef __STDC__static voiddiv_inst (int op, int rd, int rs, int rt, int const_divisor)#elsestatic voiddiv_inst (op, rd, rs, rt, const_divisor) int op, rd, rs, rt, const_divisor;#endif{ if (rd != 0 && !const_divisor) { i_type_inst_free (Y_BNE_OP, 0, rt, branch_offset (2)); trap_inst (); } if (op == Y_DIV_OP || op == Y_REM_POP) r_type_inst (Y_DIV_OP, 0, rs, rt); else r_type_inst (Y_DIVU_OP, 0, rs, rt); if (rd != 0) { if (op == Y_DIV_OP || op == Y_DIVU_OP) /* Quotient */ r_type_inst (Y_MFLO_OP, rd, 0, 0); else /* Remainder */ r_type_inst (Y_MFHI_OP, rd, 0, 0); }}#ifdef __STDC__static voidmult_inst (int op, int rd, int rs, int rt)#elsestatic voidmult_inst (op, rd, rs, rt) int op, rd, rs, rt;#endif{ if (op == Y_MULOU_POP) r_type_inst (Y_MULTU_OP, 0, rs, rt); else r_type_inst (Y_MULT_OP, 0, rs, rt); if (op == Y_MULOU_POP && rd != 0) { r_type_inst (Y_MFHI_OP, 1, 0, 0); /* Use $at */ i_type_inst_free (Y_BEQ_OP, 0, 1, branch_offset (2)); trap_inst (); } else if (op == Y_MULO_POP && rd != 0) { r_type_inst (Y_MFHI_OP, 1, 0, 0); /* use $at */ r_type_inst (Y_MFLO_OP, rd, 0, 0); r_sh_type_inst (Y_SRA_OP, rd, rd, 31); i_type_inst_free (Y_BEQ_OP, rd, 1, branch_offset (2)); trap_inst (); } if (rd != 0) r_type_inst (Y_MFLO_OP, rd, 0, 0);}#ifdef __STDC__static voidset_le_inst (int op, int rd, int rs, int rt)#elsestatic voidset_le_inst (op, rd, rs, rt) int op, rd, rs, rt;#endif{ i_type_inst_free (Y_BNE_OP, rs, rt, branch_offset (3)); i_type_inst_free (Y_ORI_OP, rd, 0, const_imm_expr (1)); i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (2)); r_type_inst ((op == Y_SLE_POP ? Y_SLT_OP : Y_SLTU_OP), rd, rs, rt);}#ifdef __STDC__static voidset_gt_inst (int op, int rd, int rs, int rt)#elsestatic voidset_gt_inst (op, rd, rs, rt) int op, rd, rs, rt;#endif{ r_type_inst (op == Y_SGT_POP ? Y_SLT_OP : Y_SLTU_OP, rd, rt, rs);}#ifdef __STDC__static voidset_ge_inst (int op, int rd, int rs, int rt)#elsestatic voidset_ge_inst (op, rd, rs, rt) int op, rd, rs, rt;#endif{ i_type_inst_free (Y_BNE_OP, rs, rt, branch_offset (3)); i_type_inst_free (Y_ORI_OP, rd, 0, const_imm_expr (1)); i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (2)); r_type_inst (op == Y_SGE_POP ? Y_SLT_OP : Y_SLTU_OP, rd, rt, rs);}#ifdef __STDC__static voidset_eq_inst (int op, int rd, int rs, int rt)#elsestatic voidset_eq_inst (op, rd, rs, rt) int op, rd, rs, rt;#endif{ imm_expr *if_eq, *if_neq; if (op == Y_SEQ_POP) if_eq = const_imm_expr (1), if_neq = const_imm_expr (0); else if_eq = const_imm_expr (0), if_neq = const_imm_expr (1); i_type_inst_free (Y_BEQ_OP, rs, rt, branch_offset (3)); /* RD <- 0 (if not equal) */ i_type_inst_free (Y_ORI_OP, rd, 0, if_neq); i_type_inst_free (Y_BEQ_OP, 0, 0, branch_offset (2)); /* Branch always */ /* RD <- 1 */ i_type_inst_free (Y_ORI_OP, rd, 0, if_eq);}/* Store the value either as a datum or instruction. */#ifdef __STDC__static voidstore_word_data (int value)#elsestatic voidstore_word_data (value) int value;#endif{ if (data_dir) store_word (value); else if (text_dir) store_instruction (inst_decode (value));}#ifdef __STDC__voidinitialize_parser (char *file_name)#elsevoidinitialize_parser (file_name) char *file_name;#endif{ input_file_name = file_name; only_id = 0; data_dir = 0; text_dir = 1;}#ifdef __STDC__static voidcheck_imm_range(imm_expr* expr, int32 min, int32 max)#elsestatic voidcheck_imm_range() imm_expr* expr; int32 min; int32 max;#endif{ if (expr->symbol == NULL || SYMBOL_IS_DEFINED (expr->symbol)) { /* If expression can be evaluated, compare its value against the limits and complain if the value is out of bounds. */ int32 value = eval_imm_expr (expr); if (value < min || max < value) { char str[200]; sprintf (str, "immediate value (%d) out of range (%d .. %d)", value, min, max); yywarn (str); } }}#ifdef __STDC__static voidcheck_uimm_range(imm_expr* expr, uint32 min, uint32 max)#elsestatic voidcheck_uimm_range()^ imm_expr* expr; int32 umin; int32 umax;#endif{ if (expr->symbol == NULL || SYMBOL_IS_DEFINED (expr->symbol)) { /* If expression can be evaluated, compare its value against the limits and complain if the value is out of bounds. */ uint32 value = eval_imm_expr (expr); if (value < min || max < value) { char str[200]; sprintf (str, "immediate value (%d) out of range (%d .. %d)", value, min, max); yywarn (str); } }}#ifdef __STDC__voidyyerror (char *s)#elsevoidyyerror (s) char *s;#endif{ parse_error_occurred = 1; yywarn (s);}#ifdef __STDC__voidyywarn (char *s)#elsevoidyywarn (s) char *s;#endif{ error ("spim: (parser) %s on line %d of file %s\n", s, line_no, input_file_name); print_erroneous_line ();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -