6c67d98c4a
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru> Reviewed-by: Brian Cain <bcain@quicinc.com>
252 lines
9.6 KiB
C
252 lines
9.6 KiB
C
/*
|
|
* Copyright(c) 2019-2022 rev.ng Labs Srl. All Rights Reserved.
|
|
*
|
|
* This program 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 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 this program; if not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef IDEF_PARSER_H
|
|
#define IDEF_PARSER_H
|
|
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <glib.h>
|
|
|
|
#define TCGV_NAME_SIZE 7
|
|
#define MAX_WRITTEN_REGS 32
|
|
#define OFFSET_STR_LEN 32
|
|
#define ALLOC_LIST_LEN 32
|
|
#define ALLOC_NAME_SIZE 32
|
|
#define INIT_LIST_LEN 32
|
|
#define OUT_BUF_LEN (1024 * 1024)
|
|
#define SIGNATURE_BUF_LEN (128 * 1024)
|
|
#define HEADER_BUF_LEN (128 * 1024)
|
|
|
|
/* Variadic macros to wrap the buffer printing functions */
|
|
#define EMIT(c, ...) \
|
|
do { \
|
|
g_string_append_printf((c)->out_str, __VA_ARGS__); \
|
|
} while (0)
|
|
|
|
#define EMIT_SIG(c, ...) \
|
|
do { \
|
|
g_string_append_printf((c)->signature_str, __VA_ARGS__); \
|
|
} while (0)
|
|
|
|
#define EMIT_HEAD(c, ...) \
|
|
do { \
|
|
g_string_append_printf((c)->header_str, __VA_ARGS__); \
|
|
} while (0)
|
|
|
|
/**
|
|
* Type of register, assigned to the HexReg.type field
|
|
*/
|
|
typedef enum { GENERAL_PURPOSE, CONTROL, MODIFIER, DOTNEW } HexRegType;
|
|
|
|
typedef enum { UNKNOWN_SIGNEDNESS, SIGNED, UNSIGNED } HexSignedness;
|
|
|
|
/**
|
|
* Semantic record of the REG tokens, identifying registers
|
|
*/
|
|
typedef struct HexReg {
|
|
uint8_t id; /**< Identifier of the register */
|
|
HexRegType type; /**< Type of the register */
|
|
unsigned bit_width; /**< Bit width of the reg, 32 or 64 bits */
|
|
} HexReg;
|
|
|
|
/**
|
|
* Data structure, identifying a TCGv temporary value
|
|
*/
|
|
typedef struct HexTmp {
|
|
unsigned index; /**< Index of the TCGv temporary value */
|
|
} HexTmp;
|
|
|
|
/**
|
|
* Enum of the possible immediate, an immediate is a value which is known
|
|
* at tinycode generation time, e.g. an integer value, not a TCGv
|
|
*/
|
|
enum ImmUnionTag {
|
|
I,
|
|
VARIABLE,
|
|
VALUE,
|
|
QEMU_TMP,
|
|
IMM_PC,
|
|
IMM_CONSTEXT,
|
|
};
|
|
|
|
/**
|
|
* Semantic record of the IMM token, identifying an immediate constant
|
|
*/
|
|
typedef struct HexImm {
|
|
union {
|
|
char id; /**< Identifier, used when type is VARIABLE */
|
|
uint64_t value; /**< Immediate value, used when type is VALUE */
|
|
uint64_t index; /**< Index, used when type is QEMU_TMP */
|
|
};
|
|
enum ImmUnionTag type; /**< Type of the immediate */
|
|
} HexImm;
|
|
|
|
/**
|
|
* Semantic record of the PRED token, identifying a predicate
|
|
*/
|
|
typedef struct HexPred {
|
|
char id; /**< Identifier of the predicate */
|
|
} HexPred;
|
|
|
|
/**
|
|
* Semantic record of the SAT token, identifying the saturate operator
|
|
* Note: All saturates are assumed to implicitly set overflow.
|
|
*/
|
|
typedef struct HexSat {
|
|
HexSignedness signedness; /**< Signedness of the sat. op. */
|
|
} HexSat;
|
|
|
|
/**
|
|
* Semantic record of the CAST token, identifying the cast operator
|
|
*/
|
|
typedef struct HexCast {
|
|
unsigned bit_width; /**< Bit width of the cast operator */
|
|
HexSignedness signedness; /**< Unsigned flag for the cast operator */
|
|
} HexCast;
|
|
|
|
/**
|
|
* Semantic record of the EXTRACT token, identifying the cast operator
|
|
*/
|
|
typedef struct HexExtract {
|
|
unsigned bit_width; /**< Bit width of the extract operator */
|
|
unsigned storage_bit_width; /**< Actual bit width of the extract operator */
|
|
HexSignedness signedness; /**< Unsigned flag for the extract operator */
|
|
} HexExtract;
|
|
|
|
/**
|
|
* Semantic record of the MPY token, identifying the fMPY multiplication
|
|
* operator
|
|
*/
|
|
typedef struct HexMpy {
|
|
unsigned first_bit_width; /**< Bit width of 1st operand of fMPY */
|
|
unsigned second_bit_width; /**< Bit width of 2nd operand of fMPY */
|
|
HexSignedness first_signedness; /**< Signedness of 1st operand of fMPY */
|
|
HexSignedness second_signedness; /**< Signedness of 2nd operand of fMPY */
|
|
} HexMpy;
|
|
|
|
/**
|
|
* Semantic record of the VARID token, identifying declared variables
|
|
* of the input language
|
|
*/
|
|
typedef struct HexVar {
|
|
GString *name; /**< Name of the VARID variable */
|
|
} HexVar;
|
|
|
|
/**
|
|
* Data structure uniquely identifying a declared VARID variable, used for
|
|
* keeping track of declared variable, so that any variable is declared only
|
|
* once, and its properties are propagated through all the subsequent instances
|
|
* of that variable
|
|
*/
|
|
typedef struct Var {
|
|
GString *name; /**< Name of the VARID variable */
|
|
uint8_t bit_width; /**< Bit width of the VARID variable */
|
|
HexSignedness signedness; /**< Unsigned flag for the VARID var */
|
|
} Var;
|
|
|
|
/**
|
|
* Enum of the possible rvalue types, used in the HexValue.type field
|
|
*/
|
|
typedef enum RvalueUnionTag {
|
|
REGISTER, REGISTER_ARG, TEMP, IMMEDIATE, PREDICATE, VARID
|
|
} RvalueUnionTag;
|
|
|
|
/**
|
|
* Semantic record of the rvalue token, identifying any numeric value,
|
|
* immediate or register based. The rvalue tokens are combined together
|
|
* through the use of several operators, to encode expressions
|
|
*/
|
|
typedef struct HexValue {
|
|
union {
|
|
HexReg reg; /**< rvalue of register type */
|
|
HexTmp tmp; /**< rvalue of temporary type */
|
|
HexImm imm; /**< rvalue of immediate type */
|
|
HexPred pred; /**< rvalue of predicate type */
|
|
HexVar var; /**< rvalue of declared variable type */
|
|
};
|
|
RvalueUnionTag type; /**< Type of the rvalue */
|
|
unsigned bit_width; /**< Bit width of the rvalue */
|
|
HexSignedness signedness; /**< Unsigned flag for the rvalue */
|
|
bool is_dotnew; /**< rvalue of predicate type is dotnew? */
|
|
} HexValue;
|
|
|
|
/**
|
|
* State of ternary operator
|
|
*/
|
|
typedef enum TernaryState { IN_LEFT, IN_RIGHT } TernaryState;
|
|
|
|
/**
|
|
* Data structure used to handle side effects inside ternary operators
|
|
*/
|
|
typedef struct Ternary {
|
|
TernaryState state;
|
|
HexValue cond;
|
|
} Ternary;
|
|
|
|
/**
|
|
* Operator type, used for referencing the correct operator when calling the
|
|
* gen_bin_op() function, which in turn will generate the correct code to
|
|
* execute the operation between the two rvalues
|
|
*/
|
|
typedef enum OpType {
|
|
ADD_OP, SUB_OP, MUL_OP, ASL_OP, ASR_OP, LSR_OP, ANDB_OP, ORB_OP,
|
|
XORB_OP, ANDL_OP, MINI_OP, MAXI_OP
|
|
} OpType;
|
|
|
|
/**
|
|
* Data structure including instruction specific information, to be cleared
|
|
* out after the compilation of each instruction
|
|
*/
|
|
typedef struct Inst {
|
|
GString *name; /**< Name of the compiled instruction */
|
|
char *code_begin; /**< Beginning of instruction input code */
|
|
char *code_end; /**< End of instruction input code */
|
|
unsigned tmp_count; /**< Index of the last declared TCGv temp */
|
|
unsigned qemu_tmp_count; /**< Index of the last declared int temp */
|
|
unsigned if_count; /**< Index of the last declared if label */
|
|
unsigned error_count; /**< Number of generated errors */
|
|
GArray *allocated; /**< Allocated declaredVARID vars */
|
|
GArray *init_list; /**< List of initialized registers */
|
|
GArray *strings; /**< Strings allocated by the instruction */
|
|
} Inst;
|
|
|
|
/**
|
|
* Data structure representing the whole translation context, which in a
|
|
* reentrant flex/bison parser just like ours is passed between the scanner
|
|
* and the parser, holding all the necessary information to perform the
|
|
* parsing, this data structure survives between the compilation of different
|
|
* instructions
|
|
*/
|
|
typedef struct Context {
|
|
void *scanner; /**< Reentrant parser state pointer */
|
|
char *input_buffer; /**< Buffer containing the input code */
|
|
GString *out_str; /**< String containing the output code */
|
|
GString *signature_str; /**< String containing the signatures code */
|
|
GString *header_str; /**< String containing the header code */
|
|
FILE *defines_file; /**< FILE * of the generated header */
|
|
FILE *output_file; /**< FILE * of the C output file */
|
|
FILE *enabled_file; /**< FILE * of the list of enabled inst */
|
|
GArray *ternary; /**< Array to track nesting of ternary ops */
|
|
unsigned total_insn; /**< Number of instructions in input file */
|
|
unsigned implemented_insn; /**< Instruction compiled without errors */
|
|
Inst inst; /**< Parsing data of the current inst */
|
|
} Context;
|
|
|
|
#endif /* IDEF_PARSER_H */
|