| /* bfin-defs.h ADI Blackfin gas header file |
| Copyright (C) 2005-2021 Free Software Foundation, Inc. |
| |
| This file is part of GAS, the GNU Assembler. |
| |
| GAS is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 3, or (at your option) |
| any later version. |
| |
| GAS is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GAS; see the file COPYING. If not, write to the Free |
| Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA |
| 02110-1301, USA. */ |
| |
| #ifndef BFIN_PARSE_H |
| #define BFIN_PARSE_H |
| |
| #include "opcode/bfin.h" |
| |
| #define PCREL 1 |
| #define CODE_FRAG_SIZE 4096 /* 1 page. */ |
| |
| |
| /* Definition for all status bits. */ |
| typedef enum |
| { |
| c_0, |
| c_1, |
| c_4, |
| c_2, |
| c_uimm2, |
| c_uimm3, |
| c_imm3, |
| c_pcrel4, |
| c_imm4, |
| c_uimm4s4, |
| c_uimm4, |
| c_uimm4s2, |
| c_negimm5s4, |
| c_imm5, |
| c_uimm5, |
| c_imm6, |
| c_imm7, |
| c_imm8, |
| c_uimm8, |
| c_pcrel8, |
| c_uimm8s4, |
| c_pcrel8s4, |
| c_lppcrel10, |
| c_pcrel10, |
| c_pcrel12, |
| c_imm16s4, |
| c_luimm16, |
| c_imm16, |
| c_huimm16, |
| c_rimm16, |
| c_imm16s2, |
| c_uimm16s4, |
| c_uimm16, |
| c_pcrel24 |
| } const_forms_t; |
| |
| |
| /* High-Nibble: group code, low nibble: register code. */ |
| |
| |
| #define T_REG_R 0x00 |
| #define T_REG_P 0x10 |
| #define T_REG_I 0x20 |
| #define T_REG_B 0x30 |
| #define T_REG_L 0x34 |
| #define T_REG_M 0x24 |
| #define T_REG_A 0x40 |
| |
| /* All registers above this value don't |
| belong to a usable register group. */ |
| #define T_NOGROUP 0xa0 |
| |
| /* Flags. */ |
| #define F_REG_NONE 0 |
| #define F_REG_HIGH 1 |
| #define F_REG_LOW 2 |
| |
| enum machine_registers |
| { |
| REG_R0 = T_REG_R, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7, |
| REG_P0 = T_REG_P, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP, |
| REG_I0 = T_REG_I, REG_I1, REG_I2, REG_I3, |
| REG_M0 = T_REG_M, REG_M1, REG_M2, REG_M3, |
| REG_B0 = T_REG_B, REG_B1, REG_B2, REG_B3, |
| REG_L0 = T_REG_L, REG_L1, REG_L2, REG_L3, |
| REG_A0x = T_REG_A, REG_A0w, REG_A1x, REG_A1w, |
| REG_ASTAT = 0x46, |
| REG_RETS = 0x47, |
| REG_LC0 = 0x60, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, |
| REG_CYCLES, REG_CYCLES2, |
| REG_USP = 0x70, REG_SEQSTAT, REG_SYSCFG, |
| REG_RETI, REG_RETX, REG_RETN, REG_RETE, REG_EMUDAT, |
| |
| /* These don't have groups. */ |
| REG_sftreset = T_NOGROUP, REG_omode, REG_excause, REG_emucause, |
| REG_idle_req, REG_hwerrcause, |
| REG_A0 = 0xc0, REG_A1, REG_CC, |
| /* Pseudo registers, used only for distinction from symbols. */ |
| REG_RL0, REG_RL1, REG_RL2, REG_RL3, |
| REG_RL4, REG_RL5, REG_RL6, REG_RL7, |
| REG_RH0, REG_RH1, REG_RH2, REG_RH3, |
| REG_RH4, REG_RH5, REG_RH6, REG_RH7, |
| REG_LASTREG |
| }; |
| |
| /* Status register flags. */ |
| |
| enum statusflags |
| { |
| S_AZ = 0, |
| S_AN, |
| S_AC0_COPY, |
| S_V_COPY, |
| S_AQ = 6, |
| S_RND_MOD = 8, |
| S_AC0 = 12, |
| S_AC1, |
| S_AV0 = 16, |
| S_AV0S, |
| S_AV1, |
| S_AV1S, |
| S_V = 24, |
| S_VS = 25 |
| }; |
| |
| |
| enum reg_class |
| { |
| rc_dregs_lo, |
| rc_dregs_hi, |
| rc_dregs, |
| rc_dregs_pair, |
| rc_pregs, |
| rc_spfp, |
| rc_dregs_hilo, |
| rc_accum_ext, |
| rc_accum_word, |
| rc_accum, |
| rc_iregs, |
| rc_mregs, |
| rc_bregs, |
| rc_lregs, |
| rc_dpregs, |
| rc_gregs, |
| rc_regs, |
| rc_statbits, |
| rc_ignore_bits, |
| rc_ccstat, |
| rc_counters, |
| rc_dregs2_sysregs1, |
| rc_open, |
| rc_sysregs2, |
| rc_sysregs3, |
| rc_allregs, |
| LIM_REG_CLASSES |
| }; |
| |
| /* Register type checking macros. */ |
| |
| #define CODE_MASK 0x07 |
| #define CLASS_MASK 0xf0 |
| |
| #define REG_SAME(a, b) ((a).regno == (b).regno) |
| #define REG_EQUAL(a, b) (((a).regno & CODE_MASK) == ((b).regno & CODE_MASK)) |
| #define REG_CLASS(a) ((a).regno & 0xf0) |
| #define IS_A1(a) ((a).regno == REG_A1) |
| #define IS_H(a) ((a).flags & F_REG_HIGH ? 1: 0) |
| #define IS_EVEN(r) ((r).regno % 2 == 0) |
| #define IS_HCOMPL(a, b) (REG_EQUAL(a, b) && \ |
| ((a).flags & F_REG_HIGH) != ((b).flags & F_REG_HIGH)) |
| |
| /* register type checking. */ |
| #define _TYPECHECK(r, x) (((r).regno & CLASS_MASK) == T_REG_##x) |
| |
| #define IS_DREG(r) _TYPECHECK(r, R) |
| #define IS_DREG_H(r) (_TYPECHECK(r, R) && IS_H(r)) |
| #define IS_DREG_L(r) (_TYPECHECK(r, R) && !IS_H(r)) |
| #define IS_PREG(r) _TYPECHECK(r, P) |
| #define IS_IREG(r) (((r).regno & 0xf4) == T_REG_I) |
| #define IS_MREG(r) (((r).regno & 0xf4) == T_REG_M) |
| #define IS_BREG(r) (((r).regno & 0xf4) == T_REG_B) |
| #define IS_LREG(r) (((r).regno & 0xf4) == T_REG_L) |
| #define IS_CREG(r) ((r).regno == REG_LC0 || (r).regno == REG_LC1) |
| #define IS_EMUDAT(r) ((r).regno == REG_EMUDAT) |
| #define IS_ALLREG(r) ((r).regno < T_NOGROUP) |
| |
| #define IS_GENREG(r) \ |
| (IS_DREG (r) || IS_PREG (r) \ |
| || (r).regno == REG_A0x || (r).regno == REG_A0w \ |
| || (r).regno == REG_A1x || (r).regno == REG_A1w) |
| |
| #define IS_DAGREG(r) \ |
| (IS_IREG (r) || IS_MREG (r) || IS_BREG (r) || IS_LREG (r)) |
| |
| #define IS_SYSREG(r) \ |
| ((r).regno == REG_ASTAT || (r).regno == REG_SEQSTAT \ |
| || (r).regno == REG_SYSCFG || (r).regno == REG_RETI \ |
| || (r).regno == REG_RETX || (r).regno == REG_RETN \ |
| || (r).regno == REG_RETE || (r).regno == REG_RETS \ |
| || (r).regno == REG_LC0 || (r).regno == REG_LC1 \ |
| || (r).regno == REG_LT0 || (r).regno == REG_LT1 \ |
| || (r).regno == REG_LB0 || (r).regno == REG_LB1 \ |
| || (r).regno == REG_CYCLES || (r).regno == REG_CYCLES2 \ |
| || (r).regno == REG_EMUDAT) |
| |
| /* Expression value macros. */ |
| |
| typedef enum |
| { |
| ones_compl, |
| twos_compl, |
| mult, |
| divide, |
| mod, |
| add, |
| sub, |
| lsh, |
| rsh, |
| logand, |
| logior, |
| logxor |
| } expr_opcodes_t; |
| |
| struct expressionS; |
| |
| #define SYMBOL_T symbolS* |
| |
| struct expression_cell |
| { |
| int value; |
| SYMBOL_T symbol; |
| }; |
| |
| /* User Type Definitions. */ |
| struct bfin_insn |
| { |
| unsigned long value; |
| struct bfin_insn *next; |
| struct expression_cell *exp; |
| int pcrel; |
| int reloc; |
| }; |
| |
| #define INSTR_T struct bfin_insn* |
| #define EXPR_T struct expression_cell* |
| |
| typedef struct expr_node_struct Expr_Node; |
| |
| extern INSTR_T gencode (unsigned long x); |
| extern INSTR_T conscode (INSTR_T head, INSTR_T tail); |
| extern INSTR_T conctcode (INSTR_T head, INSTR_T tail); |
| extern INSTR_T note_reloc |
| (INSTR_T code, Expr_Node *, int reloc,int pcrel); |
| extern INSTR_T note_reloc1 |
| (INSTR_T code, const char * sym, int reloc, int pcrel); |
| extern INSTR_T note_reloc2 |
| (INSTR_T code, const char *symbol, int reloc, int value, int pcrel); |
| |
| /* Types of expressions. */ |
| typedef enum |
| { |
| Expr_Node_Binop, /* Binary operator. */ |
| Expr_Node_Unop, /* Unary operator. */ |
| Expr_Node_Reloc, /* Symbol to be relocated. */ |
| Expr_Node_GOT_Reloc, /* Symbol to be relocated using the GOT. */ |
| Expr_Node_Constant /* Constant. */ |
| } Expr_Node_Type; |
| |
| /* Types of operators. */ |
| typedef enum |
| { |
| Expr_Op_Type_Add, |
| Expr_Op_Type_Sub, |
| Expr_Op_Type_Mult, |
| Expr_Op_Type_Div, |
| Expr_Op_Type_Mod, |
| Expr_Op_Type_Lshift, |
| Expr_Op_Type_Rshift, |
| Expr_Op_Type_BAND, /* Bitwise AND. */ |
| Expr_Op_Type_BOR, /* Bitwise OR. */ |
| Expr_Op_Type_BXOR, /* Bitwise exclusive OR. */ |
| Expr_Op_Type_LAND, /* Logical AND. */ |
| Expr_Op_Type_LOR, /* Logical OR. */ |
| Expr_Op_Type_NEG, |
| Expr_Op_Type_COMP /* Complement. */ |
| } Expr_Op_Type; |
| |
| /* The value that can be stored ... depends on type. */ |
| typedef union |
| { |
| const char *s_value; /* if relocation symbol, the text. */ |
| long long i_value; /* if constant, the value. */ |
| Expr_Op_Type op_value; /* if operator, the value. */ |
| } Expr_Node_Value; |
| |
| /* The expression node. */ |
| struct expr_node_struct |
| { |
| Expr_Node_Type type; |
| Expr_Node_Value value; |
| Expr_Node *Left_Child; |
| Expr_Node *Right_Child; |
| }; |
| |
| |
| /* Operations on the expression node. */ |
| Expr_Node *Expr_Node_Create (Expr_Node_Type type, |
| Expr_Node_Value value, |
| Expr_Node *Left_Child, |
| Expr_Node *Right_Child); |
| |
| /* Generate the reloc structure as a series of instructions. */ |
| INSTR_T Expr_Node_Gen_Reloc (Expr_Node *head, int parent_reloc); |
| |
| #define MKREF(x) mkexpr (0,x) |
| |
| #define NULL_CODE ((INSTR_T) 0) |
| |
| #ifndef EXPR_VALUE |
| #define EXPR_VALUE(x) (((x)->type == Expr_Node_Constant) ? ((x)->value.i_value) : 0) |
| #endif |
| #ifndef EXPR_SYMBOL |
| #define EXPR_SYMBOL(x) ((x)->symbol) |
| #endif |
| |
| |
| typedef long reg_t; |
| |
| |
| typedef struct _register |
| { |
| reg_t regno; /* Register ID as defined in machine_registers. */ |
| int flags; |
| } Register; |
| |
| |
| typedef struct _macfunc |
| { |
| char n; |
| char op; |
| char w; |
| char P; |
| Register dst; |
| Register s0; |
| Register s1; |
| } Macfunc; |
| |
| typedef struct _opt_mode |
| { |
| int MM; |
| int mod; |
| } Opt_mode; |
| |
| typedef enum |
| { |
| SEMANTIC_ERROR, |
| NO_INSN_GENERATED, |
| INSN_GENERATED |
| } parse_state; |
| |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| extern int debug_codeselection; |
| |
| void error (const char *format, ...); |
| void warn (char *format, ...); |
| int semantic_error (char *syntax); |
| void semantic_error_2 (char *syntax); |
| |
| EXPR_T mkexpr (int, SYMBOL_T); |
| |
| /* Defined in bfin-lex.l. */ |
| void set_start_state (void); |
| |
| extern int insn_regmask (int, int); |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| #endif /* BFIN_PARSE_H */ |
| |