| 1 | /* bfin-defs.h ADI Blackfin gas header file |
| 2 | Copyright (C) 2005-2020 Free Software Foundation, Inc. |
| 3 | |
| 4 | This file is part of GAS, the GNU Assembler. |
| 5 | |
| 6 | GAS is free software; you can redistribute it and/or modify |
| 7 | it under the terms of the GNU General Public License as published by |
| 8 | the Free Software Foundation; either version 3, or (at your option) |
| 9 | any later version. |
| 10 | |
| 11 | GAS is distributed in the hope that it will be useful, |
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | GNU General Public License for more details. |
| 15 | |
| 16 | You should have received a copy of the GNU General Public License |
| 17 | along with GAS; see the file COPYING. If not, write to the Free |
| 18 | Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA |
| 19 | 02110-1301, USA. */ |
| 20 | |
| 21 | #ifndef BFIN_PARSE_H |
| 22 | #define BFIN_PARSE_H |
| 23 | |
| 24 | #include "opcode/bfin.h" |
| 25 | |
| 26 | #define PCREL 1 |
| 27 | #define CODE_FRAG_SIZE 4096 /* 1 page. */ |
| 28 | |
| 29 | |
| 30 | /* Definition for all status bits. */ |
| 31 | typedef enum |
| 32 | { |
| 33 | c_0, |
| 34 | c_1, |
| 35 | c_4, |
| 36 | c_2, |
| 37 | c_uimm2, |
| 38 | c_uimm3, |
| 39 | c_imm3, |
| 40 | c_pcrel4, |
| 41 | c_imm4, |
| 42 | c_uimm4s4, |
| 43 | c_uimm4, |
| 44 | c_uimm4s2, |
| 45 | c_negimm5s4, |
| 46 | c_imm5, |
| 47 | c_uimm5, |
| 48 | c_imm6, |
| 49 | c_imm7, |
| 50 | c_imm8, |
| 51 | c_uimm8, |
| 52 | c_pcrel8, |
| 53 | c_uimm8s4, |
| 54 | c_pcrel8s4, |
| 55 | c_lppcrel10, |
| 56 | c_pcrel10, |
| 57 | c_pcrel12, |
| 58 | c_imm16s4, |
| 59 | c_luimm16, |
| 60 | c_imm16, |
| 61 | c_huimm16, |
| 62 | c_rimm16, |
| 63 | c_imm16s2, |
| 64 | c_uimm16s4, |
| 65 | c_uimm16, |
| 66 | c_pcrel24 |
| 67 | } const_forms_t; |
| 68 | |
| 69 | |
| 70 | /* High-Nibble: group code, low nibble: register code. */ |
| 71 | |
| 72 | |
| 73 | #define T_REG_R 0x00 |
| 74 | #define T_REG_P 0x10 |
| 75 | #define T_REG_I 0x20 |
| 76 | #define T_REG_B 0x30 |
| 77 | #define T_REG_L 0x34 |
| 78 | #define T_REG_M 0x24 |
| 79 | #define T_REG_A 0x40 |
| 80 | |
| 81 | /* All registers above this value don't |
| 82 | belong to a usable register group. */ |
| 83 | #define T_NOGROUP 0xa0 |
| 84 | |
| 85 | /* Flags. */ |
| 86 | #define F_REG_NONE 0 |
| 87 | #define F_REG_HIGH 1 |
| 88 | #define F_REG_LOW 2 |
| 89 | |
| 90 | enum machine_registers |
| 91 | { |
| 92 | REG_R0 = T_REG_R, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7, |
| 93 | REG_P0 = T_REG_P, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP, |
| 94 | REG_I0 = T_REG_I, REG_I1, REG_I2, REG_I3, |
| 95 | REG_M0 = T_REG_M, REG_M1, REG_M2, REG_M3, |
| 96 | REG_B0 = T_REG_B, REG_B1, REG_B2, REG_B3, |
| 97 | REG_L0 = T_REG_L, REG_L1, REG_L2, REG_L3, |
| 98 | REG_A0x = T_REG_A, REG_A0w, REG_A1x, REG_A1w, |
| 99 | REG_ASTAT = 0x46, |
| 100 | REG_RETS = 0x47, |
| 101 | REG_LC0 = 0x60, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, |
| 102 | REG_CYCLES, REG_CYCLES2, |
| 103 | REG_USP = 0x70, REG_SEQSTAT, REG_SYSCFG, |
| 104 | REG_RETI, REG_RETX, REG_RETN, REG_RETE, REG_EMUDAT, |
| 105 | |
| 106 | /* These don't have groups. */ |
| 107 | REG_sftreset = T_NOGROUP, REG_omode, REG_excause, REG_emucause, |
| 108 | REG_idle_req, REG_hwerrcause, |
| 109 | REG_A0 = 0xc0, REG_A1, REG_CC, |
| 110 | /* Pseudo registers, used only for distinction from symbols. */ |
| 111 | REG_RL0, REG_RL1, REG_RL2, REG_RL3, |
| 112 | REG_RL4, REG_RL5, REG_RL6, REG_RL7, |
| 113 | REG_RH0, REG_RH1, REG_RH2, REG_RH3, |
| 114 | REG_RH4, REG_RH5, REG_RH6, REG_RH7, |
| 115 | REG_LASTREG |
| 116 | }; |
| 117 | |
| 118 | /* Status register flags. */ |
| 119 | |
| 120 | enum statusflags |
| 121 | { |
| 122 | S_AZ = 0, |
| 123 | S_AN, |
| 124 | S_AC0_COPY, |
| 125 | S_V_COPY, |
| 126 | S_AQ = 6, |
| 127 | S_RND_MOD = 8, |
| 128 | S_AC0 = 12, |
| 129 | S_AC1, |
| 130 | S_AV0 = 16, |
| 131 | S_AV0S, |
| 132 | S_AV1, |
| 133 | S_AV1S, |
| 134 | S_V = 24, |
| 135 | S_VS = 25 |
| 136 | }; |
| 137 | |
| 138 | |
| 139 | enum reg_class |
| 140 | { |
| 141 | rc_dregs_lo, |
| 142 | rc_dregs_hi, |
| 143 | rc_dregs, |
| 144 | rc_dregs_pair, |
| 145 | rc_pregs, |
| 146 | rc_spfp, |
| 147 | rc_dregs_hilo, |
| 148 | rc_accum_ext, |
| 149 | rc_accum_word, |
| 150 | rc_accum, |
| 151 | rc_iregs, |
| 152 | rc_mregs, |
| 153 | rc_bregs, |
| 154 | rc_lregs, |
| 155 | rc_dpregs, |
| 156 | rc_gregs, |
| 157 | rc_regs, |
| 158 | rc_statbits, |
| 159 | rc_ignore_bits, |
| 160 | rc_ccstat, |
| 161 | rc_counters, |
| 162 | rc_dregs2_sysregs1, |
| 163 | rc_open, |
| 164 | rc_sysregs2, |
| 165 | rc_sysregs3, |
| 166 | rc_allregs, |
| 167 | LIM_REG_CLASSES |
| 168 | }; |
| 169 | |
| 170 | /* Register type checking macros. */ |
| 171 | |
| 172 | #define CODE_MASK 0x07 |
| 173 | #define CLASS_MASK 0xf0 |
| 174 | |
| 175 | #define REG_SAME(a, b) ((a).regno == (b).regno) |
| 176 | #define REG_EQUAL(a, b) (((a).regno & CODE_MASK) == ((b).regno & CODE_MASK)) |
| 177 | #define REG_CLASS(a) ((a).regno & 0xf0) |
| 178 | #define IS_A1(a) ((a).regno == REG_A1) |
| 179 | #define IS_H(a) ((a).flags & F_REG_HIGH ? 1: 0) |
| 180 | #define IS_EVEN(r) ((r).regno % 2 == 0) |
| 181 | #define IS_HCOMPL(a, b) (REG_EQUAL(a, b) && \ |
| 182 | ((a).flags & F_REG_HIGH) != ((b).flags & F_REG_HIGH)) |
| 183 | |
| 184 | /* register type checking. */ |
| 185 | #define _TYPECHECK(r, x) (((r).regno & CLASS_MASK) == T_REG_##x) |
| 186 | |
| 187 | #define IS_DREG(r) _TYPECHECK(r, R) |
| 188 | #define IS_DREG_H(r) (_TYPECHECK(r, R) && IS_H(r)) |
| 189 | #define IS_DREG_L(r) (_TYPECHECK(r, R) && !IS_H(r)) |
| 190 | #define IS_PREG(r) _TYPECHECK(r, P) |
| 191 | #define IS_IREG(r) (((r).regno & 0xf4) == T_REG_I) |
| 192 | #define IS_MREG(r) (((r).regno & 0xf4) == T_REG_M) |
| 193 | #define IS_BREG(r) (((r).regno & 0xf4) == T_REG_B) |
| 194 | #define IS_LREG(r) (((r).regno & 0xf4) == T_REG_L) |
| 195 | #define IS_CREG(r) ((r).regno == REG_LC0 || (r).regno == REG_LC1) |
| 196 | #define IS_EMUDAT(r) ((r).regno == REG_EMUDAT) |
| 197 | #define IS_ALLREG(r) ((r).regno < T_NOGROUP) |
| 198 | |
| 199 | #define IS_GENREG(r) \ |
| 200 | (IS_DREG (r) || IS_PREG (r) \ |
| 201 | || (r).regno == REG_A0x || (r).regno == REG_A0w \ |
| 202 | || (r).regno == REG_A1x || (r).regno == REG_A1w) |
| 203 | |
| 204 | #define IS_DAGREG(r) \ |
| 205 | (IS_IREG (r) || IS_MREG (r) || IS_BREG (r) || IS_LREG (r)) |
| 206 | |
| 207 | #define IS_SYSREG(r) \ |
| 208 | ((r).regno == REG_ASTAT || (r).regno == REG_SEQSTAT \ |
| 209 | || (r).regno == REG_SYSCFG || (r).regno == REG_RETI \ |
| 210 | || (r).regno == REG_RETX || (r).regno == REG_RETN \ |
| 211 | || (r).regno == REG_RETE || (r).regno == REG_RETS \ |
| 212 | || (r).regno == REG_LC0 || (r).regno == REG_LC1 \ |
| 213 | || (r).regno == REG_LT0 || (r).regno == REG_LT1 \ |
| 214 | || (r).regno == REG_LB0 || (r).regno == REG_LB1 \ |
| 215 | || (r).regno == REG_CYCLES || (r).regno == REG_CYCLES2 \ |
| 216 | || (r).regno == REG_EMUDAT) |
| 217 | |
| 218 | /* Expression value macros. */ |
| 219 | |
| 220 | typedef enum |
| 221 | { |
| 222 | ones_compl, |
| 223 | twos_compl, |
| 224 | mult, |
| 225 | divide, |
| 226 | mod, |
| 227 | add, |
| 228 | sub, |
| 229 | lsh, |
| 230 | rsh, |
| 231 | logand, |
| 232 | logior, |
| 233 | logxor |
| 234 | } expr_opcodes_t; |
| 235 | |
| 236 | struct expressionS; |
| 237 | |
| 238 | #define SYMBOL_T symbolS* |
| 239 | |
| 240 | struct expression_cell |
| 241 | { |
| 242 | int value; |
| 243 | SYMBOL_T symbol; |
| 244 | }; |
| 245 | |
| 246 | /* User Type Definitions. */ |
| 247 | struct bfin_insn |
| 248 | { |
| 249 | unsigned long value; |
| 250 | struct bfin_insn *next; |
| 251 | struct expression_cell *exp; |
| 252 | int pcrel; |
| 253 | int reloc; |
| 254 | }; |
| 255 | |
| 256 | #define INSTR_T struct bfin_insn* |
| 257 | #define EXPR_T struct expression_cell* |
| 258 | |
| 259 | typedef struct expr_node_struct Expr_Node; |
| 260 | |
| 261 | extern INSTR_T gencode (unsigned long x); |
| 262 | extern INSTR_T conscode (INSTR_T head, INSTR_T tail); |
| 263 | extern INSTR_T conctcode (INSTR_T head, INSTR_T tail); |
| 264 | extern INSTR_T note_reloc |
| 265 | (INSTR_T code, Expr_Node *, int reloc,int pcrel); |
| 266 | extern INSTR_T note_reloc1 |
| 267 | (INSTR_T code, const char * sym, int reloc, int pcrel); |
| 268 | extern INSTR_T note_reloc2 |
| 269 | (INSTR_T code, const char *symbol, int reloc, int value, int pcrel); |
| 270 | |
| 271 | /* Types of expressions. */ |
| 272 | typedef enum |
| 273 | { |
| 274 | Expr_Node_Binop, /* Binary operator. */ |
| 275 | Expr_Node_Unop, /* Unary operator. */ |
| 276 | Expr_Node_Reloc, /* Symbol to be relocated. */ |
| 277 | Expr_Node_GOT_Reloc, /* Symbol to be relocated using the GOT. */ |
| 278 | Expr_Node_Constant /* Constant. */ |
| 279 | } Expr_Node_Type; |
| 280 | |
| 281 | /* Types of operators. */ |
| 282 | typedef enum |
| 283 | { |
| 284 | Expr_Op_Type_Add, |
| 285 | Expr_Op_Type_Sub, |
| 286 | Expr_Op_Type_Mult, |
| 287 | Expr_Op_Type_Div, |
| 288 | Expr_Op_Type_Mod, |
| 289 | Expr_Op_Type_Lshift, |
| 290 | Expr_Op_Type_Rshift, |
| 291 | Expr_Op_Type_BAND, /* Bitwise AND. */ |
| 292 | Expr_Op_Type_BOR, /* Bitwise OR. */ |
| 293 | Expr_Op_Type_BXOR, /* Bitwise exclusive OR. */ |
| 294 | Expr_Op_Type_LAND, /* Logical AND. */ |
| 295 | Expr_Op_Type_LOR, /* Logical OR. */ |
| 296 | Expr_Op_Type_NEG, |
| 297 | Expr_Op_Type_COMP /* Complement. */ |
| 298 | } Expr_Op_Type; |
| 299 | |
| 300 | /* The value that can be stored ... depends on type. */ |
| 301 | typedef union |
| 302 | { |
| 303 | const char *s_value; /* if relocation symbol, the text. */ |
| 304 | long long i_value; /* if constant, the value. */ |
| 305 | Expr_Op_Type op_value; /* if operator, the value. */ |
| 306 | } Expr_Node_Value; |
| 307 | |
| 308 | /* The expression node. */ |
| 309 | struct expr_node_struct |
| 310 | { |
| 311 | Expr_Node_Type type; |
| 312 | Expr_Node_Value value; |
| 313 | Expr_Node *Left_Child; |
| 314 | Expr_Node *Right_Child; |
| 315 | }; |
| 316 | |
| 317 | |
| 318 | /* Operations on the expression node. */ |
| 319 | Expr_Node *Expr_Node_Create (Expr_Node_Type type, |
| 320 | Expr_Node_Value value, |
| 321 | Expr_Node *Left_Child, |
| 322 | Expr_Node *Right_Child); |
| 323 | |
| 324 | /* Generate the reloc structure as a series of instructions. */ |
| 325 | INSTR_T Expr_Node_Gen_Reloc (Expr_Node *head, int parent_reloc); |
| 326 | |
| 327 | #define MKREF(x) mkexpr (0,x) |
| 328 | |
| 329 | #define NULL_CODE ((INSTR_T) 0) |
| 330 | |
| 331 | #ifndef EXPR_VALUE |
| 332 | #define EXPR_VALUE(x) (((x)->type == Expr_Node_Constant) ? ((x)->value.i_value) : 0) |
| 333 | #endif |
| 334 | #ifndef EXPR_SYMBOL |
| 335 | #define EXPR_SYMBOL(x) ((x)->symbol) |
| 336 | #endif |
| 337 | |
| 338 | |
| 339 | typedef long reg_t; |
| 340 | |
| 341 | |
| 342 | typedef struct _register |
| 343 | { |
| 344 | reg_t regno; /* Register ID as defined in machine_registers. */ |
| 345 | int flags; |
| 346 | } Register; |
| 347 | |
| 348 | |
| 349 | typedef struct _macfunc |
| 350 | { |
| 351 | char n; |
| 352 | char op; |
| 353 | char w; |
| 354 | char P; |
| 355 | Register dst; |
| 356 | Register s0; |
| 357 | Register s1; |
| 358 | } Macfunc; |
| 359 | |
| 360 | typedef struct _opt_mode |
| 361 | { |
| 362 | int MM; |
| 363 | int mod; |
| 364 | } Opt_mode; |
| 365 | |
| 366 | typedef enum |
| 367 | { |
| 368 | SEMANTIC_ERROR, |
| 369 | NO_INSN_GENERATED, |
| 370 | INSN_GENERATED |
| 371 | } parse_state; |
| 372 | |
| 373 | |
| 374 | #ifdef __cplusplus |
| 375 | extern "C" { |
| 376 | #endif |
| 377 | |
| 378 | extern int debug_codeselection; |
| 379 | |
| 380 | void error (const char *format, ...); |
| 381 | void warn (char *format, ...); |
| 382 | int semantic_error (char *syntax); |
| 383 | void semantic_error_2 (char *syntax); |
| 384 | |
| 385 | EXPR_T mkexpr (int, SYMBOL_T); |
| 386 | |
| 387 | /* Defined in bfin-lex.l. */ |
| 388 | void set_start_state (void); |
| 389 | |
| 390 | extern int insn_regmask (int, int); |
| 391 | #ifdef __cplusplus |
| 392 | } |
| 393 | #endif |
| 394 | |
| 395 | #endif /* BFIN_PARSE_H */ |
| 396 | |