RE: [PATCH v6 02/12] target/hexagon: import README for idef-parser

2021-09-07 Thread Taylor Simpson


> -Original Message-
> From: Alessandro Di Federico 
> Sent: Tuesday, July 20, 2021 7:30 AM
> To: qemu-devel@nongnu.org
> Cc: Taylor Simpson ; Brian Cain
> ; bab...@rev.ng; ni...@rev.ng;
> richard.hender...@linaro.org; Alessandro Di Federico 
> Subject: [PATCH v6 02/12] target/hexagon: import README for idef-parser
> 
> From: Alessandro Di Federico 
> 
> Signed-off-by: Alessandro Di Federico 
> ---
>  target/hexagon/idef-parser/README.rst | 447

> +Now let's have a quick look at the generated code, line by line.
> +
> +::
> +
> +   tcg_gen_movi_i32(RdV, 0);
> +
> +This code starts by zero-initializing ``RdV``, since reading from that
> +register without initialization will cause a segmentation fault by
> +QEMU.  This is emitted since a declaration of the ``RdV`` register was
> +parsed, but we got no indication that the variable has been initialized by 
> the
> caller.

You should only need this for predicated instructions.  For non-predicated 
instructions, RdV will always be written.

> +Parser Structure
> +

Before you describe the parser, you should describe what 
gen_idef_parser_funcs.py does and the contents of idef_parser_input.h.inc and 
idef_parser_input.preprocessed.h.inc.


> +Expressions
> +~~~

Rather than describing the grammar in detail here, it would be better to state 
that we are parsing C language statements
and describe what things need to be handled specially (e.g., macros, variables 
like RdV, etc).

> +Debugging
> +-

In this section, you should describe how to narrow down to a specific 
instruction tag (e.g., A2_add) that is emitting incorrect TCG code
when a test failure is identified.  In other words, how do you switch back to 
the C helper function instead of the idef-parser generated version, and how can 
you binary search to the one emitting incorrect code?



[PATCH v6 02/12] target/hexagon: import README for idef-parser

2021-07-20 Thread Alessandro Di Federico via
From: Alessandro Di Federico 

Signed-off-by: Alessandro Di Federico 
---
 target/hexagon/idef-parser/README.rst | 447 ++
 target/hexagon/README |   5 +
 2 files changed, 452 insertions(+)
 create mode 100644 target/hexagon/idef-parser/README.rst

diff --git a/target/hexagon/idef-parser/README.rst 
b/target/hexagon/idef-parser/README.rst
new file mode 100644
index 00..9f20bce36a
--- /dev/null
+++ b/target/hexagon/idef-parser/README.rst
@@ -0,0 +1,447 @@
+Hexagon ISA instruction definitions to tinycode generator compiler
+--
+
+idef-parser is a small compiler able to translate the Hexagon ISA description
+language into tinycode generator code, that can be easily integrated into QEMU.
+
+Compilation Example
+---
+
+To better understand the scope of the idef-parser, we'll explore an applicative
+example. Let's start by one of the simplest Hexagon instruction: the ``add``.
+
+The ISA description language represents the ``add`` instruction as
+follows:
+
+.. code:: c
+
+   A2_add(RdV, in RsV, in RtV) {
+   { RdV=RsV+RtV;}
+   }
+
+idef-parser will compile the above code into the following code:
+
+.. code:: c
+
+   /* A2_add */
+   void emit_A2_add(DisasContext *ctx, Insn *insn, Packet *pkt, TCGv_i32 RdV,
+TCGv_i32 RsV, TCGv_i32 RtV)
+   /*  { RdV=RsV+RtV;} */
+   {
+   tcg_gen_movi_i32(RdV, 0);
+   TCGv_i32 tmp_0 = tcg_temp_new_i32();
+   tcg_gen_add_i32(tmp_0, RsV, RtV);
+   tcg_gen_mov_i32(RdV, tmp_0);
+   tcg_temp_free_i32(tmp_0);
+   }
+
+The output of the compilation process will be a function, containing the
+tinycode generator code, implementing the correct semantics. That function will
+not access any global variable, because all the accessed data structures will 
be
+passed explicitly as function parameters. Among the passed parameters we will
+have TCGv (tinycode variables) representing the input and output registers of
+the architecture, integers representing the immediates that come from the code,
+and other data structures which hold information about the disassemblation
+context (``DisasContext`` struct).
+
+Let's begin by describing the input code. The ``add`` instruction is associated
+with a unique identifier, in this case ``A2_add``, which allows to distinguish
+variants of the same instruction, and expresses the class to which the
+instruction belongs, in this case ``A2`` corresponds to the Hexagon
+``ALU32/ALU`` instruction subclass.
+
+After the instruction identifier, we have a series of parameters that 
represents
+TCG variables that will be passed to the generated function. Parameters marked
+with ``in`` are already initialized, while the others are output parameters.
+
+We will leverage this information to infer several information:
+
+-  Fill in the output function signature with the correct TCGv registers
+-  Fill in the output function signature with the immediate integers
+-  Keep track of which registers, among the declared one, have been
+   initialized
+
+Let's now observe the actual instruction description code, in this case:
+
+.. code:: c
+
+   { RdV=RsV+RtV;}
+
+This code is composed by a subset of the C syntax, and is the result of the
+application of some macro definitions contained in the ``macros.h`` file.
+
+This file is used to reduce the complexity of the input language where complex
+variants of similar constructs can be mapped to a unique primitive, so that the
+idef-parser has to handle a lower number of computation primitives.
+
+As you may notice, the description code modifies the registers which have been
+declared by the declaration statements. In this case all the three registers
+will be declared, ``RsV`` and ``RtV`` will also be read and ``RdV`` will be
+written.
+
+Now let's have a quick look at the generated code, line by line.
+
+::
+
+   tcg_gen_movi_i32(RdV, 0);
+
+This code starts by zero-initializing ``RdV``, since reading from that register
+without initialization will cause a segmentation fault by QEMU.  This is 
emitted
+since a declaration of the ``RdV`` register was parsed, but we got no 
indication
+that the variable has been initialized by the caller.
+
+::
+
+   TCGv_i32 tmp_0 = tcg_temp_new_i32();
+
+Then we are declaring a temporary TCGv to hold the result from the sum
+operation.
+
+::
+
+   tcg_gen_add_i32(tmp_0, RsV, RtV);
+
+Now we are actually generating the sum tinycode operator between the selected
+registers, storing the result in the just declared temporary.
+
+::
+
+   tcg_gen_mov_i32(RdV, tmp_0);
+
+The result of the addition is now stored in the temporary, we move it into the
+correct destination register. This might not seem an efficient code, but QEMU
+will perform some tinycode optimization, reducing the unnecessary copy.
+
+::
+
+   tcg_temp_free_i32(tmp_0);
+
+Finally, we free the temporary we used to hold the addition result.
+
+Parser Structure
+