[PATCH v2] Hexagon: lldb read/write predicate registers p0/p1/p2/p3

2024-06-13 Thread Taylor Simpson
hexagon-core.xml only exposes register p3_0 which is an alias that
aggregates the predicate registers.  It is more convenient for users
to interact directly with the predicate registers.

Tested with lldb downloaded from this location
https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.4/clang+llvm-18.1.4-x86_64-linux-gnu-ubuntu-18.04.tar.xz

BEFORE:
(lldb) reg read p3_0
p3_0 = 0x
(lldb) reg read p0
error: Invalid register name 'p0'.
(lldb) reg write p1 0xf
error: Register not found for 'p1'.

AFTER:
(lldb) reg read p3_0
p3_0 = 0x
(lldb) reg read p0
  p0 = 0x00
(lldb) reg read -s 1
Predicate Registers:
p0 = 0x00
p1 = 0x00
p2 = 0x00
p3 = 0x00

(lldb) reg write p1 0xf
(lldb) reg read p3_0
p3_0 = 0x0f00
(lldb) reg write p3_0 0xff00ff00
(lldb) reg read -s 1
Predicate Registers:
p0 = 0x00
p1 = 0xff
p2 = 0x00
p3 = 0xff

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gdbstub.c | 19 ++-
 gdb-xml/hexagon-core.xml |  6 +-
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/gdbstub.c b/target/hexagon/gdbstub.c
index 502c6987f0..94e1db8ef8 100644
--- a/target/hexagon/gdbstub.c
+++ b/target/hexagon/gdbstub.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -36,6 +36,14 @@ int hexagon_gdb_read_register(CPUState *cs, GByteArray 
*mem_buf, int n)
 return gdb_get_regl(mem_buf, env->gpr[n]);
 }
 
+n -= TOTAL_PER_THREAD_REGS;
+
+if (n < NUM_PREGS) {
+return gdb_get_reg8(mem_buf, env->pred[n]);
+}
+
+n -= NUM_PREGS;
+
 g_assert_not_reached();
 }
 
@@ -56,6 +64,15 @@ int hexagon_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 return sizeof(target_ulong);
 }
 
+n -= TOTAL_PER_THREAD_REGS;
+
+if (n < NUM_PREGS) {
+env->pred[n] = ldtul_p(mem_buf) & 0xff;
+return sizeof(uint8_t);
+}
+
+n -= NUM_PREGS;
+
 g_assert_not_reached();
 }
 
diff --git a/gdb-xml/hexagon-core.xml b/gdb-xml/hexagon-core.xml
index e181163cff..b94378112a 100644
--- a/gdb-xml/hexagon-core.xml
+++ b/gdb-xml/hexagon-core.xml
@@ -1,6 +1,6 @@
 
 

[PATCH] Hexagon: lldb read/write predicate registers p0/p1/p2/p3

2024-06-12 Thread Taylor Simpson
hexagon-core.xml only exposes register p3_0 which is an alias that
aggregates the predicate registers.  It is more convenient for users
to interact directly with the predicate registers.

Tested with lldb downloaded from this location
https://github.com/llvm/llvm-project/releases/download/llvmorg-18.1.4/clang+llvm-18.1.4-x86_64-linux-gnu-ubuntu-18.04.tar.xz

BEFORE:
(lldb) reg read p3_0
p3_0 = 0x
(lldb) reg read p0
error: Invalid register name 'p0'.
(lldb) reg write p1 0xf
error: Register not found for 'p1'.

AFTER:
(lldb) reg read p3_0
p3_0 = 0x
(lldb) reg read p0
  p0 = 0x00
(lldb) reg read -s 1
Predicate Registers:
p0 = 0x00
p1 = 0x00
p2 = 0x00
p3 = 0x00

(lldb) reg write p1 0xf
(lldb) reg read p3_0
p3_0 = 0x0f00
(lldb) reg write p3_0 0xff00ff00
(lldb) reg read -s 1
Predicate Registers:
p0 = 0x00
p1 = 0xff
p2 = 0x00
p3 = 0xff

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gdbstub.c | 19 ++-
 gdb-xml/hexagon-core.xml |  6 +-
 2 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/gdbstub.c b/target/hexagon/gdbstub.c
index 502c6987f0..e67e627fc9 100644
--- a/target/hexagon/gdbstub.c
+++ b/target/hexagon/gdbstub.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -36,6 +36,14 @@ int hexagon_gdb_read_register(CPUState *cs, GByteArray 
*mem_buf, int n)
 return gdb_get_regl(mem_buf, env->gpr[n]);
 }
 
+n -= TOTAL_PER_THREAD_REGS;
+
+if (n < NUM_PREGS) {
+return gdb_get_reg8(mem_buf, env->pred[n]);
+}
+
+n -= NUM_PREGS;
+
 g_assert_not_reached();
 }
 
@@ -56,6 +64,15 @@ int hexagon_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 return sizeof(target_ulong);
 }
 
+n -= TOTAL_PER_THREAD_REGS;
+
+if (n < NUM_PREGS) {
+env->pred[n] = ldtul_p(mem_buf);
+return sizeof(uint8_t);
+}
+
+n -= NUM_PREGS;
+
 g_assert_not_reached();
 }
 
diff --git a/gdb-xml/hexagon-core.xml b/gdb-xml/hexagon-core.xml
index e181163cff..b94378112a 100644
--- a/gdb-xml/hexagon-core.xml
+++ b/gdb-xml/hexagon-core.xml
@@ -1,6 +1,6 @@
 
 

[PATCH v2 3/9] Hexagon (target/hexagon) Mark dest_idx in trans functions

2024-03-06 Thread Taylor Simpson
Check that the value matches opcode_reginfo/opcode_wregs

Signed-off-by: Taylor Simpson 
---
 target/hexagon/insn.h   | 1 +
 target/hexagon/decode.c | 2 ++
 target/hexagon/mmvec/decode_ext_mmvec.c | 2 ++
 target/hexagon/gen_trans_funcs.py   | 6 ++
 4 files changed, 11 insertions(+)

diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index 36502bf056..a770379958 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -40,6 +40,7 @@ struct Instruction {
 uint32_t which_extended:1;/* If has an extender, which immediate */
 uint32_t new_value_producer_slot:4;
 int32_t new_read_idx;
+int32_t dest_idx;
 
 bool part1;  /*
   * cmp-jumps are split into two insns.
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 4595e30384..a4d8500fea 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -184,6 +184,8 @@ decode_fill_newvalue_regno(Packet *packet)
 
 /* Now patch up the consumer with the register number */
 dst_idx = dststr - opcode_reginfo[def_opcode];
+g_assert(packet->insn[def_idx].dest_idx != -1 &&
+ packet->insn[def_idx].dest_idx == dst_idx);
 packet->insn[i].regno[use_regidx] =
 packet->insn[def_idx].regno[dst_idx];
 /*
diff --git a/target/hexagon/mmvec/decode_ext_mmvec.c 
b/target/hexagon/mmvec/decode_ext_mmvec.c
index e9007f5d71..c1320406df 100644
--- a/target/hexagon/mmvec/decode_ext_mmvec.c
+++ b/target/hexagon/mmvec/decode_ext_mmvec.c
@@ -86,6 +86,8 @@ check_new_value(Packet *pkt)
 /* still not there, we have a bad packet */
 g_assert_not_reached();
 }
+g_assert(pkt->insn[def_idx].dest_idx != -1 &&
+ pkt->insn[def_idx].dest_idx == dststr - reginfo);
 int def_regnum = pkt->insn[def_idx].regno[dststr - reginfo];
 /* Now patch up the consumer with the register number */
 pkt->insn[i].regno[use_regidx] = def_regnum ^ def_oreg;
diff --git a/target/hexagon/gen_trans_funcs.py 
b/target/hexagon/gen_trans_funcs.py
index 8acecdb993..1201172dda 100755
--- a/target/hexagon/gen_trans_funcs.py
+++ b/target/hexagon/gen_trans_funcs.py
@@ -69,6 +69,7 @@ def mark_which_imm_extended(f, tag):
 ## insn->regno[1] = args->Rs;
 ## insn->regno[2] = args->Rt;
 ## insn->new_read_idx = -1;
+## insn->dest_idx = 0;
 ## return true;
 ## }
 ##
@@ -86,6 +87,7 @@ def gen_trans_funcs(f):
 """))
 
 new_read_idx = -1
+dest_idx = -1
 for regno, (reg_type, reg_id, *_) in enumerate(regs):
 reg = hex_common.get_register(tag, reg_type, reg_id)
 f.write(code_fmt(f"""\
@@ -93,6 +95,9 @@ def gen_trans_funcs(f):
 """))
 if reg.is_read() and reg.is_new():
 new_read_idx = regno
+# dest_idx should be the first destination, so check for -1
+if reg.is_written() and dest_idx == -1:
+dest_idx = regno
 
 if len(imms) != 0:
 mark_which_imm_extended(f, tag)
@@ -115,6 +120,7 @@ def gen_trans_funcs(f):
 
 f.write(code_fmt(f"""\
 insn->new_read_idx = {new_read_idx};
+insn->dest_idx = {dest_idx};
 """))
 f.write(textwrap.dedent(f"""\
 return true;
-- 
2.34.1




[PATCH v2 8/9] Hexagon (target/hexagon) Remove gen_shortcode.py

2024-03-06 Thread Taylor Simpson
This data structure is not used

Signed-off-by: Taylor Simpson 
---
 target/hexagon/opcodes.c|  7 
 target/hexagon/README   |  1 -
 target/hexagon/gen_shortcode.py | 63 -
 target/hexagon/meson.build  | 10 --
 4 files changed, 81 deletions(-)
 delete mode 100755 target/hexagon/gen_shortcode.py

diff --git a/target/hexagon/opcodes.c b/target/hexagon/opcodes.c
index 02ae9cf787..c8bde2f9e9 100644
--- a/target/hexagon/opcodes.c
+++ b/target/hexagon/opcodes.c
@@ -37,13 +37,6 @@ const char * const opcode_names[] = {
 };
 
 
-const char * const opcode_short_semantics[] = {
-#define DEF_SHORTCODE(TAG, SHORTCODE)  [TAG] = #SHORTCODE,
-#include "shortcode_generated.h.inc"
-#undef DEF_SHORTCODE
-NULL
-};
-
 DECLARE_BITMAP(opcode_attribs[XX_LAST_OPCODE], A_ZZ_LASTATTRIB);
 
 static void init_attribs(int tag, ...)
diff --git a/target/hexagon/README b/target/hexagon/README
index 065c05154d..65b4fcc0fa 100644
--- a/target/hexagon/README
+++ b/target/hexagon/README
@@ -46,7 +46,6 @@ header files in /target/hexagon
 gen_printinsn.py-> printinsn_generated.h.inc
 gen_op_attribs.py   -> op_attribs_generated.h.inc
 gen_helper_protos.py-> helper_protos_generated.h.inc
-gen_shortcode.py-> shortcode_generated.h.inc
 gen_tcg_funcs.py-> tcg_funcs_generated.c.inc
 gen_tcg_func_table.py   -> tcg_func_table_generated.c.inc
 gen_helper_funcs.py -> helper_funcs_generated.c.inc
diff --git a/target/hexagon/gen_shortcode.py b/target/hexagon/gen_shortcode.py
deleted file mode 100755
index deb94446c4..00
--- a/target/hexagon/gen_shortcode.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env python3
-
-##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. 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/>.
-##
-
-import sys
-import re
-import string
-import hex_common
-
-
-def gen_shortcode(f, tag):
-f.write(f"DEF_SHORTCODE({tag}, {hex_common.semdict[tag]})\n")
-
-
-def main():
-hex_common.read_semantics_file(sys.argv[1])
-hex_common.read_attribs_file(sys.argv[2])
-hex_common.calculate_attribs()
-tagregs = hex_common.get_tagregs()
-tagimms = hex_common.get_tagimms()
-
-with open(sys.argv[3], "w") as f:
-f.write("#ifndef DEF_SHORTCODE\n")
-f.write("#define DEF_SHORTCODE(TAG,SHORTCODE)/* Nothing */\n")
-f.write("#endif\n")
-
-for tag in hex_common.tags:
-## Skip the priv instructions
-if "A_PRIV" in hex_common.attribdict[tag]:
-continue
-## Skip the guest instructions
-if "A_GUEST" in hex_common.attribdict[tag]:
-continue
-## Skip the diag instructions
-if tag == "Y6_diag":
-continue
-if tag == "Y6_diag0":
-continue
-if tag == "Y6_diag1":
-continue
-
-gen_shortcode(f, tag)
-
-f.write("#undef DEF_SHORTCODE\n")
-
-
-if __name__ == "__main__":
-main()
diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build
index b3a0944d3b..988e7489ba 100644
--- a/target/hexagon/meson.build
+++ b/target/hexagon/meson.build
@@ -42,21 +42,11 @@ hexagon_ss.add(semantics_generated)
 #
 # Step 2
 # We use Python scripts to generate the following files
-# shortcode_generated.h.inc
 # tcg_func_table_generated.c.inc
 # printinsn_generated.h.inc
 # op_attribs_generated.h.inc
 # opcodes_def_generated.h.inc
 #
-shortcode_generated = custom_target(
-'shortcode_generated.h.inc',
-output: 'shortcode_generated.h.inc',
-depends: [semantics_generated],
-depend_files: [hex_common_py, attribs_def],
-command: [python, files('gen_shortcode.py'), semantics_generated, 
attribs_def, '@OUTPUT@'],
-)
-hexagon_ss.add(shortcode_generated)
-
 tcg_func_table_generated = custom_target(
 'tcg_func_table_generated.c.inc',
 output: 'tcg_func_table_generated.c.inc',
-- 
2.34.1




[PATCH v2 2/9] Hexagon (target/hexagon) Mark new_read_idx in trans functions

2024-03-06 Thread Taylor Simpson
Check that the value matches opcode_reginfo

Signed-off-by: Taylor Simpson 
---
 target/hexagon/insn.h   |  3 ++-
 target/hexagon/decode.c |  2 ++
 target/hexagon/mmvec/decode_ext_mmvec.c |  2 ++
 target/hexagon/gen_trans_funcs.py   | 15 ++-
 4 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index 3e7a22c91e..36502bf056 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -39,6 +39,7 @@ struct Instruction {
 uint32_t slot:3;
 uint32_t which_extended:1;/* If has an extender, which immediate */
 uint32_t new_value_producer_slot:4;
+int32_t new_read_idx;
 
 bool part1;  /*
   * cmp-jumps are split into two insns.
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index a40210ca1e..4595e30384 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -131,6 +131,8 @@ decode_fill_newvalue_regno(Packet *packet)
 use_regidx = strchr(opcode_reginfo[use_opcode], 's') -
 opcode_reginfo[use_opcode];
 }
+g_assert(packet->insn[i].new_read_idx != -1 &&
+ packet->insn[i].new_read_idx == use_regidx);
 
 /*
  * What's encoded at the N-field is the offset to who's producing
diff --git a/target/hexagon/mmvec/decode_ext_mmvec.c 
b/target/hexagon/mmvec/decode_ext_mmvec.c
index 202d84c7c0..e9007f5d71 100644
--- a/target/hexagon/mmvec/decode_ext_mmvec.c
+++ b/target/hexagon/mmvec/decode_ext_mmvec.c
@@ -41,6 +41,8 @@ check_new_value(Packet *pkt)
 GET_ATTRIB(use_opcode, A_STORE)) {
 int use_regidx = strchr(opcode_reginfo[use_opcode], 's') -
 opcode_reginfo[use_opcode];
+g_assert(pkt->insn[i].new_read_idx != -1 &&
+ pkt->insn[i].new_read_idx == use_regidx);
 /*
  * What's encoded at the N-field is the offset to who's producing
  * the value.
diff --git a/target/hexagon/gen_trans_funcs.py 
b/target/hexagon/gen_trans_funcs.py
index 53e844a44b..8acecdb993 100755
--- a/target/hexagon/gen_trans_funcs.py
+++ b/target/hexagon/gen_trans_funcs.py
@@ -68,6 +68,7 @@ def mark_which_imm_extended(f, tag):
 ## insn->regno[0] = args->Rd;
 ## insn->regno[1] = args->Rs;
 ## insn->regno[2] = args->Rt;
+## insn->new_read_idx = -1;
 ## return true;
 ## }
 ##
@@ -84,14 +85,14 @@ def gen_trans_funcs(f):
 insn->opcode = {tag};
 """))
 
-regno = 0
-for reg in regs:
-reg_type = reg[0]
-reg_id = reg[1]
+new_read_idx = -1
+for regno, (reg_type, reg_id, *_) in enumerate(regs):
+reg = hex_common.get_register(tag, reg_type, reg_id)
 f.write(code_fmt(f"""\
 insn->regno[{regno}] = args->{reg_type}{reg_id};
 """))
-regno += 1
+if reg.is_read() and reg.is_new():
+new_read_idx = regno
 
 if len(imms) != 0:
 mark_which_imm_extended(f, tag)
@@ -112,6 +113,9 @@ def gen_trans_funcs(f):
 insn->immed[{immno}] = args->{imm_type}{imm_letter};
 """))
 
+f.write(code_fmt(f"""\
+insn->new_read_idx = {new_read_idx};
+"""))
 f.write(textwrap.dedent(f"""\
 return true;
 {close_curly}
@@ -120,5 +124,6 @@ def gen_trans_funcs(f):
 
 if __name__ == "__main__":
 hex_common.read_semantics_file(sys.argv[1])
+hex_common.init_registers()
 with open(sys.argv[2], "w") as f:
 gen_trans_funcs(f)
-- 
2.34.1




[PATCH v2 9/9] Hexagon (target/hexagon) Remove hex_common.read_attribs_file

2024-03-06 Thread Taylor Simpson
The attribinfo data structure is not used
Adjust the command-line arguments to the python scripts
Add hex_common.read_common_files for TCG/helper generation scripts

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_analyze_funcs.py | 21 ++-
 target/hexagon/gen_helper_funcs.py  | 21 ++-
 target/hexagon/gen_helper_protos.py | 21 ++-
 target/hexagon/gen_idef_parser_funcs.py |  5 ++--
 target/hexagon/gen_op_attribs.py|  5 ++--
 target/hexagon/gen_opcodes_def.py   |  4 +--
 target/hexagon/gen_printinsn.py |  5 ++--
 target/hexagon/gen_tcg_func_table.py|  5 ++--
 target/hexagon/gen_tcg_funcs.py | 21 ++-
 target/hexagon/hex_common.py| 35 +++--
 target/hexagon/meson.build  | 31 +++---
 11 files changed, 54 insertions(+), 120 deletions(-)

diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index a9af666cef..b73b4e2349 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2022-2024 Qualcomm Innovation Center, Inc. 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
@@ -67,24 +67,7 @@ def gen_analyze_func(f, tag, regs, imms):
 
 
 def main():
-hex_common.read_semantics_file(sys.argv[1])
-hex_common.read_attribs_file(sys.argv[2])
-hex_common.read_overrides_file(sys.argv[3])
-hex_common.read_overrides_file(sys.argv[4])
-## Whether or not idef-parser is enabled is
-## determined by the number of arguments to
-## this script:
-##
-##   5 args. -> not enabled,
-##   6 args. -> idef-parser enabled.
-##
-## The 6:th arg. then holds a list of the successfully
-## parsed instructions.
-is_idef_parser_enabled = len(sys.argv) > 6
-if is_idef_parser_enabled:
-hex_common.read_idef_parser_enabled_file(sys.argv[5])
-hex_common.calculate_attribs()
-hex_common.init_registers()
+hex_common.read_common_files()
 tagregs = hex_common.get_tagregs()
 tagimms = hex_common.get_tagimms()
 
diff --git a/target/hexagon/gen_helper_funcs.py 
b/target/hexagon/gen_helper_funcs.py
index 9cc3d69c49..e9685bff2f 100755
--- a/target/hexagon/gen_helper_funcs.py
+++ b/target/hexagon/gen_helper_funcs.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -102,24 +102,7 @@ def gen_helper_function(f, tag, tagregs, tagimms):
 
 
 def main():
-hex_common.read_semantics_file(sys.argv[1])
-hex_common.read_attribs_file(sys.argv[2])
-hex_common.read_overrides_file(sys.argv[3])
-hex_common.read_overrides_file(sys.argv[4])
-## Whether or not idef-parser is enabled is
-## determined by the number of arguments to
-## this script:
-##
-##   5 args. -> not enabled,
-##   6 args. -> idef-parser enabled.
-##
-## The 6:th arg. then holds a list of the successfully
-## parsed instructions.
-is_idef_parser_enabled = len(sys.argv) > 6
-if is_idef_parser_enabled:
-hex_common.read_idef_parser_enabled_file(sys.argv[5])
-hex_common.calculate_attribs()
-hex_common.init_registers()
+hex_common.read_common_files()
 tagregs = hex_common.get_tagregs()
 tagimms = hex_common.get_tagimms()
 
diff --git a/target/hexagon/gen_helper_protos.py 
b/target/hexagon/gen_helper_protos.py
index c82b0f54e4..4cc72a1581 100755
--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -44,24 +44,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
 
 
 def main():
-hex_common.read_semantics_file(sys.argv[1])
-hex_common.read_attribs_file(sys.argv[2])
-hex_common.read_overrides_file(sys.argv[3])
-hex_common.read_overrides_file(sys.argv[4])
-## Whether or not idef-parser is enabled is
-## determined by the number of arguments to
-## this script:
-##
-##   5 args. -> not enabled,
-##   6 args. -> idef-parser enabled.
-##
-## The 6:th arg. then holds a list of the suc

[PATCH v2 1/9] Hexagon (target/hexagon) Add is_old/is_new to Register class

2024-03-06 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 target/hexagon/hex_common.py | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 195620c7ec..4bacef223f 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -397,10 +397,18 @@ def is_readwrite(self):
 class OldSource(Source):
 def reg_tcg(self):
 return f"{self.regtype}{self.regid}V"
+def is_old(self):
+return True
+def is_new(self):
+return False
 
 class NewSource(Source):
 def reg_tcg(self):
 return f"{self.regtype}{self.regid}N"
+def is_old(self):
+return False
+def is_new(self):
+return True
 
 class ReadWrite:
 def reg_tcg(self):
@@ -413,6 +421,10 @@ def is_read(self):
 return True
 def is_readwrite(self):
 return True
+def is_old(self):
+return True
+def is_new(self):
+return False
 
 class GprDest(Register, Single, Dest):
 def decl_tcg(self, f, tag, regno):
-- 
2.34.1




[PATCH v2 4/9] Hexagon (target/hexagon) Mark has_pred_dest in trans functions

2024-03-06 Thread Taylor Simpson
Check that the value matches opcode_wregs

Signed-off-by: Taylor Simpson 
---
 target/hexagon/insn.h | 1 +
 target/hexagon/decode.c   | 3 +++
 target/hexagon/gen_trans_funcs.py | 5 +
 3 files changed, 9 insertions(+)

diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index a770379958..24dcf7fe9f 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -41,6 +41,7 @@ struct Instruction {
 uint32_t new_value_producer_slot:4;
 int32_t new_read_idx;
 int32_t dest_idx;
+bool has_pred_dest;
 
 bool part1;  /*
   * cmp-jumps are split into two insns.
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index a4d8500fea..84a3899556 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -366,6 +366,9 @@ static void decode_shuffle_for_execution(Packet *packet)
 for (flag = false, i = 0; i < last_insn + 1; i++) {
 int opcode = packet->insn[i].opcode;
 
+g_assert(packet->insn[i].has_pred_dest ==
+ (strstr(opcode_wregs[opcode], "Pd4") ||
+  strstr(opcode_wregs[opcode], "Pe4")));
 if ((strstr(opcode_wregs[opcode], "Pd4") ||
  strstr(opcode_wregs[opcode], "Pe4")) &&
 GET_ATTRIB(opcode, A_STORE) == 0) {
diff --git a/target/hexagon/gen_trans_funcs.py 
b/target/hexagon/gen_trans_funcs.py
index 1201172dda..9f86b4edbd 100755
--- a/target/hexagon/gen_trans_funcs.py
+++ b/target/hexagon/gen_trans_funcs.py
@@ -70,6 +70,7 @@ def mark_which_imm_extended(f, tag):
 ## insn->regno[2] = args->Rt;
 ## insn->new_read_idx = -1;
 ## insn->dest_idx = 0;
+## insn->has_pred_dest = false;
 ## return true;
 ## }
 ##
@@ -88,6 +89,7 @@ def gen_trans_funcs(f):
 
 new_read_idx = -1
 dest_idx = -1
+has_pred_dest = "false"
 for regno, (reg_type, reg_id, *_) in enumerate(regs):
 reg = hex_common.get_register(tag, reg_type, reg_id)
 f.write(code_fmt(f"""\
@@ -98,6 +100,8 @@ def gen_trans_funcs(f):
 # dest_idx should be the first destination, so check for -1
 if reg.is_written() and dest_idx == -1:
 dest_idx = regno
+if reg_type == "P" and reg.is_written() and not reg.is_read():
+has_pred_dest = "true"
 
 if len(imms) != 0:
 mark_which_imm_extended(f, tag)
@@ -121,6 +125,7 @@ def gen_trans_funcs(f):
 f.write(code_fmt(f"""\
 insn->new_read_idx = {new_read_idx};
 insn->dest_idx = {dest_idx};
+insn->has_pred_dest = {has_pred_dest};
 """))
 f.write(textwrap.dedent(f"""\
 return true;
-- 
2.34.1




[PATCH v2 5/9] Hexagon (tests/tcg/hexagon) Test HVX .new read from high half of pair

2024-03-06 Thread Taylor Simpson
Make sure the decoding of HVX .new is correctly handling this case

Signed-off-by: Taylor Simpson 
---
 tests/tcg/hexagon/hvx_misc.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c
index b45170acd1..1fe14b5158 100644
--- a/tests/tcg/hexagon/hvx_misc.c
+++ b/tests/tcg/hexagon/hvx_misc.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2021-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2021-2024 Qualcomm Innovation Center, Inc. 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
@@ -231,6 +231,7 @@ static void test_masked_store(bool invert)
 static void test_new_value_store(void)
 {
 void *p0 = buffer0;
+void *p1 = buffer1;
 void *pout = output;
 
 asm("{\n\t"
@@ -242,6 +243,19 @@ static void test_new_value_store(void)
 expect[0] = buffer0[0];
 
 check_output_w(__LINE__, 1);
+
+/* Test the .new read from the high half of a pair */
+asm("v7 = vmem(%0 + #0)\n\t"
+"v12 = vmem(%1 + #0)\n\t"
+"{\n\t"
+"v5:4 = vcombine(v12, v7)\n\t"
+"vmem(%2 + #0) = v5.new\n\t"
+"}\n\t"
+: : "r"(p0), "r"(p1), "r"(pout) : "v4", "v5", "v7", "v12", "memory");
+
+expect[0] = buffer1[0];
+
+check_output_w(__LINE__, 1);
 }
 
 static void test_max_temps()
-- 
2.34.1




[PATCH v2 0/9] Clean up .new decode and scripts

2024-03-06 Thread Taylor Simpson
During .new decode, there are several places where strchr is used.
We remove these by generating the values that are needed.

Once we have generated the proper values, we no longer need
op_regs_generated.h.inc.  We remove the script that generates it as
well as the code in meson.build

We also remove the script and meson.build code that creates
shortcode_generated.h.inc.  The data structure that includes it is
not used.

We remove hex_common.read_attribs_file.  The Python data structures built
during this step are not used.

 Changes in v2 
Address feedback from Matheus Tavares Bernardino 
Mark Philippe's Reviewed-by on patch 01
Update example comment in gen_trans_funcs.py



Taylor Simpson (9):
  Hexagon (target/hexagon) Add is_old/is_new to Register class
  Hexagon (target/hexagon) Mark new_read_idx in trans functions
  Hexagon (target/hexagon) Mark dest_idx in trans functions
  Hexagon (target/hexagon) Mark has_pred_dest in trans functions
  Hexagon (tests/tcg/hexagon) Test HVX .new read from high half of pair
  Hexagon (target/hexagon) Remove uses of op_regs_generated.h.inc
  Hexagon (target/hexagon) Remove gen_op_regs.py
  Hexagon (target/hexagon) Remove gen_shortcode.py
  Hexagon (target/hexagon) Remove hex_common.read_attribs_file

 target/hexagon/insn.h   |   5 +-
 target/hexagon/opcodes.h|   4 -
 target/hexagon/decode.c |  50 ++
 target/hexagon/mmvec/decode_ext_mmvec.c |  30 ++
 target/hexagon/opcodes.c|  35 ---
 tests/tcg/hexagon/hvx_misc.c|  16 ++-
 target/hexagon/README   |   2 -
 target/hexagon/gen_analyze_funcs.py |  21 +---
 target/hexagon/gen_helper_funcs.py  |  21 +---
 target/hexagon/gen_helper_protos.py |  21 +---
 target/hexagon/gen_idef_parser_funcs.py |   5 +-
 target/hexagon/gen_op_attribs.py|   5 +-
 target/hexagon/gen_op_regs.py   | 125 
 target/hexagon/gen_opcodes_def.py   |   4 +-
 target/hexagon/gen_printinsn.py |   5 +-
 target/hexagon/gen_shortcode.py |  63 
 target/hexagon/gen_tcg_func_table.py|   5 +-
 target/hexagon/gen_tcg_funcs.py |  21 +---
 target/hexagon/gen_trans_funcs.py   |  26 -
 target/hexagon/hex_common.py|  49 +++---
 target/hexagon/meson.build  |  55 ---
 21 files changed, 122 insertions(+), 446 deletions(-)
 delete mode 100755 target/hexagon/gen_op_regs.py
 delete mode 100755 target/hexagon/gen_shortcode.py

-- 
2.34.1




[PATCH v2 6/9] Hexagon (target/hexagon) Remove uses of op_regs_generated.h.inc

2024-03-06 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/opcodes.h|  4 --
 target/hexagon/decode.c | 57 +++--
 target/hexagon/mmvec/decode_ext_mmvec.c | 34 +++
 target/hexagon/opcodes.c| 28 
 4 files changed, 13 insertions(+), 110 deletions(-)

diff --git a/target/hexagon/opcodes.h b/target/hexagon/opcodes.h
index fa7e321950..0ee11bd445 100644
--- a/target/hexagon/opcodes.h
+++ b/target/hexagon/opcodes.h
@@ -40,10 +40,6 @@ typedef enum {
 
 extern const char * const opcode_names[];
 
-extern const char * const opcode_reginfo[];
-extern const char * const opcode_rregs[];
-extern const char * const opcode_wregs[];
-
 typedef struct {
 const char * const encoding;
 const EncClass enc_class;
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 84a3899556..23deba2426 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -115,24 +115,13 @@ static void
 decode_fill_newvalue_regno(Packet *packet)
 {
 int i, use_regidx, offset, def_idx, dst_idx;
-uint16_t def_opcode, use_opcode;
-char *dststr;
 
 for (i = 1; i < packet->num_insns; i++) {
 if (GET_ATTRIB(packet->insn[i].opcode, A_DOTNEWVALUE) &&
 !GET_ATTRIB(packet->insn[i].opcode, A_EXTENSION)) {
-use_opcode = packet->insn[i].opcode;
-
-/* It's a store, so we're adjusting the Nt field */
-if (GET_ATTRIB(use_opcode, A_STORE)) {
-use_regidx = strchr(opcode_reginfo[use_opcode], 't') -
-opcode_reginfo[use_opcode];
-} else {/* It's a Jump, so we're adjusting the Ns field */
-use_regidx = strchr(opcode_reginfo[use_opcode], 's') -
-opcode_reginfo[use_opcode];
-}
-g_assert(packet->insn[i].new_read_idx != -1 &&
- packet->insn[i].new_read_idx == use_regidx);
+
+g_assert(packet->insn[i].new_read_idx != -1);
+use_regidx = packet->insn[i].new_read_idx;
 
 /*
  * What's encoded at the N-field is the offset to who's producing
@@ -153,39 +142,9 @@ decode_fill_newvalue_regno(Packet *packet)
  */
 g_assert(!((def_idx < 0) || (def_idx > (packet->num_insns - 1;
 
-/*
- * packet->insn[def_idx] is the producer
- * Figure out which type of destination it produces
- * and the corresponding index in the reginfo
- */
-def_opcode = packet->insn[def_idx].opcode;
-dststr = strstr(opcode_wregs[def_opcode], "Rd");
-if (dststr) {
-dststr = strchr(opcode_reginfo[def_opcode], 'd');
-} else {
-dststr = strstr(opcode_wregs[def_opcode], "Rx");
-if (dststr) {
-dststr = strchr(opcode_reginfo[def_opcode], 'x');
-} else {
-dststr = strstr(opcode_wregs[def_opcode], "Re");
-if (dststr) {
-dststr = strchr(opcode_reginfo[def_opcode], 'e');
-} else {
-dststr = strstr(opcode_wregs[def_opcode], "Ry");
-if (dststr) {
-dststr = strchr(opcode_reginfo[def_opcode], 'y');
-} else {
-g_assert_not_reached();
-}
-}
-}
-}
-g_assert(dststr != NULL);
-
 /* Now patch up the consumer with the register number */
-dst_idx = dststr - opcode_reginfo[def_opcode];
-g_assert(packet->insn[def_idx].dest_idx != -1 &&
- packet->insn[def_idx].dest_idx == dst_idx);
+g_assert(packet->insn[def_idx].dest_idx != -1);
+dst_idx = packet->insn[def_idx].dest_idx;
 packet->insn[i].regno[use_regidx] =
 packet->insn[def_idx].regno[dst_idx];
 /*
@@ -366,11 +325,7 @@ static void decode_shuffle_for_execution(Packet *packet)
 for (flag = false, i = 0; i < last_insn + 1; i++) {
 int opcode = packet->insn[i].opcode;
 
-g_assert(packet->insn[i].has_pred_dest ==
- (strstr(opcode_wregs[opcode], "Pd4") ||
-  strstr(opcode_wregs[opcode], "Pe4")));
-if ((strstr(opcode_wregs[opcode], "Pd4") ||
- strstr(opcode_wregs[opcode], "Pe4")) &&
+if (packet->insn[i].has_pred_dest &&
 GET_ATTRIB(opcode, A_STORE) == 0) {
 /* This should be a compare (not a store conditional) */
 if (flag) {
diff --git a/target/hexagon/mmvec/decode_

[PATCH v2 7/9] Hexagon (target/hexagon) Remove gen_op_regs.py

2024-03-06 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/README |   1 -
 target/hexagon/gen_op_regs.py | 125 --
 target/hexagon/meson.build|  14 +---
 3 files changed, 2 insertions(+), 138 deletions(-)
 delete mode 100755 target/hexagon/gen_op_regs.py

diff --git a/target/hexagon/README b/target/hexagon/README
index 746ebec378..065c05154d 100644
--- a/target/hexagon/README
+++ b/target/hexagon/README
@@ -43,7 +43,6 @@ target/hexagon/gen_semantics.c.  This step produces
 That file is consumed by the following python scripts to produce the indicated
 header files in /target/hexagon
 gen_opcodes_def.py  -> opcodes_def_generated.h.inc
-gen_op_regs.py  -> op_regs_generated.h.inc
 gen_printinsn.py-> printinsn_generated.h.inc
 gen_op_attribs.py   -> op_attribs_generated.h.inc
 gen_helper_protos.py-> helper_protos_generated.h.inc
diff --git a/target/hexagon/gen_op_regs.py b/target/hexagon/gen_op_regs.py
deleted file mode 100755
index 7b7b33895a..00
--- a/target/hexagon/gen_op_regs.py
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/env python3
-
-##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. 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/>.
-##
-
-import sys
-import re
-import string
-import hex_common
-
-
-##
-## Generate the register and immediate operands for each instruction
-##
-def calculate_regid_reg(tag):
-def letter_inc(x):
-return chr(ord(x) + 1)
-
-ordered_implregs = ["SP", "FP", "LR"]
-srcdst_lett = "X"
-src_lett = "S"
-dst_lett = "D"
-retstr = ""
-mapdict = {}
-for reg in ordered_implregs:
-reg_rd = 0
-reg_wr = 0
-if ("A_IMPLICIT_WRITES_" + reg) in hex_common.attribdict[tag]:
-reg_wr = 1
-if reg_rd and reg_wr:
-retstr += srcdst_lett
-mapdict[srcdst_lett] = reg
-srcdst_lett = letter_inc(srcdst_lett)
-elif reg_rd:
-retstr += src_lett
-mapdict[src_lett] = reg
-src_lett = letter_inc(src_lett)
-elif reg_wr:
-retstr += dst_lett
-mapdict[dst_lett] = reg
-dst_lett = letter_inc(dst_lett)
-return retstr, mapdict
-
-
-def calculate_regid_letters(tag):
-retstr, mapdict = calculate_regid_reg(tag)
-return retstr
-
-
-def strip_reg_prefix(x):
-y = x.replace("UREG.", "")
-y = y.replace("MREG.", "")
-return y.replace("GREG.", "")
-
-
-def main():
-hex_common.read_semantics_file(sys.argv[1])
-hex_common.read_attribs_file(sys.argv[2])
-hex_common.init_registers()
-tagregs = hex_common.get_tagregs(full=True)
-tagimms = hex_common.get_tagimms()
-
-with open(sys.argv[3], "w") as f:
-for tag in hex_common.tags:
-regs = tagregs[tag]
-rregs = []
-wregs = []
-regids = ""
-for regtype, regid, _, numregs in regs:
-reg = hex_common.get_register(tag, regtype, regid)
-if reg.is_read():
-if regid[0] not in regids:
-regids += regid[0]
-rregs.append(regtype + regid + numregs)
-if reg.is_written():
-wregs.append(regtype + regid + numregs)
-if regid[0] not in regids:
-regids += regid[0]
-for attrib in hex_common.attribdict[tag]:
-if hex_common.attribinfo[attrib]["rreg"]:
-rregs.append(strip_reg_prefix(attribinfo[attrib]["rreg"]))
-if hex_common.attribinfo[attrib]["wreg"]:
-wregs.append(strip_reg_prefix(attribinfo[attrib]["wreg"]))
-regids += calculate_regid_letters(tag)
-f.write(
-f'REGINFO({tag},"{regids}",\t/*RD:*/\t"{",".join(rregs)}",'
-f'\t/*WR:*/\t"{",".join(wregs)}")\n'
-)
-
-for tag in hex_common.tags:
-i

[PATCH 5/9] Hexagon (tests/tcg/hexagon) Test HVX .new read from high half of pair

2024-02-26 Thread Taylor Simpson
Make sure the decoding of HVX .new is correctly handling this case

Signed-off-by: Taylor Simpson 
---
 tests/tcg/hexagon/hvx_misc.c | 16 +++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c
index b45170acd1..1fe14b5158 100644
--- a/tests/tcg/hexagon/hvx_misc.c
+++ b/tests/tcg/hexagon/hvx_misc.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2021-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2021-2024 Qualcomm Innovation Center, Inc. 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
@@ -231,6 +231,7 @@ static void test_masked_store(bool invert)
 static void test_new_value_store(void)
 {
 void *p0 = buffer0;
+void *p1 = buffer1;
 void *pout = output;
 
 asm("{\n\t"
@@ -242,6 +243,19 @@ static void test_new_value_store(void)
 expect[0] = buffer0[0];
 
 check_output_w(__LINE__, 1);
+
+/* Test the .new read from the high half of a pair */
+asm("v7 = vmem(%0 + #0)\n\t"
+"v12 = vmem(%1 + #0)\n\t"
+"{\n\t"
+"v5:4 = vcombine(v12, v7)\n\t"
+"vmem(%2 + #0) = v5.new\n\t"
+"}\n\t"
+: : "r"(p0), "r"(p1), "r"(pout) : "v4", "v5", "v7", "v12", "memory");
+
+expect[0] = buffer1[0];
+
+check_output_w(__LINE__, 1);
 }
 
 static void test_max_temps()
-- 
2.34.1




[PATCH 8/9] Hexagon (target/hexagon) Remove gen_shortcode.py

2024-02-26 Thread Taylor Simpson
This data structure is not used

Signed-off-by: Taylor Simpson 
---
 target/hexagon/opcodes.c|  7 
 target/hexagon/README   |  1 -
 target/hexagon/gen_shortcode.py | 63 -
 target/hexagon/meson.build  | 10 --
 4 files changed, 81 deletions(-)
 delete mode 100755 target/hexagon/gen_shortcode.py

diff --git a/target/hexagon/opcodes.c b/target/hexagon/opcodes.c
index 02ae9cf787..c8bde2f9e9 100644
--- a/target/hexagon/opcodes.c
+++ b/target/hexagon/opcodes.c
@@ -37,13 +37,6 @@ const char * const opcode_names[] = {
 };
 
 
-const char * const opcode_short_semantics[] = {
-#define DEF_SHORTCODE(TAG, SHORTCODE)  [TAG] = #SHORTCODE,
-#include "shortcode_generated.h.inc"
-#undef DEF_SHORTCODE
-NULL
-};
-
 DECLARE_BITMAP(opcode_attribs[XX_LAST_OPCODE], A_ZZ_LASTATTRIB);
 
 static void init_attribs(int tag, ...)
diff --git a/target/hexagon/README b/target/hexagon/README
index 065c05154d..65b4fcc0fa 100644
--- a/target/hexagon/README
+++ b/target/hexagon/README
@@ -46,7 +46,6 @@ header files in /target/hexagon
 gen_printinsn.py-> printinsn_generated.h.inc
 gen_op_attribs.py   -> op_attribs_generated.h.inc
 gen_helper_protos.py-> helper_protos_generated.h.inc
-gen_shortcode.py-> shortcode_generated.h.inc
 gen_tcg_funcs.py-> tcg_funcs_generated.c.inc
 gen_tcg_func_table.py   -> tcg_func_table_generated.c.inc
 gen_helper_funcs.py -> helper_funcs_generated.c.inc
diff --git a/target/hexagon/gen_shortcode.py b/target/hexagon/gen_shortcode.py
deleted file mode 100755
index deb94446c4..00
--- a/target/hexagon/gen_shortcode.py
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/usr/bin/env python3
-
-##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. 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/>.
-##
-
-import sys
-import re
-import string
-import hex_common
-
-
-def gen_shortcode(f, tag):
-f.write(f"DEF_SHORTCODE({tag}, {hex_common.semdict[tag]})\n")
-
-
-def main():
-hex_common.read_semantics_file(sys.argv[1])
-hex_common.read_attribs_file(sys.argv[2])
-hex_common.calculate_attribs()
-tagregs = hex_common.get_tagregs()
-tagimms = hex_common.get_tagimms()
-
-with open(sys.argv[3], "w") as f:
-f.write("#ifndef DEF_SHORTCODE\n")
-f.write("#define DEF_SHORTCODE(TAG,SHORTCODE)/* Nothing */\n")
-f.write("#endif\n")
-
-for tag in hex_common.tags:
-## Skip the priv instructions
-if "A_PRIV" in hex_common.attribdict[tag]:
-continue
-## Skip the guest instructions
-if "A_GUEST" in hex_common.attribdict[tag]:
-continue
-## Skip the diag instructions
-if tag == "Y6_diag":
-continue
-if tag == "Y6_diag0":
-continue
-if tag == "Y6_diag1":
-continue
-
-gen_shortcode(f, tag)
-
-f.write("#undef DEF_SHORTCODE\n")
-
-
-if __name__ == "__main__":
-main()
diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build
index b3a0944d3b..988e7489ba 100644
--- a/target/hexagon/meson.build
+++ b/target/hexagon/meson.build
@@ -42,21 +42,11 @@ hexagon_ss.add(semantics_generated)
 #
 # Step 2
 # We use Python scripts to generate the following files
-# shortcode_generated.h.inc
 # tcg_func_table_generated.c.inc
 # printinsn_generated.h.inc
 # op_attribs_generated.h.inc
 # opcodes_def_generated.h.inc
 #
-shortcode_generated = custom_target(
-'shortcode_generated.h.inc',
-output: 'shortcode_generated.h.inc',
-depends: [semantics_generated],
-depend_files: [hex_common_py, attribs_def],
-command: [python, files('gen_shortcode.py'), semantics_generated, 
attribs_def, '@OUTPUT@'],
-)
-hexagon_ss.add(shortcode_generated)
-
 tcg_func_table_generated = custom_target(
 'tcg_func_table_generated.c.inc',
 output: 'tcg_func_table_generated.c.inc',
-- 
2.34.1




[PATCH 4/9] Hexagon (target/hexagon) Mark has_pred_dest in trans functions

2024-02-26 Thread Taylor Simpson
Check that the value matches opcode_wregs

Signed-off-by: Taylor Simpson 
---
 target/hexagon/insn.h | 1 +
 target/hexagon/decode.c   | 3 +++
 target/hexagon/gen_trans_funcs.py | 4 
 3 files changed, 8 insertions(+)

diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index a770379958..24dcf7fe9f 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -41,6 +41,7 @@ struct Instruction {
 uint32_t new_value_producer_slot:4;
 int32_t new_read_idx;
 int32_t dest_idx;
+bool has_pred_dest;
 
 bool part1;  /*
   * cmp-jumps are split into two insns.
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index a4d8500fea..84a3899556 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -366,6 +366,9 @@ static void decode_shuffle_for_execution(Packet *packet)
 for (flag = false, i = 0; i < last_insn + 1; i++) {
 int opcode = packet->insn[i].opcode;
 
+g_assert(packet->insn[i].has_pred_dest ==
+ (strstr(opcode_wregs[opcode], "Pd4") ||
+  strstr(opcode_wregs[opcode], "Pe4")));
 if ((strstr(opcode_wregs[opcode], "Pd4") ||
  strstr(opcode_wregs[opcode], "Pe4")) &&
 GET_ATTRIB(opcode, A_STORE) == 0) {
diff --git a/target/hexagon/gen_trans_funcs.py 
b/target/hexagon/gen_trans_funcs.py
index 07292e0170..f1972fd2dd 100755
--- a/target/hexagon/gen_trans_funcs.py
+++ b/target/hexagon/gen_trans_funcs.py
@@ -86,6 +86,7 @@ def gen_trans_funcs(f):
 
 new_read_idx = -1
 dest_idx = -1
+has_pred_dest = "false"
 for regno, regstruct in enumerate(regs):
 reg_type, reg_id, _, _ = regstruct
 reg = hex_common.get_register(tag, reg_type, reg_id)
@@ -96,6 +97,8 @@ def gen_trans_funcs(f):
 new_read_idx = regno
 if reg.is_written() and dest_idx == -1:
 dest_idx = regno
+if reg_type == "P" and not reg.is_read():
+has_pred_dest = "true"
 
 if len(imms) != 0:
 mark_which_imm_extended(f, tag)
@@ -119,6 +122,7 @@ def gen_trans_funcs(f):
 f.write(code_fmt(f"""\
 insn->new_read_idx = {new_read_idx};
 insn->dest_idx = {dest_idx};
+insn->has_pred_dest = {has_pred_dest};
 """))
 f.write(textwrap.dedent(f"""\
 return true;
-- 
2.34.1




[PATCH 1/9] Hexagon (target/hexagon) Add is_old/is_new to Register class

2024-02-26 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/hex_common.py | 14 +-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 195620c7ec..4bacef223f 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -397,10 +397,18 @@ def is_readwrite(self):
 class OldSource(Source):
 def reg_tcg(self):
 return f"{self.regtype}{self.regid}V"
+def is_old(self):
+return True
+def is_new(self):
+return False
 
 class NewSource(Source):
 def reg_tcg(self):
 return f"{self.regtype}{self.regid}N"
+def is_old(self):
+return False
+def is_new(self):
+return True
 
 class ReadWrite:
 def reg_tcg(self):
@@ -413,6 +421,10 @@ def is_read(self):
 return True
 def is_readwrite(self):
 return True
+def is_old(self):
+return True
+def is_new(self):
+return False
 
 class GprDest(Register, Single, Dest):
 def decl_tcg(self, f, tag, regno):
-- 
2.34.1




[PATCH 3/9] Hexagon (target/hexagon) Mark dest_idx in trans functions

2024-02-26 Thread Taylor Simpson
Check that the value matches opcode_reginfo/opcode_wregs

Signed-off-by: Taylor Simpson 
---
 target/hexagon/insn.h   | 1 +
 target/hexagon/decode.c | 2 ++
 target/hexagon/mmvec/decode_ext_mmvec.c | 2 ++
 target/hexagon/gen_trans_funcs.py   | 4 
 4 files changed, 9 insertions(+)

diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index 36502bf056..a770379958 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -40,6 +40,7 @@ struct Instruction {
 uint32_t which_extended:1;/* If has an extender, which immediate */
 uint32_t new_value_producer_slot:4;
 int32_t new_read_idx;
+int32_t dest_idx;
 
 bool part1;  /*
   * cmp-jumps are split into two insns.
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 4595e30384..a4d8500fea 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -184,6 +184,8 @@ decode_fill_newvalue_regno(Packet *packet)
 
 /* Now patch up the consumer with the register number */
 dst_idx = dststr - opcode_reginfo[def_opcode];
+g_assert(packet->insn[def_idx].dest_idx != -1 &&
+ packet->insn[def_idx].dest_idx == dst_idx);
 packet->insn[i].regno[use_regidx] =
 packet->insn[def_idx].regno[dst_idx];
 /*
diff --git a/target/hexagon/mmvec/decode_ext_mmvec.c 
b/target/hexagon/mmvec/decode_ext_mmvec.c
index e9007f5d71..c1320406df 100644
--- a/target/hexagon/mmvec/decode_ext_mmvec.c
+++ b/target/hexagon/mmvec/decode_ext_mmvec.c
@@ -86,6 +86,8 @@ check_new_value(Packet *pkt)
 /* still not there, we have a bad packet */
 g_assert_not_reached();
 }
+g_assert(pkt->insn[def_idx].dest_idx != -1 &&
+ pkt->insn[def_idx].dest_idx == dststr - reginfo);
 int def_regnum = pkt->insn[def_idx].regno[dststr - reginfo];
 /* Now patch up the consumer with the register number */
 pkt->insn[i].regno[use_regidx] = def_regnum ^ def_oreg;
diff --git a/target/hexagon/gen_trans_funcs.py 
b/target/hexagon/gen_trans_funcs.py
index 79475b2946..07292e0170 100755
--- a/target/hexagon/gen_trans_funcs.py
+++ b/target/hexagon/gen_trans_funcs.py
@@ -85,6 +85,7 @@ def gen_trans_funcs(f):
 """))
 
 new_read_idx = -1
+dest_idx = -1
 for regno, regstruct in enumerate(regs):
 reg_type, reg_id, _, _ = regstruct
 reg = hex_common.get_register(tag, reg_type, reg_id)
@@ -93,6 +94,8 @@ def gen_trans_funcs(f):
 """))
 if reg.is_read() and reg.is_new():
 new_read_idx = regno
+if reg.is_written() and dest_idx == -1:
+dest_idx = regno
 
 if len(imms) != 0:
 mark_which_imm_extended(f, tag)
@@ -115,6 +118,7 @@ def gen_trans_funcs(f):
 
 f.write(code_fmt(f"""\
 insn->new_read_idx = {new_read_idx};
+insn->dest_idx = {dest_idx};
 """))
 f.write(textwrap.dedent(f"""\
 return true;
-- 
2.34.1




[PATCH 9/9] Hexagon (target/hexagon) Remove hex_common.read_attribs_file

2024-02-26 Thread Taylor Simpson
The attribinfo data structure is not used
Adjust the command-line arguments to the python scripts
Add hex_common.read_common_files for TCG/helper generation scripts

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_analyze_funcs.py | 21 ++-
 target/hexagon/gen_helper_funcs.py  | 21 ++-
 target/hexagon/gen_helper_protos.py | 21 ++-
 target/hexagon/gen_idef_parser_funcs.py |  5 ++--
 target/hexagon/gen_op_attribs.py|  5 ++--
 target/hexagon/gen_opcodes_def.py   |  4 +--
 target/hexagon/gen_printinsn.py |  5 ++--
 target/hexagon/gen_tcg_func_table.py|  5 ++--
 target/hexagon/gen_tcg_funcs.py | 21 ++-
 target/hexagon/hex_common.py| 35 +++--
 target/hexagon/meson.build  | 31 +++---
 11 files changed, 54 insertions(+), 120 deletions(-)

diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index a9af666cef..b73b4e2349 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2022-2024 Qualcomm Innovation Center, Inc. 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
@@ -67,24 +67,7 @@ def gen_analyze_func(f, tag, regs, imms):
 
 
 def main():
-hex_common.read_semantics_file(sys.argv[1])
-hex_common.read_attribs_file(sys.argv[2])
-hex_common.read_overrides_file(sys.argv[3])
-hex_common.read_overrides_file(sys.argv[4])
-## Whether or not idef-parser is enabled is
-## determined by the number of arguments to
-## this script:
-##
-##   5 args. -> not enabled,
-##   6 args. -> idef-parser enabled.
-##
-## The 6:th arg. then holds a list of the successfully
-## parsed instructions.
-is_idef_parser_enabled = len(sys.argv) > 6
-if is_idef_parser_enabled:
-hex_common.read_idef_parser_enabled_file(sys.argv[5])
-hex_common.calculate_attribs()
-hex_common.init_registers()
+hex_common.read_common_files()
 tagregs = hex_common.get_tagregs()
 tagimms = hex_common.get_tagimms()
 
diff --git a/target/hexagon/gen_helper_funcs.py 
b/target/hexagon/gen_helper_funcs.py
index 9cc3d69c49..e9685bff2f 100755
--- a/target/hexagon/gen_helper_funcs.py
+++ b/target/hexagon/gen_helper_funcs.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -102,24 +102,7 @@ def gen_helper_function(f, tag, tagregs, tagimms):
 
 
 def main():
-hex_common.read_semantics_file(sys.argv[1])
-hex_common.read_attribs_file(sys.argv[2])
-hex_common.read_overrides_file(sys.argv[3])
-hex_common.read_overrides_file(sys.argv[4])
-## Whether or not idef-parser is enabled is
-## determined by the number of arguments to
-## this script:
-##
-##   5 args. -> not enabled,
-##   6 args. -> idef-parser enabled.
-##
-## The 6:th arg. then holds a list of the successfully
-## parsed instructions.
-is_idef_parser_enabled = len(sys.argv) > 6
-if is_idef_parser_enabled:
-hex_common.read_idef_parser_enabled_file(sys.argv[5])
-hex_common.calculate_attribs()
-hex_common.init_registers()
+hex_common.read_common_files()
 tagregs = hex_common.get_tagregs()
 tagimms = hex_common.get_tagimms()
 
diff --git a/target/hexagon/gen_helper_protos.py 
b/target/hexagon/gen_helper_protos.py
index c82b0f54e4..4cc72a1581 100755
--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -44,24 +44,7 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
 
 
 def main():
-hex_common.read_semantics_file(sys.argv[1])
-hex_common.read_attribs_file(sys.argv[2])
-hex_common.read_overrides_file(sys.argv[3])
-hex_common.read_overrides_file(sys.argv[4])
-## Whether or not idef-parser is enabled is
-## determined by the number of arguments to
-## this script:
-##
-##   5 args. -> not enabled,
-##   6 args. -> idef-parser enabled.
-##
-## The 6:th arg. then holds a list of the suc

[PATCH 0/9] Hexagon (target/hexagon) Clean up .new decode and scripts

2024-02-26 Thread Taylor Simpson
During .new decode, there are several places where strchr is used.
We remove these by generating the values that are needed.

Once we have generated the proper values, we no longer need
op_regs_generated.h.inc.  We remove the script that generates it as
well as the code in meson.build

We also remove the script and meson.build code that creates
shortcode_generated.h.inc.  The data structure that includes it is
not used.

We remove hex_common.read_attribs_file.  The Python data structures built
during this step are not used.


Taylor Simpson (9):
  Hexagon (target/hexagon) Add is_old/is_new to Register class
  Hexagon (target/hexagon) Mark new_read_idx in trans functions
  Hexagon (target/hexagon) Mark dest_idx in trans functions
  Hexagon (target/hexagon) Mark has_pred_dest in trans functions
  Hexagon (tests/tcg/hexagon) Test HVX .new read from high half of pair
  Hexagon (target/hexagon) Remove uses of op_regs_generated.h.inc
  Hexagon (target/hexagon) Remove gen_op_regs.py
  Hexagon (target/hexagon) Remove gen_shortcode.py
  Hexagon (target/hexagon) Remove hex_common.read_attribs_file

 target/hexagon/insn.h   |   5 +-
 target/hexagon/opcodes.h|   4 -
 target/hexagon/decode.c |  50 ++
 target/hexagon/mmvec/decode_ext_mmvec.c |  30 ++
 target/hexagon/opcodes.c|  35 ---
 tests/tcg/hexagon/hvx_misc.c|  16 ++-
 target/hexagon/README   |   2 -
 target/hexagon/gen_analyze_funcs.py |  21 +---
 target/hexagon/gen_helper_funcs.py  |  21 +---
 target/hexagon/gen_helper_protos.py |  21 +---
 target/hexagon/gen_idef_parser_funcs.py |   5 +-
 target/hexagon/gen_op_attribs.py|   5 +-
 target/hexagon/gen_op_regs.py   | 125 
 target/hexagon/gen_opcodes_def.py   |   4 +-
 target/hexagon/gen_printinsn.py |   5 +-
 target/hexagon/gen_shortcode.py |  63 
 target/hexagon/gen_tcg_func_table.py|   5 +-
 target/hexagon/gen_tcg_funcs.py |  21 +---
 target/hexagon/gen_trans_funcs.py   |  23 -
 target/hexagon/hex_common.py|  49 +++---
 target/hexagon/meson.build  |  55 ---
 21 files changed, 119 insertions(+), 446 deletions(-)
 delete mode 100755 target/hexagon/gen_op_regs.py
 delete mode 100755 target/hexagon/gen_shortcode.py

-- 
2.34.1




[PATCH 7/9] Hexagon (target/hexagon) Remove gen_op_regs.py

2024-02-26 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/README |   1 -
 target/hexagon/gen_op_regs.py | 125 --
 target/hexagon/meson.build|  14 +---
 3 files changed, 2 insertions(+), 138 deletions(-)
 delete mode 100755 target/hexagon/gen_op_regs.py

diff --git a/target/hexagon/README b/target/hexagon/README
index 746ebec378..065c05154d 100644
--- a/target/hexagon/README
+++ b/target/hexagon/README
@@ -43,7 +43,6 @@ target/hexagon/gen_semantics.c.  This step produces
 That file is consumed by the following python scripts to produce the indicated
 header files in /target/hexagon
 gen_opcodes_def.py  -> opcodes_def_generated.h.inc
-gen_op_regs.py  -> op_regs_generated.h.inc
 gen_printinsn.py-> printinsn_generated.h.inc
 gen_op_attribs.py   -> op_attribs_generated.h.inc
 gen_helper_protos.py-> helper_protos_generated.h.inc
diff --git a/target/hexagon/gen_op_regs.py b/target/hexagon/gen_op_regs.py
deleted file mode 100755
index 7b7b33895a..00
--- a/target/hexagon/gen_op_regs.py
+++ /dev/null
@@ -1,125 +0,0 @@
-#!/usr/bin/env python3
-
-##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. 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/>.
-##
-
-import sys
-import re
-import string
-import hex_common
-
-
-##
-## Generate the register and immediate operands for each instruction
-##
-def calculate_regid_reg(tag):
-def letter_inc(x):
-return chr(ord(x) + 1)
-
-ordered_implregs = ["SP", "FP", "LR"]
-srcdst_lett = "X"
-src_lett = "S"
-dst_lett = "D"
-retstr = ""
-mapdict = {}
-for reg in ordered_implregs:
-reg_rd = 0
-reg_wr = 0
-if ("A_IMPLICIT_WRITES_" + reg) in hex_common.attribdict[tag]:
-reg_wr = 1
-if reg_rd and reg_wr:
-retstr += srcdst_lett
-mapdict[srcdst_lett] = reg
-srcdst_lett = letter_inc(srcdst_lett)
-elif reg_rd:
-retstr += src_lett
-mapdict[src_lett] = reg
-src_lett = letter_inc(src_lett)
-elif reg_wr:
-retstr += dst_lett
-mapdict[dst_lett] = reg
-dst_lett = letter_inc(dst_lett)
-return retstr, mapdict
-
-
-def calculate_regid_letters(tag):
-retstr, mapdict = calculate_regid_reg(tag)
-return retstr
-
-
-def strip_reg_prefix(x):
-y = x.replace("UREG.", "")
-y = y.replace("MREG.", "")
-return y.replace("GREG.", "")
-
-
-def main():
-hex_common.read_semantics_file(sys.argv[1])
-hex_common.read_attribs_file(sys.argv[2])
-hex_common.init_registers()
-tagregs = hex_common.get_tagregs(full=True)
-tagimms = hex_common.get_tagimms()
-
-with open(sys.argv[3], "w") as f:
-for tag in hex_common.tags:
-regs = tagregs[tag]
-rregs = []
-wregs = []
-regids = ""
-for regtype, regid, _, numregs in regs:
-reg = hex_common.get_register(tag, regtype, regid)
-if reg.is_read():
-if regid[0] not in regids:
-regids += regid[0]
-rregs.append(regtype + regid + numregs)
-if reg.is_written():
-wregs.append(regtype + regid + numregs)
-if regid[0] not in regids:
-regids += regid[0]
-for attrib in hex_common.attribdict[tag]:
-if hex_common.attribinfo[attrib]["rreg"]:
-rregs.append(strip_reg_prefix(attribinfo[attrib]["rreg"]))
-if hex_common.attribinfo[attrib]["wreg"]:
-wregs.append(strip_reg_prefix(attribinfo[attrib]["wreg"]))
-regids += calculate_regid_letters(tag)
-f.write(
-f'REGINFO({tag},"{regids}",\t/*RD:*/\t"{",".join(rregs)}",'
-f'\t/*WR:*/\t"{",".join(wregs)}")\n'
-)
-
-for tag in hex_common.tags:
-i

[PATCH 6/9] Hexagon (target/hexagon) Remove uses of op_regs_generated.h.inc

2024-02-26 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/opcodes.h|  4 --
 target/hexagon/decode.c | 57 +++--
 target/hexagon/mmvec/decode_ext_mmvec.c | 34 +++
 target/hexagon/opcodes.c| 28 
 4 files changed, 13 insertions(+), 110 deletions(-)

diff --git a/target/hexagon/opcodes.h b/target/hexagon/opcodes.h
index fa7e321950..0ee11bd445 100644
--- a/target/hexagon/opcodes.h
+++ b/target/hexagon/opcodes.h
@@ -40,10 +40,6 @@ typedef enum {
 
 extern const char * const opcode_names[];
 
-extern const char * const opcode_reginfo[];
-extern const char * const opcode_rregs[];
-extern const char * const opcode_wregs[];
-
 typedef struct {
 const char * const encoding;
 const EncClass enc_class;
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 84a3899556..23deba2426 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -115,24 +115,13 @@ static void
 decode_fill_newvalue_regno(Packet *packet)
 {
 int i, use_regidx, offset, def_idx, dst_idx;
-uint16_t def_opcode, use_opcode;
-char *dststr;
 
 for (i = 1; i < packet->num_insns; i++) {
 if (GET_ATTRIB(packet->insn[i].opcode, A_DOTNEWVALUE) &&
 !GET_ATTRIB(packet->insn[i].opcode, A_EXTENSION)) {
-use_opcode = packet->insn[i].opcode;
-
-/* It's a store, so we're adjusting the Nt field */
-if (GET_ATTRIB(use_opcode, A_STORE)) {
-use_regidx = strchr(opcode_reginfo[use_opcode], 't') -
-opcode_reginfo[use_opcode];
-} else {/* It's a Jump, so we're adjusting the Ns field */
-use_regidx = strchr(opcode_reginfo[use_opcode], 's') -
-opcode_reginfo[use_opcode];
-}
-g_assert(packet->insn[i].new_read_idx != -1 &&
- packet->insn[i].new_read_idx == use_regidx);
+
+g_assert(packet->insn[i].new_read_idx != -1);
+use_regidx = packet->insn[i].new_read_idx;
 
 /*
  * What's encoded at the N-field is the offset to who's producing
@@ -153,39 +142,9 @@ decode_fill_newvalue_regno(Packet *packet)
  */
 g_assert(!((def_idx < 0) || (def_idx > (packet->num_insns - 1;
 
-/*
- * packet->insn[def_idx] is the producer
- * Figure out which type of destination it produces
- * and the corresponding index in the reginfo
- */
-def_opcode = packet->insn[def_idx].opcode;
-dststr = strstr(opcode_wregs[def_opcode], "Rd");
-if (dststr) {
-dststr = strchr(opcode_reginfo[def_opcode], 'd');
-} else {
-dststr = strstr(opcode_wregs[def_opcode], "Rx");
-if (dststr) {
-dststr = strchr(opcode_reginfo[def_opcode], 'x');
-} else {
-dststr = strstr(opcode_wregs[def_opcode], "Re");
-if (dststr) {
-dststr = strchr(opcode_reginfo[def_opcode], 'e');
-} else {
-dststr = strstr(opcode_wregs[def_opcode], "Ry");
-if (dststr) {
-dststr = strchr(opcode_reginfo[def_opcode], 'y');
-} else {
-g_assert_not_reached();
-}
-}
-}
-}
-g_assert(dststr != NULL);
-
 /* Now patch up the consumer with the register number */
-dst_idx = dststr - opcode_reginfo[def_opcode];
-g_assert(packet->insn[def_idx].dest_idx != -1 &&
- packet->insn[def_idx].dest_idx == dst_idx);
+g_assert(packet->insn[def_idx].dest_idx != -1);
+dst_idx = packet->insn[def_idx].dest_idx;
 packet->insn[i].regno[use_regidx] =
 packet->insn[def_idx].regno[dst_idx];
 /*
@@ -366,11 +325,7 @@ static void decode_shuffle_for_execution(Packet *packet)
 for (flag = false, i = 0; i < last_insn + 1; i++) {
 int opcode = packet->insn[i].opcode;
 
-g_assert(packet->insn[i].has_pred_dest ==
- (strstr(opcode_wregs[opcode], "Pd4") ||
-  strstr(opcode_wregs[opcode], "Pe4")));
-if ((strstr(opcode_wregs[opcode], "Pd4") ||
- strstr(opcode_wregs[opcode], "Pe4")) &&
+if (packet->insn[i].has_pred_dest &&
 GET_ATTRIB(opcode, A_STORE) == 0) {
 /* This should be a compare (not a store conditional) */
 if (flag) {
diff --git a/target/hexagon/mmvec/decode_

[PATCH 2/9] Hexagon (target/hexagon) Mark new_read_idx in trans functions

2024-02-26 Thread Taylor Simpson
Check that the value matches opcode_reginfo

Signed-off-by: Taylor Simpson 
---
 target/hexagon/insn.h   |  3 ++-
 target/hexagon/decode.c |  2 ++
 target/hexagon/mmvec/decode_ext_mmvec.c |  2 ++
 target/hexagon/gen_trans_funcs.py   | 15 ++-
 4 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index 3e7a22c91e..36502bf056 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -39,6 +39,7 @@ struct Instruction {
 uint32_t slot:3;
 uint32_t which_extended:1;/* If has an extender, which immediate */
 uint32_t new_value_producer_slot:4;
+int32_t new_read_idx;
 
 bool part1;  /*
   * cmp-jumps are split into two insns.
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index a40210ca1e..4595e30384 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -131,6 +131,8 @@ decode_fill_newvalue_regno(Packet *packet)
 use_regidx = strchr(opcode_reginfo[use_opcode], 's') -
 opcode_reginfo[use_opcode];
 }
+g_assert(packet->insn[i].new_read_idx != -1 &&
+ packet->insn[i].new_read_idx == use_regidx);
 
 /*
  * What's encoded at the N-field is the offset to who's producing
diff --git a/target/hexagon/mmvec/decode_ext_mmvec.c 
b/target/hexagon/mmvec/decode_ext_mmvec.c
index 202d84c7c0..e9007f5d71 100644
--- a/target/hexagon/mmvec/decode_ext_mmvec.c
+++ b/target/hexagon/mmvec/decode_ext_mmvec.c
@@ -41,6 +41,8 @@ check_new_value(Packet *pkt)
 GET_ATTRIB(use_opcode, A_STORE)) {
 int use_regidx = strchr(opcode_reginfo[use_opcode], 's') -
 opcode_reginfo[use_opcode];
+g_assert(pkt->insn[i].new_read_idx != -1 &&
+ pkt->insn[i].new_read_idx == use_regidx);
 /*
  * What's encoded at the N-field is the offset to who's producing
  * the value.
diff --git a/target/hexagon/gen_trans_funcs.py 
b/target/hexagon/gen_trans_funcs.py
index 53e844a44b..79475b2946 100755
--- a/target/hexagon/gen_trans_funcs.py
+++ b/target/hexagon/gen_trans_funcs.py
@@ -84,14 +84,15 @@ def gen_trans_funcs(f):
 insn->opcode = {tag};
 """))
 
-regno = 0
-for reg in regs:
-reg_type = reg[0]
-reg_id = reg[1]
+new_read_idx = -1
+for regno, regstruct in enumerate(regs):
+reg_type, reg_id, _, _ = regstruct
+reg = hex_common.get_register(tag, reg_type, reg_id)
 f.write(code_fmt(f"""\
 insn->regno[{regno}] = args->{reg_type}{reg_id};
 """))
-regno += 1
+if reg.is_read() and reg.is_new():
+new_read_idx = regno
 
 if len(imms) != 0:
 mark_which_imm_extended(f, tag)
@@ -112,6 +113,9 @@ def gen_trans_funcs(f):
 insn->immed[{immno}] = args->{imm_type}{imm_letter};
 """))
 
+f.write(code_fmt(f"""\
+insn->new_read_idx = {new_read_idx};
+"""))
 f.write(textwrap.dedent(f"""\
 return true;
 {close_curly}
@@ -120,5 +124,6 @@ def gen_trans_funcs(f):
 
 if __name__ == "__main__":
 hex_common.read_semantics_file(sys.argv[1])
+hex_common.init_registers()
 with open(sys.argv[2], "w") as f:
 gen_trans_funcs(f)
-- 
2.34.1




[PATCH v3 1/3] Hexagon (target/hexagon) Pass P0 explicitly to helpers that need it

2024-02-13 Thread Taylor Simpson
Rather than reading P0 from the env, pass it explicitly

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Tested-by: Anton Johansson 
---
 target/hexagon/macros.h  |  4 ++--
 target/hexagon/hex_common.py | 12 +++-
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 1376d6ccc1..aedc863fab 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -358,7 +358,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int 
shift)
 #endif
 #define fREAD_PC() (PC)
 
-#define fREAD_P0() (env->pred[0])
+#define fREAD_P0() (P0)
 
 #define fCHECK_PCALIGN(A)
 
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 195620c7ec..14dcf261b4 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -197,6 +197,10 @@ def get_tagimms():
 return dict(zip(tags, list(map(compute_tag_immediates, tags
 
 
+def need_p0(tag):
+return "A_IMPLICIT_READS_P0" in attribdict[tag]
+
+
 def need_slot(tag):
 if (
 "A_CVI_SCATTER" not in attribdict[tag]
@@ -1118,6 +1122,12 @@ def helper_args(tag, regs, imms):
 "tcg_constant_tl(ctx->next_PC)",
 "target_ulong next_PC"
 ))
+if need_p0(tag):
+args.append(HelperArg(
+"i32",
+"hex_pred[0]",
+"uint32_t P0"
+))
 if need_slot(tag):
 args.append(HelperArg(
 "i32",
-- 
2.34.1




[PATCH v3 0/3] Hexagon (target/hexagon) Only pass env to generated helper when needed

2024-02-13 Thread Taylor Simpson
Currently, we pass env to every generated helper.  When the semantics of
the instruction only depend on the arguments, this is unnecessary and
adds extra overhead to the helper call.

 Changes in v3 
Update copyright year to 2024
Mark Reviewed-by/Tested-by: Anton Johansson 

 Changes in v2 
- Separate patches to pass P0 and SP explicitly to helpers that need it
- Add the TCG_CALL_NO_RWG_SE flag to any non-HVX helpers that
  don't get ptr to env


Taylor Simpson (3):
  Hexagon (target/hexagon) Pass P0 explicitly to helpers that need it
  Hexagon (target/hexagon) Pass SP explicitly to helpers that need it
  Hexagon (target/hexagon) Only pass env to generated helper when needed

 target/hexagon/gen_tcg.h|  5 +++-
 target/hexagon/macros.h |  6 ++--
 target/hexagon/attribs_def.h.inc|  3 +-
 target/hexagon/gen_helper_protos.py | 12 ++--
 target/hexagon/hex_common.py| 46 +
 5 files changed, 59 insertions(+), 13 deletions(-)

-- 
2.34.1




[PATCH v3 2/3] Hexagon (target/hexagon) Pass SP explicitly to helpers that need it

2024-02-13 Thread Taylor Simpson
Rather than reading SP from the env, pass it explicitly

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Tested-by: Anton Johansson 
---
 target/hexagon/macros.h  |  2 +-
 target/hexagon/attribs_def.h.inc |  3 ++-
 target/hexagon/hex_common.py | 11 +++
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index aedc863fab..feb798c6c0 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -343,7 +343,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int 
shift)
 
 #define fREAD_LR() (env->gpr[HEX_REG_LR])
 
-#define fREAD_SP() (env->gpr[HEX_REG_SP])
+#define fREAD_SP() (SP)
 #define fREAD_LC0 (env->gpr[HEX_REG_LC0])
 #define fREAD_LC1 (env->gpr[HEX_REG_LC1])
 #define fREAD_SA0 (env->gpr[HEX_REG_SA0])
diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 87942d46f4..9e3a05f882 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -117,6 +117,7 @@ DEF_ATTRIB(IMPLICIT_READS_P1, "Reads the P1 register", "", 
"")
 DEF_ATTRIB(IMPLICIT_READS_P2, "Reads the P2 register", "", "")
 DEF_ATTRIB(IMPLICIT_READS_P3, "Reads the P3 register", "", "")
 DEF_ATTRIB(IMPLICIT_WRITES_USR, "May write USR", "", "")
+DEF_ATTRIB(IMPLICIT_READS_SP, "Reads the SP register", "", "")
 DEF_ATTRIB(COMMUTES, "The operation is communitive", "", "")
 DEF_ATTRIB(DEALLOCRET, "dealloc_return", "", "")
 DEF_ATTRIB(DEALLOCFRAME, "deallocframe", "", "")
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 14dcf261b4..b96f67972d 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -101,6 +101,7 @@ def calculate_attribs():
 add_qemu_macro_attrib('fLSBNEW1', 'A_IMPLICIT_READS_P1')
 add_qemu_macro_attrib('fLSBNEW1NOT', 'A_IMPLICIT_READS_P1')
 add_qemu_macro_attrib('fREAD_P3', 'A_IMPLICIT_READS_P3')
+add_qemu_macro_attrib('fREAD_SP', 'A_IMPLICIT_READS_SP')
 
 # Recurse down macros, find attributes from sub-macros
 macroValues = list(macros.values())
@@ -201,6 +202,10 @@ def need_p0(tag):
 return "A_IMPLICIT_READS_P0" in attribdict[tag]
 
 
+def need_sp(tag):
+return "A_IMPLICIT_READS_SP" in attribdict[tag]
+
+
 def need_slot(tag):
 if (
 "A_CVI_SCATTER" not in attribdict[tag]
@@ -1128,6 +1133,12 @@ def helper_args(tag, regs, imms):
 "hex_pred[0]",
 "uint32_t P0"
 ))
+if need_sp(tag):
+args.append(HelperArg(
+"i32",
+"hex_gpr[HEX_REG_SP]",
+"uint32_t SP"
+))
 if need_slot(tag):
 args.append(HelperArg(
 "i32",
-- 
2.34.1




[PATCH v3 3/3] Hexagon (target/hexagon) Only pass env to generated helper when needed

2024-02-13 Thread Taylor Simpson
Currently, we pass env to every generated helper.  When the semantics of
the instruction only depend on the arguments, this is unnecessary and
adds extra overhead to the helper call.

We add the TCG_CALL_NO_RWG_SE flag to any non-HVX helpers that don't get
the ptr to env.

The A2_nop and SA1_setin1 instructions end up with no arguments.  This
results in a "old-style function definition" error from the compiler, so
we write overrides for them.

With this change, the number of helpers with env argument is
idef-parser enabled:329 total, 23 with env
idef-parser disabled:   1543 total, 550 with env

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Tested-by: Anton Johansson 
---
 target/hexagon/gen_tcg.h|  5 -
 target/hexagon/gen_helper_protos.py | 12 ++--
 target/hexagon/hex_common.py| 23 ++-
 3 files changed, 32 insertions(+), 8 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 1c4391b415..3fc1f4e281 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -1369,3 +1369,6 @@
 gen_helper_raise_exception(tcg_env, excp); \
 } while (0)
 #endif
+
+#define fGEN_TCG_A2_nop(SHORTCODE) do { } while (0)
+#define fGEN_TCG_SA1_setin1(SHORTCODE) tcg_gen_movi_tl(RdV, -1)
diff --git a/target/hexagon/gen_helper_protos.py 
b/target/hexagon/gen_helper_protos.py
index c82b0f54e4..f8578d5033 100755
--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -40,7 +40,15 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
 declared.append(arg.proto_arg)
 
 arguments = ", ".join(declared)
-f.write(f"DEF_HELPER_{len(declared) - 1}({tag}, {arguments})\n")
+
+## Add the TCG_CALL_NO_RWG_SE flag to helpers that don't take the env
+## argument and aren't HVX instructions.  Since HVX instructions take
+## pointers to their arguments, they will have side effects.
+if hex_common.need_env(tag) or hex_common.is_hvx_insn(tag):
+f.write(f"DEF_HELPER_{len(declared) - 1}({tag}, {arguments})\n")
+else:
+f.write(f"DEF_HELPER_FLAGS_{len(declared) - 1}({tag}, "
+f"TCG_CALL_NO_RWG_SE, {arguments})\n")
 
 
 def main():
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index b96f67972d..d3d8560fcf 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -206,6 +206,18 @@ def need_sp(tag):
 return "A_IMPLICIT_READS_SP" in attribdict[tag]
 
 
+def is_hvx_insn(tag):
+return "A_CVI" in attribdict[tag]
+
+
+def need_env(tag):
+return ("A_STORE" in attribdict[tag] or
+"A_LOAD" in attribdict[tag] or
+"A_CVI_GATHER" in attribdict[tag] or
+"A_CVI_SCATTER" in attribdict[tag] or
+"A_IMPLICIT_WRITES_USR" in attribdict[tag])
+
+
 def need_slot(tag):
 if (
 "A_CVI_SCATTER" not in attribdict[tag]
@@ -1069,11 +1081,12 @@ def helper_args(tag, regs, imms):
 args = []
 
 ## First argument is the CPU state
-args.append(HelperArg(
-"env",
-"tcg_env",
-"CPUHexagonState *env"
-))
+if need_env(tag):
+args.append(HelperArg(
+"env",
+"tcg_env",
+"CPUHexagonState *env"
+))
 
 ## For predicated instructions, we pass in the destination register
 if is_predicated(tag):
-- 
2.34.1




[PATCH v2 1/3] Hexagon (target/hexagon) Pass P0 explicitly to helpers that need it

2024-02-05 Thread Taylor Simpson
Rather than reading P0 from the env, pass it explicitly

Signed-off-by: Taylor Simpson 
---
 target/hexagon/macros.h  |  2 +-
 target/hexagon/hex_common.py | 10 ++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 1376d6ccc1..9c700ce8ef 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -358,7 +358,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int 
shift)
 #endif
 #define fREAD_PC() (PC)
 
-#define fREAD_P0() (env->pred[0])
+#define fREAD_P0() (P0)
 
 #define fCHECK_PCALIGN(A)
 
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 195620c7ec..2dbd0ea737 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -197,6 +197,10 @@ def get_tagimms():
 return dict(zip(tags, list(map(compute_tag_immediates, tags
 
 
+def need_p0(tag):
+return "A_IMPLICIT_READS_P0" in attribdict[tag]
+
+
 def need_slot(tag):
 if (
 "A_CVI_SCATTER" not in attribdict[tag]
@@ -1118,6 +1122,12 @@ def helper_args(tag, regs, imms):
 "tcg_constant_tl(ctx->next_PC)",
 "target_ulong next_PC"
 ))
+if need_p0(tag):
+args.append(HelperArg(
+"i32",
+"hex_pred[0]",
+"uint32_t P0"
+))
 if need_slot(tag):
 args.append(HelperArg(
 "i32",
-- 
2.34.1




[PATCH v2 2/3] Hexagon (target/hexagon) Pass SP explicitly to helpers that need it

2024-02-05 Thread Taylor Simpson
Rather than reading SP from the env, pass it explicitly

Signed-off-by: Taylor Simpson 
---
 target/hexagon/macros.h  |  2 +-
 target/hexagon/attribs_def.h.inc |  1 +
 target/hexagon/hex_common.py | 11 +++
 3 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 9c700ce8ef..4b8665a9da 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -343,7 +343,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int 
shift)
 
 #define fREAD_LR() (env->gpr[HEX_REG_LR])
 
-#define fREAD_SP() (env->gpr[HEX_REG_SP])
+#define fREAD_SP() (SP)
 #define fREAD_LC0 (env->gpr[HEX_REG_LC0])
 #define fREAD_LC1 (env->gpr[HEX_REG_LC1])
 #define fREAD_SA0 (env->gpr[HEX_REG_SA0])
diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 87942d46f4..8949ee09cf 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -117,6 +117,7 @@ DEF_ATTRIB(IMPLICIT_READS_P1, "Reads the P1 register", "", 
"")
 DEF_ATTRIB(IMPLICIT_READS_P2, "Reads the P2 register", "", "")
 DEF_ATTRIB(IMPLICIT_READS_P3, "Reads the P3 register", "", "")
 DEF_ATTRIB(IMPLICIT_WRITES_USR, "May write USR", "", "")
+DEF_ATTRIB(IMPLICIT_READS_SP, "Reads the SP register", "", "")
 DEF_ATTRIB(COMMUTES, "The operation is communitive", "", "")
 DEF_ATTRIB(DEALLOCRET, "dealloc_return", "", "")
 DEF_ATTRIB(DEALLOCFRAME, "deallocframe", "", "")
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 2dbd0ea737..eb28aa98fe 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -101,6 +101,7 @@ def calculate_attribs():
 add_qemu_macro_attrib('fLSBNEW1', 'A_IMPLICIT_READS_P1')
 add_qemu_macro_attrib('fLSBNEW1NOT', 'A_IMPLICIT_READS_P1')
 add_qemu_macro_attrib('fREAD_P3', 'A_IMPLICIT_READS_P3')
+add_qemu_macro_attrib('fREAD_SP', 'A_IMPLICIT_READS_SP')
 
 # Recurse down macros, find attributes from sub-macros
 macroValues = list(macros.values())
@@ -201,6 +202,10 @@ def need_p0(tag):
 return "A_IMPLICIT_READS_P0" in attribdict[tag]
 
 
+def need_sp(tag):
+return "A_IMPLICIT_READS_SP" in attribdict[tag]
+
+
 def need_slot(tag):
 if (
 "A_CVI_SCATTER" not in attribdict[tag]
@@ -1128,6 +1133,12 @@ def helper_args(tag, regs, imms):
 "hex_pred[0]",
 "uint32_t P0"
 ))
+if need_sp(tag):
+args.append(HelperArg(
+"i32",
+"hex_gpr[HEX_REG_SP]",
+"uint32_t SP"
+))
 if need_slot(tag):
 args.append(HelperArg(
 "i32",
-- 
2.34.1




[PATCH v2 3/3] Hexagon (target/hexagon) Only pass env to generated helper when needed

2024-02-05 Thread Taylor Simpson
Currently, we pass env to every generated helper.  When the semantics of
the instruction only depend on the arguments, this is unnecessary and
adds extra overhead to the helper call.

We add the TCG_CALL_NO_RWG_SE flag to any non-HVX helpers that don't get
the ptr to env.

The A2_nop and SA1_setin1 instructions end up with no arguments.  This
results in a "old-style function definition" error from the compiler, so
we write overrides for them.

With this change, the number of helpers with env argument is
idef-parser enabled:329 total, 23 with env
idef-parser disabled:   1543 total, 550 with env

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_tcg.h|  3 +++
 target/hexagon/gen_helper_protos.py | 10 +-
 target/hexagon/hex_common.py| 23 ++-
 3 files changed, 30 insertions(+), 6 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 1c4391b415..e9ac2e3fe0 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1369,3 +1369,6 @@
 gen_helper_raise_exception(tcg_env, excp); \
 } while (0)
 #endif
+
+#define fGEN_TCG_A2_nop(SHORTCODE) do { } while (0)
+#define fGEN_TCG_SA1_setin1(SHORTCODE) tcg_gen_movi_tl(RdV, -1)
diff --git a/target/hexagon/gen_helper_protos.py 
b/target/hexagon/gen_helper_protos.py
index c82b0f54e4..6e98429752 100755
--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -40,7 +40,15 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
 declared.append(arg.proto_arg)
 
 arguments = ", ".join(declared)
-f.write(f"DEF_HELPER_{len(declared) - 1}({tag}, {arguments})\n")
+
+## Add the TCG_CALL_NO_RWG_SE flag to helpers that don't take the env
+## argument and aren't HVX instructions.  Since HVX instructions take
+## pointers to their arguments, they will have side effects.
+if hex_common.need_env(tag) or hex_common.is_hvx_insn(tag):
+f.write(f"DEF_HELPER_{len(declared) - 1}({tag}, {arguments})\n")
+else:
+f.write(f"DEF_HELPER_FLAGS_{len(declared) - 1}({tag}, "
+f"TCG_CALL_NO_RWG_SE, {arguments})\n")
 
 
 def main():
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index eb28aa98fe..ee08195aba 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -206,6 +206,18 @@ def need_sp(tag):
 return "A_IMPLICIT_READS_SP" in attribdict[tag]
 
 
+def is_hvx_insn(tag):
+return "A_CVI" in attribdict[tag]
+
+
+def need_env(tag):
+return ("A_STORE" in attribdict[tag] or
+"A_LOAD" in attribdict[tag] or
+"A_CVI_GATHER" in attribdict[tag] or
+"A_CVI_SCATTER" in attribdict[tag] or
+"A_IMPLICIT_WRITES_USR" in attribdict[tag])
+
+
 def need_slot(tag):
 if (
 "A_CVI_SCATTER" not in attribdict[tag]
@@ -1069,11 +1081,12 @@ def helper_args(tag, regs, imms):
 args = []
 
 ## First argument is the CPU state
-args.append(HelperArg(
-"env",
-"tcg_env",
-"CPUHexagonState *env"
-))
+if need_env(tag):
+args.append(HelperArg(
+"env",
+"tcg_env",
+"CPUHexagonState *env"
+))
 
 ## For predicated instructions, we pass in the destination register
 if is_predicated(tag):
-- 
2.34.1




[PATCH v2 0/3] Hexagon (target/hexagon) Only pass env to generated helper when needed

2024-02-05 Thread Taylor Simpson
Currently, we pass env to every generated helper.  When the semantics of
the instruction only depend on the arguments, this is unnecessary and
adds extra overhead to the helper call.

 Changes in v2 
- Separate patches to pass P0 and SP explicitly to helpers that need it
- Add the TCG_CALL_NO_RWG_SE flag to any non-HVX helpers that
  don't get ptr to env

Taylor Simpson (3):
  Hexagon (target/hexagon) Pass P0 explicitly to helpers that need it
  Hexagon (target/hexagon) Pass SP explicitly to helpers that need it
  Hexagon (target/hexagon) Only pass env to generated helper when needed

 target/hexagon/gen_tcg.h|  3 ++
 target/hexagon/macros.h |  4 +--
 target/hexagon/attribs_def.h.inc|  1 +
 target/hexagon/gen_helper_protos.py | 10 ++-
 target/hexagon/hex_common.py| 44 +
 5 files changed, 54 insertions(+), 8 deletions(-)

-- 
2.34.1




[PATCH] Hexagon (target/hexagon) Only pass env to generated helper when needed

2024-02-02 Thread Taylor Simpson
Currently, we pass env to every generated helper.  When the semantics of
the instruction only depend on the arguments, this is unnecessary and
adds extra overhead to the helper call.

The A2_nop and SA1_setin1 instructions end up with no arguments.  This
results in a "old-style function definition" error from the compiler, so
we write overrides for them.

With this change, the number of helpers with env argument is
idef-parser enabled:329 total, 23 with env
idef-parser disabled:   1543 total, 553 with env

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_tcg.h |  3 +++
 target/hexagon/attribs_def.h.inc |  1 +
 target/hexagon/hex_common.py | 22 +-
 3 files changed, 21 insertions(+), 5 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 1c4391b415..e9ac2e3fe0 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1369,3 +1369,6 @@
 gen_helper_raise_exception(tcg_env, excp); \
 } while (0)
 #endif
+
+#define fGEN_TCG_A2_nop(SHORTCODE) do { } while (0)
+#define fGEN_TCG_SA1_setin1(SHORTCODE) tcg_gen_movi_tl(RdV, -1)
diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 87942d46f4..8949ee09cf 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -117,6 +117,7 @@ DEF_ATTRIB(IMPLICIT_READS_P1, "Reads the P1 register", "", 
"")
 DEF_ATTRIB(IMPLICIT_READS_P2, "Reads the P2 register", "", "")
 DEF_ATTRIB(IMPLICIT_READS_P3, "Reads the P3 register", "", "")
 DEF_ATTRIB(IMPLICIT_WRITES_USR, "May write USR", "", "")
+DEF_ATTRIB(IMPLICIT_READS_SP, "Reads the SP register", "", "")
 DEF_ATTRIB(COMMUTES, "The operation is communitive", "", "")
 DEF_ATTRIB(DEALLOCRET, "dealloc_return", "", "")
 DEF_ATTRIB(DEALLOCFRAME, "deallocframe", "", "")
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 195620c7ec..12bc410bb2 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -101,6 +101,7 @@ def calculate_attribs():
 add_qemu_macro_attrib('fLSBNEW1', 'A_IMPLICIT_READS_P1')
 add_qemu_macro_attrib('fLSBNEW1NOT', 'A_IMPLICIT_READS_P1')
 add_qemu_macro_attrib('fREAD_P3', 'A_IMPLICIT_READS_P3')
+add_qemu_macro_attrib('fREAD_SP', 'A_IMPLICIT_READS_SP')
 
 # Recurse down macros, find attributes from sub-macros
 macroValues = list(macros.values())
@@ -197,6 +198,16 @@ def get_tagimms():
 return dict(zip(tags, list(map(compute_tag_immediates, tags
 
 
+def need_env(tag):
+return ("A_STORE" in attribdict[tag] or
+"A_LOAD" in attribdict[tag] or
+"A_CVI_GATHER" in attribdict[tag] or
+"A_CVI_SCATTER" in attribdict[tag] or
+"A_IMPLICIT_WRITES_USR" in attribdict[tag] or
+"A_IMPLICIT_READS_P0" in attribdict[tag] or
+"A_IMPLICIT_READS_SP" in attribdict[tag])
+
+
 def need_slot(tag):
 if (
 "A_CVI_SCATTER" not in attribdict[tag]
@@ -1060,11 +1071,12 @@ def helper_args(tag, regs, imms):
 args = []
 
 ## First argument is the CPU state
-args.append(HelperArg(
-"env",
-"tcg_env",
-"CPUHexagonState *env"
-))
+if need_env(tag):
+args.append(HelperArg(
+"env",
+"tcg_env",
+"CPUHexagonState *env"
+))
 
 ## For predicated instructions, we pass in the destination register
 if is_predicated(tag):
-- 
2.34.1




[PATCH v2 3/3] Hexagon (target/hexagon) Enable more short-circuit packets (HVX)

2024-02-01 Thread Taylor Simpson
Look for read-after-write instead of overlap of reads and writes

HVX instructions with helpers have pass-by-reference semantics, so
we check for overlaps of reads and writes within the same instruction.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/translate.h  | 88 +++--
 target/hexagon/translate.c  | 58 ++-
 target/hexagon/gen_analyze_funcs.py | 19 ---
 target/hexagon/hex_common.py| 45 ++-
 4 files changed, 115 insertions(+), 95 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index d5e7f49ad8..00cc2bcd63 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -50,23 +50,27 @@ typedef struct DisasContext {
 int tmp_vregs_num[VECTOR_TEMPS_MAX];
 int vreg_log[NUM_VREGS];
 int vreg_log_idx;
+DECLARE_BITMAP(vregs_written, NUM_VREGS);
+DECLARE_BITMAP(insn_vregs_written, NUM_VREGS);
 DECLARE_BITMAP(vregs_updated_tmp, NUM_VREGS);
 DECLARE_BITMAP(vregs_updated, NUM_VREGS);
 DECLARE_BITMAP(vregs_select, NUM_VREGS);
 DECLARE_BITMAP(predicated_future_vregs, NUM_VREGS);
 DECLARE_BITMAP(predicated_tmp_vregs, NUM_VREGS);
-DECLARE_BITMAP(vregs_read, NUM_VREGS);
+DECLARE_BITMAP(insn_vregs_read, NUM_VREGS);
 int qreg_log[NUM_QREGS];
 int qreg_log_idx;
-DECLARE_BITMAP(qregs_read, NUM_QREGS);
+DECLARE_BITMAP(qregs_written, NUM_QREGS);
+DECLARE_BITMAP(insn_qregs_written, NUM_QREGS);
+DECLARE_BITMAP(insn_qregs_read, NUM_QREGS);
 bool pre_commit;
 bool need_commit;
 TCGCond branch_cond;
 target_ulong branch_dest;
 bool is_tight_loop;
 bool short_circuit;
-bool has_hvx_helper;
 bool read_after_write;
+bool has_hvx_overlap;
 TCGv new_value[TOTAL_PER_THREAD_REGS];
 TCGv new_pred_value[NUM_PREGS];
 TCGv pred_written;
@@ -146,10 +150,25 @@ intptr_t ctx_future_vreg_off(DisasContext *ctx, int 
regnum,
 intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
   int num, bool alloc_ok);
 
+static inline void ctx_start_hvx_insn(DisasContext *ctx)
+{
+bitmap_zero(ctx->insn_vregs_written, NUM_VREGS);
+bitmap_zero(ctx->insn_vregs_read, NUM_VREGS);
+bitmap_zero(ctx->insn_qregs_written, NUM_QREGS);
+bitmap_zero(ctx->insn_qregs_read, NUM_QREGS);
+}
+
 static inline void ctx_log_vreg_write(DisasContext *ctx,
   int rnum, VRegWriteType type,
-  bool is_predicated)
+  bool is_predicated, bool has_helper)
 {
+if (has_helper) {
+set_bit(rnum, ctx->insn_vregs_written);
+if (test_bit(rnum, ctx->insn_vregs_read)) {
+ctx->has_hvx_overlap = true;
+}
+}
+set_bit(rnum, ctx->vregs_written);
 if (type != EXT_TMP) {
 if (!test_bit(rnum, ctx->vregs_updated)) {
 ctx->vreg_log[ctx->vreg_log_idx] = rnum;
@@ -175,42 +194,77 @@ static inline void ctx_log_vreg_write(DisasContext *ctx,
 
 static inline void ctx_log_vreg_write_pair(DisasContext *ctx,
int rnum, VRegWriteType type,
-   bool is_predicated)
+   bool is_predicated, bool has_helper)
 {
-ctx_log_vreg_write(ctx, rnum ^ 0, type, is_predicated);
-ctx_log_vreg_write(ctx, rnum ^ 1, type, is_predicated);
+ctx_log_vreg_write(ctx, rnum ^ 0, type, is_predicated, has_helper);
+ctx_log_vreg_write(ctx, rnum ^ 1, type, is_predicated, has_helper);
 }
 
-static inline void ctx_log_vreg_read(DisasContext *ctx, int rnum)
+static inline void ctx_log_vreg_read(DisasContext *ctx, int rnum,
+ bool has_helper)
 {
-set_bit(rnum, ctx->vregs_read);
+if (has_helper) {
+set_bit(rnum, ctx->insn_vregs_read);
+if (test_bit(rnum, ctx->insn_vregs_written)) {
+ctx->has_hvx_overlap = true;
+}
+}
+if (test_bit(rnum, ctx->vregs_written)) {
+ctx->read_after_write = true;
+}
 }
 
-static inline void ctx_log_vreg_read_new(DisasContext *ctx, int rnum)
+static inline void ctx_log_vreg_read_new(DisasContext *ctx, int rnum,
+ bool has_helper)
 {
 g_assert(is_gather_store_insn(ctx) ||
  test_bit(rnum, ctx->vregs_updated) ||
  test_bit(rnum, ctx->vregs_select) ||
  test_bit(rnum, ctx->vregs_updated_tmp));
-set_bit(rnum, ctx->vregs_read);
+if (has_helper) {
+set_bit(rnum, ctx->insn_vregs_read);
+if (test_bit(rnum, ctx->insn_vregs_written)) {
+ctx->has_hvx_overlap = true;
+}
+}
+if (is_gather_store_insn(ctx)) {
+ctx->read_after_write = true;
+}
 }
 
-static inline void ctx_log_vreg_read_pair(DisasContext *ctx, int r

[PATCH v2 2/3] Hexagon (target/hexagon) Enable more short-circuit packets (scalar core)

2024-02-01 Thread Taylor Simpson
Look for read-after-write instead of overlap of reads and writes

Here is an example with overalp but no read-after-write:
0x000200fc:  0x38103876 {   R0 = add(R0,R1); R6 = add(R6,R7) }

BEFORE:
  000200fc
 mov_i32 loc2,$0x0
 mov_i32 loc2,r0
 add_i32 loc3,loc2,r1
 mov_i32 loc2,loc3
 mov_i32 loc4,$0x0
 mov_i32 loc4,r6
 add_i32 loc5,loc4,r7
 mov_i32 loc4,loc5
 mov_i32 r0,loc2
 mov_i32 r6,loc4

AFTER:
  000200fc
 add_i32 loc2,r0,r1
 mov_i32 r0,loc2
 add_i32 loc3,r6,r7
 mov_i32 r6,loc3

We can also short-circuit packets with .new values by reading from the
real destination instead of the temporary.
0x00020100:  0x78005ff3 {   R19 = #0xff
0x00020104:  0x2002e204 if (cmp.eq(N19.new,R2)) jump:t PC+8 }

BEFORE:
  00020100
 mov_i32 pc,$0x20108
 mov_i32 loc8,$0x0
 mov_i32 loc8,$0xff
 setcond_i32 loc10,loc8,r2,eq
 mov_i32 loc6,loc10
 mov_i32 r19,loc8
 add_i32 pkt_cnt,pkt_cnt,$0x2
 add_i32 insn_cnt,insn_cnt,$0x4
 brcond_i32 loc6,$0x0,eq,$L1
 goto_tb $0x0
 mov_i32 pc,$0x20108
 exit_tb $0x7fbb5440
 set_label $L1
 goto_tb $0x1
 exit_tb $0x7fbb5441
 set_label $L0
 exit_tb $0x7fbb5443

AFTER:
  00020100
 mov_i32 pc,$0x20108
 mov_i32 r19,$0xff
 setcond_i32 loc7,r19,r2,eq
 mov_i32 loc4,loc7
 add_i32 pkt_cnt,pkt_cnt,$0x2
 add_i32 insn_cnt,insn_cnt,$0x4
 brcond_i32 loc4,$0x0,eq,$L1
 goto_tb $0x0
 mov_i32 pc,$0x20108
 exit_tb $0x7f976440
 set_label $L1
 goto_tb $0x1
 exit_tb $0x7f976441
 set_label $L0
 exit_tb $0x7f976443

Signed-off-by: Taylor Simpson 
---
 target/hexagon/translate.h | 13 +++--
 target/hexagon/translate.c | 21 -
 2 files changed, 11 insertions(+), 23 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index f06d71fc53..d5e7f49ad8 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -38,12 +38,10 @@ typedef struct DisasContext {
 int reg_log[REG_WRITES_MAX];
 int reg_log_idx;
 DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
-DECLARE_BITMAP(regs_read, TOTAL_PER_THREAD_REGS);
 DECLARE_BITMAP(predicated_regs, TOTAL_PER_THREAD_REGS);
 int preg_log[PRED_WRITES_MAX];
 int preg_log_idx;
 DECLARE_BITMAP(pregs_written, NUM_PREGS);
-DECLARE_BITMAP(pregs_read, NUM_PREGS);
 uint8_t store_width[STORES_MAX];
 bool s1_store_processed;
 int future_vregs_idx;
@@ -68,6 +66,7 @@ typedef struct DisasContext {
 bool is_tight_loop;
 bool short_circuit;
 bool has_hvx_helper;
+bool read_after_write;
 TCGv new_value[TOTAL_PER_THREAD_REGS];
 TCGv new_pred_value[NUM_PREGS];
 TCGv pred_written;
@@ -88,13 +87,14 @@ static inline void ctx_log_pred_write(DisasContext *ctx, 
int pnum)
 
 static inline void ctx_log_pred_read(DisasContext *ctx, int pnum)
 {
-set_bit(pnum, ctx->pregs_read);
+if (test_bit(pnum, ctx->pregs_written)) {
+ctx->read_after_write = true;
+}
 }
 
 static inline void ctx_log_pred_read_new(DisasContext *ctx, int pnum)
 {
 g_assert(test_bit(pnum, ctx->pregs_written));
-set_bit(pnum, ctx->pregs_read);
 }
 
 static inline void ctx_log_reg_write(DisasContext *ctx, int rnum,
@@ -125,13 +125,14 @@ static inline void ctx_log_reg_write_pair(DisasContext 
*ctx, int rnum,
 
 static inline void ctx_log_reg_read(DisasContext *ctx, int rnum)
 {
-set_bit(rnum, ctx->regs_read);
+if (test_bit(rnum, ctx->regs_written)) {
+ctx->read_after_write = true;
+}
 }
 
 static inline void ctx_log_reg_read_new(DisasContext *ctx, int rnum)
 {
 g_assert(test_bit(rnum, ctx->regs_written));
-set_bit(rnum, ctx->regs_read);
 }
 
 static inline void ctx_log_reg_read_pair(DisasContext *ctx, int rnum)
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 95579ae243..751ca71790 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -394,20 +394,8 @@ static bool need_commit(DisasContext *ctx)
 }
 }
 
-/* Check for overlap between register reads and writes */
-for (int i = 0; i < ctx->reg_log_idx; i++) {
-int rnum = ctx->reg_log[i];
-if (test_bit(rnum, ctx->regs_read)) {
-return true;
-}
-}
-
-/* Check for overlap between predicate reads and writes */
-for (int i = 0; i < ctx->preg_log_idx; i++) {
-int pnum = ctx->preg_log[i];
-if (test_bit(pnum, ctx->pregs_read)) {
-return true;
-}
+if (ctx->read_after_write) {
+return true;
 }
 
 /* Check for overlap between HVX reads and writes */
@@ -466,6 +454,7 @@ sta

[PATCH v2 0/3] Hexagon (target/hexagon) Enable more short-circuit packets

2024-02-01 Thread Taylor Simpson
This patch series improves the set of packets that can short-circuit
the commit packet logic and write the results directly during the
execution of each instruction in the packet.

The key observation is that checking for overlap between register reads
and writes is different from read-after-write.  For example, this packet
{ R0 = add(R0,R1); R6 = add(R6,R7) }
has an overlap between the reads and writes without doing a read after a
write.  Therefore, it is safe to write directly into the destination
registers during instruction execution.

Another example is a .new register read.  These can read from either the
destination register or a temporary location.

HVX instructions with generated helpers require special handling.
The semantics of the helpers are pass-by-reference, so we still need the
overlap check for these.

* Changes in v2 *
Conform to object oriented generators patch
https://lists.gnu.org/archive/html/qemu-devel/2023-12/msg01211.html


Taylor Simpson (3):
  Hexagon (target/hexagon) Analyze reads before writes
  Hexagon (target/hexagon) Enable more short-circuit packets (scalar
core)
  Hexagon (target/hexagon) Enable more short-circuit packets (HVX)

 target/hexagon/translate.h  | 119 +++-
 target/hexagon/translate.c  |  77 ++
 target/hexagon/README   |   9 ++-
 target/hexagon/gen_analyze_funcs.py |  55 -
 target/hexagon/hex_common.py|  98 +--
 5 files changed, 200 insertions(+), 158 deletions(-)

-- 
2.34.1




[PATCH v2 1/3] Hexagon (target/hexagon) Analyze reads before writes

2024-02-01 Thread Taylor Simpson
We divide gen_analyze_funcs.py into 3 phases
Declare the operands
Analyze the register reads
Analyze the register writes

We also create special versions of ctx_log_*_read for new operands
Check that the operand is written before the read

This is a precursor to improving the analysis for short-circuiting
the packet semantics in a subsequent commit

Signed-off-by: Taylor Simpson 
---
 target/hexagon/translate.h  | 26 +++-
 target/hexagon/README   |  9 +++--
 target/hexagon/gen_analyze_funcs.py | 34 ++--
 target/hexagon/hex_common.py| 63 +++--
 4 files changed, 83 insertions(+), 49 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 4dd59c6726..f06d71fc53 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2024 Qualcomm Innovation Center, Inc. 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
@@ -75,6 +75,8 @@ typedef struct DisasContext {
 TCGv dczero_addr;
 } DisasContext;
 
+bool is_gather_store_insn(DisasContext *ctx);
+
 static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
 {
 if (!test_bit(pnum, ctx->pregs_written)) {
@@ -89,6 +91,12 @@ static inline void ctx_log_pred_read(DisasContext *ctx, int 
pnum)
 set_bit(pnum, ctx->pregs_read);
 }
 
+static inline void ctx_log_pred_read_new(DisasContext *ctx, int pnum)
+{
+g_assert(test_bit(pnum, ctx->pregs_written));
+set_bit(pnum, ctx->pregs_read);
+}
+
 static inline void ctx_log_reg_write(DisasContext *ctx, int rnum,
  bool is_predicated)
 {
@@ -120,6 +128,12 @@ static inline void ctx_log_reg_read(DisasContext *ctx, int 
rnum)
 set_bit(rnum, ctx->regs_read);
 }
 
+static inline void ctx_log_reg_read_new(DisasContext *ctx, int rnum)
+{
+g_assert(test_bit(rnum, ctx->regs_written));
+set_bit(rnum, ctx->regs_read);
+}
+
 static inline void ctx_log_reg_read_pair(DisasContext *ctx, int rnum)
 {
 ctx_log_reg_read(ctx, rnum);
@@ -171,6 +185,15 @@ static inline void ctx_log_vreg_read(DisasContext *ctx, 
int rnum)
 set_bit(rnum, ctx->vregs_read);
 }
 
+static inline void ctx_log_vreg_read_new(DisasContext *ctx, int rnum)
+{
+g_assert(is_gather_store_insn(ctx) ||
+ test_bit(rnum, ctx->vregs_updated) ||
+ test_bit(rnum, ctx->vregs_select) ||
+ test_bit(rnum, ctx->vregs_updated_tmp));
+set_bit(rnum, ctx->vregs_read);
+}
+
 static inline void ctx_log_vreg_read_pair(DisasContext *ctx, int rnum)
 {
 ctx_log_vreg_read(ctx, rnum ^ 0);
@@ -205,7 +228,6 @@ extern TCGv hex_vstore_addr[VSTORES_MAX];
 extern TCGv hex_vstore_size[VSTORES_MAX];
 extern TCGv hex_vstore_pending[VSTORES_MAX];
 
-bool is_gather_store_insn(DisasContext *ctx);
 void process_store(DisasContext *ctx, int slot_num);
 
 FIELD(PROBE_PKT_SCALAR_STORE_S0, MMU_IDX,   0, 2)
diff --git a/target/hexagon/README b/target/hexagon/README
index 746ebec378..c1d8c8d0ab 100644
--- a/target/hexagon/README
+++ b/target/hexagon/README
@@ -183,10 +183,11 @@ when the override is present.
 }
 
 We also generate an analyze_ function for each instruction.  Currently,
-these functions record the writes to registers by calling ctx_log_*.  During
-gen_start_packet, we invoke the analyze_ function for each instruction in
-the packet, and we mark the implicit writes.  After the analysis is performed,
-we initialize the result register for each of the predicated assignments.
+these functions record the reads and writes to registers by calling ctx_log_*.
+During gen_start_packet, we invoke the analyze_ function for each 
instruction in
+the packet, and we mark the implicit writes.  The analysis determines if the 
packet
+semantics can be short-circuited.  If not, we initialize the result register 
for each
+of the predicated assignments.
 
 In addition to instruction semantics, we use a generator to create the decode
 tree.  This generation is a four step process.
diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index a9af666cef..890e6a3a95 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python3
 
 ##
-##  Copyright(c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+##  Copyright(c) 2022-2024 Qualcomm Innovation Center, Inc. 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
@@ -44,15 +44,25 @@ def gen_analyze_func(f, tag, regs, imms):
 
 f.write("Insn *insn G_GNUC_UNUSED = ctx->insn;\n"

[PATCH v2 2/3] Hexagon (target/hexagon) Use QEMU decodetree (16-bit instructions)

2024-01-15 Thread Taylor Simpson
Section 10.3 of the Hexagon V73 Programmer's Reference Manual

A duplex is encoded as a 32-bit instruction with bits [15:14] set to 00.
The sub-instructions that comprise a duplex are encoded as 13-bit fields
in the duplex.

Create a decoder for each subinstruction class (a, l1, l2, s1, s2).

Extend gen_trans_funcs.py to handle all instructions rather than
filter by instruction class.

There is a g_assert_not_reached() in decode_insns() in decode.c to
verify we never try to use the old decoder on 16-bit instructions.

Signed-off-by: Taylor Simpson 
Reviewed-by: Brian Cain 
---
 target/hexagon/decode.c   | 85 +
 target/hexagon/README |  1 +
 target/hexagon/gen_decodetree.py  | 12 -
 target/hexagon/gen_trans_funcs.py | 12 +
 target/hexagon/meson.build| 90 +++
 5 files changed, 188 insertions(+), 12 deletions(-)

diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index bddad1f75e..160b23a895 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -60,6 +60,7 @@ static int decode_mapped_reg_##NAME(DisasContext *ctx, int x) 
\
 }
 DECODE_MAPPED(R_16)
 DECODE_MAPPED(R_8)
+DECODE_MAPPED(R__8)
 
 /* Helper function for decodetree_trans_funcs_generated.c.inc */
 static int shift_left(DisasContext *ctx, int x, int n, int immno)
@@ -77,6 +78,13 @@ static int shift_left(DisasContext *ctx, int x, int n, int 
immno)
 #include "decode_normal_generated.c.inc"
 #include "decode_hvx_generated.c.inc"
 
+/* Include the generated decoder for 16 bit insn */
+#include "decode_subinsn_a_generated.c.inc"
+#include "decode_subinsn_l1_generated.c.inc"
+#include "decode_subinsn_l2_generated.c.inc"
+#include "decode_subinsn_s1_generated.c.inc"
+#include "decode_subinsn_s2_generated.c.inc"
+
 /* Include the generated helpers for the decoder */
 #include "decodetree_trans_funcs_generated.c.inc"
 
@@ -790,6 +798,63 @@ decode_insns_tablewalk(Insn *insn, const DectreeTable 
*table,
 }
 }
 
+/*
+ * Section 10.3 of the Hexagon V73 Programmer's Reference Manual
+ *
+ * A duplex is encoded as a 32-bit instruction with bits [15:14] set to 00.
+ * The sub-instructions that comprise a duplex are encoded as 13-bit fields
+ * in the duplex.
+ *
+ * Per table 10-4, the 4-bit duplex iclass is encoded in bits 31:29, 13
+ */
+static uint32_t get_duplex_iclass(uint32_t encoding)
+{
+uint32_t iclass = extract32(encoding, 13, 1);
+iclass = deposit32(iclass, 1, 3, extract32(encoding, 29, 3));
+return iclass;
+}
+
+/*
+ * Per table 10-5, the duplex ICLASS field values that specify the group of
+ * each sub-instruction in a duplex
+ *
+ * This table points to the decode instruction for each entry in the table
+ */
+typedef bool (*subinsn_decode_func)(DisasContext *ctx, uint16_t insn);
+typedef struct {
+subinsn_decode_func decode_slot0_subinsn;
+subinsn_decode_func decode_slot1_subinsn;
+} subinsn_decode_groups;
+
+static const subinsn_decode_groups decode_groups[16] = {
+[0x0] = { decode_subinsn_l1, decode_subinsn_l1 },
+[0x1] = { decode_subinsn_l2, decode_subinsn_l1 },
+[0x2] = { decode_subinsn_l2, decode_subinsn_l2 },
+[0x3] = { decode_subinsn_a,  decode_subinsn_a },
+[0x4] = { decode_subinsn_l1, decode_subinsn_a },
+[0x5] = { decode_subinsn_l2, decode_subinsn_a },
+[0x6] = { decode_subinsn_s1, decode_subinsn_a },
+[0x7] = { decode_subinsn_s2, decode_subinsn_a },
+[0x8] = { decode_subinsn_s1, decode_subinsn_l1 },
+[0x9] = { decode_subinsn_s1, decode_subinsn_l2 },
+[0xa] = { decode_subinsn_s1, decode_subinsn_s1 },
+[0xb] = { decode_subinsn_s2, decode_subinsn_s1 },
+[0xc] = { decode_subinsn_s2, decode_subinsn_l1 },
+[0xd] = { decode_subinsn_s2, decode_subinsn_l2 },
+[0xe] = { decode_subinsn_s2, decode_subinsn_s2 },
+[0xf] = { NULL,  NULL },  /* Reserved */
+};
+
+static uint16_t get_slot0_subinsn(uint32_t encoding)
+{
+return extract32(encoding, 0, 13);
+}
+
+static uint16_t get_slot1_subinsn(uint32_t encoding)
+{
+return extract32(encoding, 16, 13);
+}
+
 static unsigned int
 decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding)
 {
@@ -805,8 +870,28 @@ decode_insns(DisasContext *ctx, Insn *insn, uint32_t 
encoding)
 table = _table_DECODE_ROOT_32;
 g_assert_not_reached();
 } else {
+uint32_t iclass = get_duplex_iclass(encoding);
+unsigned int slot0_subinsn = get_slot0_subinsn(encoding);
+unsigned int slot1_subinsn = get_slot1_subinsn(encoding);
+subinsn_decode_func decode_slot0_subinsn =
+decode_groups[iclass].decode_slot0_subinsn;
+subinsn_decode_func decode_slot1_subinsn =
+decode_groups[iclass].decode_slot1_subinsn;
+
+/* The slot1 subinsn needs to be in the packet first */
+if (decode_slot1_subinsn(ctx, slot1_subinsn)) {
+   

[PATCH v2 0/3] Hexagon (target/hexagon) Use QEMU decodetree

2024-01-15 Thread Taylor Simpson
Replace the old Hexagon dectree.py with QEMU decodetree

 Changes in v2 
Suggested Python improvements from Brian Cain 


Taylor Simpson (3):
  Hexagon (target/hexagon) Use QEMU decodetree (32-bit instructions)
  Hexagon (target/hexagon) Use QEMU decodetree (16-bit instructions)
  Hexagon (target/hexagon) Remove old dectree.py

 target/hexagon/decode.h |   5 +-
 target/hexagon/opcodes.h|   2 -
 target/hexagon/decode.c | 435 +++-
 target/hexagon/gen_dectree_import.c |  49 
 target/hexagon/opcodes.c|  29 --
 target/hexagon/translate.c  |   4 +-
 target/hexagon/README   |  14 +-
 target/hexagon/dectree.py   | 403 --
 target/hexagon/gen_decodetree.py| 198 +
 target/hexagon/gen_trans_funcs.py   | 124 
 target/hexagon/meson.build  | 147 +-
 11 files changed, 586 insertions(+), 824 deletions(-)
 delete mode 100755 target/hexagon/dectree.py
 create mode 100755 target/hexagon/gen_decodetree.py
 create mode 100755 target/hexagon/gen_trans_funcs.py

-- 
2.34.1




[PATCH v2 3/3] Hexagon (target/hexagon) Remove old dectree.py

2024-01-15 Thread Taylor Simpson
Now that we are using QEMU decodetree.py, remove the old decoder

Signed-off-by: Taylor Simpson 
Reviewed-by: Brian Cain 
---
 target/hexagon/opcodes.h|   2 -
 target/hexagon/decode.c | 344 
 target/hexagon/gen_dectree_import.c |  49 
 target/hexagon/opcodes.c|  29 --
 target/hexagon/dectree.py   | 403 
 target/hexagon/meson.build  |  12 -
 6 files changed, 839 deletions(-)
 delete mode 100755 target/hexagon/dectree.py

diff --git a/target/hexagon/opcodes.h b/target/hexagon/opcodes.h
index 6e90e00fe2..fa7e321950 100644
--- a/target/hexagon/opcodes.h
+++ b/target/hexagon/opcodes.h
@@ -53,6 +53,4 @@ extern const OpcodeEncoding opcode_encodings[XX_LAST_OPCODE];
 
 void opcode_init(void);
 
-int opcode_which_immediate_is_extended(Opcode opcode);
-
 #endif
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 160b23a895..a40210ca1e 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -88,175 +88,6 @@ static int shift_left(DisasContext *ctx, int x, int n, int 
immno)
 /* Include the generated helpers for the decoder */
 #include "decodetree_trans_funcs_generated.c.inc"
 
-typedef struct {
-const struct DectreeTable *table_link;
-const struct DectreeTable *table_link_b;
-Opcode opcode;
-enum {
-DECTREE_ENTRY_INVALID,
-DECTREE_TABLE_LINK,
-DECTREE_SUBINSNS,
-DECTREE_EXTSPACE,
-DECTREE_TERMINAL
-} type;
-} DectreeEntry;
-
-typedef struct DectreeTable {
-unsigned int (*lookup_function)(int startbit, int width, uint32_t opcode);
-unsigned int size;
-unsigned int startbit;
-unsigned int width;
-const DectreeEntry table[];
-} DectreeTable;
-
-#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) \
-static const DectreeTable dectree_table_##TAG;
-#define TABLE_LINK(TABLE) /* NOTHING */
-#define TERMINAL(TAG, ENC)/* NOTHING */
-#define SUBINSNS(TAG, CLASSA, CLASSB, ENC)/* NOTHING */
-#define EXTSPACE(TAG, ENC)/* NOTHING */
-#define INVALID() /* NOTHING */
-#define DECODE_END_TABLE(...) /* NOTHING */
-#define DECODE_MATCH_INFO(...)/* NOTHING */
-#define DECODE_LEGACY_MATCH_INFO(...) /* NOTHING */
-#define DECODE_OPINFO(...)/* NOTHING */
-
-#include "dectree_generated.h.inc"
-
-#undef DECODE_OPINFO
-#undef DECODE_MATCH_INFO
-#undef DECODE_LEGACY_MATCH_INFO
-#undef DECODE_END_TABLE
-#undef INVALID
-#undef TERMINAL
-#undef SUBINSNS
-#undef EXTSPACE
-#undef TABLE_LINK
-#undef DECODE_NEW_TABLE
-#undef DECODE_SEPARATOR_BITS
-
-#define DECODE_SEPARATOR_BITS(START, WIDTH) NULL, START, WIDTH
-#define DECODE_NEW_TABLE_HELPER(TAG, SIZE, FN, START, WIDTH) \
-static const DectreeTable dectree_table_##TAG = { \
-.size = SIZE, \
-.lookup_function = FN, \
-.startbit = START, \
-.width = WIDTH, \
-.table = {
-#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) \
-DECODE_NEW_TABLE_HELPER(TAG, SIZE, WHATNOT)
-
-#define TABLE_LINK(TABLE) \
-{ .type = DECTREE_TABLE_LINK, .table_link = _table_##TABLE },
-#define TERMINAL(TAG, ENC) \
-{ .type = DECTREE_TERMINAL, .opcode = TAG  },
-#define SUBINSNS(TAG, CLASSA, CLASSB, ENC) \
-{ \
-.type = DECTREE_SUBINSNS, \
-.table_link = _table_DECODE_SUBINSN_##CLASSA, \
-.table_link_b = _table_DECODE_SUBINSN_##CLASSB \
-},
-#define EXTSPACE(TAG, ENC) { .type = DECTREE_EXTSPACE },
-#define INVALID() { .type = DECTREE_ENTRY_INVALID, .opcode = XX_LAST_OPCODE },
-
-#define DECODE_END_TABLE(...) } };
-
-#define DECODE_MATCH_INFO(...)/* NOTHING */
-#define DECODE_LEGACY_MATCH_INFO(...) /* NOTHING */
-#define DECODE_OPINFO(...)/* NOTHING */
-
-#include "dectree_generated.h.inc"
-
-#undef DECODE_OPINFO
-#undef DECODE_MATCH_INFO
-#undef DECODE_LEGACY_MATCH_INFO
-#undef DECODE_END_TABLE
-#undef INVALID
-#undef TERMINAL
-#undef SUBINSNS
-#undef EXTSPACE
-#undef TABLE_LINK
-#undef DECODE_NEW_TABLE
-#undef DECODE_NEW_TABLE_HELPER
-#undef DECODE_SEPARATOR_BITS
-
-static const DectreeTable dectree_table_DECODE_EXT_EXT_noext = {
-.size = 1, .lookup_function = NULL, .startbit = 0, .width = 0,
-.table = {
-{ .type = DECTREE_ENTRY_INVALID, .opcode = XX_LAST_OPCODE },
-}
-};
-
-static const DectreeTable *ext_trees[XX_LAST_EXT_IDX];
-
-static void decode_ext_init(void)
-{
-int i;
-for (i = EXT_IDX_noext; i < EXT_IDX_noext_AFTER; i++) {
-ext_trees[i] = _table_DECODE_EXT_EXT_noext;
-}
-for (i = EXT_IDX_mmvec; i < EXT_IDX_mmvec_AFTER; i++) {
-ext_trees[i] = _table_DECODE_EXT_EXT_mmvec;
-}
-}
-
-typedef struct {
-uint32_t mask;
-uint32_t match;
-} DecodeITableEntry;
-
-#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT)  /* NOTHING */
-#define TABLE_LINK(T

[PATCH v2 1/3] Hexagon (target/hexagon) Use QEMU decodetree (32-bit instructions)

2024-01-15 Thread Taylor Simpson
The Decodetree Specification can be found here
https://www.qemu.org/docs/master/devel/decodetree.html

Covers all 32-bit instructions, including HVX

We generate separate decoders for each instruction class.  The reason
will be more apparent in the next patch in this series.

We add 2 new scripts
gen_decodetree.pyGenerate the input to decodetree.py
gen_trans_funcs.py   Generate the trans_* functions used by the
 output of decodetree.py

Since the functions generated by decodetree.py take DisasContext * as an
argument, we add the argument to a couple of functions that didn't need
it previously.  We also set the insn field in DisasContext during decode
because it is used by the trans_* functions.

There is a g_assert_not_reached() in decode_insns() in decode.c to
verify we never try to use the old decoder on 32-bit instructions

Signed-off-by: Taylor Simpson 
Reviewed-by: Brian Cain 
---
 target/hexagon/decode.h   |   5 +-
 target/hexagon/decode.c   |  54 -
 target/hexagon/translate.c|   4 +-
 target/hexagon/README |  13 +-
 target/hexagon/gen_decodetree.py  | 190 ++
 target/hexagon/gen_trans_funcs.py | 132 +
 target/hexagon/meson.build|  55 +
 7 files changed, 439 insertions(+), 14 deletions(-)
 create mode 100755 target/hexagon/gen_decodetree.py
 create mode 100755 target/hexagon/gen_trans_funcs.py

diff --git a/target/hexagon/decode.h b/target/hexagon/decode.h
index c66f5ea64d..3f3012b978 100644
--- a/target/hexagon/decode.h
+++ b/target/hexagon/decode.h
@@ -21,12 +21,13 @@
 #include "cpu.h"
 #include "opcodes.h"
 #include "insn.h"
+#include "translate.h"
 
 void decode_init(void);
 
 void decode_send_insn_to(Packet *packet, int start, int newloc);
 
-int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
-  bool disas_only);
+int decode_packet(DisasContext *ctx, int max_words, const uint32_t *words,
+  Packet *pkt, bool disas_only);
 
 #endif
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 946c55cc71..bddad1f75e 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -52,6 +52,34 @@ DEF_REGMAP(R_8,   8,  0, 1, 2, 3, 4, 5, 6, 7)
 #define DECODE_MAPPED_REG(OPNUM, NAME) \
 insn->regno[OPNUM] = DECODE_REGISTER_##NAME[insn->regno[OPNUM]];
 
+/* Helper functions for decode_*_generated.c.inc */
+#define DECODE_MAPPED(NAME) \
+static int decode_mapped_reg_##NAME(DisasContext *ctx, int x) \
+{ \
+return DECODE_REGISTER_##NAME[x]; \
+}
+DECODE_MAPPED(R_16)
+DECODE_MAPPED(R_8)
+
+/* Helper function for decodetree_trans_funcs_generated.c.inc */
+static int shift_left(DisasContext *ctx, int x, int n, int immno)
+{
+int ret = x;
+Insn *insn = ctx->insn;
+if (!insn->extension_valid ||
+insn->which_extended != immno) {
+ret <<= n;
+}
+return ret;
+}
+
+/* Include the generated decoder for 32 bit insn */
+#include "decode_normal_generated.c.inc"
+#include "decode_hvx_generated.c.inc"
+
+/* Include the generated helpers for the decoder */
+#include "decodetree_trans_funcs_generated.c.inc"
+
 typedef struct {
 const struct DectreeTable *table_link;
 const struct DectreeTable *table_link_b;
@@ -550,7 +578,8 @@ apply_extender(Packet *pkt, int i, uint32_t extender)
 int immed_num;
 uint32_t base_immed;
 
-immed_num = opcode_which_immediate_is_extended(pkt->insn[i].opcode);
+immed_num = pkt->insn[i].which_extended;
+g_assert(immed_num == 
opcode_which_immediate_is_extended(pkt->insn[i].opcode));
 base_immed = pkt->insn[i].immed[immed_num];
 
 pkt->insn[i].immed[immed_num] = extender | fZXTN(6, 32, base_immed);
@@ -762,12 +791,19 @@ decode_insns_tablewalk(Insn *insn, const DectreeTable 
*table,
 }
 
 static unsigned int
-decode_insns(Insn *insn, uint32_t encoding)
+decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding)
 {
 const DectreeTable *table;
 if (parse_bits(encoding) != 0) {
+if (decode_normal(ctx, encoding) ||
+decode_hvx(ctx, encoding)) {
+insn->generate = opcode_genptr[insn->opcode];
+insn->iclass = iclass_bits(encoding);
+return 1;
+}
 /* Start with PP table - 32 bit instructions */
 table = _table_DECODE_ROOT_32;
+g_assert_not_reached();
 } else {
 /* start with EE table - duplex instructions */
 table = _table_DECODE_ROOT_EE;
@@ -916,8 +952,8 @@ decode_set_slot_number(Packet *pkt)
  * or number of words used on success
  */
 
-int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
-  bool disas_only)
+int decode_packet(DisasContext *ctx, int max_words, const uint32_t *words,
+  Packet *pkt, bool disas_only)
 {
 int 

[PATCH v2 0/3] Hexagon (target/hexagon) Use QEMU decodetree

2024-01-08 Thread Taylor Simpson
Replace the old Hexagon dectree.py with QEMU decodetree

Taylor Simpson (3):
  Hexagon (target/hexagon) Use QEMU decodetree (32-bit instructions)
  Hexagon (target/hexagon) Use QEMU decodetree (16-bit instructions)
  Hexagon (target/hexagon) Remove old dectree.py

 target/hexagon/decode.h |   5 +-
 target/hexagon/opcodes.h|   2 -
 target/hexagon/decode.c | 435 +++-
 target/hexagon/gen_dectree_import.c |  49 
 target/hexagon/opcodes.c|  29 --
 target/hexagon/translate.c  |   4 +-
 target/hexagon/README   |  14 +-
 target/hexagon/dectree.py   | 403 --
 target/hexagon/gen_decodetree.py| 203 +
 target/hexagon/gen_trans_funcs.py   | 124 
 target/hexagon/meson.build  | 147 +-
 11 files changed, 591 insertions(+), 824 deletions(-)
 delete mode 100755 target/hexagon/dectree.py
 create mode 100755 target/hexagon/gen_decodetree.py
 create mode 100755 target/hexagon/gen_trans_funcs.py

-- 
2.34.1




[PATCH v2 1/3] Hexagon (target/hexagon) Use QEMU decodetree (32-bit instructions)

2024-01-08 Thread Taylor Simpson
The Decodetree Specification can be found here
https://www.qemu.org/docs/master/devel/decodetree.html

Covers all 32-bit instructions, including HVX

We generate separate decoders for each instruction class.  The reason
will be more apparent in the next patch in this series.

We add 2 new scripts
gen_decodetree.pyGenerate the input to decodetree.py
gen_trans_funcs.py   Generate the trans_* functions used by the
 output of decodetree.py

Since the functions generated by decodetree.py take DisasContext * as an
argument, we add the argument to a couple of functions that didn't need
it previously.  We also set the insn field in DisasContext during decode
because it is used by the trans_* functions.

There is a g_assert_not_reached() in decode_insns() in decode.c to
verify we never try to use the old decoder on 32-bit instructions

Signed-off-by: Taylor Simpson 
---
 target/hexagon/decode.h   |   5 +-
 target/hexagon/decode.c   |  54 -
 target/hexagon/translate.c|   4 +-
 target/hexagon/README |  13 +-
 target/hexagon/gen_decodetree.py  | 193 ++
 target/hexagon/gen_trans_funcs.py | 132 
 target/hexagon/meson.build|  55 +
 7 files changed, 442 insertions(+), 14 deletions(-)
 create mode 100755 target/hexagon/gen_decodetree.py
 create mode 100755 target/hexagon/gen_trans_funcs.py

diff --git a/target/hexagon/decode.h b/target/hexagon/decode.h
index c66f5ea64d..3f3012b978 100644
--- a/target/hexagon/decode.h
+++ b/target/hexagon/decode.h
@@ -21,12 +21,13 @@
 #include "cpu.h"
 #include "opcodes.h"
 #include "insn.h"
+#include "translate.h"
 
 void decode_init(void);
 
 void decode_send_insn_to(Packet *packet, int start, int newloc);
 
-int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
-  bool disas_only);
+int decode_packet(DisasContext *ctx, int max_words, const uint32_t *words,
+  Packet *pkt, bool disas_only);
 
 #endif
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 946c55cc71..bddad1f75e 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -52,6 +52,34 @@ DEF_REGMAP(R_8,   8,  0, 1, 2, 3, 4, 5, 6, 7)
 #define DECODE_MAPPED_REG(OPNUM, NAME) \
 insn->regno[OPNUM] = DECODE_REGISTER_##NAME[insn->regno[OPNUM]];
 
+/* Helper functions for decode_*_generated.c.inc */
+#define DECODE_MAPPED(NAME) \
+static int decode_mapped_reg_##NAME(DisasContext *ctx, int x) \
+{ \
+return DECODE_REGISTER_##NAME[x]; \
+}
+DECODE_MAPPED(R_16)
+DECODE_MAPPED(R_8)
+
+/* Helper function for decodetree_trans_funcs_generated.c.inc */
+static int shift_left(DisasContext *ctx, int x, int n, int immno)
+{
+int ret = x;
+Insn *insn = ctx->insn;
+if (!insn->extension_valid ||
+insn->which_extended != immno) {
+ret <<= n;
+}
+return ret;
+}
+
+/* Include the generated decoder for 32 bit insn */
+#include "decode_normal_generated.c.inc"
+#include "decode_hvx_generated.c.inc"
+
+/* Include the generated helpers for the decoder */
+#include "decodetree_trans_funcs_generated.c.inc"
+
 typedef struct {
 const struct DectreeTable *table_link;
 const struct DectreeTable *table_link_b;
@@ -550,7 +578,8 @@ apply_extender(Packet *pkt, int i, uint32_t extender)
 int immed_num;
 uint32_t base_immed;
 
-immed_num = opcode_which_immediate_is_extended(pkt->insn[i].opcode);
+immed_num = pkt->insn[i].which_extended;
+g_assert(immed_num == 
opcode_which_immediate_is_extended(pkt->insn[i].opcode));
 base_immed = pkt->insn[i].immed[immed_num];
 
 pkt->insn[i].immed[immed_num] = extender | fZXTN(6, 32, base_immed);
@@ -762,12 +791,19 @@ decode_insns_tablewalk(Insn *insn, const DectreeTable 
*table,
 }
 
 static unsigned int
-decode_insns(Insn *insn, uint32_t encoding)
+decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding)
 {
 const DectreeTable *table;
 if (parse_bits(encoding) != 0) {
+if (decode_normal(ctx, encoding) ||
+decode_hvx(ctx, encoding)) {
+insn->generate = opcode_genptr[insn->opcode];
+insn->iclass = iclass_bits(encoding);
+return 1;
+}
 /* Start with PP table - 32 bit instructions */
 table = _table_DECODE_ROOT_32;
+g_assert_not_reached();
 } else {
 /* start with EE table - duplex instructions */
 table = _table_DECODE_ROOT_EE;
@@ -916,8 +952,8 @@ decode_set_slot_number(Packet *pkt)
  * or number of words used on success
  */
 
-int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
-  bool disas_only)
+int decode_packet(DisasContext *ctx, int max_words, const uint32_t *words,
+  Packet *pkt, bool disas_only)
 {
 int num_insns = 0;
 int wor

[PATCH v2 2/3] Hexagon (target/hexagon) Use QEMU decodetree (16-bit instructions)

2024-01-08 Thread Taylor Simpson
Section 10.3 of the Hexagon V73 Programmer's Reference Manual

A duplex is encoded as a 32-bit instruction with bits [15:14] set to 00.
The sub-instructions that comprise a duplex are encoded as 13-bit fields
in the duplex.

Create a decoder for each subinstruction class (a, l1, l2, s1, s2).

Extend gen_trans_funcs.py to handle all instructions rather than
filter by instruction class.

There is a g_assert_not_reached() in decode_insns() in decode.c to
verify we never try to use the old decoder on 16-bit instructions.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/decode.c   | 85 +
 target/hexagon/README |  1 +
 target/hexagon/gen_decodetree.py  | 14 -
 target/hexagon/gen_trans_funcs.py | 12 +
 target/hexagon/meson.build| 90 +++
 5 files changed, 190 insertions(+), 12 deletions(-)

diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index bddad1f75e..160b23a895 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -60,6 +60,7 @@ static int decode_mapped_reg_##NAME(DisasContext *ctx, int x) 
\
 }
 DECODE_MAPPED(R_16)
 DECODE_MAPPED(R_8)
+DECODE_MAPPED(R__8)
 
 /* Helper function for decodetree_trans_funcs_generated.c.inc */
 static int shift_left(DisasContext *ctx, int x, int n, int immno)
@@ -77,6 +78,13 @@ static int shift_left(DisasContext *ctx, int x, int n, int 
immno)
 #include "decode_normal_generated.c.inc"
 #include "decode_hvx_generated.c.inc"
 
+/* Include the generated decoder for 16 bit insn */
+#include "decode_subinsn_a_generated.c.inc"
+#include "decode_subinsn_l1_generated.c.inc"
+#include "decode_subinsn_l2_generated.c.inc"
+#include "decode_subinsn_s1_generated.c.inc"
+#include "decode_subinsn_s2_generated.c.inc"
+
 /* Include the generated helpers for the decoder */
 #include "decodetree_trans_funcs_generated.c.inc"
 
@@ -790,6 +798,63 @@ decode_insns_tablewalk(Insn *insn, const DectreeTable 
*table,
 }
 }
 
+/*
+ * Section 10.3 of the Hexagon V73 Programmer's Reference Manual
+ *
+ * A duplex is encoded as a 32-bit instruction with bits [15:14] set to 00.
+ * The sub-instructions that comprise a duplex are encoded as 13-bit fields
+ * in the duplex.
+ *
+ * Per table 10-4, the 4-bit duplex iclass is encoded in bits 31:29, 13
+ */
+static uint32_t get_duplex_iclass(uint32_t encoding)
+{
+uint32_t iclass = extract32(encoding, 13, 1);
+iclass = deposit32(iclass, 1, 3, extract32(encoding, 29, 3));
+return iclass;
+}
+
+/*
+ * Per table 10-5, the duplex ICLASS field values that specify the group of
+ * each sub-instruction in a duplex
+ *
+ * This table points to the decode instruction for each entry in the table
+ */
+typedef bool (*subinsn_decode_func)(DisasContext *ctx, uint16_t insn);
+typedef struct {
+subinsn_decode_func decode_slot0_subinsn;
+subinsn_decode_func decode_slot1_subinsn;
+} subinsn_decode_groups;
+
+static const subinsn_decode_groups decode_groups[16] = {
+[0x0] = { decode_subinsn_l1, decode_subinsn_l1 },
+[0x1] = { decode_subinsn_l2, decode_subinsn_l1 },
+[0x2] = { decode_subinsn_l2, decode_subinsn_l2 },
+[0x3] = { decode_subinsn_a,  decode_subinsn_a },
+[0x4] = { decode_subinsn_l1, decode_subinsn_a },
+[0x5] = { decode_subinsn_l2, decode_subinsn_a },
+[0x6] = { decode_subinsn_s1, decode_subinsn_a },
+[0x7] = { decode_subinsn_s2, decode_subinsn_a },
+[0x8] = { decode_subinsn_s1, decode_subinsn_l1 },
+[0x9] = { decode_subinsn_s1, decode_subinsn_l2 },
+[0xa] = { decode_subinsn_s1, decode_subinsn_s1 },
+[0xb] = { decode_subinsn_s2, decode_subinsn_s1 },
+[0xc] = { decode_subinsn_s2, decode_subinsn_l1 },
+[0xd] = { decode_subinsn_s2, decode_subinsn_l2 },
+[0xe] = { decode_subinsn_s2, decode_subinsn_s2 },
+[0xf] = { NULL,  NULL },  /* Reserved */
+};
+
+static uint16_t get_slot0_subinsn(uint32_t encoding)
+{
+return extract32(encoding, 0, 13);
+}
+
+static uint16_t get_slot1_subinsn(uint32_t encoding)
+{
+return extract32(encoding, 16, 13);
+}
+
 static unsigned int
 decode_insns(DisasContext *ctx, Insn *insn, uint32_t encoding)
 {
@@ -805,8 +870,28 @@ decode_insns(DisasContext *ctx, Insn *insn, uint32_t 
encoding)
 table = _table_DECODE_ROOT_32;
 g_assert_not_reached();
 } else {
+uint32_t iclass = get_duplex_iclass(encoding);
+unsigned int slot0_subinsn = get_slot0_subinsn(encoding);
+unsigned int slot1_subinsn = get_slot1_subinsn(encoding);
+subinsn_decode_func decode_slot0_subinsn =
+decode_groups[iclass].decode_slot0_subinsn;
+subinsn_decode_func decode_slot1_subinsn =
+decode_groups[iclass].decode_slot1_subinsn;
+
+/* The slot1 subinsn needs to be in the packet first */
+if (decode_slot1_subinsn(ctx, slot1_subinsn)) {
+insn->gener

[PATCH v2 3/3] Hexagon (target/hexagon) Remove old dectree.py

2024-01-08 Thread Taylor Simpson
Now that we are using QEMU decodetree.py, remove the old decoder

Signed-off-by: Taylor Simpson 
---
 target/hexagon/opcodes.h|   2 -
 target/hexagon/decode.c | 344 
 target/hexagon/gen_dectree_import.c |  49 
 target/hexagon/opcodes.c|  29 --
 target/hexagon/dectree.py   | 403 
 target/hexagon/meson.build  |  12 -
 6 files changed, 839 deletions(-)
 delete mode 100755 target/hexagon/dectree.py

diff --git a/target/hexagon/opcodes.h b/target/hexagon/opcodes.h
index 6e90e00fe2..fa7e321950 100644
--- a/target/hexagon/opcodes.h
+++ b/target/hexagon/opcodes.h
@@ -53,6 +53,4 @@ extern const OpcodeEncoding opcode_encodings[XX_LAST_OPCODE];
 
 void opcode_init(void);
 
-int opcode_which_immediate_is_extended(Opcode opcode);
-
 #endif
diff --git a/target/hexagon/decode.c b/target/hexagon/decode.c
index 160b23a895..a40210ca1e 100644
--- a/target/hexagon/decode.c
+++ b/target/hexagon/decode.c
@@ -88,175 +88,6 @@ static int shift_left(DisasContext *ctx, int x, int n, int 
immno)
 /* Include the generated helpers for the decoder */
 #include "decodetree_trans_funcs_generated.c.inc"
 
-typedef struct {
-const struct DectreeTable *table_link;
-const struct DectreeTable *table_link_b;
-Opcode opcode;
-enum {
-DECTREE_ENTRY_INVALID,
-DECTREE_TABLE_LINK,
-DECTREE_SUBINSNS,
-DECTREE_EXTSPACE,
-DECTREE_TERMINAL
-} type;
-} DectreeEntry;
-
-typedef struct DectreeTable {
-unsigned int (*lookup_function)(int startbit, int width, uint32_t opcode);
-unsigned int size;
-unsigned int startbit;
-unsigned int width;
-const DectreeEntry table[];
-} DectreeTable;
-
-#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) \
-static const DectreeTable dectree_table_##TAG;
-#define TABLE_LINK(TABLE) /* NOTHING */
-#define TERMINAL(TAG, ENC)/* NOTHING */
-#define SUBINSNS(TAG, CLASSA, CLASSB, ENC)/* NOTHING */
-#define EXTSPACE(TAG, ENC)/* NOTHING */
-#define INVALID() /* NOTHING */
-#define DECODE_END_TABLE(...) /* NOTHING */
-#define DECODE_MATCH_INFO(...)/* NOTHING */
-#define DECODE_LEGACY_MATCH_INFO(...) /* NOTHING */
-#define DECODE_OPINFO(...)/* NOTHING */
-
-#include "dectree_generated.h.inc"
-
-#undef DECODE_OPINFO
-#undef DECODE_MATCH_INFO
-#undef DECODE_LEGACY_MATCH_INFO
-#undef DECODE_END_TABLE
-#undef INVALID
-#undef TERMINAL
-#undef SUBINSNS
-#undef EXTSPACE
-#undef TABLE_LINK
-#undef DECODE_NEW_TABLE
-#undef DECODE_SEPARATOR_BITS
-
-#define DECODE_SEPARATOR_BITS(START, WIDTH) NULL, START, WIDTH
-#define DECODE_NEW_TABLE_HELPER(TAG, SIZE, FN, START, WIDTH) \
-static const DectreeTable dectree_table_##TAG = { \
-.size = SIZE, \
-.lookup_function = FN, \
-.startbit = START, \
-.width = WIDTH, \
-.table = {
-#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT) \
-DECODE_NEW_TABLE_HELPER(TAG, SIZE, WHATNOT)
-
-#define TABLE_LINK(TABLE) \
-{ .type = DECTREE_TABLE_LINK, .table_link = _table_##TABLE },
-#define TERMINAL(TAG, ENC) \
-{ .type = DECTREE_TERMINAL, .opcode = TAG  },
-#define SUBINSNS(TAG, CLASSA, CLASSB, ENC) \
-{ \
-.type = DECTREE_SUBINSNS, \
-.table_link = _table_DECODE_SUBINSN_##CLASSA, \
-.table_link_b = _table_DECODE_SUBINSN_##CLASSB \
-},
-#define EXTSPACE(TAG, ENC) { .type = DECTREE_EXTSPACE },
-#define INVALID() { .type = DECTREE_ENTRY_INVALID, .opcode = XX_LAST_OPCODE },
-
-#define DECODE_END_TABLE(...) } };
-
-#define DECODE_MATCH_INFO(...)/* NOTHING */
-#define DECODE_LEGACY_MATCH_INFO(...) /* NOTHING */
-#define DECODE_OPINFO(...)/* NOTHING */
-
-#include "dectree_generated.h.inc"
-
-#undef DECODE_OPINFO
-#undef DECODE_MATCH_INFO
-#undef DECODE_LEGACY_MATCH_INFO
-#undef DECODE_END_TABLE
-#undef INVALID
-#undef TERMINAL
-#undef SUBINSNS
-#undef EXTSPACE
-#undef TABLE_LINK
-#undef DECODE_NEW_TABLE
-#undef DECODE_NEW_TABLE_HELPER
-#undef DECODE_SEPARATOR_BITS
-
-static const DectreeTable dectree_table_DECODE_EXT_EXT_noext = {
-.size = 1, .lookup_function = NULL, .startbit = 0, .width = 0,
-.table = {
-{ .type = DECTREE_ENTRY_INVALID, .opcode = XX_LAST_OPCODE },
-}
-};
-
-static const DectreeTable *ext_trees[XX_LAST_EXT_IDX];
-
-static void decode_ext_init(void)
-{
-int i;
-for (i = EXT_IDX_noext; i < EXT_IDX_noext_AFTER; i++) {
-ext_trees[i] = _table_DECODE_EXT_EXT_noext;
-}
-for (i = EXT_IDX_mmvec; i < EXT_IDX_mmvec_AFTER; i++) {
-ext_trees[i] = _table_DECODE_EXT_EXT_mmvec;
-}
-}
-
-typedef struct {
-uint32_t mask;
-uint32_t match;
-} DecodeITableEntry;
-
-#define DECODE_NEW_TABLE(TAG, SIZE, WHATNOT)  /* NOTHING */
-#define TABLE_LINK(TABLE)

[PATCH v2 4/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs

2023-12-10 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_helper_funcs.py | 368 +
 target/hexagon/hex_common.py   |  48 +++-
 2 files changed, 103 insertions(+), 313 deletions(-)

diff --git a/target/hexagon/gen_helper_funcs.py 
b/target/hexagon/gen_helper_funcs.py
index ce21d3b688..9cc3d69c49 100755
--- a/target/hexagon/gen_helper_funcs.py
+++ b/target/hexagon/gen_helper_funcs.py
@@ -23,181 +23,14 @@
 import hex_common
 
 
-##
-## Helpers for gen_helper_function
-##
-def gen_decl_ea(f):
-f.write("uint32_t EA;\n")
-
-
-def gen_helper_return_type(f, regtype, regid, regno):
-if regno > 1:
-f.write(", ")
-f.write("int32_t")
-
-
-def gen_helper_return_type_pair(f, regtype, regid, regno):
-if regno > 1:
-f.write(", ")
-f.write("int64_t")
-
-
-def gen_helper_arg(f, regtype, regid, regno):
-if regno > 0:
-f.write(", ")
-f.write(f"int32_t {regtype}{regid}V")
-
-
-def gen_helper_arg_new(f, regtype, regid, regno):
-if regno >= 0:
-f.write(", ")
-f.write(f"int32_t {regtype}{regid}N")
-
-
-def gen_helper_arg_pair(f, regtype, regid, regno):
-if regno >= 0:
-f.write(", ")
-f.write(f"int64_t {regtype}{regid}V")
-
-
-def gen_helper_arg_ext(f, regtype, regid, regno):
-if regno > 0:
-f.write(", ")
-f.write(f"void *{regtype}{regid}V_void")
-
-
-def gen_helper_arg_ext_pair(f, regtype, regid, regno):
-if regno > 0:
-f.write(", ")
-f.write(f"void *{regtype}{regid}V_void")
-
-
-def gen_helper_arg_opn(f, regtype, regid, i, tag):
-if hex_common.is_pair(regid):
-if hex_common.is_hvx_reg(regtype):
-gen_helper_arg_ext_pair(f, regtype, regid, i)
-else:
-gen_helper_arg_pair(f, regtype, regid, i)
-elif hex_common.is_single(regid):
-if hex_common.is_old_val(regtype, regid, tag):
-if hex_common.is_hvx_reg(regtype):
-gen_helper_arg_ext(f, regtype, regid, i)
-else:
-gen_helper_arg(f, regtype, regid, i)
-elif hex_common.is_new_val(regtype, regid, tag):
-gen_helper_arg_new(f, regtype, regid, i)
-else:
-hex_common.bad_register(regtype, regid)
-else:
-hex_common.bad_register(regtype, regid)
-
-
-def gen_helper_arg_imm(f, immlett):
-f.write(f", int32_t {hex_common.imm_name(immlett)}")
-
-
-def gen_helper_dest_decl(f, regtype, regid, regno, subfield=""):
-f.write(f"int32_t {regtype}{regid}V{subfield} = 0;\n")
-
-
-def gen_helper_dest_decl_pair(f, regtype, regid, regno, subfield=""):
-f.write(f"int64_t {regtype}{regid}V{subfield} = 0;\n")
-
-
-def gen_helper_dest_decl_ext(f, regtype, regid):
-if regtype == "Q":
-f.write(
-f"/* {regtype}{regid}V is *(MMQReg *)" 
f"({regtype}{regid}V_void) */\n"
-)
-else:
-f.write(
-f"/* {regtype}{regid}V is *(MMVector *)"
-f"({regtype}{regid}V_void) */\n"
-)
-
-
-def gen_helper_dest_decl_ext_pair(f, regtype, regid, regno):
-f.write(
-f"/* {regtype}{regid}V is *(MMVectorPair *))"
-f"{regtype}{regid}V_void) */\n"
-)
-
-
-def gen_helper_dest_decl_opn(f, regtype, regid, i):
-if hex_common.is_pair(regid):
-if hex_common.is_hvx_reg(regtype):
-gen_helper_dest_decl_ext_pair(f, regtype, regid, i)
-else:
-gen_helper_dest_decl_pair(f, regtype, regid, i)
-elif hex_common.is_single(regid):
-if hex_common.is_hvx_reg(regtype):
-gen_helper_dest_decl_ext(f, regtype, regid)
-else:
-gen_helper_dest_decl(f, regtype, regid, i)
-else:
-hex_common.bad_register(regtype, regid)
-
-
-def gen_helper_src_var_ext(f, regtype, regid):
-if regtype == "Q":
-f.write(
-f"/* {regtype}{regid}V is *(MMQReg *)" 
f"({regtype}{regid}V_void) */\n"
-)
-else:
-f.write(
-f"/* {regtype}{regid}V is *(MMVector *)"
-f"({regtype}{regid}V_void) */\n"
-)
-
-
-def gen_helper_src_var_ext_pair(f, regtype, regid, regno):
-f.write(
-f"/* {regtype}{regid}V{regno} is *(MMVectorPair *)"
-f"({regtype}{regid}V{regno}_void) */\n"
-)
-
-
-def gen_helper_return(f, regtype, regid, regno):
-f.write(f"return {regtype}{regid}V;\n")
-
-
-def gen_helper_return_pair(f, regtype, regid, regno):
-f.write(f"return {regtype}{regid}V;\n")
-
-
-def gen_helper_dst_write_ext(f, regtype, regid):
-return
-
-
-def gen_helper_dst_write_ext_pair

[PATCH v2 8/9] Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute

2023-12-10 Thread Taylor Simpson
This is the only remaining use of the is_written function.  We will
remove it in the subsequent commit.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/attribs_def.h.inc |  1 -
 target/hexagon/hex_common.py | 11 ---
 2 files changed, 12 deletions(-)

diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 21d457fa4a..87942d46f4 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -117,7 +117,6 @@ DEF_ATTRIB(IMPLICIT_READS_P1, "Reads the P1 register", "", 
"")
 DEF_ATTRIB(IMPLICIT_READS_P2, "Reads the P2 register", "", "")
 DEF_ATTRIB(IMPLICIT_READS_P3, "Reads the P3 register", "", "")
 DEF_ATTRIB(IMPLICIT_WRITES_USR, "May write USR", "", "")
-DEF_ATTRIB(WRITES_PRED_REG, "Writes a predicate register", "", "")
 DEF_ATTRIB(COMMUTES, "The operation is communitive", "", "")
 DEF_ATTRIB(DEALLOCRET, "dealloc_return", "", "")
 DEF_ATTRIB(DEALLOCFRAME, "deallocframe", "", "")
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 4565dd1953..ca5e9630c1 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -94,10 +94,6 @@ def is_cond_call(tag):
 def calculate_attribs():
 add_qemu_macro_attrib("fREAD_PC", "A_IMPLICIT_READS_PC")
 add_qemu_macro_attrib("fTRAP", "A_IMPLICIT_READS_PC")
-add_qemu_macro_attrib("fWRITE_P0", "A_WRITES_PRED_REG")
-add_qemu_macro_attrib("fWRITE_P1", "A_WRITES_PRED_REG")
-add_qemu_macro_attrib("fWRITE_P2", "A_WRITES_PRED_REG")
-add_qemu_macro_attrib("fWRITE_P3", "A_WRITES_PRED_REG")
 add_qemu_macro_attrib("fSET_OVERFLOW", "A_IMPLICIT_WRITES_USR")
 add_qemu_macro_attrib("fSET_LPCFG", "A_IMPLICIT_WRITES_USR")
 add_qemu_macro_attrib("fLOAD", "A_SCALAR_LOAD")
@@ -122,13 +118,6 @@ def calculate_attribs():
 continue
 macro = macros[macname]
 attribdict[tag] |= set(macro.attribs)
-# Figure out which instructions write predicate registers
-tagregs = get_tagregs()
-for tag in tags:
-regs = tagregs[tag]
-for regtype, regid in regs:
-if regtype == "P" and is_written(regid):
-attribdict[tag].add("A_WRITES_PRED_REG")
 # Mark conditional jumps and calls
 # Not all instructions are properly marked with A_CONDEXEC
 for tag in tags:
-- 
2.34.1




[PATCH v2 5/9] Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs

2023-12-10 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_idef_parser_funcs.py | 20 
 1 file changed, 4 insertions(+), 16 deletions(-)

diff --git a/target/hexagon/gen_idef_parser_funcs.py 
b/target/hexagon/gen_idef_parser_funcs.py
index f4518e653f..550a48cb7b 100644
--- a/target/hexagon/gen_idef_parser_funcs.py
+++ b/target/hexagon/gen_idef_parser_funcs.py
@@ -46,6 +46,7 @@ def main():
 hex_common.read_semantics_file(sys.argv[1])
 hex_common.read_attribs_file(sys.argv[2])
 hex_common.calculate_attribs()
+hex_common.init_registers()
 tagregs = hex_common.get_tagregs()
 tagimms = hex_common.get_tagimms()
 
@@ -132,22 +133,9 @@ def main():
 
 arguments = []
 for regtype, regid in regs:
-prefix = "in " if hex_common.is_read(regid) else ""
-
-is_pair = hex_common.is_pair(regid)
-is_single_old = hex_common.is_single(regid) and 
hex_common.is_old_val(
-regtype, regid, tag
-)
-is_single_new = hex_common.is_single(regid) and 
hex_common.is_new_val(
-regtype, regid, tag
-)
-
-if is_pair or is_single_old:
-arguments.append(f"{prefix}{regtype}{regid}V")
-elif is_single_new:
-arguments.append(f"{prefix}{regtype}{regid}N")
-else:
-hex_common.bad_register(regtype, regid)
+reg = hex_common.get_register(tag, regtype, regid)
+prefix = "in " if reg.is_read() else ""
+arguments.append(f"{prefix}{reg.reg_tcg()}")
 
 for immlett, bits, immshift in imms:
 arguments.append(hex_common.imm_name(immlett))
-- 
2.34.1




[PATCH v2 7/9] Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs

2023-12-10 Thread Taylor Simpson
This patch conflicts with
https://lists.gnu.org/archive/html/qemu-devel/2023-11/msg00729.html
If that series goes in first, we'll rework this patch and vice versa.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_analyze_funcs.py | 163 +---
 target/hexagon/hex_common.py| 151 ++
 2 files changed, 157 insertions(+), 157 deletions(-)

diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index c3b521abef..a9af666cef 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -23,162 +23,6 @@
 import hex_common
 
 
-##
-## Helpers for gen_analyze_func
-##
-def is_predicated(tag):
-return "A_CONDEXEC" in hex_common.attribdict[tag]
-
-
-def analyze_opn_old(f, tag, regtype, regid, regno):
-regN = f"{regtype}{regid}N"
-predicated = "true" if is_predicated(tag) else "false"
-if regtype == "R":
-if regid in {"ss", "tt"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_reg_read_pair(ctx, {regN});\n")
-elif regid in {"dd", "ee", "xx", "yy"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_reg_write_pair(ctx, {regN}, 
{predicated});\n")
-elif regid in {"s", "t", "u", "v"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_reg_read(ctx, {regN});\n")
-elif regid in {"d", "e", "x", "y"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_reg_write(ctx, {regN}, {predicated});\n")
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "P":
-if regid in {"s", "t", "u", "v"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_pred_read(ctx, {regN});\n")
-elif regid in {"d", "e", "x"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_pred_write(ctx, {regN});\n")
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "C":
-if regid == "ss":
-f.write(
-f"const int {regN} = insn->regno[{regno}] "
-"+ HEX_REG_SA0;\n"
-)
-f.write(f"ctx_log_reg_read_pair(ctx, {regN});\n")
-elif regid == "dd":
-f.write(f"const int {regN} = insn->regno[{regno}] " "+ 
HEX_REG_SA0;\n")
-f.write(f"ctx_log_reg_write_pair(ctx, {regN}, 
{predicated});\n")
-elif regid == "s":
-f.write(
-f"const int {regN} = insn->regno[{regno}] "
-"+ HEX_REG_SA0;\n"
-)
-f.write(f"ctx_log_reg_read(ctx, {regN});\n")
-elif regid == "d":
-f.write(f"const int {regN} = insn->regno[{regno}] " "+ 
HEX_REG_SA0;\n")
-f.write(f"ctx_log_reg_write(ctx, {regN}, {predicated});\n")
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "M":
-if regid == "u":
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_reg_read(ctx, {regN});\n")
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "V":
-newv = "EXT_DFL"
-if hex_common.is_new_result(tag):
-newv = "EXT_NEW"
-elif hex_common.is_tmp_result(tag):
-newv = "EXT_TMP"
-if regid in {"dd", "xx"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(
-f"ctx_log_vreg_write_pair(ctx, {regN}, {newv}, " 
f"{predicated});\n"
-)
-elif regid in {"uu", "vv"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_vreg_read_pair(ctx, {regN});\n")
-elif regid in {"s", "u", "v", "w"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-  

[PATCH v2 9/9] Hexagon (target/hexagon) Remove dead functions from hex_common.py

2023-12-10 Thread Taylor Simpson
These functions are no longer used after making the generators
object oriented.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/hex_common.py | 51 
 1 file changed, 51 deletions(-)

diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index ca5e9630c1..195620c7ec 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -33,9 +33,6 @@
 overrides = {}  # tags with helper overrides
 idef_parser_enabled = {}  # tags enabled for idef-parser
 
-def bad_register(regtype, regid):
-raise Exception(f"Bad register parse: regtype '{regtype}' regid '{regid}'")
-
 # We should do this as a hash for performance,
 # but to keep order let's keep it as a list.
 def uniquify(seq):
@@ -200,46 +197,6 @@ def get_tagimms():
 return dict(zip(tags, list(map(compute_tag_immediates, tags
 
 
-def is_pair(regid):
-return len(regid) == 2
-
-
-def is_single(regid):
-return len(regid) == 1
-
-
-def is_written(regid):
-return regid[0] in "dexy"
-
-
-def is_writeonly(regid):
-return regid[0] in "de"
-
-
-def is_read(regid):
-return regid[0] in "stuvwxy"
-
-
-def is_readwrite(regid):
-return regid[0] in "xy"
-
-
-def is_scalar_reg(regtype):
-return regtype in "RPC"
-
-
-def is_hvx_reg(regtype):
-return regtype in "VQ"
-
-
-def is_old_val(regtype, regid, tag):
-return regtype + regid + "V" in semdict[tag]
-
-
-def is_new_val(regtype, regid, tag):
-return regtype + regid + "N" in semdict[tag]
-
-
 def need_slot(tag):
 if (
 "A_CVI_SCATTER" not in attribdict[tag]
@@ -280,14 +237,6 @@ def skip_qemu_helper(tag):
 return tag in overrides.keys()
 
 
-def is_tmp_result(tag):
-return "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]
-
-
-def is_new_result(tag):
-return "A_CVI_NEW" in attribdict[tag]
-
-
 def is_idef_parser_enabled(tag):
 return tag in idef_parser_enabled
 
-- 
2.34.1




[PATCH v2 0/9] Hexagon (target/hexagon) Make generators object oriented

2023-12-10 Thread Taylor Simpson
See commit message in second patch

 Changes in v2 
Address feedback from Brian Cain 
- Consolidate logic to create helper arg lists


Taylor Simpson (9):
  Hexagon (target/hexagon) Clean up handling of modifier registers
  Hexagon (target/hexagon) Make generators object oriented -
gen_tcg_funcs
  Hexagon (target/hexagon) Make generators object oriented -
gen_helper_protos
  Hexagon (target/hexagon) Make generators object oriented -
gen_helper_funcs
  Hexagon (target/hexagon) Make generators object oriented -
gen_idef_parser_funcs
  Hexagon (target/hexagon) Make generators object oriented - gen_op_regs
  Hexagon (target/hexagon) Make generators object oriented -
gen_analyze_funcs
  Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute
  Hexagon (target/hexagon) Remove dead functions from hex_common.py

 target/hexagon/gen_tcg.h|   9 +-
 target/hexagon/macros.h |   3 +-
 target/hexagon/attribs_def.h.inc|   1 -
 target/hexagon/idef-parser/parser-helpers.c |   8 +-
 target/hexagon/gen_analyze_funcs.py | 163 +---
 target/hexagon/gen_helper_funcs.py  | 368 ++--
 target/hexagon/gen_helper_protos.py | 149 +---
 target/hexagon/gen_idef_parser_funcs.py |  20 +-
 target/hexagon/gen_op_regs.py   |   6 +-
 target/hexagon/gen_tcg_funcs.py | 566 +---
 target/hexagon/hex_common.py| 921 ++--
 11 files changed, 964 insertions(+), 1250 deletions(-)

-- 
2.34.1




[PATCH v2 2/9] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs

2023-12-10 Thread Taylor Simpson
The generators are generally a bunch of Python if-then-else
statements based on the regtype and regid.  Encapsulate regtype/regid
into a class hierarchy.  Clients lookup the register and invoke
methods.

This has several advantages for making the code easier to read,
understand, and maintain
- The class name makes it more clear what the operand does
- All the methods for a given type of operand are together
- Don't need hex_common.bad_register
  If a regtype/regid is missing, the lookup in hex_common.get_register
  will fail
- We can remove the functions in hex_common that use regtype/regid
  (e.g., is_read)

This patch creates the class hierarchy in hex_common and converts
gen_tcg_funcs.py.  The other scripts will be converted in subsequent
patches in this series.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_tcg_funcs.py | 571 ++-
 target/hexagon/hex_common.py| 659 
 2 files changed, 683 insertions(+), 547 deletions(-)

diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index 02d93bc5ce..3d8e3cb6a2 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -23,466 +23,13 @@
 import hex_common
 
 
-##
-## Helpers for gen_tcg_func
-##
-def gen_decl_ea_tcg(f, tag):
-f.write("TCGv EA G_GNUC_UNUSED = tcg_temp_new();\n")
-
-
-def genptr_decl_pair_writable(f, tag, regtype, regid, regno):
-regN = f"{regtype}{regid}N"
-if regtype == "R":
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-elif regtype == "C":
-f.write(f"const int {regN} = insn->regno[{regno}] + 
HEX_REG_SA0;\n")
-else:
-hex_common.bad_register(regtype, regid)
-f.write(f"TCGv_i64 {regtype}{regid}V = " f"get_result_gpr_pair(ctx, 
{regN});\n")
-
-
-def genptr_decl_writable(f, tag, regtype, regid, regno):
-regN = f"{regtype}{regid}N"
-if regtype == "R":
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"TCGv {regtype}{regid}V = get_result_gpr(ctx, {regN});\n")
-elif regtype == "C":
-f.write(f"const int {regN} = insn->regno[{regno}] + 
HEX_REG_SA0;\n")
-f.write(f"TCGv {regtype}{regid}V = get_result_gpr(ctx, {regN});\n")
-elif regtype == "P":
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"TCGv {regtype}{regid}V = tcg_temp_new();\n")
-else:
-hex_common.bad_register(regtype, regid)
-
-
-def genptr_decl(f, tag, regtype, regid, regno):
-regN = f"{regtype}{regid}N"
-if regtype == "R":
-if regid in {"ss", "tt"}:
-f.write(f"TCGv_i64 {regtype}{regid}V = tcg_temp_new_i64();\n")
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-elif regid in {"dd", "ee", "xx", "yy"}:
-genptr_decl_pair_writable(f, tag, regtype, regid, regno)
-elif regid in {"s", "t", "u", "v"}:
-f.write(
-f"TCGv {regtype}{regid}V = " 
f"hex_gpr[insn->regno[{regno}]];\n"
-)
-elif regid in {"d", "e", "x", "y"}:
-genptr_decl_writable(f, tag, regtype, regid, regno)
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "P":
-if regid in {"s", "t", "u", "v"}:
-f.write(
-f"TCGv {regtype}{regid}V = " 
f"hex_pred[insn->regno[{regno}]];\n"
-)
-elif regid in {"d", "e", "x"}:
-genptr_decl_writable(f, tag, regtype, regid, regno)
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "C":
-if regid == "ss":
-f.write(f"TCGv_i64 {regtype}{regid}V = " 
f"tcg_temp_new_i64();\n")
-f.write(f"const int {regN} = insn->regno[{regno}] + " 
"HEX_REG_SA0;\n")
-elif regid == "dd":
-genptr_decl_pair_writable(f, tag, regtype, regid, regno)
-elif regid == "s":
-f.write(f"TCGv {regtype}{regid}V = tcg_temp_new();\n")
-f.write(
-f"const int {regtype}{regid}N = insn->regno[{regno}] + "
-"HEX_REG_SA0;\n"
-)
-elif regid == "d":
-genptr_decl_writable(f, tag, regtype, regid, regno)
-else:
-hex_common.bad_register(regtype, regid)

[PATCH v2 1/9] Hexagon (target/hexagon) Clean up handling of modifier registers

2023-12-10 Thread Taylor Simpson
Currently, the register number (MuN) for modifier registers is the
modifier register number rather than the index into hex_gpr.  This
patch changes MuN to the hex_gpr index, which is consistent with
the handling of control registers.

Note that HELPER(fcircadd) needs the CS register corresponding to the
modifier register specified in the instruction.  We create a TCGv
variable "CS" to hold the value to pass to the helper.

Reviewed-by: Brian Cain 
Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_tcg.h|  9 -
 target/hexagon/macros.h |  3 +--
 target/hexagon/idef-parser/parser-helpers.c |  8 +++-
 target/hexagon/gen_tcg_funcs.py | 13 +
 4 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index d992059fce..1c4391b415 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -68,15 +68,14 @@
 do { \
 TCGv tcgv_siV = tcg_constant_tl(siV); \
 tcg_gen_mov_tl(EA, RxV); \
-gen_helper_fcircadd(RxV, RxV, tcgv_siV, MuV, \
-hex_gpr[HEX_REG_CS0 + MuN]); \
+gen_helper_fcircadd(RxV, RxV, tcgv_siV, MuV, CS); \
 } while (0)
 #define GET_EA_pcr(SHIFT) \
 do { \
 TCGv ireg = tcg_temp_new(); \
 tcg_gen_mov_tl(EA, RxV); \
 gen_read_ireg(ireg, MuV, (SHIFT)); \
-gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
+gen_helper_fcircadd(RxV, RxV, ireg, MuV, CS); \
 } while (0)
 
 /* Instructions with multiple definitions */
@@ -113,7 +112,7 @@
 TCGv ireg = tcg_temp_new(); \
 tcg_gen_mov_tl(EA, RxV); \
 gen_read_ireg(ireg, MuV, SHIFT); \
-gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
+gen_helper_fcircadd(RxV, RxV, ireg, MuV, CS); \
 LOAD; \
 } while (0)
 
@@ -427,7 +426,7 @@
 TCGv BYTE G_GNUC_UNUSED = tcg_temp_new(); \
 tcg_gen_mov_tl(EA, RxV); \
 gen_read_ireg(ireg, MuV, SHIFT); \
-gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
+gen_helper_fcircadd(RxV, RxV, ireg, MuV, CS); \
 STORE; \
 } while (0)
 
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 9a51b5709b..939f22e76b 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -462,8 +462,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int 
shift)
 #define fPM_CIRI(REG, IMM, MVAL) \
 do { \
 TCGv tcgv_siV = tcg_constant_tl(siV); \
-gen_helper_fcircadd(REG, REG, tcgv_siV, MuV, \
-hex_gpr[HEX_REG_CS0 + MuN]); \
+gen_helper_fcircadd(REG, REG, tcgv_siV, MuV, CS); \
 } while (0)
 #else
 #define fEA_IMM(IMM)do { EA = (IMM); } while (0)
diff --git a/target/hexagon/idef-parser/parser-helpers.c 
b/target/hexagon/idef-parser/parser-helpers.c
index 4af020933a..95f2b43076 100644
--- a/target/hexagon/idef-parser/parser-helpers.c
+++ b/target/hexagon/idef-parser/parser-helpers.c
@@ -1541,10 +1541,8 @@ void gen_circ_op(Context *c,
  HexValue *increment,
  HexValue *modifier)
 {
-HexValue cs = gen_tmp(c, locp, 32, UNSIGNED);
 HexValue increment_m = *increment;
 increment_m = rvalue_materialize(c, locp, _m);
-OUT(c, locp, "gen_read_reg(", , ", HEX_REG_CS0 + MuN);\n");
 OUT(c,
 locp,
 "gen_helper_fcircadd(",
@@ -1555,7 +1553,7 @@ void gen_circ_op(Context *c,
 _m,
 ", ",
 modifier);
-OUT(c, locp, ", ", , ");\n");
+OUT(c, locp, ", CS);\n");
 }
 
 HexValue gen_locnt_op(Context *c, YYLTYPE *locp, HexValue *src)
@@ -2080,9 +2078,9 @@ void emit_arg(Context *c, YYLTYPE *locp, HexValue *arg)
 char reg_id[5];
 reg_compose(c, locp, &(arg->reg), reg_id);
 EMIT_SIG(c, ", %s %s", type, reg_id);
-/* MuV register requires also MuN to provide its index */
+/* MuV register requires also CS for circular addressing*/
 if (arg->reg.type == MODIFIER) {
-EMIT_SIG(c, ", int MuN");
+EMIT_SIG(c, ", TCGv CS");
 }
 }
 break;
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index f5246cee6d..02d93bc5ce 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -99,10 +99,15 @@ def genptr_decl(f, tag, regtype, regid, regno):
 hex_common.bad_register(regtype, regid)
 elif regtype == "M":
 if regid == "u":
-f.write(f"const int {regtype}{regid}N = " 
f"insn->regno[{regno}];\n")
 f.write(
-f"TCGv {regtype}{regid}V = hex_gpr[{regtype}{regid}N + "
-

[PATCH v2 3/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos

2023-12-10 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_helper_protos.py | 149 ++--
 target/hexagon/hex_common.py|   7 --
 2 files changed, 8 insertions(+), 148 deletions(-)

diff --git a/target/hexagon/gen_helper_protos.py 
b/target/hexagon/gen_helper_protos.py
index 131043795a..c82b0f54e4 100755
--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -22,39 +22,6 @@
 import string
 import hex_common
 
-##
-## Helpers for gen_helper_prototype
-##
-def_helper_types = {
-"N": "s32",
-"O": "s32",
-"P": "s32",
-"M": "s32",
-"C": "s32",
-"R": "s32",
-"V": "ptr",
-"Q": "ptr",
-}
-
-def_helper_types_pair = {
-"R": "s64",
-"C": "s64",
-"S": "s64",
-"G": "s64",
-"V": "ptr",
-"Q": "ptr",
-}
-
-
-def gen_def_helper_opn(f, tag, regtype, regid, i):
-if hex_common.is_pair(regid):
-f.write(f", {def_helper_types_pair[regtype]}")
-elif hex_common.is_single(regid):
-f.write(f", {def_helper_types[regtype]}")
-else:
-hex_common.bad_register(regtype, regid)
-
-
 ##
 ## Generate the DEF_HELPER prototype for an instruction
 ## For A2_add: Rd32=add(Rs32,Rt32)
@@ -65,116 +32,15 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
 regs = tagregs[tag]
 imms = tagimms[tag]
 
-numresults = 0
-numscalarresults = 0
-numscalarreadwrite = 0
-for regtype, regid in regs:
-if hex_common.is_written(regid):
-numresults += 1
-if hex_common.is_scalar_reg(regtype):
-numscalarresults += 1
-if hex_common.is_readwrite(regid):
-if hex_common.is_scalar_reg(regtype):
-numscalarreadwrite += 1
-
-if numscalarresults > 1:
-## The helper is bogus when there is more than one result
-f.write(f"DEF_HELPER_1({tag}, void, env)\n")
-else:
-## Figure out how many arguments the helper will take
-if numscalarresults == 0:
-def_helper_size = len(regs) + len(imms) + numscalarreadwrite + 1
-if hex_common.need_pkt_has_multi_cof(tag):
-def_helper_size += 1
-if hex_common.need_pkt_need_commit(tag):
-def_helper_size += 1
-if hex_common.need_part1(tag):
-def_helper_size += 1
-if hex_common.need_slot(tag):
-def_helper_size += 1
-if hex_common.need_PC(tag):
-def_helper_size += 1
-if hex_common.helper_needs_next_PC(tag):
-def_helper_size += 1
-if hex_common.need_condexec_reg(tag, regs):
-def_helper_size += 1
-f.write(f"DEF_HELPER_{def_helper_size}({tag}")
-## The return type is void
-f.write(", void")
-else:
-def_helper_size = len(regs) + len(imms) + numscalarreadwrite
-if hex_common.need_pkt_has_multi_cof(tag):
-def_helper_size += 1
-if hex_common.need_pkt_need_commit(tag):
-def_helper_size += 1
-if hex_common.need_part1(tag):
-def_helper_size += 1
-if hex_common.need_slot(tag):
-def_helper_size += 1
-if hex_common.need_PC(tag):
-def_helper_size += 1
-if hex_common.need_condexec_reg(tag, regs):
-def_helper_size += 1
-if hex_common.helper_needs_next_PC(tag):
-def_helper_size += 1
-f.write(f"DEF_HELPER_{def_helper_size}({tag}")
-
-## Generate the qemu DEF_HELPER type for each result
-## Iterate over this list twice
-## - Emit the scalar result
-## - Emit the vector result
-i = 0
-for regtype, regid in regs:
-if hex_common.is_written(regid):
-if not hex_common.is_hvx_reg(regtype):
-gen_def_helper_opn(f, tag, regtype, regid, i)
-i += 1
-
-## Put the env between the outputs and inputs
-f.write(", env")
-i += 1
-
-# Second pass
-for regtype, regid in regs:
-if hex_common.is_written(regid):
-if hex_common.is_hvx_reg(regtype):
-gen_def_helper_opn(f, tag, regtype, regid, i)
-i += 1
-
-## For conditional instructions, we pass in the destination register
-if "A_CONDEXEC" in hex_common.attribdict[tag]:
-for regtype, regid in regs:
-if hex_common.is_writeonly(regid) and not 
hex_common.is_hvx_reg(
-   

[PATCH v2 6/9] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs

2023-12-10 Thread Taylor Simpson
Reviewed-by: Brian Cain 
Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_op_regs.py | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/gen_op_regs.py b/target/hexagon/gen_op_regs.py
index a8a7712129..7b7b33895a 100755
--- a/target/hexagon/gen_op_regs.py
+++ b/target/hexagon/gen_op_regs.py
@@ -70,6 +70,7 @@ def strip_reg_prefix(x):
 def main():
 hex_common.read_semantics_file(sys.argv[1])
 hex_common.read_attribs_file(sys.argv[2])
+hex_common.init_registers()
 tagregs = hex_common.get_tagregs(full=True)
 tagimms = hex_common.get_tagimms()
 
@@ -80,11 +81,12 @@ def main():
 wregs = []
 regids = ""
 for regtype, regid, _, numregs in regs:
-if hex_common.is_read(regid):
+reg = hex_common.get_register(tag, regtype, regid)
+if reg.is_read():
 if regid[0] not in regids:
 regids += regid[0]
 rregs.append(regtype + regid + numregs)
-if hex_common.is_written(regid):
+if reg.is_written():
 wregs.append(regtype + regid + numregs)
 if regid[0] not in regids:
 regids += regid[0]
-- 
2.34.1




[PATCH 4/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_funcs

2023-12-04 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_helper_funcs.py | 400 +++--
 target/hexagon/hex_common.py   |  58 -
 2 files changed, 151 insertions(+), 307 deletions(-)

diff --git a/target/hexagon/gen_helper_funcs.py 
b/target/hexagon/gen_helper_funcs.py
index ce21d3b688..60b7e95e8c 100755
--- a/target/hexagon/gen_helper_funcs.py
+++ b/target/hexagon/gen_helper_funcs.py
@@ -23,181 +23,14 @@
 import hex_common
 
 
-##
-## Helpers for gen_helper_function
-##
-def gen_decl_ea(f):
-f.write("uint32_t EA;\n")
-
-
-def gen_helper_return_type(f, regtype, regid, regno):
-if regno > 1:
-f.write(", ")
-f.write("int32_t")
-
-
-def gen_helper_return_type_pair(f, regtype, regid, regno):
-if regno > 1:
-f.write(", ")
-f.write("int64_t")
-
-
-def gen_helper_arg(f, regtype, regid, regno):
-if regno > 0:
-f.write(", ")
-f.write(f"int32_t {regtype}{regid}V")
-
-
-def gen_helper_arg_new(f, regtype, regid, regno):
-if regno >= 0:
-f.write(", ")
-f.write(f"int32_t {regtype}{regid}N")
-
-
-def gen_helper_arg_pair(f, regtype, regid, regno):
-if regno >= 0:
-f.write(", ")
-f.write(f"int64_t {regtype}{regid}V")
-
-
-def gen_helper_arg_ext(f, regtype, regid, regno):
-if regno > 0:
-f.write(", ")
-f.write(f"void *{regtype}{regid}V_void")
-
-
-def gen_helper_arg_ext_pair(f, regtype, regid, regno):
-if regno > 0:
-f.write(", ")
-f.write(f"void *{regtype}{regid}V_void")
-
-
-def gen_helper_arg_opn(f, regtype, regid, i, tag):
-if hex_common.is_pair(regid):
-if hex_common.is_hvx_reg(regtype):
-gen_helper_arg_ext_pair(f, regtype, regid, i)
-else:
-gen_helper_arg_pair(f, regtype, regid, i)
-elif hex_common.is_single(regid):
-if hex_common.is_old_val(regtype, regid, tag):
-if hex_common.is_hvx_reg(regtype):
-gen_helper_arg_ext(f, regtype, regid, i)
-else:
-gen_helper_arg(f, regtype, regid, i)
-elif hex_common.is_new_val(regtype, regid, tag):
-gen_helper_arg_new(f, regtype, regid, i)
-else:
-hex_common.bad_register(regtype, regid)
-else:
-hex_common.bad_register(regtype, regid)
-
-
-def gen_helper_arg_imm(f, immlett):
-f.write(f", int32_t {hex_common.imm_name(immlett)}")
-
-
-def gen_helper_dest_decl(f, regtype, regid, regno, subfield=""):
-f.write(f"int32_t {regtype}{regid}V{subfield} = 0;\n")
-
-
-def gen_helper_dest_decl_pair(f, regtype, regid, regno, subfield=""):
-f.write(f"int64_t {regtype}{regid}V{subfield} = 0;\n")
-
-
-def gen_helper_dest_decl_ext(f, regtype, regid):
-if regtype == "Q":
-f.write(
-f"/* {regtype}{regid}V is *(MMQReg *)" 
f"({regtype}{regid}V_void) */\n"
-)
-else:
-f.write(
-f"/* {regtype}{regid}V is *(MMVector *)"
-f"({regtype}{regid}V_void) */\n"
-)
-
-
-def gen_helper_dest_decl_ext_pair(f, regtype, regid, regno):
-f.write(
-f"/* {regtype}{regid}V is *(MMVectorPair *))"
-f"{regtype}{regid}V_void) */\n"
-)
-
-
-def gen_helper_dest_decl_opn(f, regtype, regid, i):
-if hex_common.is_pair(regid):
-if hex_common.is_hvx_reg(regtype):
-gen_helper_dest_decl_ext_pair(f, regtype, regid, i)
-else:
-gen_helper_dest_decl_pair(f, regtype, regid, i)
-elif hex_common.is_single(regid):
-if hex_common.is_hvx_reg(regtype):
-gen_helper_dest_decl_ext(f, regtype, regid)
-else:
-gen_helper_dest_decl(f, regtype, regid, i)
-else:
-hex_common.bad_register(regtype, regid)
-
-
-def gen_helper_src_var_ext(f, regtype, regid):
-if regtype == "Q":
-f.write(
-f"/* {regtype}{regid}V is *(MMQReg *)" 
f"({regtype}{regid}V_void) */\n"
-)
-else:
-f.write(
-f"/* {regtype}{regid}V is *(MMVector *)"
-f"({regtype}{regid}V_void) */\n"
-)
-
-
-def gen_helper_src_var_ext_pair(f, regtype, regid, regno):
-f.write(
-f"/* {regtype}{regid}V{regno} is *(MMVectorPair *)"
-f"({regtype}{regid}V{regno}_void) */\n"
-)
-
-
-def gen_helper_return(f, regtype, regid, regno):
-f.write(f"return {regtype}{regid}V;\n")
-
-
-def gen_helper_return_pair(f, regtype, regid, regno):
-f.write(f"return {regtype}{regid}V;\n")
-
-
-def gen_helper_dst_write_ext(f, regtype, regid):
-return
-
-
-def gen_helper_dst_write_ext_pair

[PATCH 9/9] Hexagon (target/hexagon) Remove dead functions from hex_common.py

2023-12-04 Thread Taylor Simpson
These functions are no longer used after making the generators
object oriented.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/hex_common.py | 51 
 1 file changed, 51 deletions(-)

diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index 59fed78ab0..90d61a1b16 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -33,9 +33,6 @@
 overrides = {}  # tags with helper overrides
 idef_parser_enabled = {}  # tags enabled for idef-parser
 
-def bad_register(regtype, regid):
-raise Exception(f"Bad register parse: regtype '{regtype}' regid '{regid}'")
-
 # We should do this as a hash for performance,
 # but to keep order let's keep it as a list.
 def uniquify(seq):
@@ -200,46 +197,6 @@ def get_tagimms():
 return dict(zip(tags, list(map(compute_tag_immediates, tags
 
 
-def is_pair(regid):
-return len(regid) == 2
-
-
-def is_single(regid):
-return len(regid) == 1
-
-
-def is_written(regid):
-return regid[0] in "dexy"
-
-
-def is_writeonly(regid):
-return regid[0] in "de"
-
-
-def is_read(regid):
-return regid[0] in "stuvwxy"
-
-
-def is_readwrite(regid):
-return regid[0] in "xy"
-
-
-def is_scalar_reg(regtype):
-return regtype in "RPC"
-
-
-def is_hvx_reg(regtype):
-return regtype in "VQ"
-
-
-def is_old_val(regtype, regid, tag):
-return regtype + regid + "V" in semdict[tag]
-
-
-def is_new_val(regtype, regid, tag):
-return regtype + regid + "N" in semdict[tag]
-
-
 def need_slot(tag):
 if (
 "A_CVI_SCATTER" not in attribdict[tag]
@@ -280,14 +237,6 @@ def skip_qemu_helper(tag):
 return tag in overrides.keys()
 
 
-def is_tmp_result(tag):
-return "A_CVI_TMP" in attribdict[tag] or "A_CVI_TMP_DST" in attribdict[tag]
-
-
-def is_new_result(tag):
-return "A_CVI_NEW" in attribdict[tag]
-
-
 def is_idef_parser_enabled(tag):
 return tag in idef_parser_enabled
 
-- 
2.34.1




[PATCH 7/9] Hexagon (target/hexagon) Make generators object oriented - gen_analyze_funcs

2023-12-04 Thread Taylor Simpson
This patch conflicts with
https://lists.gnu.org/archive/html/qemu-devel/2023-11/msg00729.html
If that series goes in first, we'll rework this patch and vice versa.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_analyze_funcs.py | 163 +---
 target/hexagon/hex_common.py| 151 ++
 2 files changed, 157 insertions(+), 157 deletions(-)

diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index c3b521abef..a9af666cef 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -23,162 +23,6 @@
 import hex_common
 
 
-##
-## Helpers for gen_analyze_func
-##
-def is_predicated(tag):
-return "A_CONDEXEC" in hex_common.attribdict[tag]
-
-
-def analyze_opn_old(f, tag, regtype, regid, regno):
-regN = f"{regtype}{regid}N"
-predicated = "true" if is_predicated(tag) else "false"
-if regtype == "R":
-if regid in {"ss", "tt"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_reg_read_pair(ctx, {regN});\n")
-elif regid in {"dd", "ee", "xx", "yy"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_reg_write_pair(ctx, {regN}, 
{predicated});\n")
-elif regid in {"s", "t", "u", "v"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_reg_read(ctx, {regN});\n")
-elif regid in {"d", "e", "x", "y"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_reg_write(ctx, {regN}, {predicated});\n")
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "P":
-if regid in {"s", "t", "u", "v"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_pred_read(ctx, {regN});\n")
-elif regid in {"d", "e", "x"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_pred_write(ctx, {regN});\n")
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "C":
-if regid == "ss":
-f.write(
-f"const int {regN} = insn->regno[{regno}] "
-"+ HEX_REG_SA0;\n"
-)
-f.write(f"ctx_log_reg_read_pair(ctx, {regN});\n")
-elif regid == "dd":
-f.write(f"const int {regN} = insn->regno[{regno}] " "+ 
HEX_REG_SA0;\n")
-f.write(f"ctx_log_reg_write_pair(ctx, {regN}, 
{predicated});\n")
-elif regid == "s":
-f.write(
-f"const int {regN} = insn->regno[{regno}] "
-"+ HEX_REG_SA0;\n"
-)
-f.write(f"ctx_log_reg_read(ctx, {regN});\n")
-elif regid == "d":
-f.write(f"const int {regN} = insn->regno[{regno}] " "+ 
HEX_REG_SA0;\n")
-f.write(f"ctx_log_reg_write(ctx, {regN}, {predicated});\n")
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "M":
-if regid == "u":
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_reg_read(ctx, {regN});\n")
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "V":
-newv = "EXT_DFL"
-if hex_common.is_new_result(tag):
-newv = "EXT_NEW"
-elif hex_common.is_tmp_result(tag):
-newv = "EXT_TMP"
-if regid in {"dd", "xx"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(
-f"ctx_log_vreg_write_pair(ctx, {regN}, {newv}, " 
f"{predicated});\n"
-)
-elif regid in {"uu", "vv"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_vreg_read_pair(ctx, {regN});\n")
-elif regid in {"s", "u", "v", "w"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-  

[PATCH 1/9] Hexagon (target/hexagon) Clean up handling of modifier registers

2023-12-04 Thread Taylor Simpson
Currently, the register number (MuN) for modifier registers is the
modifier register number rather than the index into hex_gpr.  This
patch changes MuN to the hex_gpr index, which is consistent with
the handling of control registers.

Note that HELPER(fcircadd) needs the CS register corresponding to the
modifier register specified in the instruction.  We create a TCGv
variable "CS" to hold the value to pass to the helper.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_tcg.h|  9 -
 target/hexagon/macros.h |  3 +--
 target/hexagon/idef-parser/parser-helpers.c |  8 +++-
 target/hexagon/gen_tcg_funcs.py | 13 +
 4 files changed, 17 insertions(+), 16 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index d992059fce..1c4391b415 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -68,15 +68,14 @@
 do { \
 TCGv tcgv_siV = tcg_constant_tl(siV); \
 tcg_gen_mov_tl(EA, RxV); \
-gen_helper_fcircadd(RxV, RxV, tcgv_siV, MuV, \
-hex_gpr[HEX_REG_CS0 + MuN]); \
+gen_helper_fcircadd(RxV, RxV, tcgv_siV, MuV, CS); \
 } while (0)
 #define GET_EA_pcr(SHIFT) \
 do { \
 TCGv ireg = tcg_temp_new(); \
 tcg_gen_mov_tl(EA, RxV); \
 gen_read_ireg(ireg, MuV, (SHIFT)); \
-gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
+gen_helper_fcircadd(RxV, RxV, ireg, MuV, CS); \
 } while (0)
 
 /* Instructions with multiple definitions */
@@ -113,7 +112,7 @@
 TCGv ireg = tcg_temp_new(); \
 tcg_gen_mov_tl(EA, RxV); \
 gen_read_ireg(ireg, MuV, SHIFT); \
-gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
+gen_helper_fcircadd(RxV, RxV, ireg, MuV, CS); \
 LOAD; \
 } while (0)
 
@@ -427,7 +426,7 @@
 TCGv BYTE G_GNUC_UNUSED = tcg_temp_new(); \
 tcg_gen_mov_tl(EA, RxV); \
 gen_read_ireg(ireg, MuV, SHIFT); \
-gen_helper_fcircadd(RxV, RxV, ireg, MuV, hex_gpr[HEX_REG_CS0 + MuN]); \
+gen_helper_fcircadd(RxV, RxV, ireg, MuV, CS); \
 STORE; \
 } while (0)
 
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 9a51b5709b..939f22e76b 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -462,8 +462,7 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int 
shift)
 #define fPM_CIRI(REG, IMM, MVAL) \
 do { \
 TCGv tcgv_siV = tcg_constant_tl(siV); \
-gen_helper_fcircadd(REG, REG, tcgv_siV, MuV, \
-hex_gpr[HEX_REG_CS0 + MuN]); \
+gen_helper_fcircadd(REG, REG, tcgv_siV, MuV, CS); \
 } while (0)
 #else
 #define fEA_IMM(IMM)do { EA = (IMM); } while (0)
diff --git a/target/hexagon/idef-parser/parser-helpers.c 
b/target/hexagon/idef-parser/parser-helpers.c
index 4af020933a..95f2b43076 100644
--- a/target/hexagon/idef-parser/parser-helpers.c
+++ b/target/hexagon/idef-parser/parser-helpers.c
@@ -1541,10 +1541,8 @@ void gen_circ_op(Context *c,
  HexValue *increment,
  HexValue *modifier)
 {
-HexValue cs = gen_tmp(c, locp, 32, UNSIGNED);
 HexValue increment_m = *increment;
 increment_m = rvalue_materialize(c, locp, _m);
-OUT(c, locp, "gen_read_reg(", , ", HEX_REG_CS0 + MuN);\n");
 OUT(c,
 locp,
 "gen_helper_fcircadd(",
@@ -1555,7 +1553,7 @@ void gen_circ_op(Context *c,
 _m,
 ", ",
 modifier);
-OUT(c, locp, ", ", , ");\n");
+OUT(c, locp, ", CS);\n");
 }
 
 HexValue gen_locnt_op(Context *c, YYLTYPE *locp, HexValue *src)
@@ -2080,9 +2078,9 @@ void emit_arg(Context *c, YYLTYPE *locp, HexValue *arg)
 char reg_id[5];
 reg_compose(c, locp, &(arg->reg), reg_id);
 EMIT_SIG(c, ", %s %s", type, reg_id);
-/* MuV register requires also MuN to provide its index */
+/* MuV register requires also CS for circular addressing*/
 if (arg->reg.type == MODIFIER) {
-EMIT_SIG(c, ", int MuN");
+EMIT_SIG(c, ", TCGv CS");
 }
 }
 break;
diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index f5246cee6d..02d93bc5ce 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -99,10 +99,15 @@ def genptr_decl(f, tag, regtype, regid, regno):
 hex_common.bad_register(regtype, regid)
 elif regtype == "M":
 if regid == "u":
-f.write(f"const int {regtype}{regid}N = " 
f"insn->regno[{regno}];\n")
 f.write(
-f"TCGv {regtype}{regid}V = hex_gpr[{regtype}{regid}N + "
-"

[PATCH 2/9] Hexagon (target/hexagon) Make generators object oriented - gen_tcg_funcs

2023-12-04 Thread Taylor Simpson
The generators are generally a bunch of Python if-then-else
statements based on the regtype and regid.  Encapsulate regtype/regid
into a class hierarchy.  Clients lookup the register and invoke
methods.

This has several advantages for making the code easier to read,
understand, and maintain
- The class name makes it more clear what the operand does
- All the methods for a given type of operand are together
- Don't need hex_common.bad_register
  If a regtype/regid is missing, the lookup in hex_common.get_register
  will fail
- We can remove the functions in hex_common that use regtype/regid
  (e.g., is_read)

This patch creates the class hierarchy in hex_common and converts
gen_tcg_funcs.py.  The other scripts will be converted in subsequent
patches in this series.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_tcg_funcs.py | 583 +++-
 target/hexagon/hex_common.py| 542 +
 2 files changed, 589 insertions(+), 536 deletions(-)

diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index 02d93bc5ce..8c2bc03c10 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -23,466 +23,13 @@
 import hex_common
 
 
-##
-## Helpers for gen_tcg_func
-##
-def gen_decl_ea_tcg(f, tag):
-f.write("TCGv EA G_GNUC_UNUSED = tcg_temp_new();\n")
-
-
-def genptr_decl_pair_writable(f, tag, regtype, regid, regno):
-regN = f"{regtype}{regid}N"
-if regtype == "R":
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-elif regtype == "C":
-f.write(f"const int {regN} = insn->regno[{regno}] + 
HEX_REG_SA0;\n")
-else:
-hex_common.bad_register(regtype, regid)
-f.write(f"TCGv_i64 {regtype}{regid}V = " f"get_result_gpr_pair(ctx, 
{regN});\n")
-
-
-def genptr_decl_writable(f, tag, regtype, regid, regno):
-regN = f"{regtype}{regid}N"
-if regtype == "R":
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"TCGv {regtype}{regid}V = get_result_gpr(ctx, {regN});\n")
-elif regtype == "C":
-f.write(f"const int {regN} = insn->regno[{regno}] + 
HEX_REG_SA0;\n")
-f.write(f"TCGv {regtype}{regid}V = get_result_gpr(ctx, {regN});\n")
-elif regtype == "P":
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"TCGv {regtype}{regid}V = tcg_temp_new();\n")
-else:
-hex_common.bad_register(regtype, regid)
-
-
-def genptr_decl(f, tag, regtype, regid, regno):
-regN = f"{regtype}{regid}N"
-if regtype == "R":
-if regid in {"ss", "tt"}:
-f.write(f"TCGv_i64 {regtype}{regid}V = tcg_temp_new_i64();\n")
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-elif regid in {"dd", "ee", "xx", "yy"}:
-genptr_decl_pair_writable(f, tag, regtype, regid, regno)
-elif regid in {"s", "t", "u", "v"}:
-f.write(
-f"TCGv {regtype}{regid}V = " 
f"hex_gpr[insn->regno[{regno}]];\n"
-)
-elif regid in {"d", "e", "x", "y"}:
-genptr_decl_writable(f, tag, regtype, regid, regno)
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "P":
-if regid in {"s", "t", "u", "v"}:
-f.write(
-f"TCGv {regtype}{regid}V = " 
f"hex_pred[insn->regno[{regno}]];\n"
-)
-elif regid in {"d", "e", "x"}:
-genptr_decl_writable(f, tag, regtype, regid, regno)
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "C":
-if regid == "ss":
-f.write(f"TCGv_i64 {regtype}{regid}V = " 
f"tcg_temp_new_i64();\n")
-f.write(f"const int {regN} = insn->regno[{regno}] + " 
"HEX_REG_SA0;\n")
-elif regid == "dd":
-genptr_decl_pair_writable(f, tag, regtype, regid, regno)
-elif regid == "s":
-f.write(f"TCGv {regtype}{regid}V = tcg_temp_new();\n")
-f.write(
-f"const int {regtype}{regid}N = insn->regno[{regno}] + "
-"HEX_REG_SA0;\n"
-)
-elif regid == "d":
-genptr_decl_writable(f, tag, regtype, regid, regno)
-else:
-hex_common.bad_register(regtype,

[PATCH 6/9] Hexagon (target/hexagon) Make generators object oriented - gen_op_regs

2023-12-04 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_op_regs.py | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/gen_op_regs.py b/target/hexagon/gen_op_regs.py
index a8a7712129..7b7b33895a 100755
--- a/target/hexagon/gen_op_regs.py
+++ b/target/hexagon/gen_op_regs.py
@@ -70,6 +70,7 @@ def strip_reg_prefix(x):
 def main():
 hex_common.read_semantics_file(sys.argv[1])
 hex_common.read_attribs_file(sys.argv[2])
+hex_common.init_registers()
 tagregs = hex_common.get_tagregs(full=True)
 tagimms = hex_common.get_tagimms()
 
@@ -80,11 +81,12 @@ def main():
 wregs = []
 regids = ""
 for regtype, regid, _, numregs in regs:
-if hex_common.is_read(regid):
+reg = hex_common.get_register(tag, regtype, regid)
+if reg.is_read():
 if regid[0] not in regids:
 regids += regid[0]
 rregs.append(regtype + regid + numregs)
-if hex_common.is_written(regid):
+if reg.is_written():
 wregs.append(regtype + regid + numregs)
 if regid[0] not in regids:
 regids += regid[0]
-- 
2.34.1




[PATCH 8/9] Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute

2023-12-04 Thread Taylor Simpson
This is the only remaining use of the is_written function.  We will
remove it in the subsequent commit.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/attribs_def.h.inc |  1 -
 target/hexagon/hex_common.py | 11 ---
 2 files changed, 12 deletions(-)

diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 21d457fa4a..87942d46f4 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -117,7 +117,6 @@ DEF_ATTRIB(IMPLICIT_READS_P1, "Reads the P1 register", "", 
"")
 DEF_ATTRIB(IMPLICIT_READS_P2, "Reads the P2 register", "", "")
 DEF_ATTRIB(IMPLICIT_READS_P3, "Reads the P3 register", "", "")
 DEF_ATTRIB(IMPLICIT_WRITES_USR, "May write USR", "", "")
-DEF_ATTRIB(WRITES_PRED_REG, "Writes a predicate register", "", "")
 DEF_ATTRIB(COMMUTES, "The operation is communitive", "", "")
 DEF_ATTRIB(DEALLOCRET, "dealloc_return", "", "")
 DEF_ATTRIB(DEALLOCFRAME, "deallocframe", "", "")
diff --git a/target/hexagon/hex_common.py b/target/hexagon/hex_common.py
index e64d114cf3..59fed78ab0 100755
--- a/target/hexagon/hex_common.py
+++ b/target/hexagon/hex_common.py
@@ -94,10 +94,6 @@ def is_cond_call(tag):
 def calculate_attribs():
 add_qemu_macro_attrib("fREAD_PC", "A_IMPLICIT_READS_PC")
 add_qemu_macro_attrib("fTRAP", "A_IMPLICIT_READS_PC")
-add_qemu_macro_attrib("fWRITE_P0", "A_WRITES_PRED_REG")
-add_qemu_macro_attrib("fWRITE_P1", "A_WRITES_PRED_REG")
-add_qemu_macro_attrib("fWRITE_P2", "A_WRITES_PRED_REG")
-add_qemu_macro_attrib("fWRITE_P3", "A_WRITES_PRED_REG")
 add_qemu_macro_attrib("fSET_OVERFLOW", "A_IMPLICIT_WRITES_USR")
 add_qemu_macro_attrib("fSET_LPCFG", "A_IMPLICIT_WRITES_USR")
 add_qemu_macro_attrib("fLOAD", "A_SCALAR_LOAD")
@@ -122,13 +118,6 @@ def calculate_attribs():
 continue
 macro = macros[macname]
 attribdict[tag] |= set(macro.attribs)
-# Figure out which instructions write predicate registers
-tagregs = get_tagregs()
-for tag in tags:
-regs = tagregs[tag]
-for regtype, regid in regs:
-if regtype == "P" and is_written(regid):
-attribdict[tag].add("A_WRITES_PRED_REG")
 # Mark conditional jumps and calls
 # Not all instructions are properly marked with A_CONDEXEC
 for tag in tags:
-- 
2.34.1




[PATCH 3/9] Hexagon (target/hexagon) Make generators object oriented - gen_helper_protos

2023-12-04 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_helper_protos.py | 184 
 target/hexagon/hex_common.py|  15 +--
 2 files changed, 55 insertions(+), 144 deletions(-)

diff --git a/target/hexagon/gen_helper_protos.py 
b/target/hexagon/gen_helper_protos.py
index 131043795a..9277199e1d 100755
--- a/target/hexagon/gen_helper_protos.py
+++ b/target/hexagon/gen_helper_protos.py
@@ -22,39 +22,6 @@
 import string
 import hex_common
 
-##
-## Helpers for gen_helper_prototype
-##
-def_helper_types = {
-"N": "s32",
-"O": "s32",
-"P": "s32",
-"M": "s32",
-"C": "s32",
-"R": "s32",
-"V": "ptr",
-"Q": "ptr",
-}
-
-def_helper_types_pair = {
-"R": "s64",
-"C": "s64",
-"S": "s64",
-"G": "s64",
-"V": "ptr",
-"Q": "ptr",
-}
-
-
-def gen_def_helper_opn(f, tag, regtype, regid, i):
-if hex_common.is_pair(regid):
-f.write(f", {def_helper_types_pair[regtype]}")
-elif hex_common.is_single(regid):
-f.write(f", {def_helper_types[regtype]}")
-else:
-hex_common.bad_register(regtype, regid)
-
-
 ##
 ## Generate the DEF_HELPER prototype for an instruction
 ## For A2_add: Rd32=add(Rs32,Rt32)
@@ -65,116 +32,62 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
 regs = tagregs[tag]
 imms = tagimms[tag]
 
-numresults = 0
+## If there is a scalar result, it is the return type
+return_type = ""
 numscalarresults = 0
-numscalarreadwrite = 0
 for regtype, regid in regs:
-if hex_common.is_written(regid):
-numresults += 1
-if hex_common.is_scalar_reg(regtype):
+reg = hex_common.get_register(tag, regtype, regid)
+if reg.is_written() and reg.is_scalar_reg():
+return_type = reg.helper_proto_type()
 numscalarresults += 1
-if hex_common.is_readwrite(regid):
-if hex_common.is_scalar_reg(regtype):
-numscalarreadwrite += 1
+if numscalarresults == 0:
+return_type = "void"
 
 if numscalarresults > 1:
-## The helper is bogus when there is more than one result
-f.write(f"DEF_HELPER_1({tag}, void, env)\n")
-else:
-## Figure out how many arguments the helper will take
-if numscalarresults == 0:
-def_helper_size = len(regs) + len(imms) + numscalarreadwrite + 1
-if hex_common.need_pkt_has_multi_cof(tag):
-def_helper_size += 1
-if hex_common.need_pkt_need_commit(tag):
-def_helper_size += 1
-if hex_common.need_part1(tag):
-def_helper_size += 1
-if hex_common.need_slot(tag):
-def_helper_size += 1
-if hex_common.need_PC(tag):
-def_helper_size += 1
-if hex_common.helper_needs_next_PC(tag):
-def_helper_size += 1
-if hex_common.need_condexec_reg(tag, regs):
-def_helper_size += 1
-f.write(f"DEF_HELPER_{def_helper_size}({tag}")
-## The return type is void
-f.write(", void")
-else:
-def_helper_size = len(regs) + len(imms) + numscalarreadwrite
-if hex_common.need_pkt_has_multi_cof(tag):
-def_helper_size += 1
-if hex_common.need_pkt_need_commit(tag):
-def_helper_size += 1
-if hex_common.need_part1(tag):
-def_helper_size += 1
-if hex_common.need_slot(tag):
-def_helper_size += 1
-if hex_common.need_PC(tag):
-def_helper_size += 1
-if hex_common.need_condexec_reg(tag, regs):
-def_helper_size += 1
-if hex_common.helper_needs_next_PC(tag):
-def_helper_size += 1
-f.write(f"DEF_HELPER_{def_helper_size}({tag}")
-
-## Generate the qemu DEF_HELPER type for each result
-## Iterate over this list twice
-## - Emit the scalar result
-## - Emit the vector result
-i = 0
-for regtype, regid in regs:
-if hex_common.is_written(regid):
-if not hex_common.is_hvx_reg(regtype):
-gen_def_helper_opn(f, tag, regtype, regid, i)
-i += 1
+raise Exception("numscalarresults > 1")
 
-## Put the env between the outputs and inputs
-f.write(", env")
-i += 1
+declared = []
+declared.append(return_type)
 
-# Second pass
-for regtyp

[PATCH 0/9] Hexagon (target/hexagon) Make generators object oriented

2023-12-04 Thread Taylor Simpson
See commit message in second patch

Taylor Simpson (9):
  Hexagon (target/hexagon) Clean up handling of modifier registers
  Hexagon (target/hexagon) Make generators object oriented -
gen_tcg_funcs
  Hexagon (target/hexagon) Make generators object oriented -
gen_helper_protos
  Hexagon (target/hexagon) Make generators object oriented -
gen_helper_funcs
  Hexagon (target/hexagon) Make generators object oriented -
gen_idef_parser_funcs
  Hexagon (target/hexagon) Make generators object oriented - gen_op_regs
  Hexagon (target/hexagon) Make generators object oriented -
gen_analyze_funcs
  Hexagon (target/hexagon) Remove unused WRITES_PRED_REG attribute
  Hexagon (target/hexagon) Remove dead functions from hex_common.py

 target/hexagon/gen_tcg.h|   9 +-
 target/hexagon/macros.h |   3 +-
 target/hexagon/attribs_def.h.inc|   1 -
 target/hexagon/idef-parser/parser-helpers.c |   8 +-
 target/hexagon/gen_analyze_funcs.py | 163 +---
 target/hexagon/gen_helper_funcs.py  | 400 +++---
 target/hexagon/gen_helper_protos.py | 184 ++---
 target/hexagon/gen_idef_parser_funcs.py |  20 +-
 target/hexagon/gen_op_regs.py   |   6 +-
 target/hexagon/gen_tcg_funcs.py | 578 ++
 target/hexagon/hex_common.py| 818 ++--
 11 files changed, 963 insertions(+), 1227 deletions(-)

-- 
2.34.1




[PATCH 5/9] Hexagon (target/hexagon) Make generators object oriented - gen_idef_parser_funcs

2023-12-04 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_idef_parser_funcs.py | 20 
 1 file changed, 4 insertions(+), 16 deletions(-)

diff --git a/target/hexagon/gen_idef_parser_funcs.py 
b/target/hexagon/gen_idef_parser_funcs.py
index f4518e653f..550a48cb7b 100644
--- a/target/hexagon/gen_idef_parser_funcs.py
+++ b/target/hexagon/gen_idef_parser_funcs.py
@@ -46,6 +46,7 @@ def main():
 hex_common.read_semantics_file(sys.argv[1])
 hex_common.read_attribs_file(sys.argv[2])
 hex_common.calculate_attribs()
+hex_common.init_registers()
 tagregs = hex_common.get_tagregs()
 tagimms = hex_common.get_tagimms()
 
@@ -132,22 +133,9 @@ def main():
 
 arguments = []
 for regtype, regid in regs:
-prefix = "in " if hex_common.is_read(regid) else ""
-
-is_pair = hex_common.is_pair(regid)
-is_single_old = hex_common.is_single(regid) and 
hex_common.is_old_val(
-regtype, regid, tag
-)
-is_single_new = hex_common.is_single(regid) and 
hex_common.is_new_val(
-regtype, regid, tag
-)
-
-if is_pair or is_single_old:
-arguments.append(f"{prefix}{regtype}{regid}V")
-elif is_single_new:
-arguments.append(f"{prefix}{regtype}{regid}N")
-else:
-hex_common.bad_register(regtype, regid)
+reg = hex_common.get_register(tag, regtype, regid)
+prefix = "in " if reg.is_read() else ""
+arguments.append(f"{prefix}{reg.reg_tcg()}")
 
 for immlett, bits, immshift in imms:
 arguments.append(hex_common.imm_name(immlett))
-- 
2.34.1




[PATCH] Hexagon (target/hexagon) Fix shadow variable when idef-parser is off

2023-11-30 Thread Taylor Simpson
Adding -Werror=shadow=compatible-local causes Hexagon not to build
when idef-parser is off.  The "label" variable in CHECK_NOSHUF_PRED
shadows a variable in the surrounding code.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/macros.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 9a51b5709b..f99390e2a8 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -93,13 +93,13 @@
 
 #define CHECK_NOSHUF_PRED(GET_EA, SIZE, PRED) \
 do { \
-TCGLabel *label = gen_new_label(); \
-tcg_gen_brcondi_tl(TCG_COND_EQ, PRED, 0, label); \
+TCGLabel *noshuf_label = gen_new_label(); \
+tcg_gen_brcondi_tl(TCG_COND_EQ, PRED, 0, noshuf_label); \
 GET_EA; \
 if (insn->slot == 0 && ctx->pkt->pkt_has_store_s1) { \
 probe_noshuf_load(EA, SIZE, ctx->mem_idx); \
 } \
-gen_set_label(label); \
+gen_set_label(noshuf_label); \
 if (insn->slot == 0 && ctx->pkt->pkt_has_store_s1) { \
 process_store(ctx, 1); \
 } \
-- 
2.34.1




[RFC PATCH] Hexagon (target/hexagon) Make generators object oriented

2023-11-09 Thread Taylor Simpson
RFC - This patch handles gen_tcg_funcs.py.  I'd like to get comments
on the general approach before working on the other Python scripts.

The generators are generally a bunch of Python if-then-else
statements based on the regtype and regid.  Encapsulate regtype/regid
into a class hierarchy.  Clients lookup the register and invoke
methods.

This has several advantages for making the code easier to read,
understand, and maintain
- The class name makes it more clear what the operand does
- All the methods for a given type of operand are together
- Don't need as many calls to hex_common.bad_register
- We can remove the functions in hex_common that use regtype/regid
  (e.g., is_read)

Signed-off-by: Taylor Simpson 
---
 target/hexagon/gen_tcg_funcs.py | 568 +++-
 target/hexagon/hex_common.py| 467 ++
 2 files changed, 509 insertions(+), 526 deletions(-)

diff --git a/target/hexagon/gen_tcg_funcs.py b/target/hexagon/gen_tcg_funcs.py
index f5246cee6d..f7a0c59397 100755
--- a/target/hexagon/gen_tcg_funcs.py
+++ b/target/hexagon/gen_tcg_funcs.py
@@ -23,454 +23,6 @@
 import hex_common
 
 
-##
-## Helpers for gen_tcg_func
-##
-def gen_decl_ea_tcg(f, tag):
-f.write("TCGv EA G_GNUC_UNUSED = tcg_temp_new();\n")
-
-
-def genptr_decl_pair_writable(f, tag, regtype, regid, regno):
-regN = f"{regtype}{regid}N"
-if regtype == "R":
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-elif regtype == "C":
-f.write(f"const int {regN} = insn->regno[{regno}] + 
HEX_REG_SA0;\n")
-else:
-hex_common.bad_register(regtype, regid)
-f.write(f"TCGv_i64 {regtype}{regid}V = " f"get_result_gpr_pair(ctx, 
{regN});\n")
-
-
-def genptr_decl_writable(f, tag, regtype, regid, regno):
-regN = f"{regtype}{regid}N"
-if regtype == "R":
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"TCGv {regtype}{regid}V = get_result_gpr(ctx, {regN});\n")
-elif regtype == "C":
-f.write(f"const int {regN} = insn->regno[{regno}] + 
HEX_REG_SA0;\n")
-f.write(f"TCGv {regtype}{regid}V = get_result_gpr(ctx, {regN});\n")
-elif regtype == "P":
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"TCGv {regtype}{regid}V = tcg_temp_new();\n")
-else:
-hex_common.bad_register(regtype, regid)
-
-
-def genptr_decl(f, tag, regtype, regid, regno):
-regN = f"{regtype}{regid}N"
-if regtype == "R":
-if regid in {"ss", "tt"}:
-f.write(f"TCGv_i64 {regtype}{regid}V = tcg_temp_new_i64();\n")
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-elif regid in {"dd", "ee", "xx", "yy"}:
-genptr_decl_pair_writable(f, tag, regtype, regid, regno)
-elif regid in {"s", "t", "u", "v"}:
-f.write(
-f"TCGv {regtype}{regid}V = " 
f"hex_gpr[insn->regno[{regno}]];\n"
-)
-elif regid in {"d", "e", "x", "y"}:
-genptr_decl_writable(f, tag, regtype, regid, regno)
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "P":
-if regid in {"s", "t", "u", "v"}:
-f.write(
-f"TCGv {regtype}{regid}V = " 
f"hex_pred[insn->regno[{regno}]];\n"
-)
-elif regid in {"d", "e", "x"}:
-genptr_decl_writable(f, tag, regtype, regid, regno)
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "C":
-if regid == "ss":
-f.write(f"TCGv_i64 {regtype}{regid}V = " 
f"tcg_temp_new_i64();\n")
-f.write(f"const int {regN} = insn->regno[{regno}] + " 
"HEX_REG_SA0;\n")
-elif regid == "dd":
-genptr_decl_pair_writable(f, tag, regtype, regid, regno)
-elif regid == "s":
-f.write(f"TCGv {regtype}{regid}V = tcg_temp_new();\n")
-f.write(
-f"const int {regtype}{regid}N = insn->regno[{regno}] + "
-"HEX_REG_SA0;\n"
-)
-elif regid == "d":
-genptr_decl_writable(f, tag, regtype, regid, regno)
-else:
-hex_common.bad_register(regtype, regid)
-elif regtype == "M":
-if regid == "u":
-f

[PATCH 2/3] Hexagon (target/hexagon) Enable more short-circuit packets (scalar core)

2023-11-03 Thread Taylor Simpson
Look for read-after-write instead of overlap of reads and writes

Here is an example with overalp but no read-after-write:
0x000200fc:  0x38103876 {   R0 = add(R0,R1); R6 = add(R6,R7) }

BEFORE:
  000200fc
 mov_i32 loc2,$0x0
 mov_i32 loc2,r0
 add_i32 loc3,loc2,r1
 mov_i32 loc2,loc3
 mov_i32 loc4,$0x0
 mov_i32 loc4,r6
 add_i32 loc5,loc4,r7
 mov_i32 loc4,loc5
 mov_i32 r0,loc2
 mov_i32 r6,loc4

AFTER:
  000200fc
 add_i32 loc2,r0,r1
 mov_i32 r0,loc2
 add_i32 loc3,r6,r7
 mov_i32 r6,loc3

We can also short-circuit packets with .new values by reading from the
real destination instead of the temporary.
0x00020100:  0x78005ff3 {   R19 = #0xff
0x00020104:  0x2002e204 if (cmp.eq(N19.new,R2)) jump:t PC+8 }

BEFORE:
  00020100
 mov_i32 pc,$0x20108
 mov_i32 loc8,$0x0
 mov_i32 loc8,$0xff
 setcond_i32 loc10,loc8,r2,eq
 mov_i32 loc6,loc10
 mov_i32 r19,loc8
 add_i32 pkt_cnt,pkt_cnt,$0x2
 add_i32 insn_cnt,insn_cnt,$0x4
 brcond_i32 loc6,$0x0,eq,$L1
 goto_tb $0x0
 mov_i32 pc,$0x20108
 exit_tb $0x7fbb5440
 set_label $L1
 goto_tb $0x1
 exit_tb $0x7fbb5441
 set_label $L0
 exit_tb $0x7fbb5443

AFTER:
  00020100
 mov_i32 pc,$0x20108
 mov_i32 r19,$0xff
 setcond_i32 loc7,r19,r2,eq
 mov_i32 loc4,loc7
 add_i32 pkt_cnt,pkt_cnt,$0x2
 add_i32 insn_cnt,insn_cnt,$0x4
 brcond_i32 loc4,$0x0,eq,$L1
 goto_tb $0x0
 mov_i32 pc,$0x20108
 exit_tb $0x7f976440
 set_label $L1
 goto_tb $0x1
 exit_tb $0x7f976441
 set_label $L0
 exit_tb $0x7f976443

Signed-off-by: Taylor Simpson 
---
 target/hexagon/translate.h  | 13 +++--
 target/hexagon/translate.c  | 19 +++
 target/hexagon/gen_tcg_funcs.py |  2 +-
 3 files changed, 11 insertions(+), 23 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index b2fe3a048d..7bb19ee672 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -38,12 +38,10 @@ typedef struct DisasContext {
 int reg_log[REG_WRITES_MAX];
 int reg_log_idx;
 DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
-DECLARE_BITMAP(regs_read, TOTAL_PER_THREAD_REGS);
 DECLARE_BITMAP(predicated_regs, TOTAL_PER_THREAD_REGS);
 int preg_log[PRED_WRITES_MAX];
 int preg_log_idx;
 DECLARE_BITMAP(pregs_written, NUM_PREGS);
-DECLARE_BITMAP(pregs_read, NUM_PREGS);
 uint8_t store_width[STORES_MAX];
 bool s1_store_processed;
 int future_vregs_idx;
@@ -68,6 +66,7 @@ typedef struct DisasContext {
 bool is_tight_loop;
 bool short_circuit;
 bool has_hvx_helper;
+bool read_after_write;
 TCGv new_value[TOTAL_PER_THREAD_REGS];
 TCGv new_pred_value[NUM_PREGS];
 TCGv pred_written;
@@ -88,13 +87,14 @@ static inline void ctx_log_pred_write(DisasContext *ctx, 
int pnum)
 
 static inline void ctx_log_pred_read(DisasContext *ctx, int pnum)
 {
-set_bit(pnum, ctx->pregs_read);
+if (test_bit(pnum, ctx->pregs_written)) {
+ctx->read_after_write = true;
+}
 }
 
 static inline void ctx_log_pred_read_new(DisasContext *ctx, int pnum)
 {
 g_assert(test_bit(pnum, ctx->pregs_written));
-set_bit(pnum, ctx->pregs_read);
 }
 
 static inline void ctx_log_reg_write(DisasContext *ctx, int rnum,
@@ -125,13 +125,14 @@ static inline void ctx_log_reg_write_pair(DisasContext 
*ctx, int rnum,
 
 static inline void ctx_log_reg_read(DisasContext *ctx, int rnum)
 {
-set_bit(rnum, ctx->regs_read);
+if (test_bit(rnum, ctx->regs_written)) {
+ctx->read_after_write = true;
+}
 }
 
 static inline void ctx_log_reg_read_new(DisasContext *ctx, int rnum)
 {
 g_assert(test_bit(rnum, ctx->regs_written));
-set_bit(rnum, ctx->regs_read);
 }
 
 static inline void ctx_log_reg_read_pair(DisasContext *ctx, int rnum)
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 666c061180..9dab26ee17 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -394,20 +394,8 @@ static bool need_commit(DisasContext *ctx)
 }
 }
 
-/* Check for overlap between register reads and writes */
-for (int i = 0; i < ctx->reg_log_idx; i++) {
-int rnum = ctx->reg_log[i];
-if (test_bit(rnum, ctx->regs_read)) {
-return true;
-}
-}
-
-/* Check for overlap between predicate reads and writes */
-for (int i = 0; i < ctx->preg_log_idx; i++) {
-int pnum = ctx->preg_log[i];
-if (test_bit(pnum, ctx->pregs_read)) {
-return true;
-}
+if (ctx->read_after_write) {
+return true;
 }
 
 /* Check for overlap between HVX reads and writes */
@@ -466,6 +454,7 @@ static void analyze_packet(DisasContext *ctx)
 {
 Packet *pkt = ctx->pkt;
 ctx->has_hvx_helper = false;
+ctx->read_after_write = false;
 for (int i = 0; i < pkt->num_insns; i++) {
 Insn *insn = >insn[i];
 ctx->insn = insn;
@@ -490,11 +479,9 

[PATCH 3/3] Hexagon (target/hexagon) Enable more short-circuit packets (HVX)

2023-11-03 Thread Taylor Simpson
Look for read-after-write instead of overlap of reads and writes
HVX instructions with helpers have pass-by-reference semantics, so
we check for overlaps of reads and writes within the same instruction.

Signed-off-by: Taylor Simpson 
---
 target/hexagon/translate.h  | 88 +++--
 target/hexagon/translate.c  | 58 ++-
 target/hexagon/gen_analyze_funcs.py | 51 +++--
 target/hexagon/hex_common.py| 10 
 4 files changed, 120 insertions(+), 87 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 7bb19ee672..7f47db71e8 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -50,23 +50,27 @@ typedef struct DisasContext {
 int tmp_vregs_num[VECTOR_TEMPS_MAX];
 int vreg_log[NUM_VREGS];
 int vreg_log_idx;
+DECLARE_BITMAP(vregs_written, NUM_VREGS);
+DECLARE_BITMAP(insn_vregs_written, NUM_VREGS);
 DECLARE_BITMAP(vregs_updated_tmp, NUM_VREGS);
 DECLARE_BITMAP(vregs_updated, NUM_VREGS);
 DECLARE_BITMAP(vregs_select, NUM_VREGS);
 DECLARE_BITMAP(predicated_future_vregs, NUM_VREGS);
 DECLARE_BITMAP(predicated_tmp_vregs, NUM_VREGS);
-DECLARE_BITMAP(vregs_read, NUM_VREGS);
+DECLARE_BITMAP(insn_vregs_read, NUM_VREGS);
 int qreg_log[NUM_QREGS];
 int qreg_log_idx;
-DECLARE_BITMAP(qregs_read, NUM_QREGS);
+DECLARE_BITMAP(qregs_written, NUM_QREGS);
+DECLARE_BITMAP(insn_qregs_written, NUM_QREGS);
+DECLARE_BITMAP(insn_qregs_read, NUM_QREGS);
 bool pre_commit;
 bool need_commit;
 TCGCond branch_cond;
 target_ulong branch_dest;
 bool is_tight_loop;
 bool short_circuit;
-bool has_hvx_helper;
 bool read_after_write;
+bool has_hvx_overlap;
 TCGv new_value[TOTAL_PER_THREAD_REGS];
 TCGv new_pred_value[NUM_PREGS];
 TCGv pred_written;
@@ -146,10 +150,25 @@ intptr_t ctx_future_vreg_off(DisasContext *ctx, int 
regnum,
 intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
   int num, bool alloc_ok);
 
+static inline void ctx_start_hvx_insn(DisasContext *ctx)
+{
+bitmap_zero(ctx->insn_vregs_written, NUM_VREGS);
+bitmap_zero(ctx->insn_vregs_read, NUM_VREGS);
+bitmap_zero(ctx->insn_qregs_written, NUM_QREGS);
+bitmap_zero(ctx->insn_qregs_read, NUM_QREGS);
+}
+
 static inline void ctx_log_vreg_write(DisasContext *ctx,
   int rnum, VRegWriteType type,
-  bool is_predicated)
+  bool is_predicated, bool has_helper)
 {
+if (has_helper) {
+set_bit(rnum, ctx->insn_vregs_written);
+if (test_bit(rnum, ctx->insn_vregs_read)) {
+ctx->has_hvx_overlap = true;
+}
+}
+set_bit(rnum, ctx->vregs_written);
 if (type != EXT_TMP) {
 if (!test_bit(rnum, ctx->vregs_updated)) {
 ctx->vreg_log[ctx->vreg_log_idx] = rnum;
@@ -175,42 +194,77 @@ static inline void ctx_log_vreg_write(DisasContext *ctx,
 
 static inline void ctx_log_vreg_write_pair(DisasContext *ctx,
int rnum, VRegWriteType type,
-   bool is_predicated)
+   bool is_predicated, bool has_helper)
 {
-ctx_log_vreg_write(ctx, rnum ^ 0, type, is_predicated);
-ctx_log_vreg_write(ctx, rnum ^ 1, type, is_predicated);
+ctx_log_vreg_write(ctx, rnum ^ 0, type, is_predicated, has_helper);
+ctx_log_vreg_write(ctx, rnum ^ 1, type, is_predicated, has_helper);
 }
 
-static inline void ctx_log_vreg_read(DisasContext *ctx, int rnum)
+static inline void ctx_log_vreg_read(DisasContext *ctx, int rnum,
+ bool has_helper)
 {
-set_bit(rnum, ctx->vregs_read);
+if (has_helper) {
+set_bit(rnum, ctx->insn_vregs_read);
+if (test_bit(rnum, ctx->insn_vregs_written)) {
+ctx->has_hvx_overlap = true;
+}
+}
+if (test_bit(rnum, ctx->vregs_written)) {
+ctx->read_after_write = true;
+}
 }
 
-static inline void ctx_log_vreg_read_new(DisasContext *ctx, int rnum)
+static inline void ctx_log_vreg_read_new(DisasContext *ctx, int rnum,
+ bool has_helper)
 {
 g_assert(is_gather_store_insn(ctx) ||
  test_bit(rnum, ctx->vregs_updated) ||
  test_bit(rnum, ctx->vregs_select) ||
  test_bit(rnum, ctx->vregs_updated_tmp));
-set_bit(rnum, ctx->vregs_read);
+if (has_helper) {
+set_bit(rnum, ctx->insn_vregs_read);
+if (test_bit(rnum, ctx->insn_vregs_written)) {
+ctx->has_hvx_overlap = true;
+}
+}
+if (is_gather_store_insn(ctx)) {
+ctx->read_after_write = true;
+}
 }
 
-static inline void ctx_log_vreg_read_pair(DisasContext *ctx, int r

[PATCH 0/3] Hexagon (target/hexagon) Enable more short-circuit packets

2023-11-03 Thread Taylor Simpson
This patch series improves the set of packets that can short-circuit
the commit packet logic and write the results directly during the
execution of each instruction in the packet.

The key observation is that checking for overlap between register reads
and writes is different from read-after-write.  For example, this packet
{ R0 = add(R0,R1); R6 = add(R6,R7) }
has an overlap between the reads and writes without doing a read after a
write.  Therefore, it is safe to write directly into the destination
registers during instruction execution.

Another example is a .new register read.  These can read from either the
destination register or a temporary location.

HVX instructions with generated helpers require special handling.
The semantics of the helpers are pass-by-reference, so we still need the
overlap check for these.

Taylor Simpson (3):
  Hexagon (target/hexagon) Analyze reads before writes
  Hexagon (target/hexagon) Enable more short-circuit packets (scalar
core)
  Hexagon (target/hexagon) Enable more short-circuit packets (HVX)

 target/hexagon/translate.h  | 117 ++---
 target/hexagon/translate.c  |  75 +
 target/hexagon/README   |   7 +-
 target/hexagon/gen_analyze_funcs.py | 252 
 target/hexagon/gen_tcg_funcs.py |   2 +-
 target/hexagon/hex_common.py|  10 ++
 6 files changed, 227 insertions(+), 236 deletions(-)

-- 
2.34.1




[PATCH 1/3] Hexagon (target/hexagon) Analyze reads before writes

2023-11-03 Thread Taylor Simpson
We divide gen_analyze_funcs.py into 3 phases
Declare the operands
Analyze the register reads
Analyze the register writes

We also create special versions of ctx_log_*_read for new operands
Check that the operand is written before the read

This is a precursor to improving the analysis for short-circuiting
the packet semantics in a subsequent commit

Signed-off-by: Taylor Simpson 
---
 target/hexagon/translate.h  |  24 ++-
 target/hexagon/README   |   7 +-
 target/hexagon/gen_analyze_funcs.py | 221 +++-
 3 files changed, 111 insertions(+), 141 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 4dd59c6726..b2fe3a048d 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -75,6 +75,8 @@ typedef struct DisasContext {
 TCGv dczero_addr;
 } DisasContext;
 
+bool is_gather_store_insn(DisasContext *ctx);
+
 static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
 {
 if (!test_bit(pnum, ctx->pregs_written)) {
@@ -89,6 +91,12 @@ static inline void ctx_log_pred_read(DisasContext *ctx, int 
pnum)
 set_bit(pnum, ctx->pregs_read);
 }
 
+static inline void ctx_log_pred_read_new(DisasContext *ctx, int pnum)
+{
+g_assert(test_bit(pnum, ctx->pregs_written));
+set_bit(pnum, ctx->pregs_read);
+}
+
 static inline void ctx_log_reg_write(DisasContext *ctx, int rnum,
  bool is_predicated)
 {
@@ -120,6 +128,12 @@ static inline void ctx_log_reg_read(DisasContext *ctx, int 
rnum)
 set_bit(rnum, ctx->regs_read);
 }
 
+static inline void ctx_log_reg_read_new(DisasContext *ctx, int rnum)
+{
+g_assert(test_bit(rnum, ctx->regs_written));
+set_bit(rnum, ctx->regs_read);
+}
+
 static inline void ctx_log_reg_read_pair(DisasContext *ctx, int rnum)
 {
 ctx_log_reg_read(ctx, rnum);
@@ -171,6 +185,15 @@ static inline void ctx_log_vreg_read(DisasContext *ctx, 
int rnum)
 set_bit(rnum, ctx->vregs_read);
 }
 
+static inline void ctx_log_vreg_read_new(DisasContext *ctx, int rnum)
+{
+g_assert(is_gather_store_insn(ctx) ||
+ test_bit(rnum, ctx->vregs_updated) ||
+ test_bit(rnum, ctx->vregs_select) ||
+ test_bit(rnum, ctx->vregs_updated_tmp));
+set_bit(rnum, ctx->vregs_read);
+}
+
 static inline void ctx_log_vreg_read_pair(DisasContext *ctx, int rnum)
 {
 ctx_log_vreg_read(ctx, rnum ^ 0);
@@ -205,7 +228,6 @@ extern TCGv hex_vstore_addr[VSTORES_MAX];
 extern TCGv hex_vstore_size[VSTORES_MAX];
 extern TCGv hex_vstore_pending[VSTORES_MAX];
 
-bool is_gather_store_insn(DisasContext *ctx);
 void process_store(DisasContext *ctx, int slot_num);
 
 FIELD(PROBE_PKT_SCALAR_STORE_S0, MMU_IDX,   0, 2)
diff --git a/target/hexagon/README b/target/hexagon/README
index 69b2ffe9bb..7dd74629eb 100644
--- a/target/hexagon/README
+++ b/target/hexagon/README
@@ -183,10 +183,11 @@ when the override is present.
 }
 
 We also generate an analyze_ function for each instruction.  Currently,
-these functions record the writes to registers by calling ctx_log_*.  During
+these functions record the reads and writes to registers by calling ctx_log_*. 
 During
 gen_start_packet, we invoke the analyze_ function for each instruction in
-the packet, and we mark the implicit writes.  After the analysis is performed,
-we initialize the result register for each of the predicated assignments.
+the packet, and we mark the implicit writes.  The analysis determines if the 
packet
+semantics can be short-circuited.  If not, we initialize the result register 
for each
+of the predicated assignments.
 
 In addition to instruction semantics, we use a generator to create the decode
 tree.  This generation is also a two step process.  The first step is to run
diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index c3b521abef..40b9473c44 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -22,157 +22,90 @@
 import string
 import hex_common
 
-
 ##
 ## Helpers for gen_analyze_func
 ##
 def is_predicated(tag):
 return "A_CONDEXEC" in hex_common.attribdict[tag]
 
+def vreg_write_type(tag):
+newv = "EXT_DFL"
+if hex_common.is_new_result(tag):
+newv = "EXT_NEW"
+elif hex_common.is_tmp_result(tag):
+newv = "EXT_TMP"
+return newv
 
-def analyze_opn_old(f, tag, regtype, regid, regno):
+def declare_regn(f, tag, regtype, regid, regno):
 regN = f"{regtype}{regid}N"
-predicated = "true" if is_predicated(tag) else "false"
-if regtype == "R":
-if regid in {"ss", "tt"}:
-f.write(f"const int {regN} = insn->regno[{regno}];\n")
-f.write(f"ctx_log_reg_read_pair(ctx, {regN});\n")
-elif regid in {"dd", "ee", &q

[PATCH 3/3] Hexagon (target/hexagon) Enable more short-circuit packets (HVX)

2023-11-02 Thread Taylor Simpson


binstlsT1oUDf.bin
Description: test/plain


[PATCH 0/3] Hexagon (target/hexagon) Enable more short-circuit packets

2023-11-02 Thread Taylor Simpson


binQUp8uBOBfS.bin
Description: test/plain


[PATCH 1/3] Hexagon (target/hexagon) Analyze reads before writes

2023-11-02 Thread Taylor Simpson


binJqsrgMI63R.bin
Description: test/plain


[PATCH 2/3] Hexagon (target/hexagon) Enable more short-circuit packets (scalar core)

2023-11-02 Thread Taylor Simpson


binBoZeeZ311a.bin
Description: test/plain


[PULL 0/5] Hexagon update

2023-05-26 Thread Taylor Simpson
The following changes since commit a3cb6d5004ff638aefe686ecd540718a793bd1b1:

  Merge tag 'pull-tcg-20230525' of https://gitlab.com/rth7680/qemu into staging 
(2023-05-25 11:11:52 -0700)

are available in the Git repository at:

  https://github.com/quic/qemu tags/pull-hex-20230526

for you to fetch changes up to 7d196e2196d50e0dda0f87f396d4f4a7ad9aafbe:

  Hexagon (target/hexagon) Change Hexagon maintainer (2023-05-26 07:03:41 -0700)


Hexagon update


Marco Liebel (1):
  Hexagon (target/hexagon) Fix assignment to tmp registers

Matheus Tavares Bernardino (2):
  target/hexagon/*.py: clean up used 'toss' and 'numregs' vars
  Hexagon: fix outdated `hex_new_*` comments

Taylor Simpson (2):
  Hexagon (tests/tcg/hexagon) Clean up Hexagon check-tcg tests
  Hexagon (target/hexagon) Change Hexagon maintainer

 MAINTAINERS  |   2 +-
 tests/tcg/hexagon/hex_test.h | 145 +
 target/hexagon/genptr.c  |  26 ++-
 target/hexagon/mmvec/decode_ext_mmvec.c  |   8 +-
 target/hexagon/translate.c   |   2 +-
 tests/tcg/hexagon/atomics.c  |  51 ++---
 tests/tcg/hexagon/brev.c |  73 +++
 tests/tcg/hexagon/circ.c | 152 +++---
 tests/tcg/hexagon/dual_stores.c  |  25 +--
 tests/tcg/hexagon/fpstuff.c  | 341 +--
 tests/tcg/hexagon/hex_sigsegv.c  |  46 ++---
 tests/tcg/hexagon/hvx_misc.c |  31 +++
 tests/tcg/hexagon/load_align.c   | 111 +-
 tests/tcg/hexagon/load_unpack.c  | 159 +++---
 tests/tcg/hexagon/mem_noshuf.c   | 163 +++
 tests/tcg/hexagon/mem_noshuf_exception.c |  52 ++---
 tests/tcg/hexagon/misc.c | 338 ++
 tests/tcg/hexagon/multi_result.c | 171 +++-
 tests/tcg/hexagon/overflow.c |  61 +++---
 tests/tcg/hexagon/preg_alias.c   | 111 +-
 tests/tcg/hexagon/read_write_overlap.c   |  55 +++--
 tests/tcg/hexagon/reg_mut.c  |  54 ++---
 tests/tcg/hexagon/usr.c  | 109 ++
 .mailmap |   1 +
 target/hexagon/gen_analyze_funcs.py  |  10 +-
 target/hexagon/gen_helper_funcs.py   |  30 +--
 target/hexagon/gen_helper_protos.py  |  22 +-
 target/hexagon/gen_idef_parser_funcs.py  |   4 +-
 target/hexagon/gen_op_regs.py|   4 +-
 target/hexagon/gen_tcg_funcs.py  |  46 ++---
 target/hexagon/hex_common.py |  24 +--
 tests/tcg/hexagon/Makefile.target|  19 +-
 32 files changed, 1150 insertions(+), 1296 deletions(-)
 create mode 100644 tests/tcg/hexagon/hex_test.h


[PULL 3/5] target/hexagon/*.py: clean up used 'toss' and 'numregs' vars

2023-05-26 Thread Taylor Simpson
From: Matheus Tavares Bernardino 

Many Hexagon python scripts call hex_common.get_tagregs(), but only one
call site use the full reg structure given by this function. To make the
code cleaner, let's make get_tagregs() filter out the unused fields
(i.e. 'toss' and 'numregs'), properly removed the unused variables at
the call sites. The hex_common.bad_register() function is also adjusted
to work exclusively with 'regtype' and 'regid' args. For the single call
site that does use toss/numregs, we provide an optional parameter to
get_tagregs() which will restore the old full behavior.

Suggested-by: Taylor Simpson 
Signed-off-by: Matheus Tavares Bernardino 
Reviewed-by: Taylor Simpson 
Tested-by: Taylor Simpson 
Signed-off-by: Taylor Simpson 
Message-Id: 
<3ffd4ccb972879f57f499705c624e8eaba7f8b52.1684939078.git.quic_mathb...@quicinc.com>
---
 target/hexagon/gen_analyze_funcs.py | 10 +++---
 target/hexagon/gen_helper_funcs.py  | 30 
 target/hexagon/gen_helper_protos.py | 22 ++--
 target/hexagon/gen_idef_parser_funcs.py |  4 +--
 target/hexagon/gen_op_regs.py   |  4 +--
 target/hexagon/gen_tcg_funcs.py | 46 -
 target/hexagon/hex_common.py| 24 ++---
 7 files changed, 70 insertions(+), 70 deletions(-)

diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index 00868cc6cb..c3b521abef 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -165,7 +165,7 @@ def analyze_opn_new(f, tag, regtype, regid, regno):
 hex_common.bad_register(regtype, regid)
 
 
-def analyze_opn(f, tag, regtype, regid, toss, numregs, i):
+def analyze_opn(f, tag, regtype, regid, i):
 if hex_common.is_pair(regid):
 analyze_opn_old(f, tag, regtype, regid, i)
 elif hex_common.is_single(regid):
@@ -174,9 +174,9 @@ def analyze_opn(f, tag, regtype, regid, toss, numregs, i):
 elif hex_common.is_new_val(regtype, regid, tag):
 analyze_opn_new(f, tag, regtype, regid, i)
 else:
-hex_common.bad_register(regtype, regid, toss, numregs)
+hex_common.bad_register(regtype, regid)
 else:
-hex_common.bad_register(regtype, regid, toss, numregs)
+hex_common.bad_register(regtype, regid)
 
 
 ##
@@ -202,8 +202,8 @@ def gen_analyze_func(f, tag, regs, imms):
 
 i = 0
 ## Analyze all the registers
-for regtype, regid, toss, numregs in regs:
-analyze_opn(f, tag, regtype, regid, toss, numregs, i)
+for regtype, regid in regs:
+analyze_opn(f, tag, regtype, regid, i)
 i += 1
 
 has_generated_helper = not hex_common.skip_qemu_helper(
diff --git a/target/hexagon/gen_helper_funcs.py 
b/target/hexagon/gen_helper_funcs.py
index e80550f94e..ce21d3b688 100755
--- a/target/hexagon/gen_helper_funcs.py
+++ b/target/hexagon/gen_helper_funcs.py
@@ -87,9 +87,9 @@ def gen_helper_arg_opn(f, regtype, regid, i, tag):
 elif hex_common.is_new_val(regtype, regid, tag):
 gen_helper_arg_new(f, regtype, regid, i)
 else:
-hex_common.bad_register(regtype, regid, toss, numregs)
+hex_common.bad_register(regtype, regid)
 else:
-hex_common.bad_register(regtype, regid, toss, numregs)
+hex_common.bad_register(regtype, regid)
 
 
 def gen_helper_arg_imm(f, immlett):
@@ -135,7 +135,7 @@ def gen_helper_dest_decl_opn(f, regtype, regid, i):
 else:
 gen_helper_dest_decl(f, regtype, regid, i)
 else:
-hex_common.bad_register(regtype, regid, toss, numregs)
+hex_common.bad_register(regtype, regid)
 
 
 def gen_helper_src_var_ext(f, regtype, regid):
@@ -185,7 +185,7 @@ def gen_helper_return_opn(f, regtype, regid, i):
 else:
 gen_helper_return(f, regtype, regid, i)
 else:
-hex_common.bad_register(regtype, regid, toss, numregs)
+hex_common.bad_register(regtype, regid)
 
 
 ##
@@ -208,7 +208,7 @@ def gen_helper_function(f, tag, tagregs, tagimms):
 numresults = 0
 numscalarresults = 0
 numscalarreadwrite = 0
-for regtype, regid, toss, numregs in regs:
+for regtype, regid in regs:
 if hex_common.is_written(regid):
 numresults += 1
 if hex_common.is_scalar_reg(regtype):
@@ -226,7 +226,7 @@ def gen_helper_function(f, tag, tagregs, tagimms):
 ## The return type of the function is the type of the destination
 ## register (if scalar)
 i = 0
-for regtype, regid, toss, numregs in regs:
+for regtype, regid in regs:
 if hex_common.is_written(regid):
 if hex_common.is_pair(regid):
 if hex_common.is_hvx_reg(regtype):
@@ -239,7 +239,7 @@ def gen_helper_function(f, tag, tagregs, tagimms):
 else:
 gen_helper_return_type(f, regtype, regid, i)
   

[PULL 5/5] Hexagon (target/hexagon) Change Hexagon maintainer

2023-05-26 Thread Taylor Simpson
Change Hexagon maintainer from Taylor Simpson to Brian Cain
Put Taylor's gmail address in .mailmap

Signed-off-by: Taylor Simpson 
Reviewed-by: Alex Bennée 
---
 MAINTAINERS | 2 +-
 .mailmap| 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1c93ab0ee5..4b025a7b63 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -218,7 +218,7 @@ F: tests/tcg/cris/
 F: disas/cris.c
 
 Hexagon TCG CPUs
-M: Taylor Simpson 
+M: Brian Cain 
 S: Supported
 F: target/hexagon/
 X: target/hexagon/idef-parser/
diff --git a/.mailmap b/.mailmap
index bbe6d3fd69..b57da4827e 100644
--- a/.mailmap
+++ b/.mailmap
@@ -78,6 +78,7 @@ Philippe Mathieu-Daudé  
 Philippe Mathieu-Daudé  
 Stefan Brankovic  
 Yongbok Kim  
+Taylor Simpson  
 
 # Also list preferred name forms where people have changed their
 # git author config, or had utf8/latin1 encoding issues.
-- 
2.25.1



[PULL 4/5] Hexagon: fix outdated `hex_new_*` comments

2023-05-26 Thread Taylor Simpson
From: Matheus Tavares Bernardino 

Some code comments refer to hex_new_value and hex_new_pred_value, which
have been transferred to DisasContext and, in the case of hex_new_value,
should now be accessed through get_result_gpr().

In order to fix this outdated comments and also avoid having to tweak
them whenever we make a variable name change in the future, let's
replace them with pseudocode.

Suggested-by: Taylor Simpson 
Signed-off-by: Matheus Tavares Bernardino 
Reviewed-by: Taylor Simpson 
Signed-off-by: Taylor Simpson 
Message-Id: 
<8e1689e28dd7b1318369b55127cf47b82ab75921.1684939078.git.quic_mathb...@quicinc.com>
---
 target/hexagon/genptr.c| 26 --
 target/hexagon/translate.c |  2 +-
 2 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index cb2aa28a19..bcb287dd8b 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -878,9 +878,9 @@ static void gen_endloop0(DisasContext *ctx)
  */
 if (!ctx->is_tight_loop) {
 /*
- *if (hex_gpr[HEX_REG_LC0] > 1) {
- *PC = hex_gpr[HEX_REG_SA0];
- *hex_new_value[HEX_REG_LC0] = hex_gpr[HEX_REG_LC0] - 1;
+ *if (LC0 > 1) {
+ *PC = SA0;
+ *LC0--;
  *}
  */
 TCGLabel *label3 = gen_new_label();
@@ -897,9 +897,9 @@ static void gen_endloop0(DisasContext *ctx)
 static void gen_endloop1(DisasContext *ctx)
 {
 /*
- *if (hex_gpr[HEX_REG_LC1] > 1) {
- *PC = hex_gpr[HEX_REG_SA1];
- *hex_new_value[HEX_REG_LC1] = hex_gpr[HEX_REG_LC1] - 1;
+ *if (LC1 > 1) {
+ *PC = SA1;
+ *LC1--;
  *}
  */
 TCGLabel *label = gen_new_label();
@@ -946,14 +946,12 @@ static void gen_endloop01(DisasContext *ctx)
 gen_set_label(label2);
 
 /*
- *if (hex_gpr[HEX_REG_LC0] > 1) {
- *PC = hex_gpr[HEX_REG_SA0];
- *hex_new_value[HEX_REG_LC0] = hex_gpr[HEX_REG_LC0] - 1;
- *} else {
- *if (hex_gpr[HEX_REG_LC1] > 1) {
- *hex_next_pc = hex_gpr[HEX_REG_SA1];
- *hex_new_value[HEX_REG_LC1] = hex_gpr[HEX_REG_LC1] - 1;
- *}
+ *if (LC0 > 1) {
+ *PC = SA0;
+ *LC0--;
+ *} else if (LC1 > 1) {
+ *PC = SA1;
+ *LC1--;
  *}
  */
 tcg_gen_brcondi_tl(TCG_COND_LEU, hex_gpr[HEX_REG_LC0], 1, label3);
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index b18f1a9051..8838ab2364 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -556,7 +556,7 @@ static void gen_start_packet(DisasContext *ctx)
 }
 
 /*
- * Preload the predicated pred registers into hex_new_pred_value[pred_num]
+ * Preload the predicated pred registers into ctx->new_pred_value[pred_num]
  * Only endloop instructions conditionally write to pred registers
  */
 if (ctx->need_commit && pkt->pkt_has_endloop) {
-- 
2.25.1



[PULL 2/5] Hexagon (target/hexagon) Fix assignment to tmp registers

2023-05-26 Thread Taylor Simpson
From: Marco Liebel 

The order in which instructions are generated by gen_insn() influences
assignment to tmp registers. During generation, tmp instructions (e.g.
generate_V6_vassign_tmp) use vreg_src_off() to determine what kind of
register to use as source. If some instruction (e.g.
generate_V6_vmpyowh_64_acc) uses a tmp register but is generated prior
to the corresponding tmp instruction, the vregs_updated_tmp bit map
isn't updated in time.

Exmple:
{ v14.tmp = v16; v25 = v14 } This works properly because
generate_V6_vassign_tmp is generated before generate_V6_vassign
and the bit map is updated.

{ v15:14.tmp = vcombine(v21, v16); v25:24 += vmpyo(v18.w,v14.h) }
This does not work properly because vmpyo is generated before
vcombine and therefore the bit map does not yet know that there's
a tmp register.

The parentheses in the decoding function were in the wrong place.
Moving them to the correct location makes shuffling of .tmp vector
registers work as expected.

Signed-off-by: Marco Liebel 
Reviewed-by: Taylor Simpson 
Tested-by: Taylor Simpson 
Signed-off-by: Taylor Simpson 
Reviewed-by: Brian Cain 
Message-Id: <20230522174708.464197-1-quic_mlie...@quicinc.com>
---
 target/hexagon/mmvec/decode_ext_mmvec.c |  8 +++
 tests/tcg/hexagon/hvx_misc.c| 31 +
 2 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/target/hexagon/mmvec/decode_ext_mmvec.c 
b/target/hexagon/mmvec/decode_ext_mmvec.c
index 061a65ab88..174eb3b78b 100644
--- a/target/hexagon/mmvec/decode_ext_mmvec.c
+++ b/target/hexagon/mmvec/decode_ext_mmvec.c
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. 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
@@ -148,9 +148,9 @@ decode_shuffle_for_execution_vops(Packet *pkt)
 int i;
 for (i = 0; i < pkt->num_insns; i++) {
 uint16_t opcode = pkt->insn[i].opcode;
-if (GET_ATTRIB(opcode, A_LOAD) &&
-(GET_ATTRIB(opcode, A_CVI_NEW) ||
- GET_ATTRIB(opcode, A_CVI_TMP))) {
+if ((GET_ATTRIB(opcode, A_LOAD) &&
+ GET_ATTRIB(opcode, A_CVI_NEW)) ||
+GET_ATTRIB(opcode, A_CVI_TMP)) {
 /*
  * Find prior consuming vector instructions
  * Move to end of packet
diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c
index 09dec8d7a1..b45170acd1 100644
--- a/tests/tcg/hexagon/hvx_misc.c
+++ b/tests/tcg/hexagon/hvx_misc.c
@@ -60,6 +60,36 @@ static void test_load_tmp(void)
 check_output_w(__LINE__, BUFSIZE);
 }
 
+static void test_load_tmp2(void)
+{
+void *pout0 = [0];
+void *pout1 = [1];
+
+asm volatile(
+"r0 = #0x03030303\n\t"
+"v16 = vsplat(r0)\n\t"
+"r0 = #0x04040404\n\t"
+"v18 = vsplat(r0)\n\t"
+"r0 = #0x05050505\n\t"
+"v21 = vsplat(r0)\n\t"
+"{\n\t"
+"   v25:24 += vmpyo(v18.w, v14.h)\n\t"
+"   v15:14.tmp = vcombine(v21, v16)\n\t"
+"}\n\t"
+"vmem(%0 + #0) = v24\n\t"
+"vmem(%1 + #0) = v25\n\t"
+: : "r"(pout0), "r"(pout1)
+: "r0", "v16", "v18", "v21", "v24", "v25", "memory"
+);
+
+for (int i = 0; i < MAX_VEC_SIZE_BYTES / 4; ++i) {
+expect[0].w[i] = 0x180c;
+expect[1].w[i] = 0x000c1818;
+}
+
+check_output_w(__LINE__, 2);
+}
+
 static void test_load_cur(void)
 {
 void *p0 = buffer0;
@@ -435,6 +465,7 @@ int main()
 init_buffers();
 
 test_load_tmp();
+test_load_tmp2();
 test_load_cur();
 test_load_aligned();
 test_load_unaligned();
-- 
2.25.1



[PATCH 1/1] Hexagon (target/hexagon) Change Hexagon maintainer

2023-05-24 Thread Taylor Simpson
Change Hexagon maintainer from Taylor Simpson to Brian Cain
Put Taylor's gmail address in .mailmap

Signed-off-by: Taylor Simpson 
---
 MAINTAINERS | 2 +-
 .mailmap| 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1b6466496d..426d33f4cb 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -215,7 +215,7 @@ F: tests/tcg/cris/
 F: disas/cris.c
 
 Hexagon TCG CPUs
-M: Taylor Simpson 
+M: Brian Cain 
 S: Supported
 F: target/hexagon/
 X: target/hexagon/idef-parser/
diff --git a/.mailmap b/.mailmap
index bbe6d3fd69..b57da4827e 100644
--- a/.mailmap
+++ b/.mailmap
@@ -78,6 +78,7 @@ Philippe Mathieu-Daudé  
 Philippe Mathieu-Daudé  
 Stefan Brankovic  
 Yongbok Kim  
+Taylor Simpson  
 
 # Also list preferred name forms where people have changed their
 # git author config, or had utf8/latin1 encoding issues.
-- 
2.25.1



[PATCH 0/1] Change Hexagon maintainer

2023-05-24 Thread Taylor Simpson
I will be retiring from Qualcomm at the end of May, so I am placing
the maintainership in the very capable hands of Brian Cain.

Taylor Simpson (1):
  Hexagon (target/hexagon) Change Hexagon maintainer

 MAINTAINERS | 2 +-
 .mailmap| 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

-- 
2.25.1



RE: [PATCH v2 2/2] Hexagon: fix outdated `hex_new_*` comments

2023-05-24 Thread Taylor Simpson



> -Original Message-
> From: Matheus Tavares Bernardino 
> Sent: Wednesday, May 24, 2023 9:42 AM
> To: qemu-devel@nongnu.org
> Cc: Taylor Simpson ; Brian Cain
> ; Marco Liebel (QUIC) 
> Subject: [PATCH v2 2/2] Hexagon: fix outdated `hex_new_*` comments
> 
> Some code comments refer to hex_new_value and hex_new_pred_value,
> which have been transferred to DisasContext and, in the case of
> hex_new_value, should now be accessed through get_result_gpr().
> 
> In order to fix this outdated comments and also avoid having to tweak them
> whenever we make a variable name change in the future, let's replace them
> with pseudocode.
> 
> Suggested-by: Taylor Simpson 
> Signed-off-by: Matheus Tavares Bernardino 
> ---
>  target/hexagon/genptr.c| 26 --
>  target/hexagon/translate.c |  2 +-
>  2 files changed, 13 insertions(+), 15 deletions(-)

Reviewed-by: Taylor Simpson 

Queued to hex.next



RE: [PATCH v2 1/2] target/hexagon/*.py: clean up used 'toss' and 'numregs' vars

2023-05-24 Thread Taylor Simpson



> -Original Message-
> From: Matheus Tavares Bernardino 
> Sent: Wednesday, May 24, 2023 9:42 AM
> To: qemu-devel@nongnu.org
> Cc: Taylor Simpson ; Brian Cain
> ; Marco Liebel (QUIC) ;
> Alessandro Di Federico ; Anton Johansson 
> Subject: [PATCH v2 1/2] target/hexagon/*.py: clean up used 'toss' and
> 'numregs' vars
> 
> Many Hexagon python scripts call hex_common.get_tagregs(), but only one
> call site use the full reg structure given by this function. To make the code
> cleaner, let's make get_tagregs() filter out the unused fields (i.e. 'toss' 
> and
> 'numregs'), properly removed the unused variables at the call sites. The
> hex_common.bad_register() function is also adjusted to work exclusively with
> 'regtype' and 'regid' args. For the single call site that does use 
> toss/numregs,
> we provide an optional parameter to
> get_tagregs() which will restore the old full behavior.
> 
> Suggested-by: Taylor Simpson 
> Signed-off-by: Matheus Tavares Bernardino 
> ---
>  target/hexagon/gen_analyze_funcs.py | 10 +++---
>  target/hexagon/gen_helper_funcs.py  | 30 
>  target/hexagon/gen_helper_protos.py | 22 ++--
>  target/hexagon/gen_idef_parser_funcs.py |  4 +--
>  target/hexagon/gen_op_regs.py   |  4 +--
>  target/hexagon/gen_tcg_funcs.py | 46 -
>  target/hexagon/hex_common.py    | 24 ++++++---
>  7 files changed, 70 insertions(+), 70 deletions(-)

Reviewed-by: Taylor Simpson 
Tested-by: Taylor Simpson 

Queued to hex.next





RE: [PATCH 2/2] Hexagon: fix outdated `hex_new_*` references in comments

2023-05-23 Thread Taylor Simpson



> -Original Message-
> From: Matheus Tavares Bernardino 
> Sent: Tuesday, May 23, 2023 3:36 PM
> To: qemu-devel@nongnu.org
> Cc: Taylor Simpson ; Brian Cain
> ; Marco Liebel (QUIC) 
> Subject: [PATCH 2/2] Hexagon: fix outdated `hex_new_*` references in
> comments
> 
> Some code comments refer to hex_new_value and hex_new_pred_value,
> which have been transferred to DisasContext and, in the case of
> hex_new_value, should now be accessed through get_result_gpr(). Let's
> update these comments to reflect the new state of the codebase. Since they
> are only meant to assist developers, we can replace the old names with some
> pseudocode when convenient.
> 
> Signed-off-by: Matheus Tavares Bernardino 
> ---
>  target/hexagon/genptr.c| 10 +-
>  target/hexagon/translate.c |  2 +-
>  2 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c index
> cb2aa28a19..8d11d928c9 100644
> --- a/target/hexagon/genptr.c
> +++ b/target/hexagon/genptr.c
> @@ -880,7 +880,7 @@ static void gen_endloop0(DisasContext *ctx)
>  /*
>   *if (hex_gpr[HEX_REG_LC0] > 1) {
>   *PC = hex_gpr[HEX_REG_SA0];
> - *hex_new_value[HEX_REG_LC0] = hex_gpr[HEX_REG_LC0] - 1;
> + *result_gpr(HEX_REG_LC0) = hex_gpr[HEX_REG_LC0] - 1;
>   *}
>   */

Go ahead and change these completely to pseudo-code
If (LC0 > 1) {
PC = SA0;
LC0 = LC0 - 1;
}

Thanks,
Taylor




RE: [PATCH 1/2] target/hexagon/*.py: remove undef vars from bad_register()

2023-05-23 Thread Taylor Simpson



> -Original Message-
> From: Matheus Tavares Bernardino 
> Sent: Tuesday, May 23, 2023 3:36 PM
> To: qemu-devel@nongnu.org
> Cc: Taylor Simpson ; Brian Cain
> ; Marco Liebel (QUIC) 
> Subject: [PATCH 1/2] target/hexagon/*.py: remove undef vars from
> bad_register()
> 
> Some calls to `hex_common.bad_register()` in Hexagon python files are
> passing undefined variables. Let's remove those.
> 
> Signed-off-by: Matheus Tavares Bernardino 
> ---
>  target/hexagon/gen_helper_funcs.py | 8 
>  target/hexagon/gen_tcg_funcs.py| 6 +++---
>  2 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/target/hexagon/gen_helper_funcs.py
> b/target/hexagon/gen_helper_funcs.py
> index e80550f94e..367d08aceb 100755
> --- a/target/hexagon/gen_helper_funcs.py
> +++ b/target/hexagon/gen_helper_funcs.py
> @@ -87,9 +87,9 @@ def gen_helper_arg_opn(f, regtype, regid, i, tag):
>  elif hex_common.is_new_val(regtype, regid, tag):
>  gen_helper_arg_new(f, regtype, regid, i)
>  else:
> -hex_common.bad_register(regtype, regid, toss, numregs)
> +hex_common.bad_register(regtype, regid)
>  else:
> -hex_common.bad_register(regtype, regid, toss, numregs)
> +hex_common.bad_register(regtype, regid)

There are other places where toss and numregs are passed to bad_register.  
Let's go ahead and change bad_register to only take regtype and regid as 
arguments and remove those arguments everywhere.

Also, if you want to pull the thread on the sweater, go ahead and remove toss 
and numregs from the many places they are unused.

Thanks,
Taylor




RE: [PATCH] Hexagon (target/hexagon) Fix assignment to tmp registers

2023-05-22 Thread Taylor Simpson



> -Original Message-
> From: Marco Liebel (QUIC) 
> Sent: Monday, May 22, 2023 11:14 AM
> To: qemu-devel@nongnu.org
> Cc: Taylor Simpson ; Brian Cain
> ; Marco Liebel (QUIC) 
> Subject: [PATCH] Hexagon (target/hexagon) Fix assignment to tmp registers
> 
> The order in which instructions are generated by gen_insn() influences
> assignment to tmp registers. During generation, tmp instructions (e.g.
> generate_V6_vassign_tmp) use vreg_src_off() to determine what kind of
> register to use as source. If some instruction (e.g.
> generate_V6_vmpyowh_64_acc) uses a tmp register but is generated prior to
> the corresponding tmp instruction, the vregs_updated_tmp bit map isn't
> updated in time.
> 
> Exmple:
> { v14.tmp = v16; v25 = v14 } This works properly because
> generate_V6_assign_tmp is generated before generate_V6_assign and
> the bit map is updated.
> 
> { v15:14.tmp = vcombine(v21, v16); v25:24 += vmpyo(v18.w,v14.h) }
> This does not work properly because vmpyo is generated before
> vcombine and therefore the bit map does not yet know that there's
> a tmp register.
> 
> The parentheses in the decoding function were in the wrong place.
> Moving them to the correct location makes shuffling of .tmp vector registers
> work as expected.
> ---
>  target/hexagon/mmvec/decode_ext_mmvec.c |  6 ++---
>  tests/tcg/hexagon/hvx_misc.c| 31 +
>  2 files changed, 34 insertions(+), 3 deletions(-)

Two things
1) Update the copyright year in decode_ext_mmvec.c
2) Add your Signed-off-by to the commit message

Otherwise,
Tested-by: Taylor Simpson 
Reviewed-by: Taylor Simpson 

Queued for next Hexagon update



[PULL v2 44/44] Hexagon (linux-user/hexagon): handle breakpoints

2023-05-18 Thread Taylor Simpson
From: Matheus Tavares Bernardino 

This enables LLDB to work with hexagon linux-user mode through the GDB
remote protocol.

Helped-by: Richard Henderson 
Signed-off-by: Matheus Tavares Bernardino 
Reviewed-by: Richard Henderson 
Signed-off-by: Taylor Simpson 
Message-Id: 

---
 linux-user/hexagon/cpu_loop.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/linux-user/hexagon/cpu_loop.c b/linux-user/hexagon/cpu_loop.c
index b84e25bf71..7f1499ed28 100644
--- a/linux-user/hexagon/cpu_loop.c
+++ b/linux-user/hexagon/cpu_loop.c
@@ -63,6 +63,9 @@ void cpu_loop(CPUHexagonState *env)
 case EXCP_ATOMIC:
 cpu_exec_step_atomic(cs);
 break;
+case EXCP_DEBUG:
+force_sig_fault(TARGET_SIGTRAP, TARGET_TRAP_BRKPT, 0);
+break;
 default:
 EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n",
  trapnr);
-- 
2.25.1



[PULL v2 42/44] Hexagon (gdbstub): fix p3:0 read and write via stub

2023-05-18 Thread Taylor Simpson
From: Brian Cain 

Signed-off-by: Brian Cain 
Co-authored-by: Sid Manning 
Signed-off-by: Sid Manning 
Co-authored-by: Matheus Tavares Bernardino 
Signed-off-by: Matheus Tavares Bernardino 
Reviewed-by: Taylor Simpson 
Signed-off-by: Taylor Simpson 
Message-Id: 
<32e7de567cdae184a6781644454bbb19916c955b.1683214375.git.quic_mathb...@quicinc.com>
---
 target/hexagon/gdbstub.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/target/hexagon/gdbstub.c b/target/hexagon/gdbstub.c
index 46083da620..a06fed9f18 100644
--- a/target/hexagon/gdbstub.c
+++ b/target/hexagon/gdbstub.c
@@ -25,6 +25,14 @@ int hexagon_gdb_read_register(CPUState *cs, GByteArray 
*mem_buf, int n)
 HexagonCPU *cpu = HEXAGON_CPU(cs);
 CPUHexagonState *env = >env;
 
+if (n == HEX_REG_P3_0_ALIASED) {
+uint32_t p3_0 = 0;
+for (int i = 0; i < NUM_PREGS; i++) {
+p3_0 = deposit32(p3_0, i * 8, 8, env->pred[i]);
+}
+return gdb_get_regl(mem_buf, p3_0);
+}
+
 if (n < TOTAL_PER_THREAD_REGS) {
 return gdb_get_regl(mem_buf, env->gpr[n]);
 }
@@ -37,6 +45,14 @@ int hexagon_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 HexagonCPU *cpu = HEXAGON_CPU(cs);
 CPUHexagonState *env = >env;
 
+if (n == HEX_REG_P3_0_ALIASED) {
+uint32_t p3_0 = ldtul_p(mem_buf);
+for (int i = 0; i < NUM_PREGS; i++) {
+env->pred[i] = extract32(p3_0, i * 8, 8);
+}
+return sizeof(target_ulong);
+}
+
 if (n < TOTAL_PER_THREAD_REGS) {
 env->gpr[n] = ldtul_p(mem_buf);
 return sizeof(target_ulong);
-- 
2.25.1



[PULL v2 43/44] Hexagon (gdbstub): add HVX support

2023-05-18 Thread Taylor Simpson
Signed-off-by: Taylor Simpson 
Co-authored-by: Brian Cain 
Signed-off-by: Brian Cain 
Co-authored-by: Matheus Tavares Bernardino 
Signed-off-by: Matheus Tavares Bernardino 
Reviewed-by: Brian Cain 
Message-Id: 
<17cb32f34d469f705c3cc066a3583935352ee048.1683214375.git.quic_mathb...@quicinc.com>
---
 configs/targets/hexagon-linux-user.mak |  2 +-
 target/hexagon/internal.h  |  2 +
 target/hexagon/cpu.c   |  6 ++
 target/hexagon/gdbstub.c   | 68 ++
 gdb-xml/hexagon-hvx.xml| 96 ++
 5 files changed, 173 insertions(+), 1 deletion(-)
 create mode 100644 gdb-xml/hexagon-hvx.xml

diff --git a/configs/targets/hexagon-linux-user.mak 
b/configs/targets/hexagon-linux-user.mak
index fd5e222d4f..2765a4c563 100644
--- a/configs/targets/hexagon-linux-user.mak
+++ b/configs/targets/hexagon-linux-user.mak
@@ -1,2 +1,2 @@
 TARGET_ARCH=hexagon
-TARGET_XML_FILES=gdb-xml/hexagon-core.xml
+TARGET_XML_FILES=gdb-xml/hexagon-core.xml gdb-xml/hexagon-hvx.xml
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index b1bfadc3f5..d732b6bb3c 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -33,6 +33,8 @@
 
 int hexagon_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
 int hexagon_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
+int hexagon_hvx_gdb_read_register(CPUHexagonState *env, GByteArray *mem_buf, 
int n);
+int hexagon_hvx_gdb_write_register(CPUHexagonState *env, uint8_t *mem_buf, int 
n);
 
 void hexagon_debug_vreg(CPUHexagonState *env, int regnum);
 void hexagon_debug_qreg(CPUHexagonState *env, int regnum);
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 575bcc190d..f155936289 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -24,6 +24,7 @@
 #include "hw/qdev-properties.h"
 #include "fpu/softfloat-helpers.h"
 #include "tcg/tcg.h"
+#include "exec/gdbstub.h"
 
 static void hexagon_v67_cpu_init(Object *obj) { }
 static void hexagon_v68_cpu_init(Object *obj) { }
@@ -339,6 +340,11 @@ static void hexagon_cpu_realize(DeviceState *dev, Error 
**errp)
 return;
 }
 
+gdb_register_coprocessor(cs, hexagon_hvx_gdb_read_register,
+ hexagon_hvx_gdb_write_register,
+ NUM_VREGS + NUM_QREGS,
+ "hexagon-hvx.xml", 0);
+
 qemu_init_vcpu(cs);
 cpu_reset(cs);
 
diff --git a/target/hexagon/gdbstub.c b/target/hexagon/gdbstub.c
index a06fed9f18..54d37e006e 100644
--- a/target/hexagon/gdbstub.c
+++ b/target/hexagon/gdbstub.c
@@ -60,3 +60,71 @@ int hexagon_gdb_write_register(CPUState *cs, uint8_t 
*mem_buf, int n)
 
 g_assert_not_reached();
 }
+
+static int gdb_get_vreg(CPUHexagonState *env, GByteArray *mem_buf, int n)
+{
+int total = 0;
+int i;
+for (i = 0; i < ARRAY_SIZE(env->VRegs[n].uw); i++) {
+total += gdb_get_regl(mem_buf, env->VRegs[n].uw[i]);
+}
+return total;
+}
+
+static int gdb_get_qreg(CPUHexagonState *env, GByteArray *mem_buf, int n)
+{
+int total = 0;
+int i;
+for (i = 0; i < ARRAY_SIZE(env->QRegs[n].uw); i++) {
+total += gdb_get_regl(mem_buf, env->QRegs[n].uw[i]);
+}
+return total;
+}
+
+int hexagon_hvx_gdb_read_register(CPUHexagonState *env, GByteArray *mem_buf, 
int n)
+{
+if (n < NUM_VREGS) {
+return gdb_get_vreg(env, mem_buf, n);
+}
+n -= NUM_VREGS;
+
+if (n < NUM_QREGS) {
+return gdb_get_qreg(env, mem_buf, n);
+}
+
+g_assert_not_reached();
+}
+
+static int gdb_put_vreg(CPUHexagonState *env, uint8_t *mem_buf, int n)
+{
+int i;
+for (i = 0; i < ARRAY_SIZE(env->VRegs[n].uw); i++) {
+env->VRegs[n].uw[i] = ldtul_p(mem_buf);
+mem_buf += 4;
+}
+return MAX_VEC_SIZE_BYTES;
+}
+
+static int gdb_put_qreg(CPUHexagonState *env, uint8_t *mem_buf, int n)
+{
+int i;
+for (i = 0; i < ARRAY_SIZE(env->QRegs[n].uw); i++) {
+env->QRegs[n].uw[i] = ldtul_p(mem_buf);
+mem_buf += 4;
+}
+return MAX_VEC_SIZE_BYTES / 8;
+}
+
+int hexagon_hvx_gdb_write_register(CPUHexagonState *env, uint8_t *mem_buf, int 
n)
+{
+   if (n < NUM_VREGS) {
+return gdb_put_vreg(env, mem_buf, n);
+}
+n -= NUM_VREGS;
+
+if (n < NUM_QREGS) {
+return gdb_put_qreg(env, mem_buf, n);
+}
+
+g_assert_not_reached();
+}
diff --git a/gdb-xml/hexagon-hvx.xml b/gdb-xml/hexagon-hvx.xml
new file mode 100644
index 00..5f2e220733
--- /dev/null
+++ b/gdb-xml/hexagon-hvx.xml
@@ -0,0 +1,96 @@
+
+
+
+
+
+
+  
+  
+  
+  
+  
+  
+  
+  
+  
+
+
+
+
+
+
+
+
+  
+
+  
+
+
+  
+  
+
+
+
+
+  
+  
+  
+  
+  
+  
+
+
+
+
+  
+
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+
+
-- 
2.25.1



[PULL v2 41/44] Hexagon: add core gdbstub xml data for LLDB

2023-05-18 Thread Taylor Simpson
From: Matheus Tavares Bernardino 

Signed-off-by: Matheus Tavares Bernardino 
Reviewed-by: Taylor Simpson 
Signed-off-by: Taylor Simpson 
Message-Id: 

---
 MAINTAINERS|  1 +
 configs/targets/hexagon-linux-user.mak |  1 +
 target/hexagon/cpu.c   |  3 +-
 gdb-xml/hexagon-core.xml   | 84 ++
 4 files changed, 88 insertions(+), 1 deletion(-)
 create mode 100644 gdb-xml/hexagon-core.xml

diff --git a/MAINTAINERS b/MAINTAINERS
index f757369373..2e18c3cad4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -225,6 +225,7 @@ F: tests/tcg/hexagon/
 F: disas/hexagon.c
 F: configs/targets/hexagon-linux-user/default.mak
 F: docker/dockerfiles/debian-hexagon-cross.docker
+F: gdb-xml/hexagon*.xml
 
 Hexagon idef-parser
 M: Alessandro Di Federico 
diff --git a/configs/targets/hexagon-linux-user.mak 
b/configs/targets/hexagon-linux-user.mak
index 003ed0a408..fd5e222d4f 100644
--- a/configs/targets/hexagon-linux-user.mak
+++ b/configs/targets/hexagon-linux-user.mak
@@ -1 +1,2 @@
 TARGET_ARCH=hexagon
+TARGET_XML_FILES=gdb-xml/hexagon-core.xml
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 7e127059c7..575bcc190d 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -383,8 +383,9 @@ static void hexagon_cpu_class_init(ObjectClass *c, void 
*data)
 cc->get_pc = hexagon_cpu_get_pc;
 cc->gdb_read_register = hexagon_gdb_read_register;
 cc->gdb_write_register = hexagon_gdb_write_register;
-cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREGS;
+cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS;
 cc->gdb_stop_before_watchpoint = true;
+cc->gdb_core_xml_file = "hexagon-core.xml";
 cc->disas_set_info = hexagon_cpu_disas_set_info;
 cc->tcg_ops = _tcg_ops;
 }
diff --git a/gdb-xml/hexagon-core.xml b/gdb-xml/hexagon-core.xml
new file mode 100644
index 00..e181163cff
--- /dev/null
+++ b/gdb-xml/hexagon-core.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+
+
-- 
2.25.1



[PULL v2 40/44] gdbstub: add test for untimely stop-reply packets

2023-05-18 Thread Taylor Simpson
From: Matheus Tavares Bernardino 

In the previous commit, we modified gdbstub.c to only send stop-reply
packets as a response to GDB commands that accept it. Now, let's add a
test for this intended behavior. Running this test before the fix from
the previous commit fails as QEMU sends a stop-reply packet
asynchronously, when GDB was in fact waiting an ACK.

Signed-off-by: Matheus Tavares Bernardino 
Acked-by: Alex Bennée 
Signed-off-by: Taylor Simpson 
Message-Id: 

---
 tests/guest-debug/run-test.py| 16 
 .../tcg/multiarch/system/Makefile.softmmu-target | 16 +++-
 2 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/tests/guest-debug/run-test.py b/tests/guest-debug/run-test.py
index d865e46ecd..de6106a5e5 100755
--- a/tests/guest-debug/run-test.py
+++ b/tests/guest-debug/run-test.py
@@ -26,11 +26,12 @@ def get_args():
 parser.add_argument("--qargs", help="Qemu arguments for test")
 parser.add_argument("--binary", help="Binary to debug",
 required=True)
-parser.add_argument("--test", help="GDB test script",
-required=True)
+parser.add_argument("--test", help="GDB test script")
 parser.add_argument("--gdb", help="The gdb binary to use",
 default=None)
+parser.add_argument("--gdb-args", help="Additional gdb arguments")
 parser.add_argument("--output", help="A file to redirect output to")
+parser.add_argument("--stderr", help="A file to redirect stderr to")
 
 return parser.parse_args()
 
@@ -58,6 +59,10 @@ def log(output, msg):
 output = open(args.output, "w")
 else:
 output = None
+if args.stderr:
+stderr = open(args.stderr, "w")
+else:
+stderr = None
 
 socket_dir = TemporaryDirectory("qemu-gdbstub")
 socket_name = os.path.join(socket_dir.name, "gdbstub.socket")
@@ -77,6 +82,8 @@ def log(output, msg):
 
 # Now launch gdb with our test and collect the result
 gdb_cmd = "%s %s" % (args.gdb, args.binary)
+if args.gdb_args:
+gdb_cmd += " %s" % (args.gdb_args)
 # run quietly and ignore .gdbinit
 gdb_cmd += " -q -n -batch"
 # disable prompts in case of crash
@@ -84,13 +91,14 @@ def log(output, msg):
 # connect to remote
 gdb_cmd += " -ex 'target remote %s'" % (socket_name)
 # finally the test script itself
-gdb_cmd += " -x %s" % (args.test)
+if args.test:
+gdb_cmd += " -x %s" % (args.test)
 
 
 sleep(1)
 log(output, "GDB CMD: %s" % (gdb_cmd))
 
-result = subprocess.call(gdb_cmd, shell=True, stdout=output)
+result = subprocess.call(gdb_cmd, shell=True, stdout=output, stderr=stderr)
 
 # A result of greater than 128 indicates a fatal signal (likely a
 # crash due to gdb internal failure). That's a problem for GDB and
diff --git a/tests/tcg/multiarch/system/Makefile.softmmu-target 
b/tests/tcg/multiarch/system/Makefile.softmmu-target
index 5f432c95f3..fe40195d39 100644
--- a/tests/tcg/multiarch/system/Makefile.softmmu-target
+++ b/tests/tcg/multiarch/system/Makefile.softmmu-target
@@ -27,6 +27,20 @@ run-gdbstub-memory: memory
"-monitor none -display none -chardev 
file$(COMMA)path=$<.out$(COMMA)id=output $(QEMU_OPTS)" \
--bin $< --test $(MULTIARCH_SRC)/gdbstub/memory.py, \
softmmu gdbstub support)
+
+run-gdbstub-untimely-packet: hello
+   $(call run-test, $@, $(GDB_SCRIPT) \
+   --gdb $(HAVE_GDB_BIN) \
+   --gdb-args "-ex 'set debug remote 1'" \
+   --output untimely-packet.gdb.out \
+   --stderr untimely-packet.gdb.err \
+   --qemu $(QEMU) \
+   --bin $< --qargs \
+   "-monitor none -display none -chardev 
file$(COMMA)path=untimely-packet.out$(COMMA)id=output $(QEMU_OPTS)", \
+   "softmmu gdbstub untimely packets")
+   $(call quiet-command, \
+   (! grep -Fq 'Packet instead of Ack, ignoring it' 
untimely-packet.gdb.err), \
+   "GREP", "file  untimely-packet.gdb.err")
 else
 run-gdbstub-%:
$(call skip-test, "gdbstub test $*", "no guest arch support")
@@ -36,4 +50,4 @@ run-gdbstub-%:
$(call skip-test, "gdbstub test $*", "need working gdb")
 endif
 
-MULTIARCH_RUNS += run-gdbstub-memory
+MULTIARCH_RUNS += run-gdbstub-memory run-gdbstub-untimely-packet
-- 
2.25.1



[PULL v2 22/44] Hexagon (target/hexagon) Short-circuit packet HVX writes

2023-05-18 Thread Taylor Simpson
In certain cases, we can avoid the overhead of writing to future_VRegs
and write directly to VRegs.  We consider HVX reads/writes when computing
ctx->need_commit.  Then, we can early-exit from gen_commit_hvx.

Signed-off-by: Taylor Simpson 
Reviewed-by: Richard Henderson 
Message-Id: <20230427230012.3800327-14-tsimp...@quicinc.com>
---
 target/hexagon/genptr.c|  6 -
 target/hexagon/translate.c | 46 +-
 2 files changed, 50 insertions(+), 2 deletions(-)

diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index 5025e172cf..82a3408eb4 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -1104,7 +1104,11 @@ static void gen_log_vreg_write_pair(DisasContext *ctx, 
intptr_t srcoff, int num,
 
 static intptr_t get_result_qreg(DisasContext *ctx, int qnum)
 {
-return  offsetof(CPUHexagonState, future_QRegs[qnum]);
+if (ctx->need_commit) {
+return  offsetof(CPUHexagonState, future_QRegs[qnum]);
+} else {
+return  offsetof(CPUHexagonState, QRegs[qnum]);
+}
 }
 
 static void gen_vreg_load(DisasContext *ctx, intptr_t dstoff, TCGv src,
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index bcf64f725a..8e7a4377c8 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -70,6 +70,10 @@ intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
 {
 intptr_t offset;
 
+if (!ctx->need_commit) {
+return offsetof(CPUHexagonState, VRegs[regnum]);
+}
+
 /* See if it is already allocated */
 for (int i = 0; i < ctx->future_vregs_idx; i++) {
 if (ctx->future_vregs_num[i] == regnum) {
@@ -374,7 +378,7 @@ static bool need_commit(DisasContext *ctx)
 return true;
 }
 
-if (pkt->num_insns == 1) {
+if (pkt->num_insns == 1 && !pkt->pkt_has_hvx) {
 return false;
 }
 
@@ -394,6 +398,40 @@ static bool need_commit(DisasContext *ctx)
 }
 }
 
+/* Check for overlap between HVX reads and writes */
+for (int i = 0; i < ctx->vreg_log_idx; i++) {
+int vnum = ctx->vreg_log[i];
+if (test_bit(vnum, ctx->vregs_read)) {
+return true;
+}
+}
+if (!bitmap_empty(ctx->vregs_updated_tmp, NUM_VREGS)) {
+int i = find_first_bit(ctx->vregs_updated_tmp, NUM_VREGS);
+while (i < NUM_VREGS) {
+if (test_bit(i, ctx->vregs_read)) {
+return true;
+}
+i = find_next_bit(ctx->vregs_updated_tmp, NUM_VREGS, i + 1);
+}
+}
+if (!bitmap_empty(ctx->vregs_select, NUM_VREGS)) {
+int i = find_first_bit(ctx->vregs_select, NUM_VREGS);
+while (i < NUM_VREGS) {
+if (test_bit(i, ctx->vregs_read)) {
+return true;
+}
+i = find_next_bit(ctx->vregs_select, NUM_VREGS, i + 1);
+}
+}
+
+/* Check for overlap between HVX predicate reads and writes */
+for (int i = 0; i < ctx->qreg_log_idx; i++) {
+int qnum = ctx->qreg_log[i];
+if (test_bit(qnum, ctx->qregs_read)) {
+return true;
+}
+}
+
 return false;
 }
 
@@ -790,6 +828,12 @@ static void gen_commit_hvx(DisasContext *ctx)
 {
 int i;
 
+/* Early exit if not needed */
+if (!ctx->need_commit) {
+g_assert(!pkt_has_hvx_store(ctx->pkt));
+return;
+}
+
 /*
  *for (i = 0; i < ctx->vreg_log_idx; i++) {
  *int rnum = ctx->vreg_log[i];
-- 
2.25.1



[PULL v2 31/44] Hexagon (target/hexagon) Additional instructions handled by idef-parser

2023-05-18 Thread Taylor Simpson
 Changes in v3 
Fix bugs exposed by dpmpyss_rnd_s0 instruction
Set correct size/signedness for constants
Test cases added to tests/tcg/hexagon/misc.c

 Changes in v2 
Fix bug in imm_print identified in clang build

Currently, idef-parser skips all floating point instructions.  However,
there are some floating point instructions that can be handled.

The following instructions are now parsed
F2_sfimm_p
F2_sfimm_n
F2_dfimm_p
F2_dfimm_n
F2_dfmpyll
F2_dfmpylh

To make these instructions work, we fix some bugs in parser-helpers.c
gen_rvalue_extend
gen_cast_op
imm_print
lexer properly sets size/signedness of constants

Test cases added to tests/tcg/hexagon/fpstuff.c

Signed-off-by: Taylor Simpson 
Tested-by: Anton Johansson 
Reviewed-by: Anton Johansson 
Message-Id: <20230501203125.4025991-1-tsimp...@quicinc.com>
---
 target/hexagon/idef-parser/parser-helpers.h |  2 +-
 target/hexagon/idef-parser/parser-helpers.c | 61 ++---
 tests/tcg/hexagon/fpstuff.c | 54 ++
 tests/tcg/hexagon/misc.c| 35 
 target/hexagon/gen_idef_parser_funcs.py | 10 +++-
 target/hexagon/idef-parser/idef-parser.lex  | 37 +++--
 target/hexagon/idef-parser/idef-parser.y|  2 -
 7 files changed, 160 insertions(+), 41 deletions(-)

diff --git a/target/hexagon/idef-parser/parser-helpers.h 
b/target/hexagon/idef-parser/parser-helpers.h
index 1239d23a6a..7c58087169 100644
--- a/target/hexagon/idef-parser/parser-helpers.h
+++ b/target/hexagon/idef-parser/parser-helpers.h
@@ -80,7 +80,7 @@ void reg_compose(Context *c, YYLTYPE *locp, HexReg *reg, char 
reg_id[5]);
 
 void reg_print(Context *c, YYLTYPE *locp, HexReg *reg);
 
-void imm_print(Context *c, YYLTYPE *locp, HexImm *imm);
+void imm_print(Context *c, YYLTYPE *locp, HexValue *rvalue);
 
 void var_print(Context *c, YYLTYPE *locp, HexVar *var);
 
diff --git a/target/hexagon/idef-parser/parser-helpers.c 
b/target/hexagon/idef-parser/parser-helpers.c
index 6626e006f6..9550097269 100644
--- a/target/hexagon/idef-parser/parser-helpers.c
+++ b/target/hexagon/idef-parser/parser-helpers.c
@@ -167,8 +167,9 @@ void reg_print(Context *c, YYLTYPE *locp, HexReg *reg)
 EMIT(c, "hex_gpr[%u]", reg->id);
 }
 
-void imm_print(Context *c, YYLTYPE *locp, HexImm *imm)
+void imm_print(Context *c, YYLTYPE *locp, HexValue *rvalue)
 {
+HexImm *imm = >imm;
 switch (imm->type) {
 case I:
 EMIT(c, "i");
@@ -177,7 +178,21 @@ void imm_print(Context *c, YYLTYPE *locp, HexImm *imm)
 EMIT(c, "%ciV", imm->id);
 break;
 case VALUE:
-EMIT(c, "((int64_t) %" PRIu64 "ULL)", (int64_t) imm->value);
+if (rvalue->bit_width == 32) {
+if (rvalue->signedness == UNSIGNED) {
+EMIT(c, "((uint32_t) 0x%" PRIx32 ")", (uint32_t) imm->value);
+}  else {
+EMIT(c, "((int32_t) 0x%" PRIx32 ")", (int32_t) imm->value);
+}
+} else if (rvalue->bit_width == 64) {
+if (rvalue->signedness == UNSIGNED) {
+EMIT(c, "((uint64_t) 0x%" PRIx64 "ULL)", (uint64_t) 
imm->value);
+} else {
+EMIT(c, "((int64_t) 0x%" PRIx64 "LL)", (int64_t) imm->value);
+}
+} else {
+g_assert_not_reached();
+}
 break;
 case QEMU_TMP:
 EMIT(c, "qemu_tmp_%" PRIu64, imm->index);
@@ -213,7 +228,7 @@ void rvalue_print(Context *c, YYLTYPE *locp, void *pointer)
   tmp_print(c, locp, >tmp);
   break;
   case IMMEDIATE:
-  imm_print(c, locp, >imm);
+  imm_print(c, locp, rvalue);
   break;
   case VARID:
   var_print(c, locp, >var);
@@ -386,13 +401,10 @@ HexValue gen_rvalue_extend(Context *c, YYLTYPE *locp, 
HexValue *rvalue)
 
 if (rvalue->type == IMMEDIATE) {
 HexValue res = gen_imm_qemu_tmp(c, locp, 64, rvalue->signedness);
-bool is_unsigned = (rvalue->signedness == UNSIGNED);
-const char *sign_suffix = is_unsigned ? "u" : "";
 gen_c_int_type(c, locp, 64, rvalue->signedness);
-OUT(c, locp, " ", , " = ");
-OUT(c, locp, "(", sign_suffix, "int64_t) ");
-OUT(c, locp, "(", sign_suffix, "int32_t) ");
-OUT(c, locp, rvalue, ";\n");
+OUT(c, locp, " ", , " = (");
+gen_c_int_type(c, locp, 64, rvalue->signedness);
+OUT(c, locp, ")", rvalue, ";\n");
 return res;
 } else {
 HexValue res = gen_tmp(c, locp, 64, rvalue->signedness);
@@ -959,33 +971,18 @@ HexValue gen_cast_op(Context *c,
  unsigned target_width,

[PULL v2 33/44] Hexagon (target/hexagon/*.py): raise exception on reg parsing error

2023-05-18 Thread Taylor Simpson
From: Matheus Tavares Bernardino 

Currently, the python scripts used for the hexagon building will not
abort the compilation when there is an error parsing a register. Let's
make the compilation properly fail in such cases by rasing an exception
instead of just printing a warning message, which might get lost in the
output.

This patch was generated with:

 git grep -l "Bad register" *hexagon* | \
 xargs sed -i "" -e 's/print("Bad register parse: "[, 
]*\([^)]*\))/hex_common.bad_register(\1)/g'

Plus the bad_register() helper added to hex_common.py.

Signed-off-by: Matheus Tavares Bernardino 
Reviewed-by: Anton Johansson 
Tested-by: Taylor Simpson 
Reviewed-by: Taylor Simpson 
Signed-off-by: Taylor Simpson 
Message-Id: 
<1f5dbd92f68fdd89e2647e4ba527a2c32cf0f070.1683217043.git.quic_mathb...@quicinc.com>
---
 target/hexagon/gen_analyze_funcs.py | 30 +-
 target/hexagon/gen_helper_funcs.py  | 14 ++---
 target/hexagon/gen_helper_protos.py |  2 +-
 target/hexagon/gen_idef_parser_funcs.py |  2 +-
 target/hexagon/gen_tcg_funcs.py | 78 -
 target/hexagon/hex_common.py|  3 +
 6 files changed, 66 insertions(+), 63 deletions(-)

diff --git a/target/hexagon/gen_analyze_funcs.py 
b/target/hexagon/gen_analyze_funcs.py
index d040f67001..00868cc6cb 100755
--- a/target/hexagon/gen_analyze_funcs.py
+++ b/target/hexagon/gen_analyze_funcs.py
@@ -47,7 +47,7 @@ def analyze_opn_old(f, tag, regtype, regid, regno):
 f.write(f"const int {regN} = insn->regno[{regno}];\n")
 f.write(f"ctx_log_reg_write(ctx, {regN}, {predicated});\n")
 else:
-print("Bad register parse: ", regtype, regid)
+hex_common.bad_register(regtype, regid)
 elif regtype == "P":
 if regid in {"s", "t", "u", "v"}:
 f.write(f"const int {regN} = insn->regno[{regno}];\n")
@@ -56,7 +56,7 @@ def analyze_opn_old(f, tag, regtype, regid, regno):
 f.write(f"const int {regN} = insn->regno[{regno}];\n")
 f.write(f"ctx_log_pred_write(ctx, {regN});\n")
 else:
-print("Bad register parse: ", regtype, regid)
+hex_common.bad_register(regtype, regid)
 elif regtype == "C":
 if regid == "ss":
 f.write(
@@ -77,13 +77,13 @@ def analyze_opn_old(f, tag, regtype, regid, regno):
 f.write(f"const int {regN} = insn->regno[{regno}] " "+ 
HEX_REG_SA0;\n")
 f.write(f"ctx_log_reg_write(ctx, {regN}, {predicated});\n")
 else:
-print("Bad register parse: ", regtype, regid)
+hex_common.bad_register(regtype, regid)
 elif regtype == "M":
 if regid == "u":
 f.write(f"const int {regN} = insn->regno[{regno}];\n")
 f.write(f"ctx_log_reg_read(ctx, {regN});\n")
 else:
-print("Bad register parse: ", regtype, regid)
+hex_common.bad_register(regtype, regid)
 elif regtype == "V":
 newv = "EXT_DFL"
 if hex_common.is_new_result(tag):
@@ -105,7 +105,7 @@ def analyze_opn_old(f, tag, regtype, regid, regno):
 f.write(f"const int {regN} = insn->regno[{regno}];\n")
 f.write(f"ctx_log_vreg_write(ctx, {regN}, {newv}, " 
f"{predicated});\n")
 else:
-print("Bad register parse: ", regtype, regid)
+hex_common.bad_register(regtype, regid)
 elif regtype == "Q":
 if regid in {"d", "e", "x"}:
 f.write(f"const int {regN} = insn->regno[{regno}];\n")
@@ -114,7 +114,7 @@ def analyze_opn_old(f, tag, regtype, regid, regno):
 f.write(f"const int {regN} = insn->regno[{regno}];\n")
 f.write(f"ctx_log_qreg_read(ctx, {regN});\n")
 else:
-print("Bad register parse: ", regtype, regid)
+hex_common.bad_register(regtype, regid)
 elif regtype == "G":
 if regid in {"dd"}:
 f.write(f"//const int {regN} = insn->regno[{regno}];\n")
@@ -125,7 +125,7 @@ def analyze_opn_old(f, tag, regtype, regid, regno):
 elif regid in {"s"}:
 f.write(f"//const int {regN} = insn->regno[{regno}];\n")
 else:
-print("Bad register parse: ", regtype, regid)
+hex_common.bad_register(regtype, regid)
 elif regtype == "S":
 if regid in {"dd"}:
 f.write(f"//const int {regN} = insn->regno[{regno}];\n&q

[PULL v2 19/44] Hexagon (target/hexagon) Mark registers as read during packet analysis

2023-05-18 Thread Taylor Simpson
Have gen_analyze_funcs mark the registers that are read by the
instruction.  We also mark the implicit reads using instruction
attributes.

Signed-off-by: Taylor Simpson 
Reviewed-by: Richard Henderson 
Message-Id: <20230427230012.3800327-11-tsimp...@quicinc.com>
---
 target/hexagon/translate.h  | 36 +++
 target/hexagon/attribs_def.h.inc|  6 +++-
 target/hexagon/translate.c  | 20 +
 target/hexagon/gen_analyze_funcs.py | 44 -
 target/hexagon/hex_common.py|  6 
 5 files changed, 97 insertions(+), 15 deletions(-)

diff --git a/target/hexagon/translate.h b/target/hexagon/translate.h
index 4b9f21c41d..f72228859f 100644
--- a/target/hexagon/translate.h
+++ b/target/hexagon/translate.h
@@ -38,10 +38,12 @@ typedef struct DisasContext {
 int reg_log[REG_WRITES_MAX];
 int reg_log_idx;
 DECLARE_BITMAP(regs_written, TOTAL_PER_THREAD_REGS);
+DECLARE_BITMAP(regs_read, TOTAL_PER_THREAD_REGS);
 DECLARE_BITMAP(predicated_regs, TOTAL_PER_THREAD_REGS);
 int preg_log[PRED_WRITES_MAX];
 int preg_log_idx;
 DECLARE_BITMAP(pregs_written, NUM_PREGS);
+DECLARE_BITMAP(pregs_read, NUM_PREGS);
 uint8_t store_width[STORES_MAX];
 bool s1_store_processed;
 int future_vregs_idx;
@@ -55,8 +57,10 @@ typedef struct DisasContext {
 DECLARE_BITMAP(vregs_select, NUM_VREGS);
 DECLARE_BITMAP(predicated_future_vregs, NUM_VREGS);
 DECLARE_BITMAP(predicated_tmp_vregs, NUM_VREGS);
+DECLARE_BITMAP(vregs_read, NUM_VREGS);
 int qreg_log[NUM_QREGS];
 int qreg_log_idx;
+DECLARE_BITMAP(qregs_read, NUM_QREGS);
 bool pre_commit;
 TCGCond branch_cond;
 target_ulong branch_dest;
@@ -73,6 +77,11 @@ static inline void ctx_log_pred_write(DisasContext *ctx, int 
pnum)
 }
 }
 
+static inline void ctx_log_pred_read(DisasContext *ctx, int pnum)
+{
+set_bit(pnum, ctx->pregs_read);
+}
+
 static inline void ctx_log_reg_write(DisasContext *ctx, int rnum,
  bool is_predicated)
 {
@@ -99,6 +108,17 @@ static inline void ctx_log_reg_write_pair(DisasContext 
*ctx, int rnum,
 ctx_log_reg_write(ctx, rnum + 1, is_predicated);
 }
 
+static inline void ctx_log_reg_read(DisasContext *ctx, int rnum)
+{
+set_bit(rnum, ctx->regs_read);
+}
+
+static inline void ctx_log_reg_read_pair(DisasContext *ctx, int rnum)
+{
+ctx_log_reg_read(ctx, rnum);
+ctx_log_reg_read(ctx, rnum + 1);
+}
+
 intptr_t ctx_future_vreg_off(DisasContext *ctx, int regnum,
  int num, bool alloc_ok);
 intptr_t ctx_tmp_vreg_off(DisasContext *ctx, int regnum,
@@ -139,6 +159,17 @@ static inline void ctx_log_vreg_write_pair(DisasContext 
*ctx,
 ctx_log_vreg_write(ctx, rnum ^ 1, type, is_predicated);
 }
 
+static inline void ctx_log_vreg_read(DisasContext *ctx, int rnum)
+{
+set_bit(rnum, ctx->vregs_read);
+}
+
+static inline void ctx_log_vreg_read_pair(DisasContext *ctx, int rnum)
+{
+ctx_log_vreg_read(ctx, rnum ^ 0);
+ctx_log_vreg_read(ctx, rnum ^ 1);
+}
+
 static inline void ctx_log_qreg_write(DisasContext *ctx,
   int rnum)
 {
@@ -146,6 +177,11 @@ static inline void ctx_log_qreg_write(DisasContext *ctx,
 ctx->qreg_log_idx++;
 }
 
+static inline void ctx_log_qreg_read(DisasContext *ctx, int qnum)
+{
+set_bit(qnum, ctx->qregs_read);
+}
+
 extern TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
 extern TCGv hex_pred[NUM_PREGS];
 extern TCGv hex_this_PC;
diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 69da9776f0..21d457fa4a 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. 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
@@ -112,6 +112,10 @@ DEF_ATTRIB(IMPLICIT_WRITES_P1, "Writes Predicate 1", "", 
"UREG.P1")
 DEF_ATTRIB(IMPLICIT_WRITES_P2, "Writes Predicate 1", "", "UREG.P2")
 DEF_ATTRIB(IMPLICIT_WRITES_P3, "May write Predicate 3", "", "UREG.P3")
 DEF_ATTRIB(IMPLICIT_READS_PC, "Reads the PC register", "", "")
+DEF_ATTRIB(IMPLICIT_READS_P0, "Reads the P0 register", "", "")
+DEF_ATTRIB(IMPLICIT_READS_P1, "Reads the P1 register", "", "")
+DEF_ATTRIB(IMPLICIT_READS_P2, "Reads the P2 register", "", "")
+DEF_ATTRIB(IMPLICIT_READS_P3, "Reads the P3 register", "", "")
 DEF_ATTRIB(IMPLICIT_WRITES_USR, "May write USR", "", "")
 DEF_ATTRIB(WRITES_PRED_REG, "Writes 

[PULL v2 17/44] Hexagon (target/hexagon) Clean up pred_written usage

2023-05-18 Thread Taylor Simpson
Only endloop instructions will conditionally write to a predicate.
When there is an endloop instruction, we preload the values into
new_pred_value.

The only place pred_written is needed is when HEX_DEBUG is on.

We remove the last use of check_for_attrib.  However, new uses will be
introduced later in this series, so we mark it with G_GNUC_UNUSED.

Signed-off-by: Taylor Simpson 
Reviewed-by: Richard Henderson 
Message-Id: <20230427230012.3800327-9-tsimp...@quicinc.com>
---
 target/hexagon/genptr.c| 16 +---
 target/hexagon/translate.c | 53 --
 2 files changed, 23 insertions(+), 46 deletions(-)

diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index dac62b90a6..9bbaca6300 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -137,7 +137,9 @@ void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv 
val)
 tcg_gen_and_tl(hex_new_pred_value[pnum],
hex_new_pred_value[pnum], base_val);
 }
-tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
+if (HEX_DEBUG) {
+tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
+}
 set_bit(pnum, ctx->pregs_written);
 }
 
@@ -826,15 +828,13 @@ static void gen_endloop0(DisasContext *ctx)
 
 /*
  *if (lpcfg == 1) {
- *hex_new_pred_value[3] = 0xff;
- *hex_pred_written |= 1 << 3;
+ *p3 = 0xff;
  *}
  */
 TCGLabel *label1 = gen_new_label();
 tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1);
 {
-tcg_gen_movi_tl(hex_new_pred_value[3], 0xff);
-tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << 3);
+gen_log_pred_write(ctx, 3, tcg_constant_tl(0xff));
 }
 gen_set_label(label1);
 
@@ -903,14 +903,12 @@ static void gen_endloop01(DisasContext *ctx)
 
 /*
  *if (lpcfg == 1) {
- *hex_new_pred_value[3] = 0xff;
- *hex_pred_written |= 1 << 3;
+ *p3 = 0xff;
  *}
  */
 tcg_gen_brcondi_tl(TCG_COND_NE, lpcfg, 1, label1);
 {
-tcg_gen_movi_tl(hex_new_pred_value[3], 0xff);
-tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << 3);
+gen_log_pred_write(ctx, 3, tcg_constant_tl(0xff));
 }
 gen_set_label(label1);
 
diff --git a/target/hexagon/translate.c b/target/hexagon/translate.c
index 01f448a325..0b021b301a 100644
--- a/target/hexagon/translate.c
+++ b/target/hexagon/translate.c
@@ -239,7 +239,7 @@ static int read_packet_words(CPUHexagonState *env, 
DisasContext *ctx,
 return nwords;
 }
 
-static bool check_for_attrib(Packet *pkt, int attrib)
+static G_GNUC_UNUSED bool check_for_attrib(Packet *pkt, int attrib)
 {
 for (int i = 0; i < pkt->num_insns; i++) {
 if (GET_ATTRIB(pkt->insn[i].opcode, attrib)) {
@@ -262,11 +262,6 @@ static bool need_slot_cancelled(Packet *pkt)
 return false;
 }
 
-static bool need_pred_written(Packet *pkt)
-{
-return check_for_attrib(pkt, A_WRITES_PRED_REG);
-}
-
 static bool need_next_PC(DisasContext *ctx)
 {
 Packet *pkt = ctx->pkt;
@@ -414,7 +409,7 @@ static void gen_start_packet(DisasContext *ctx)
 tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], next_PC);
 }
 }
-if (need_pred_written(pkt)) {
+if (HEX_DEBUG) {
 tcg_gen_movi_tl(hex_pred_written, 0);
 }
 
@@ -428,6 +423,17 @@ static void gen_start_packet(DisasContext *ctx)
 }
 }
 
+/*
+ * Preload the predicated pred registers into hex_new_pred_value[pred_num]
+ * Only endloop instructions conditionally write to pred registers
+ */
+if (pkt->pkt_has_endloop) {
+for (int i = 0; i < ctx->preg_log_idx; i++) {
+int pred_num = ctx->preg_log[i];
+tcg_gen_mov_tl(hex_new_pred_value[pred_num], hex_pred[pred_num]);
+}
+}
+
 /* Preload the predicated HVX registers into future_VRegs and tmp_VRegs */
 if (!bitmap_empty(ctx->predicated_future_vregs, NUM_VREGS)) {
 int i = find_first_bit(ctx->predicated_future_vregs, NUM_VREGS);
@@ -535,41 +541,14 @@ static void gen_reg_writes(DisasContext *ctx)
 
 static void gen_pred_writes(DisasContext *ctx)
 {
-int i;
-
 /* Early exit if the log is empty */
 if (!ctx->preg_log_idx) {
 return;
 }
 
-/*
- * Only endloop instructions will conditionally
- * write a predicate.  If there are no endloop
- * instructions, we can use the non-conditional
- * write of the predicates.
- */
-if (ctx->pkt->pkt_has_endloop) {
-TCGv zero = tcg_constant_tl(0);
-TCGv pred_written = tcg_temp_new();
-for (i = 0; i < ctx->preg_log_idx; i++) {
-int pred_num = ctx->preg_log[i];
-
-tcg_gen_andi_tl(pred_written, hex_pred_written, 1 << pred_num);
-tcg_gen_movcond_tl(TCG_COND_NE, hex_pred[pred_num],
-   

[PULL v2 10/44] meson.build Add CONFIG_HEXAGON_IDEF_PARSER

2023-05-18 Thread Taylor Simpson
Enable conditional compilation depending on whether idef-parser
is configured

Signed-off-by: Taylor Simpson 
Reviewed-by: Richard Henderson 
Message-Id: <20230427230012.3800327-2-tsimp...@quicinc.com>
---
 meson.build | 1 +
 1 file changed, 1 insertion(+)

diff --git a/meson.build b/meson.build
index d3cf48960b..b36124fdc4 100644
--- a/meson.build
+++ b/meson.build
@@ -1866,6 +1866,7 @@ endif
 config_host_data.set('CONFIG_GTK', gtk.found())
 config_host_data.set('CONFIG_VTE', vte.found())
 config_host_data.set('CONFIG_GTK_CLIPBOARD', have_gtk_clipboard)
+config_host_data.set('CONFIG_HEXAGON_IDEF_PARSER', 
get_option('hexagon_idef_parser'))
 config_host_data.set('CONFIG_LIBATTR', have_old_libattr)
 config_host_data.set('CONFIG_LIBCAP_NG', libcap_ng.found())
 config_host_data.set('CONFIG_EBPF', libbpf.found())
-- 
2.25.1



[PULL v2 35/44] Hexagon: append eflags to unknown cpu model string

2023-05-18 Thread Taylor Simpson
From: Matheus Tavares Bernardino 

Running qemu-hexagon with a binary that was compiled for an arch version
unknown by qemu can produce a somewhat confusing message:

  qemu-hexagon: unable to find CPU model 'unknown'

Let's give a bit more info by appending the eflags so that the message
becomes:

  qemu-hexagon: unable to find CPU model 'unknown (0x69)'

Signed-off-by: Matheus Tavares Bernardino 
Signed-off-by: Taylor Simpson 
Tested-by: Taylor Simpson 
Reviewed-by: Taylor Simpson 
Message-Id: 
<8a8d013cc619b94fd4fb577ae6a8df26cedb972b.1683225804.git.quic_mathb...@quicinc.com>
---
 linux-user/hexagon/target_elf.h | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/linux-user/hexagon/target_elf.h b/linux-user/hexagon/target_elf.h
index a0271a0a2a..36056fc9f0 100644
--- a/linux-user/hexagon/target_elf.h
+++ b/linux-user/hexagon/target_elf.h
@@ -20,6 +20,9 @@
 
 static inline const char *cpu_get_model(uint32_t eflags)
 {
+static char buf[32];
+int err;
+
 /* For now, treat anything newer than v5 as a v73 */
 /* FIXME - Disable instructions that are newer than the specified arch */
 if (eflags == 0x04 ||/* v5  */
@@ -39,7 +42,9 @@ static inline const char *cpu_get_model(uint32_t eflags)
) {
 return "v73";
 }
-return "unknown";
+
+err = snprintf(buf, sizeof(buf), "unknown (0x%x)", eflags);
+return err >= 0 && err < sizeof(buf) ? buf : "unknown";
 }
 
 #endif
-- 
2.25.1



[PULL v2 14/44] Hexagon (target/hexagon) Add overrides for clr[tf]new

2023-05-18 Thread Taylor Simpson
These instructions have implicit reads from p0, so we don't want
them in helpers when idef-parser is off.

Signed-off-by: Taylor Simpson 
Reviewed-by: Richard Henderson 
Message-Id: <20230427230012.3800327-6-tsimp...@quicinc.com>
---
 target/hexagon/gen_tcg.h | 16 
 target/hexagon/macros.h  |  4 
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index ef17f2f18c..a1d7eabae7 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1101,6 +1101,22 @@
 gen_jump(ctx, riV); \
 } while (0)
 
+/* if (p0.new) r0 = #0 */
+#define fGEN_TCG_SA1_clrtnew(SHORTCODE) \
+do { \
+tcg_gen_movcond_tl(TCG_COND_EQ, RdV, \
+   hex_new_pred_value[0], tcg_constant_tl(0), \
+   RdV, tcg_constant_tl(0)); \
+} while (0)
+
+/* if (!p0.new) r0 = #0 */
+#define fGEN_TCG_SA1_clrfnew(SHORTCODE) \
+do { \
+tcg_gen_movcond_tl(TCG_COND_NE, RdV, \
+   hex_new_pred_value[0], tcg_constant_tl(0), \
+   RdV, tcg_constant_tl(0)); \
+} while (0)
+
 #define fGEN_TCG_J2_pause(SHORTCODE) \
 do { \
 uiV = uiV; \
diff --git a/target/hexagon/macros.h b/target/hexagon/macros.h
index 760630de8f..b1ff40c894 100644
--- a/target/hexagon/macros.h
+++ b/target/hexagon/macros.h
@@ -227,12 +227,8 @@ static inline void gen_cancel(uint32_t slot)
 
 #ifdef QEMU_GENERATE
 #define fLSBNEW(PVAL)   tcg_gen_andi_tl(LSB, (PVAL), 1)
-#define fLSBNEW0tcg_gen_andi_tl(LSB, hex_new_pred_value[0], 1)
-#define fLSBNEW1tcg_gen_andi_tl(LSB, hex_new_pred_value[1], 1)
 #else
 #define fLSBNEW(PVAL)   ((PVAL) & 1)
-#define fLSBNEW0(env->new_pred_value[0] & 1)
-#define fLSBNEW1(env->new_pred_value[1] & 1)
 #endif
 
 #ifdef QEMU_GENERATE
-- 
2.25.1



[PULL v2 08/44] Hexagon (target/hexagon) Add v73 scalar instructions

2023-05-18 Thread Taylor Simpson
The following instructions are added
J2_callrh
J2_junprh

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230427224057.3766963-9-tsimp...@quicinc.com>
---
 target/hexagon/gen_tcg.h  | 4 
 target/hexagon/attribs_def.h.inc  | 1 +
 target/hexagon/imported/branch.idef   | 7 ++-
 target/hexagon/imported/encode_pp.def | 2 ++
 4 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index 598d80d3ce..6f12f665db 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -653,6 +653,8 @@
 gen_call(ctx, riV)
 #define fGEN_TCG_J2_callr(SHORTCODE) \
 gen_callr(ctx, RsV)
+#define fGEN_TCG_J2_callrh(SHORTCODE) \
+gen_callr(ctx, RsV)
 
 #define fGEN_TCG_J2_callt(SHORTCODE) \
 gen_cond_call(ctx, PuV, TCG_COND_EQ, riV)
@@ -851,6 +853,8 @@
 gen_jump(ctx, riV)
 #define fGEN_TCG_J2_jumpr(SHORTCODE) \
 gen_jumpr(ctx, RsV)
+#define fGEN_TCG_J2_jumprh(SHORTCODE) \
+gen_jumpr(ctx, RsV)
 #define fGEN_TCG_J4_jumpseti(SHORTCODE) \
 do { \
 tcg_gen_movi_tl(RdV, UiV); \
diff --git a/target/hexagon/attribs_def.h.inc b/target/hexagon/attribs_def.h.inc
index 3bef60bef3..69da9776f0 100644
--- a/target/hexagon/attribs_def.h.inc
+++ b/target/hexagon/attribs_def.h.inc
@@ -89,6 +89,7 @@ DEF_ATTRIB(JUMP, "Jump-type instruction", "", "")
 DEF_ATTRIB(INDIRECT, "Absolute register jump", "", "")
 DEF_ATTRIB(CALL, "Function call instruction", "", "")
 DEF_ATTRIB(COF, "Change-of-flow instruction", "", "")
+DEF_ATTRIB(HINTED_COF, "This instruction is a hinted change-of-flow", "", "")
 DEF_ATTRIB(CONDEXEC, "May be cancelled by a predicate", "", "")
 DEF_ATTRIB(DOTNEWVALUE, "Uses a register value generated in this pkt", "", "")
 DEF_ATTRIB(NEWCMPJUMP, "Compound compare and jump", "", "")
diff --git a/target/hexagon/imported/branch.idef 
b/target/hexagon/imported/branch.idef
index 88f5f48cce..93e2e375a5 100644
--- a/target/hexagon/imported/branch.idef
+++ b/target/hexagon/imported/branch.idef
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights 
Reserved.
+ *  Copyright(c) 2019-2023 Qualcomm Innovation Center, Inc. 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
@@ -34,6 +34,9 @@ Q6INSN(J2_jump,"jump #r22:2",ATTRIBS(A_JDIR), "direct 
unconditional jump",
 Q6INSN(J2_jumpr,"jumpr Rs32",ATTRIBS(A_JINDIR), "indirect unconditional jump",
 {fJUMPR(RsN,RsV,COF_TYPE_JUMPR);})
 
+Q6INSN(J2_jumprh,"jumprh Rs32",ATTRIBS(A_JINDIR, A_HINTED_COF), "indirect 
unconditional jump",
+{fJUMPR(RsN,RsV,COF_TYPE_JUMPR);})
+
 #define OLDCOND_JUMP(TAG,OPER,OPER2,ATTRIB,DESCR,SEMANTICS) \
 Q6INSN(TAG##t,"if (Pu4) "OPER":nt 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLD(PuV),,SPECULATE_NOT_TAKEN,12,0);
 if (fLSBOLD(PuV)) { SEMANTICS; }}) \
 Q6INSN(TAG##f,"if (!Pu4) "OPER":nt 
"OPER2,ATTRIB,DESCR,{fBRANCH_SPECULATE_STALL(fLSBOLDNOT(PuV),,SPECULATE_NOT_TAKEN,12,0);
 if (fLSBOLDNOT(PuV)) { SEMANTICS; }}) \
@@ -196,6 +199,8 @@ Q6INSN(J2_callrt,"if (Pu4) callr 
Rs32",ATTRIBS(CINDIR_STD),"indirect conditional
 Q6INSN(J2_callrf,"if (!Pu4) callr Rs32",ATTRIBS(CINDIR_STD),"indirect 
conditional call if false",
 {fBRANCH_SPECULATE_STALL(fLSBOLDNOT(PuV),,SPECULATE_NOT_TAKEN,12,0);if 
(fLSBOLDNOT(PuV)) { fCALLR(RsV); }})
 
+Q6INSN(J2_callrh,"callrh Rs32",ATTRIBS(CINDIR_STD, A_HINTED_COF), "hinted 
indirect unconditional call",
+{ fCALLR(RsV); })
 
 
 
diff --git a/target/hexagon/imported/encode_pp.def 
b/target/hexagon/imported/encode_pp.def
index 763f465bfd..0cd30a5e85 100644
--- a/target/hexagon/imported/encode_pp.def
+++ b/target/hexagon/imported/encode_pp.def
@@ -524,6 +524,7 @@ DEF_FIELD32(ICLASS_J" 110-  PP-! 
",J_PT,"Predict-taken")
 
 DEF_FIELDROW_DESC32(ICLASS_J"   PP-- ","[#0] PC=(Rs), 
R31=return")
 DEF_ENC32(J2_callr, ICLASS_J"   101s  PP--  ")
+DEF_ENC32(J2_callrh,ICLASS_J"   110s  PP--  ")
 
 DEF_FIELDROW_DESC32(ICLASS_J" 0001  PP-- ","[#1] if (Pu) 
PC=(Rs), R31=return")
 DEF_ENC32(J2_callrt,ICLASS_J" 0001  000s  PPuu  ")
@@ -531,6 +532,7 @@ DEF_ENC32(J2_callrf,ICLASS_J" 0001  001s  PPuu  
")
 
 DEF_FIELDROW_DESC32(ICLASS_J" 0010  PP-- ","[#2] PC=(Rs); 
")
 DEF_ENC32(J2_jumpr,  ICLASS_J" 0010  100s  PP--  ")
+DEF_ENC32(J2_jumprh, ICLASS_J" 0010  110s  PP--  ")
 DEF_ENC32(J4_hintjumpr,  ICLASS_J" 0010  101s  PP--  ")
 
 DEF_FIELDROW_DESC32(ICLASS_J" 0011  PP-- ","[#3] if (Pu) 
PC=(Rs) ")
-- 
2.25.1



[PULL v2 09/44] Hexagon (tests/tcg/hexagon) Add v73 scalar tests

2023-05-18 Thread Taylor Simpson
Tests added for the following instructions
J2_callrh
J2_jumprh

Signed-off-by: Taylor Simpson 
Reviewed-by: Anton Johansson 
Message-Id: <20230427224057.3766963-10-tsimp...@quicinc.com>
---
 tests/tcg/hexagon/v73_scalar.c| 96 +++
 tests/tcg/hexagon/Makefile.target |  2 +
 2 files changed, 98 insertions(+)
 create mode 100644 tests/tcg/hexagon/v73_scalar.c

diff --git a/tests/tcg/hexagon/v73_scalar.c b/tests/tcg/hexagon/v73_scalar.c
new file mode 100644
index 00..fee67fc531
--- /dev/null
+++ b/tests/tcg/hexagon/v73_scalar.c
@@ -0,0 +1,96 @@
+/*
+ *  Copyright(c) 2023 Qualcomm Innovation Center, Inc. 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/>.
+ */
+
+#include 
+#include 
+#include 
+
+/*
+ *  Test the scalar core instructions that are new in v73
+ */
+
+int err;
+
+static void __check32(int line, uint32_t result, uint32_t expect)
+{
+if (result != expect) {
+printf("ERROR at line %d: 0x%08x != 0x%08x\n",
+   line, result, expect);
+err++;
+}
+}
+
+#define check32(RES, EXP) __check32(__LINE__, RES, EXP)
+
+static void __check64(int line, uint64_t result, uint64_t expect)
+{
+if (result != expect) {
+printf("ERROR at line %d: 0x%016llx != 0x%016llx\n",
+   line, result, expect);
+err++;
+}
+}
+
+#define check64(RES, EXP) __check64(__LINE__, RES, EXP)
+
+static bool my_func_called;
+
+static void my_func(void)
+{
+my_func_called = true;
+}
+
+static inline void callrh(void *func)
+{
+asm volatile("callrh %0\n\t"
+ : : "r"(func)
+ /* Mark the caller-save registers as clobbered */
+ : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9",
+   "r10", "r11", "r12", "r13", "r14", "r15", "r28",
+   "p0", "p1", "p2", "p3");
+}
+
+static void test_callrh(void)
+{
+my_func_called = false;
+callrh(_func);
+check32(my_func_called, true);
+}
+
+static void test_jumprh(void)
+{
+uint32_t res;
+asm ("%0 = #5\n\t"
+ "r0 = ##1f\n\t"
+ "jumprh r0\n\t"
+ "%0 = #3\n\t"
+ "jump 2f\n\t"
+ "1:\n\t"
+ "%0 = #1\n\t"
+ "2:\n\t"
+ : "=r"(res) : : "r0");
+check32(res, 1);
+}
+
+int main()
+{
+test_callrh();
+test_jumprh();
+
+puts(err ? "FAIL" : "PASS");
+return err ? 1 : 0;
+}
diff --git a/tests/tcg/hexagon/Makefile.target 
b/tests/tcg/hexagon/Makefile.target
index 558c056148..3172f2e4db 100644
--- a/tests/tcg/hexagon/Makefile.target
+++ b/tests/tcg/hexagon/Makefile.target
@@ -79,6 +79,7 @@ HEX_TESTS += test_vspliceb
 HEX_TESTS += v68_scalar
 HEX_TESTS += v68_hvx
 HEX_TESTS += v69_hvx
+HEX_TESTS += v73_scalar
 
 TESTS += $(HEX_TESTS)
 
@@ -98,6 +99,7 @@ v68_hvx: v68_hvx.c hvx_misc.h v6mpy_ref.c.inc
 v68_hvx: CFLAGS += -mhvx -Wno-unused-function
 v69_hvx: v69_hvx.c hvx_misc.h
 v69_hvx: CFLAGS += -mhvx -Wno-unused-function
+v73_scalar: CFLAGS += -Wno-unused-function
 
 hvx_histogram: hvx_histogram.c hvx_histogram_row.S
$(CC) $(CFLAGS) $(CROSS_CC_GUEST_CFLAGS) $^ -o $@ $(LDFLAGS)
-- 
2.25.1



  1   2   3   4   5   6   7   8   9   10   >