/*
* 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 .
*/
#ifndef IDEF_PARSER_H
#define IDEF_PARSER_H
#include
#include
#include
#include
#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 immediated, 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_NPC,
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? */
bool is_manual; /**< Opt out of automatic freeing of params */
} 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 */