Hexagon update
-----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEENjXHiM5iuR/UxZq0ewJE+xLeRCIFAmRmgQgACgkQewJE+xLe RCJLtAf8C/0kQRa4mjnbsztXuFyca53UxAv3BSBEDla4ZcMfFBoVJsGB3OP7IPXd KBQpkLyJAVye9idex5xqdp9nIfoGKDTsc6YtCfGujZ17cDpzLRDpHdUTex8PcZYK wpfM3hoVJsYRBMsojZ4OaxatjFQ+FWzrIH6FcgH086Q8TH4w9dZLNEJzHC4lOj0s 7qOuw2tgm+vOVlzsk/fv6/YD/BTeZTON3jgTPvAnvdRLb/482UpM9JkJ8E4rbte3 Ss5PUK8QTQHU0yamspGy/PfsYxiptM+jIWGd836fAGzwF12Ug27mSc1enndRtQVW pQTdnOnWuuRzOwEpd7x3xh9upACm4g== =1CyJ -----END PGP SIGNATURE----- Merge tag 'pull-hex-20230518-1' of https://github.com/quic/qemu into staging Hexagon update # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCgAdFiEENjXHiM5iuR/UxZq0ewJE+xLeRCIFAmRmgQgACgkQewJE+xLe # RCJLtAf8C/0kQRa4mjnbsztXuFyca53UxAv3BSBEDla4ZcMfFBoVJsGB3OP7IPXd # KBQpkLyJAVye9idex5xqdp9nIfoGKDTsc6YtCfGujZ17cDpzLRDpHdUTex8PcZYK # wpfM3hoVJsYRBMsojZ4OaxatjFQ+FWzrIH6FcgH086Q8TH4w9dZLNEJzHC4lOj0s # 7qOuw2tgm+vOVlzsk/fv6/YD/BTeZTON3jgTPvAnvdRLb/482UpM9JkJ8E4rbte3 # Ss5PUK8QTQHU0yamspGy/PfsYxiptM+jIWGd836fAGzwF12Ug27mSc1enndRtQVW # pQTdnOnWuuRzOwEpd7x3xh9upACm4g== # =1CyJ # -----END PGP SIGNATURE----- # gpg: Signature made Thu 18 May 2023 12:48:24 PM PDT # gpg: using RSA key 3635C788CE62B91FD4C59AB47B0244FB12DE4422 # gpg: Good signature from "Taylor Simpson (Rock on) <tsimpson@quicinc.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 3635 C788 CE62 B91F D4C5 9AB4 7B02 44FB 12DE 4422 * tag 'pull-hex-20230518-1' of https://github.com/quic/qemu: (44 commits) Hexagon (linux-user/hexagon): handle breakpoints Hexagon (gdbstub): add HVX support Hexagon (gdbstub): fix p3:0 read and write via stub Hexagon: add core gdbstub xml data for LLDB gdbstub: add test for untimely stop-reply packets gdbstub: only send stop-reply packets when allowed to Remove test_vshuff from hvx_misc tests Hexagon (decode): look for pkts with multiple insns at the same slot Hexagon (iclass): update J4_hintjumpr slot constraints Hexagon: append eflags to unknown cpu model string Hexagon: list available CPUs with `-cpu help` Hexagon (target/hexagon/*.py): raise exception on reg parsing error target/hexagon: fix = vs. == mishap Hexagon (target/hexagon) Additional instructions handled by idef-parser Hexagon (target/hexagon) Move items to DisasContext Hexagon (target/hexagon) Move pkt_has_store_s1 to DisasContext Hexagon (target/hexagon) Move pred_written to DisasContext Hexagon (target/hexagon) Move new_pred_value to DisasContext Hexagon (target/hexagon) Move new_value to DisasContext Hexagon (target/hexagon) Make special new_value for USR ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
449d6d9eb4
@ -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 <ale@rev.ng>
|
||||
|
@ -1 +1,2 @@
|
||||
TARGET_ARCH=hexagon
|
||||
TARGET_XML_FILES=gdb-xml/hexagon-core.xml gdb-xml/hexagon-hvx.xml
|
||||
|
2
configure
vendored
2
configure
vendored
@ -1269,7 +1269,7 @@ fi
|
||||
: ${cross_cc_armeb="$cross_cc_arm"}
|
||||
: ${cross_cc_cflags_armeb="-mbig-endian"}
|
||||
: ${cross_cc_hexagon="hexagon-unknown-linux-musl-clang"}
|
||||
: ${cross_cc_cflags_hexagon="-mv67 -O2 -static"}
|
||||
: ${cross_cc_cflags_hexagon="-mv73 -O2 -static"}
|
||||
: ${cross_cc_cflags_i386="-m32"}
|
||||
: ${cross_cc_cflags_ppc="-m32 -mbig-endian"}
|
||||
: ${cross_cc_cflags_ppc64="-m64 -mbig-endian"}
|
||||
|
84
gdb-xml/hexagon-core.xml
Normal file
84
gdb-xml/hexagon-core.xml
Normal file
@ -0,0 +1,84 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
|
||||
This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
(at your option) any later version. See the COPYING file in the
|
||||
top-level directory.
|
||||
|
||||
Note: this file is intended to be use with LLDB, so it contains fields
|
||||
that may be unknown to GDB. For more information on such fields, please
|
||||
see:
|
||||
https://github.com/llvm/llvm-project/blob/287aa6c4536408413b860e61fca0318a27214cf3/lldb/docs/lldb-gdb-remote.txt#L738-L860
|
||||
https://github.com/llvm/llvm-project/blob/287aa6c4536408413b860e61fca0318a27214cf3/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp#L4275-L4335
|
||||
-->
|
||||
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.hexagon.core">
|
||||
|
||||
<reg name="r00" altname="r0" bitsize="32" offset="0" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="0" generic="r00"/>
|
||||
<reg name="r01" altname="r1" bitsize="32" offset="4" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="1" generic="r01"/>
|
||||
<reg name="r02" altname="r2" bitsize="32" offset="8" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="2" generic="r02"/>
|
||||
<reg name="r03" altname="r3" bitsize="32" offset="12" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="3" generic="r03"/>
|
||||
<reg name="r04" altname="r4" bitsize="32" offset="16" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="4" generic="r04"/>
|
||||
<reg name="r05" altname="r5" bitsize="32" offset="20" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="5" generic="r05"/>
|
||||
<reg name="r06" altname="r6" bitsize="32" offset="24" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="6" generic="r06"/>
|
||||
<reg name="r07" altname="r7" bitsize="32" offset="28" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="7" generic="r07"/>
|
||||
<reg name="r08" altname="r8" bitsize="32" offset="32" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="8" generic="r08"/>
|
||||
<reg name="r09" altname="r9" bitsize="32" offset="36" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="9" generic="r09"/>
|
||||
<reg name="r10" bitsize="32" offset="40" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="10"/>
|
||||
<reg name="r11" bitsize="32" offset="44" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="11"/>
|
||||
<reg name="r12" bitsize="32" offset="48" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="12"/>
|
||||
<reg name="r13" bitsize="32" offset="52" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="13"/>
|
||||
<reg name="r14" bitsize="32" offset="56" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="14"/>
|
||||
<reg name="r15" bitsize="32" offset="60" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="15"/>
|
||||
<reg name="r16" bitsize="32" offset="64" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="16"/>
|
||||
<reg name="r17" bitsize="32" offset="68" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="17"/>
|
||||
<reg name="r18" bitsize="32" offset="72" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="18"/>
|
||||
<reg name="r19" bitsize="32" offset="76" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="19"/>
|
||||
<reg name="r20" bitsize="32" offset="80" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="20"/>
|
||||
<reg name="r21" bitsize="32" offset="84" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="21"/>
|
||||
<reg name="r22" bitsize="32" offset="88" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="22"/>
|
||||
<reg name="r23" bitsize="32" offset="92" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="23"/>
|
||||
<reg name="r24" bitsize="32" offset="96" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="24"/>
|
||||
<reg name="r25" bitsize="32" offset="100" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="25"/>
|
||||
<reg name="r26" bitsize="32" offset="104" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="26"/>
|
||||
<reg name="r27" bitsize="32" offset="108" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="27"/>
|
||||
<reg name="r28" bitsize="32" offset="112" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="28"/>
|
||||
<reg name="r29" altname="sp" bitsize="32" offset="116" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="29" generic="sp"/>
|
||||
<reg name="r30" altname="fp" bitsize="32" offset="120" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="30" generic="fp"/>
|
||||
<reg name="r31" altname="ra" bitsize="32" offset="124" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="31" generic="ra"/>
|
||||
<reg name="sa0" bitsize="32" offset="128" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="32"/>
|
||||
<reg name="lc0" bitsize="32" offset="132" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="33"/>
|
||||
<reg name="sa1" bitsize="32" offset="136" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="34"/>
|
||||
<reg name="lc1" bitsize="32" offset="140" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="35"/>
|
||||
<reg name="p3_0" bitsize="32" offset="144" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="36"/>
|
||||
<reg name="c5" bitsize="32" offset="148" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="37"/>
|
||||
<reg name="m0" bitsize="32" offset="152" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="38"/>
|
||||
<reg name="m1" bitsize="32" offset="156" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="39"/>
|
||||
<reg name="usr" bitsize="32" offset="160" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="40"/>
|
||||
<reg name="pc" bitsize="32" offset="164" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="41" generic="pc"/>
|
||||
<reg name="ugp" bitsize="32" offset="168" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="42"/>
|
||||
<reg name="gp" bitsize="32" offset="172" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="43"/>
|
||||
<reg name="cs0" bitsize="32" offset="176" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="44"/>
|
||||
<reg name="cs1" bitsize="32" offset="180" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="45"/>
|
||||
<reg name="upcyclelo" bitsize="32" offset="184" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="46"/>
|
||||
<reg name="upcyclehi" bitsize="32" offset="188" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="47"/>
|
||||
<reg name="framelimit" bitsize="32" offset="192" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="48"/>
|
||||
<reg name="framekey" bitsize="32" offset="196" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="49"/>
|
||||
<reg name="pktcountlo" bitsize="32" offset="200" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="50"/>
|
||||
<reg name="pktcounthi" bitsize="32" offset="204" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="51"/>
|
||||
<reg name="pkt_cnt" bitsize="32" offset="208" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="52"/>
|
||||
<reg name="insn_cnt" bitsize="32" offset="212" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="53"/>
|
||||
<reg name="hvx_cnt" bitsize="32" offset="216" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="54"/>
|
||||
<reg name="c23" bitsize="32" offset="220" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="55"/>
|
||||
<reg name="c24" bitsize="32" offset="224" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="56"/>
|
||||
<reg name="c25" bitsize="32" offset="228" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="57"/>
|
||||
<reg name="c26" bitsize="32" offset="232" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="58"/>
|
||||
<reg name="c27" bitsize="32" offset="236" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="59"/>
|
||||
<reg name="c28" bitsize="32" offset="240" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="60"/>
|
||||
<reg name="c29" bitsize="32" offset="244" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="61"/>
|
||||
<reg name="utimerlo" bitsize="32" offset="248" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="62"/>
|
||||
<reg name="utimerhi" bitsize="32" offset="252" encoding="uint" format="hex" group="Thread Registers" dwarf_regnum="63"/>
|
||||
|
||||
</feature>
|
96
gdb-xml/hexagon-hvx.xml
Normal file
96
gdb-xml/hexagon-hvx.xml
Normal file
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved.
|
||||
|
||||
This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
(at your option) any later version. See the COPYING file in the
|
||||
top-level directory.
|
||||
|
||||
Note: this file is intended to be use with LLDB, so it contains fields
|
||||
that may be unknown to GDB. For more information on such fields, please
|
||||
see:
|
||||
https://github.com/llvm/llvm-project/blob/287aa6c4536408413b860e61fca0318a27214cf3/lldb/docs/lldb-gdb-remote.txt#L738-L860
|
||||
https://github.com/llvm/llvm-project/blob/287aa6c4536408413b860e61fca0318a27214cf3/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp#L4275-L4335
|
||||
-->
|
||||
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.hexagon.hvx">
|
||||
|
||||
<vector id="vud" type="uint64" count="16"/>
|
||||
<vector id="vd" type="int64" count="16"/>
|
||||
<vector id="vuw" type="uint32" count="32"/>
|
||||
<vector id="vw" type="int32" count="32"/>
|
||||
<vector id="vuh" type="uint16" count="64"/>
|
||||
<vector id="vh" type="int16" count="64"/>
|
||||
<vector id="vub" type="uint8" count="128"/>
|
||||
<vector id="vb" type="int8" count="128"/>
|
||||
<union id="hex_vec">
|
||||
<field name="ud" type="vud"/>
|
||||
<field name="d" type="vd"/>
|
||||
<field name="uw" type="vuw"/>
|
||||
<field name="w" type="vw"/>
|
||||
<field name="uh" type="vuh"/>
|
||||
<field name="h" type="vh"/>
|
||||
<field name="ub" type="vub"/>
|
||||
<field name="b" type="vb"/>
|
||||
</union>
|
||||
|
||||
<flags id="ui2" size="1">
|
||||
<field name="0" start="0" end="0"/>
|
||||
<field name="1" start="1" end="1"/>
|
||||
</flags>
|
||||
<flags id="ui4" size="1">
|
||||
<field name="0" start="0" end="0"/>
|
||||
<field name="1" start="1" end="1"/>
|
||||
<field name="2" start="2" end="2"/>
|
||||
<field name="3" start="3" end="3"/>
|
||||
</flags>
|
||||
<vector id="vpd" type="uint8" count="16"/>
|
||||
<vector id="vpw" type="ui4" count="32"/>
|
||||
<vector id="vph" type="ui2" count="64"/>
|
||||
<vector id="vpb" type="bool" count="128"/>
|
||||
<union id="hex_vec_pred">
|
||||
<field name="d" type="vpd"/>
|
||||
<field name="w" type="vpw"/>
|
||||
<field name="h" type="vph"/>
|
||||
<field name="b" type="vpb"/>
|
||||
</union>
|
||||
|
||||
<reg name="v0" bitsize="1024" offset="256" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="88"/>
|
||||
<reg name="v1" bitsize="1024" offset="384" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="89"/>
|
||||
<reg name="v2" bitsize="1024" offset="512" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="90"/>
|
||||
<reg name="v3" bitsize="1024" offset="640" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="91"/>
|
||||
<reg name="v4" bitsize="1024" offset="768" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="92"/>
|
||||
<reg name="v5" bitsize="1024" offset="896" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="93"/>
|
||||
<reg name="v6" bitsize="1024" offset="1024" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="94"/>
|
||||
<reg name="v7" bitsize="1024" offset="1152" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="95"/>
|
||||
<reg name="v8" bitsize="1024" offset="1280" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="96"/>
|
||||
<reg name="v9" bitsize="1024" offset="1408" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="97"/>
|
||||
<reg name="v10" bitsize="1024" offset="1536" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="98"/>
|
||||
<reg name="v11" bitsize="1024" offset="1664" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="99"/>
|
||||
<reg name="v12" bitsize="1024" offset="1792" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="100"/>
|
||||
<reg name="v13" bitsize="1024" offset="1920" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="101"/>
|
||||
<reg name="v14" bitsize="1024" offset="2048" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="102"/>
|
||||
<reg name="v15" bitsize="1024" offset="2176" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="103"/>
|
||||
<reg name="v16" bitsize="1024" offset="2304" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="104"/>
|
||||
<reg name="v17" bitsize="1024" offset="2432" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="105"/>
|
||||
<reg name="v18" bitsize="1024" offset="2560" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="106"/>
|
||||
<reg name="v19" bitsize="1024" offset="2688" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="107"/>
|
||||
<reg name="v20" bitsize="1024" offset="2816" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="108"/>
|
||||
<reg name="v21" bitsize="1024" offset="2944" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="109"/>
|
||||
<reg name="v22" bitsize="1024" offset="3072" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="110"/>
|
||||
<reg name="v23" bitsize="1024" offset="3200" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="111"/>
|
||||
<reg name="v24" bitsize="1024" offset="3328" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="112"/>
|
||||
<reg name="v25" bitsize="1024" offset="3456" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="113"/>
|
||||
<reg name="v26" bitsize="1024" offset="3584" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="114"/>
|
||||
<reg name="v27" bitsize="1024" offset="3712" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="115"/>
|
||||
<reg name="v28" bitsize="1024" offset="3840" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="116"/>
|
||||
<reg name="v29" bitsize="1024" offset="3968" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="117"/>
|
||||
<reg name="v30" bitsize="1024" offset="4096" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="118"/>
|
||||
<reg name="v31" bitsize="1024" offset="4224" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="119"/>
|
||||
<reg name="q0" bitsize="128" offset="4352" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="120"/>
|
||||
<reg name="q1" bitsize="128" offset="4368" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="121"/>
|
||||
<reg name="q2" bitsize="128" offset="4384" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="122"/>
|
||||
<reg name="q3" bitsize="128" offset="4400" encoding="vector" format="hex" group="HVX Vector Registers" dwarf_regnum="123"/>
|
||||
|
||||
</feature>
|
@ -777,6 +777,10 @@ typedef void (*GdbCmdHandler)(GArray *params, void *user_ctx);
|
||||
/*
|
||||
* cmd_startswith -> cmd is compared using startswith
|
||||
*
|
||||
* allow_stop_reply -> true iff the gdbstub can respond to this command with a
|
||||
* "stop reply" packet. The list of commands that accept such response is
|
||||
* defined at the GDB Remote Serial Protocol documentation. see:
|
||||
* https://sourceware.org/gdb/onlinedocs/gdb/Stop-Reply-Packets.html#Stop-Reply-Packets.
|
||||
*
|
||||
* schema definitions:
|
||||
* Each schema parameter entry consists of 2 chars,
|
||||
@ -802,6 +806,7 @@ typedef struct GdbCmdParseEntry {
|
||||
const char *cmd;
|
||||
bool cmd_startswith;
|
||||
const char *schema;
|
||||
bool allow_stop_reply;
|
||||
} GdbCmdParseEntry;
|
||||
|
||||
static inline int startswith(const char *string, const char *pattern)
|
||||
@ -835,6 +840,7 @@ static int process_string_cmd(void *user_ctx, const char *data,
|
||||
}
|
||||
}
|
||||
|
||||
gdbserver_state.allow_stop_reply = cmd->allow_stop_reply;
|
||||
cmd->handler(params, user_ctx);
|
||||
return 0;
|
||||
}
|
||||
@ -1283,11 +1289,14 @@ static void handle_v_attach(GArray *params, void *user_ctx)
|
||||
gdbserver_state.g_cpu = cpu;
|
||||
gdbserver_state.c_cpu = cpu;
|
||||
|
||||
g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
|
||||
gdb_append_thread_id(cpu, gdbserver_state.str_buf);
|
||||
g_string_append_c(gdbserver_state.str_buf, ';');
|
||||
if (gdbserver_state.allow_stop_reply) {
|
||||
g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
|
||||
gdb_append_thread_id(cpu, gdbserver_state.str_buf);
|
||||
g_string_append_c(gdbserver_state.str_buf, ';');
|
||||
gdbserver_state.allow_stop_reply = false;
|
||||
cleanup:
|
||||
gdb_put_strbuf();
|
||||
gdb_put_strbuf();
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_v_kill(GArray *params, void *user_ctx)
|
||||
@ -1310,12 +1319,14 @@ static const GdbCmdParseEntry gdb_v_commands_table[] = {
|
||||
.handler = handle_v_cont,
|
||||
.cmd = "Cont",
|
||||
.cmd_startswith = 1,
|
||||
.allow_stop_reply = true,
|
||||
.schema = "s0"
|
||||
},
|
||||
{
|
||||
.handler = handle_v_attach,
|
||||
.cmd = "Attach;",
|
||||
.cmd_startswith = 1,
|
||||
.allow_stop_reply = true,
|
||||
.schema = "l0"
|
||||
},
|
||||
{
|
||||
@ -1698,10 +1709,13 @@ static void handle_gen_set(GArray *params, void *user_ctx)
|
||||
|
||||
static void handle_target_halt(GArray *params, void *user_ctx)
|
||||
{
|
||||
g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
|
||||
gdb_append_thread_id(gdbserver_state.c_cpu, gdbserver_state.str_buf);
|
||||
g_string_append_c(gdbserver_state.str_buf, ';');
|
||||
gdb_put_strbuf();
|
||||
if (gdbserver_state.allow_stop_reply) {
|
||||
g_string_printf(gdbserver_state.str_buf, "T%02xthread:", GDB_SIGNAL_TRAP);
|
||||
gdb_append_thread_id(gdbserver_state.c_cpu, gdbserver_state.str_buf);
|
||||
g_string_append_c(gdbserver_state.str_buf, ';');
|
||||
gdb_put_strbuf();
|
||||
gdbserver_state.allow_stop_reply = false;
|
||||
}
|
||||
/*
|
||||
* Remove all the breakpoints when this query is issued,
|
||||
* because gdb is doing an initial connect and the state
|
||||
@ -1725,7 +1739,8 @@ static int gdb_handle_packet(const char *line_buf)
|
||||
static const GdbCmdParseEntry target_halted_cmd_desc = {
|
||||
.handler = handle_target_halt,
|
||||
.cmd = "?",
|
||||
.cmd_startswith = 1
|
||||
.cmd_startswith = 1,
|
||||
.allow_stop_reply = true,
|
||||
};
|
||||
cmd_parser = &target_halted_cmd_desc;
|
||||
}
|
||||
@ -1736,6 +1751,7 @@ static int gdb_handle_packet(const char *line_buf)
|
||||
.handler = handle_continue,
|
||||
.cmd = "c",
|
||||
.cmd_startswith = 1,
|
||||
.allow_stop_reply = true,
|
||||
.schema = "L0"
|
||||
};
|
||||
cmd_parser = &continue_cmd_desc;
|
||||
@ -1747,6 +1763,7 @@ static int gdb_handle_packet(const char *line_buf)
|
||||
.handler = handle_cont_with_sig,
|
||||
.cmd = "C",
|
||||
.cmd_startswith = 1,
|
||||
.allow_stop_reply = true,
|
||||
.schema = "l0"
|
||||
};
|
||||
cmd_parser = &cont_with_sig_cmd_desc;
|
||||
@ -1785,6 +1802,7 @@ static int gdb_handle_packet(const char *line_buf)
|
||||
.handler = handle_step,
|
||||
.cmd = "s",
|
||||
.cmd_startswith = 1,
|
||||
.allow_stop_reply = true,
|
||||
.schema = "L0"
|
||||
};
|
||||
cmd_parser = &step_cmd_desc;
|
||||
@ -1976,6 +1994,7 @@ void gdb_read_byte(uint8_t ch)
|
||||
{
|
||||
uint8_t reply;
|
||||
|
||||
gdbserver_state.allow_stop_reply = false;
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (gdbserver_state.last_packet->len) {
|
||||
/* Waiting for a response to the last packet. If we see the start
|
||||
|
@ -65,6 +65,11 @@ typedef struct GDBState {
|
||||
GByteArray *mem_buf;
|
||||
int sstep_flags;
|
||||
int supported_sstep_flags;
|
||||
/*
|
||||
* Whether we are allowed to send a stop reply packet at this moment.
|
||||
* Must be set off after sending the stop reply itself.
|
||||
*/
|
||||
bool allow_stop_reply;
|
||||
} GDBState;
|
||||
|
||||
/* lives in main gdbstub.c */
|
||||
|
@ -43,6 +43,7 @@ static void reset_gdbserver_state(void)
|
||||
g_free(gdbserver_state.processes);
|
||||
gdbserver_state.processes = NULL;
|
||||
gdbserver_state.process_num = 0;
|
||||
gdbserver_state.allow_stop_reply = false;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -139,6 +140,10 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gdbserver_state.allow_stop_reply) {
|
||||
return;
|
||||
}
|
||||
|
||||
gdb_append_thread_id(cpu, tid);
|
||||
|
||||
switch (state) {
|
||||
@ -205,6 +210,7 @@ static void gdb_vm_state_change(void *opaque, bool running, RunState state)
|
||||
|
||||
send_packet:
|
||||
gdb_put_packet(buf->str);
|
||||
gdbserver_state.allow_stop_reply = false;
|
||||
|
||||
/* disable single step if it was enabled */
|
||||
cpu_single_step(cpu, 0);
|
||||
@ -422,8 +428,11 @@ void gdb_exit(int code)
|
||||
|
||||
trace_gdbstub_op_exiting((uint8_t)code);
|
||||
|
||||
snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
|
||||
gdb_put_packet(buf);
|
||||
if (gdbserver_state.allow_stop_reply) {
|
||||
snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
|
||||
gdb_put_packet(buf);
|
||||
gdbserver_state.allow_stop_reply = false;
|
||||
}
|
||||
|
||||
qemu_chr_fe_deinit(&gdbserver_system_state.chr, true);
|
||||
}
|
||||
|
@ -108,8 +108,11 @@ void gdb_exit(int code)
|
||||
|
||||
trace_gdbstub_op_exiting((uint8_t)code);
|
||||
|
||||
snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
|
||||
gdb_put_packet(buf);
|
||||
if (gdbserver_state.allow_stop_reply) {
|
||||
snprintf(buf, sizeof(buf), "W%02x", (uint8_t)code);
|
||||
gdb_put_packet(buf);
|
||||
gdbserver_state.allow_stop_reply = false;
|
||||
}
|
||||
}
|
||||
|
||||
int gdb_handlesig(CPUState *cpu, int sig)
|
||||
@ -127,11 +130,14 @@ int gdb_handlesig(CPUState *cpu, int sig)
|
||||
|
||||
if (sig != 0) {
|
||||
gdb_set_stop_cpu(cpu);
|
||||
g_string_printf(gdbserver_state.str_buf,
|
||||
"T%02xthread:", gdb_target_signal_to_gdb(sig));
|
||||
gdb_append_thread_id(cpu, gdbserver_state.str_buf);
|
||||
g_string_append_c(gdbserver_state.str_buf, ';');
|
||||
gdb_put_strbuf();
|
||||
if (gdbserver_state.allow_stop_reply) {
|
||||
g_string_printf(gdbserver_state.str_buf,
|
||||
"T%02xthread:", gdb_target_signal_to_gdb(sig));
|
||||
gdb_append_thread_id(cpu, gdbserver_state.str_buf);
|
||||
g_string_append_c(gdbserver_state.str_buf, ';');
|
||||
gdb_put_strbuf();
|
||||
gdbserver_state.allow_stop_reply = false;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* gdb_put_packet() might have detected that the peer terminated the
|
||||
@ -174,12 +180,14 @@ void gdb_signalled(CPUArchState *env, int sig)
|
||||
{
|
||||
char buf[4];
|
||||
|
||||
if (!gdbserver_state.init || gdbserver_user_state.fd < 0) {
|
||||
if (!gdbserver_state.init || gdbserver_user_state.fd < 0 ||
|
||||
!gdbserver_state.allow_stop_reply) {
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "X%02x", gdb_target_signal_to_gdb(sig));
|
||||
gdb_put_packet(buf);
|
||||
gdbserver_state.allow_stop_reply = false;
|
||||
}
|
||||
|
||||
static void gdb_accept_init(int fd)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
@ -20,7 +20,10 @@
|
||||
|
||||
static inline const char *cpu_get_model(uint32_t eflags)
|
||||
{
|
||||
/* For now, treat anything newer than v5 as a v67 */
|
||||
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 */
|
||||
eflags == 0x05 || /* v55 */
|
||||
@ -30,11 +33,18 @@ static inline const char *cpu_get_model(uint32_t eflags)
|
||||
eflags == 0x65 || /* v65 */
|
||||
eflags == 0x66 || /* v66 */
|
||||
eflags == 0x67 || /* v67 */
|
||||
eflags == 0x8067 /* v67t */
|
||||
eflags == 0x8067 || /* v67t */
|
||||
eflags == 0x68 || /* v68 */
|
||||
eflags == 0x69 || /* v69 */
|
||||
eflags == 0x71 || /* v71 */
|
||||
eflags == 0x8071 || /* v71t */
|
||||
eflags == 0x73 /* v73 */
|
||||
) {
|
||||
return "v67";
|
||||
return "v73";
|
||||
}
|
||||
return "unknown";
|
||||
|
||||
err = snprintf(buf, sizeof(buf), "unknown (0x%x)", eflags);
|
||||
return err >= 0 && err < sizeof(buf) ? buf : "unknown";
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -2105,6 +2105,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())
|
||||
|
@ -4,10 +4,10 @@ is a wide vector coprocessor designed for high performance computer vision,
|
||||
image processing, machine learning, and other workloads.
|
||||
|
||||
The following versions of the Hexagon core are supported
|
||||
Scalar core: v67
|
||||
https://developer.qualcomm.com/downloads/qualcomm-hexagon-v67-programmer-s-reference-manual
|
||||
HVX extension: v66
|
||||
https://developer.qualcomm.com/downloads/qualcomm-hexagon-v66-hvx-programmer-s-reference-manual
|
||||
Scalar core: v73
|
||||
https://developer.qualcomm.com/downloads/qualcomm-hexagon-v73-programmers-reference-manual-rev-aa
|
||||
HVX extension: v73
|
||||
https://developer.qualcomm.com/downloads/qualcomm-hexagon-v73-hvx-programmers-reference-manual-rev-aa
|
||||
|
||||
We presented an overview of the project at the 2019 KVM Forum.
|
||||
https://kvmforum2019.sched.com/event/Tmwc/qemu-hexagon-automatic-translation-of-the-isa-manual-pseudcode-to-tiny-code-instructions-of-a-vliw-architecture-niccolo-izzo-revng-taylor-simpson-qualcomm-innovation-center
|
||||
@ -87,7 +87,7 @@ tcg_funcs_generated.c.inc
|
||||
TCGv RsV = hex_gpr[insn->regno[1]];
|
||||
TCGv RtV = hex_gpr[insn->regno[2]];
|
||||
gen_helper_A2_add(RdV, cpu_env, RsV, RtV);
|
||||
gen_log_reg_write(RdN, RdV);
|
||||
gen_log_reg_write(ctx, RdN, RdV);
|
||||
}
|
||||
|
||||
helper_funcs_generated.c.inc
|
||||
@ -186,7 +186,7 @@ We also generate an analyze_<tag> function for each instruction. Currently,
|
||||
these functions record the writes to registers by calling ctx_log_*. During
|
||||
gen_start_packet, we invoke the analyze_<tag> function for each instruction in
|
||||
the packet, and we mark the implicit writes. After the analysis is performed,
|
||||
we initialize hex_new_value for each of the predicated assignments.
|
||||
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
|
||||
@ -304,4 +304,4 @@ Here are some handy places to set breakpoints
|
||||
At the start of execution of a packet for a given PC
|
||||
br helper_debug_start_packet if env->gpr[41] == 0xdeadbeef
|
||||
At the end of execution of a packet for a given PC
|
||||
br helper_debug_commit_end if env->this_PC == 0xdeadbeef
|
||||
br helper_debug_commit_end if this_PC == 0xdeadbeef
|
||||
|
@ -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
|
||||
@ -224,6 +224,7 @@ void arch_fpop_start(CPUHexagonState *env)
|
||||
|
||||
void arch_fpop_end(CPUHexagonState *env)
|
||||
{
|
||||
const bool pkt_need_commit = true;
|
||||
int flags = get_float_exception_flags(&env->fp_status);
|
||||
if (flags != 0) {
|
||||
SOFTFLOAT_TEST_FLAG(float_flag_inexact, FPINPF, FPINPE);
|
||||
|
@ -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
|
||||
@ -52,6 +52,12 @@ DEF_ATTRIB(REGWRSIZE_4B, "Memory width is 4 bytes", "", "")
|
||||
DEF_ATTRIB(REGWRSIZE_8B, "Memory width is 8 bytes", "", "")
|
||||
DEF_ATTRIB(MEMLIKE, "Memory-like instruction", "", "")
|
||||
DEF_ATTRIB(MEMLIKE_PACKET_RULES, "follows Memory-like packet rules", "", "")
|
||||
DEF_ATTRIB(RELEASE, "Releases a lock", "", "")
|
||||
DEF_ATTRIB(ACQUIRE, "Acquires a lock", "", "")
|
||||
|
||||
DEF_ATTRIB(RLS_INNER, "Store release inner visibility", "", "")
|
||||
DEF_ATTRIB(RLS_ALL_THREAD, "Store release among all threads", "", "")
|
||||
DEF_ATTRIB(RLS_SAME_THREAD, "Store release with the same thread", "", "")
|
||||
|
||||
/* V6 Vector attributes */
|
||||
DEF_ATTRIB(CVI, "Executes on the HVX extension", "", "")
|
||||
@ -63,23 +69,27 @@ DEF_ATTRIB(CVI_VP_VS, "Double vector permute/shft insn executes on HVX", "", "")
|
||||
DEF_ATTRIB(CVI_VX, "Multiply instruction executes on HVX", "", "")
|
||||
DEF_ATTRIB(CVI_VX_DV, "Double vector multiply insn executes on HVX", "", "")
|
||||
DEF_ATTRIB(CVI_VS, "Shift instruction executes on HVX", "", "")
|
||||
DEF_ATTRIB(CVI_VS_3SRC, "This shift needs to borrow a source register", "", "")
|
||||
DEF_ATTRIB(CVI_VS_VX, "Permute/shift and multiply insn executes on HVX", "", "")
|
||||
DEF_ATTRIB(CVI_VA, "ALU instruction executes on HVX", "", "")
|
||||
DEF_ATTRIB(CVI_VA_DV, "Double vector alu instruction executes on HVX", "", "")
|
||||
DEF_ATTRIB(CVI_4SLOT, "Consumes all the vector execution resources", "", "")
|
||||
DEF_ATTRIB(CVI_TMP, "Transient Memory Load not written to register", "", "")
|
||||
DEF_ATTRIB(CVI_REMAP, "Register Renaming not written to register file", "", "")
|
||||
DEF_ATTRIB(CVI_GATHER, "CVI Gather operation", "", "")
|
||||
DEF_ATTRIB(CVI_SCATTER, "CVI Scatter operation", "", "")
|
||||
DEF_ATTRIB(CVI_SCATTER_RELEASE, "CVI Store Release for scatter", "", "")
|
||||
DEF_ATTRIB(CVI_TMP_DST, "CVI instruction that doesn't write a register", "", "")
|
||||
DEF_ATTRIB(CVI_SLOT23, "Can execute in slot 2 or slot 3 (HVX)", "", "")
|
||||
|
||||
DEF_ATTRIB(VTCM_ALLBANK_ACCESS, "Allocates in all VTCM schedulers.", "", "")
|
||||
|
||||
/* Change-of-flow attributes */
|
||||
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", "", "")
|
||||
@ -102,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 a predicate register", "", "")
|
||||
DEF_ATTRIB(COMMUTES, "The operation is communitive", "", "")
|
||||
@ -140,6 +154,8 @@ DEF_ATTRIB(L2FETCH, "Instruction is l2fetch type", "", "")
|
||||
DEF_ATTRIB(ICINVA, "icinva", "", "")
|
||||
DEF_ATTRIB(DCCLEANINVA, "dccleaninva", "", "")
|
||||
|
||||
DEF_ATTRIB(NO_INTRINSIC, "Don't generate an intrisic", "", "")
|
||||
|
||||
/* Documentation Notes */
|
||||
DEF_ATTRIB(NOTE_CONDITIONAL, "can be conditionally executed", "", "")
|
||||
DEF_ATTRIB(NOTE_NEWVAL_SLOT0, "New-value oprnd must execute on slot 0", "", "")
|
||||
@ -148,7 +164,11 @@ DEF_ATTRIB(NOTE_NOPACKET, "solo instruction", "", "")
|
||||
DEF_ATTRIB(NOTE_AXOK, "May only be grouped with ALU32 or non-FP XTYPE.", "", "")
|
||||
DEF_ATTRIB(NOTE_LATEPRED, "The predicate can not be used as a .new", "", "")
|
||||
DEF_ATTRIB(NOTE_NVSLOT0, "Can execute only in slot 0 (ST)", "", "")
|
||||
DEF_ATTRIB(NOTE_NOVP, "Cannot be paired with a HVX permute instruction", "", "")
|
||||
DEF_ATTRIB(NOTE_VA_UNARY, "Combined with HVX ALU op (must be unary)", "", "")
|
||||
|
||||
/* V6 MMVector Notes for Documentation */
|
||||
DEF_ATTRIB(NOTE_SHIFT_RESOURCE, "Uses the HVX shift resource.", "", "")
|
||||
/* Restrictions to make note of */
|
||||
DEF_ATTRIB(RESTRICT_NOSLOT1_STORE, "Packet must not have slot 1 store", "", "")
|
||||
DEF_ATTRIB(RESTRICT_LATEPRED, "Predicate can not be used as a .new.", "", "")
|
||||
|
@ -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
|
||||
@ -24,9 +24,32 @@
|
||||
#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_v67_cpu_init(Object *obj) { }
|
||||
static void hexagon_v68_cpu_init(Object *obj) { }
|
||||
static void hexagon_v69_cpu_init(Object *obj) { }
|
||||
static void hexagon_v71_cpu_init(Object *obj) { }
|
||||
static void hexagon_v73_cpu_init(Object *obj) { }
|
||||
|
||||
static void hexagon_cpu_list_entry(gpointer data, gpointer user_data)
|
||||
{
|
||||
ObjectClass *oc = data;
|
||||
char *name = g_strdup(object_class_get_name(oc));
|
||||
if (g_str_has_suffix(name, HEXAGON_CPU_TYPE_SUFFIX)) {
|
||||
name[strlen(name) - strlen(HEXAGON_CPU_TYPE_SUFFIX)] = '\0';
|
||||
}
|
||||
qemu_printf(" %s\n", name);
|
||||
g_free(name);
|
||||
}
|
||||
|
||||
void hexagon_cpu_list(void)
|
||||
{
|
||||
GSList *list;
|
||||
list = object_class_get_list_sorted(TYPE_HEXAGON_CPU, false);
|
||||
qemu_printf("Available CPUs:\n");
|
||||
g_slist_foreach(list, hexagon_cpu_list_entry, NULL);
|
||||
g_slist_free(list);
|
||||
}
|
||||
|
||||
static ObjectClass *hexagon_cpu_class_by_name(const char *cpu_model)
|
||||
@ -52,6 +75,8 @@ static Property hexagon_lldb_compat_property =
|
||||
static Property hexagon_lldb_stack_adjust_property =
|
||||
DEFINE_PROP_UNSIGNED("lldb-stack-adjust", HexagonCPU, lldb_stack_adjust,
|
||||
0, qdev_prop_uint32, target_ulong);
|
||||
static Property hexagon_short_circuit_property =
|
||||
DEFINE_PROP_BOOL("short-circuit", HexagonCPU, short_circuit, true);
|
||||
|
||||
const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS] = {
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
@ -315,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);
|
||||
|
||||
@ -328,6 +358,7 @@ static void hexagon_cpu_init(Object *obj)
|
||||
cpu_set_cpustate_pointers(cpu);
|
||||
qdev_property_add_static(DEVICE(obj), &hexagon_lldb_compat_property);
|
||||
qdev_property_add_static(DEVICE(obj), &hexagon_lldb_stack_adjust_property);
|
||||
qdev_property_add_static(DEVICE(obj), &hexagon_short_circuit_property);
|
||||
}
|
||||
|
||||
#include "hw/core/tcg-cpu-ops.h"
|
||||
@ -358,8 +389,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 = &hexagon_tcg_ops;
|
||||
}
|
||||
@ -382,6 +414,10 @@ static const TypeInfo hexagon_cpu_type_infos[] = {
|
||||
.class_init = hexagon_cpu_class_init,
|
||||
},
|
||||
DEFINE_CPU(TYPE_HEXAGON_CPU_V67, hexagon_v67_cpu_init),
|
||||
DEFINE_CPU(TYPE_HEXAGON_CPU_V68, hexagon_v68_cpu_init),
|
||||
DEFINE_CPU(TYPE_HEXAGON_CPU_V69, hexagon_v69_cpu_init),
|
||||
DEFINE_CPU(TYPE_HEXAGON_CPU_V71, hexagon_v71_cpu_init),
|
||||
DEFINE_CPU(TYPE_HEXAGON_CPU_V73, hexagon_v73_cpu_init),
|
||||
};
|
||||
|
||||
DEFINE_TYPES(hexagon_cpu_type_infos)
|
||||
|
@ -43,6 +43,13 @@
|
||||
#define CPU_RESOLVING_TYPE TYPE_HEXAGON_CPU
|
||||
|
||||
#define TYPE_HEXAGON_CPU_V67 HEXAGON_CPU_TYPE_NAME("v67")
|
||||
#define TYPE_HEXAGON_CPU_V68 HEXAGON_CPU_TYPE_NAME("v68")
|
||||
#define TYPE_HEXAGON_CPU_V69 HEXAGON_CPU_TYPE_NAME("v69")
|
||||
#define TYPE_HEXAGON_CPU_V71 HEXAGON_CPU_TYPE_NAME("v71")
|
||||
#define TYPE_HEXAGON_CPU_V73 HEXAGON_CPU_TYPE_NAME("v73")
|
||||
|
||||
void hexagon_cpu_list(void);
|
||||
#define cpu_list hexagon_cpu_list
|
||||
|
||||
#define MMU_USER_IDX 0
|
||||
|
||||
@ -78,28 +85,21 @@ typedef struct {
|
||||
typedef struct CPUArchState {
|
||||
target_ulong gpr[TOTAL_PER_THREAD_REGS];
|
||||
target_ulong pred[NUM_PREGS];
|
||||
target_ulong branch_taken;
|
||||
|
||||
/* For comparing with LLDB on target - see adjust_stack_ptrs function */
|
||||
target_ulong last_pc_dumped;
|
||||
target_ulong stack_start;
|
||||
|
||||
uint8_t slot_cancelled;
|
||||
target_ulong new_value[TOTAL_PER_THREAD_REGS];
|
||||
target_ulong new_value_usr;
|
||||
|
||||
/*
|
||||
* Only used when HEX_DEBUG is on, but unconditionally included
|
||||
* to reduce recompile time when turning HEX_DEBUG on/off.
|
||||
*/
|
||||
target_ulong this_PC;
|
||||
target_ulong reg_written[TOTAL_PER_THREAD_REGS];
|
||||
|
||||
target_ulong new_pred_value[NUM_PREGS];
|
||||
target_ulong pred_written;
|
||||
|
||||
MemLog mem_log_stores[STORES_MAX];
|
||||
target_ulong pkt_has_store_s1;
|
||||
target_ulong dczero_addr;
|
||||
|
||||
float_status fp_status;
|
||||
|
||||
@ -146,6 +146,7 @@ struct ArchCPU {
|
||||
|
||||
bool lldb_compat;
|
||||
target_ulong lldb_stack_adjust;
|
||||
bool short_circuit;
|
||||
};
|
||||
|
||||
#include "cpu_bits.h"
|
||||
|
@ -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
|
||||
@ -797,7 +797,26 @@ static bool decode_parsebits_is_loopend(uint32_t encoding32)
|
||||
return bits == 0x2;
|
||||
}
|
||||
|
||||
static void
|
||||
static bool has_valid_slot_assignment(Packet *pkt)
|
||||
{
|
||||
int used_slots = 0;
|
||||
for (int i = 0; i < pkt->num_insns; i++) {
|
||||
int slot_mask;
|
||||
Insn *insn = &pkt->insn[i];
|
||||
if (decode_opcode_ends_loop(insn->opcode)) {
|
||||
/* We overload slot 0 for endloop. */
|
||||
continue;
|
||||
}
|
||||
slot_mask = 1 << insn->slot;
|
||||
if (used_slots & slot_mask) {
|
||||
return false;
|
||||
}
|
||||
used_slots |= slot_mask;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
decode_set_slot_number(Packet *pkt)
|
||||
{
|
||||
int slot;
|
||||
@ -886,6 +905,8 @@ decode_set_slot_number(Packet *pkt)
|
||||
/* Then push it to slot0 */
|
||||
pkt->insn[slot1_iidx].slot = 0;
|
||||
}
|
||||
|
||||
return has_valid_slot_assignment(pkt);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -961,8 +982,11 @@ int decode_packet(int max_words, const uint32_t *words, Packet *pkt,
|
||||
decode_apply_extenders(pkt);
|
||||
if (!disas_only) {
|
||||
decode_remove_extenders(pkt);
|
||||
if (!decode_set_slot_number(pkt)) {
|
||||
/* Invalid packet */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
decode_set_slot_number(pkt);
|
||||
decode_fill_newvalue_regno(pkt);
|
||||
|
||||
if (pkt->pkt_has_hvx) {
|
||||
|
@ -25,6 +25,14 @@ int hexagon_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
|
||||
HexagonCPU *cpu = HEXAGON_CPU(cs);
|
||||
CPUHexagonState *env = &cpu->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 = &cpu->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);
|
||||
@ -44,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();
|
||||
}
|
||||
|
@ -35,47 +35,55 @@ def analyze_opn_old(f, tag, regtype, regid, regno):
|
||||
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" 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" 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:
|
||||
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")
|
||||
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:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
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" 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" 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:
|
||||
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" 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):
|
||||
@ -88,22 +96,25 @@ def analyze_opn_old(f, tag, regtype, regid, regno):
|
||||
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" 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")
|
||||
f.write(f" const int {regN} = insn->regno[{regno}];\n")
|
||||
f.write(f" ctx_log_vreg_read(ctx, {regN});\n")
|
||||
elif regid in {"d", "x", "y"}:
|
||||
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")
|
||||
f.write(f" ctx_log_qreg_write(ctx, {regN});\n")
|
||||
elif regid in {"s", "t", "u", "v"}:
|
||||
f.write(f"// const int {regN} = insn->regno[{regno}];\n")
|
||||
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")
|
||||
@ -114,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")
|
||||
@ -125,30 +136,33 @@ 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)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
|
||||
|
||||
def analyze_opn_new(f, tag, regtype, regid, regno):
|
||||
regN = f"{regtype}{regid}N"
|
||||
if regtype == "N":
|
||||
if regid in {"s", "t"}:
|
||||
f.write(f"// const int {regN} = insn->regno[{regno}];\n")
|
||||
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 == "P":
|
||||
if regid in {"t", "u", "v"}:
|
||||
f.write(f"// const int {regN} = insn->regno[{regno}];\n")
|
||||
f.write(f" const int {regN} = insn->regno[{regno}];\n")
|
||||
f.write(f" ctx_log_pred_read(ctx, {regN});\n")
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "O":
|
||||
if regid == "s":
|
||||
f.write(f"// const int {regN} = insn->regno[{regno}];\n")
|
||||
f.write(f" const int {regN} = insn->regno[{regno}];\n")
|
||||
f.write(f" ctx_log_vreg_read(ctx, {regN});\n")
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
|
||||
|
||||
def analyze_opn(f, tag, regtype, regid, toss, numregs, i):
|
||||
@ -160,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:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
|
||||
##
|
||||
@ -174,8 +188,10 @@ def analyze_opn(f, tag, regtype, regid, toss, numregs, i):
|
||||
## Insn *insn G_GNUC_UNUSED = ctx->insn;
|
||||
## const int RdN = insn->regno[0];
|
||||
## ctx_log_reg_write(ctx, RdN, false);
|
||||
## // const int RsN = insn->regno[1];
|
||||
## // const int RtN = insn->regno[2];
|
||||
## const int RsN = insn->regno[1];
|
||||
## ctx_log_reg_read(ctx, RsN);
|
||||
## const int RtN = insn->regno[2];
|
||||
## ctx_log_reg_read(ctx, RtN);
|
||||
## }
|
||||
##
|
||||
def gen_analyze_func(f, tag, regs, imms):
|
||||
@ -193,8 +209,11 @@ def gen_analyze_func(f, tag, regs, imms):
|
||||
has_generated_helper = not hex_common.skip_qemu_helper(
|
||||
tag
|
||||
) and not hex_common.is_idef_parser_enabled(tag)
|
||||
if has_generated_helper and "A_SCALAR_LOAD" in hex_common.attribdict[tag]:
|
||||
f.write(" ctx->need_pkt_has_store_s1 = true;\n")
|
||||
|
||||
## Mark HVX instructions with generated helpers
|
||||
if (has_generated_helper and
|
||||
"A_CVI" in hex_common.attribdict[tag]):
|
||||
f.write(" ctx->has_hvx_helper = true;\n")
|
||||
|
||||
f.write("}\n\n")
|
||||
|
||||
|
@ -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:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
|
||||
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:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
|
||||
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:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
|
||||
##
|
||||
@ -239,7 +239,7 @@ def gen_helper_function(f, tag, tagregs, tagimms):
|
||||
else:
|
||||
gen_helper_return_type(f, regtype, regid, i)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
i += 1
|
||||
|
||||
if numscalarresults == 0:
|
||||
@ -262,7 +262,7 @@ def gen_helper_function(f, tag, tagregs, tagimms):
|
||||
# This is the return value of the function
|
||||
continue
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
i += 1
|
||||
|
||||
## For conditional instructions, we pass in the destination register
|
||||
@ -287,6 +287,8 @@ def gen_helper_function(f, tag, tagregs, tagimms):
|
||||
|
||||
if hex_common.need_pkt_has_multi_cof(tag):
|
||||
f.write(", uint32_t pkt_has_multi_cof")
|
||||
if (hex_common.need_pkt_need_commit(tag)):
|
||||
f.write(", uint32_t pkt_need_commit")
|
||||
|
||||
if hex_common.need_PC(tag):
|
||||
if i > 0:
|
||||
@ -301,7 +303,7 @@ def gen_helper_function(f, tag, tagregs, tagimms):
|
||||
if hex_common.need_slot(tag):
|
||||
if i > 0:
|
||||
f.write(", ")
|
||||
f.write("uint32_t slot")
|
||||
f.write("uint32_t slotval")
|
||||
i += 1
|
||||
if hex_common.need_part1(tag):
|
||||
if i > 0:
|
||||
@ -327,7 +329,12 @@ def gen_helper_function(f, tag, tagregs, tagimms):
|
||||
if hex_common.is_hvx_reg(regtype):
|
||||
gen_helper_src_var_ext(f, regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
if hex_common.need_slot(tag):
|
||||
if "A_LOAD" in hex_common.attribdict[tag]:
|
||||
f.write(" bool pkt_has_store_s1 = slotval & 0x1;\n")
|
||||
f.write(" uint32_t slot = slotval >> 1;\n")
|
||||
|
||||
if "A_FPOP" in hex_common.attribdict[tag]:
|
||||
f.write(" arch_fpop_start(env);\n")
|
||||
|
@ -52,7 +52,7 @@ def gen_def_helper_opn(f, tag, regtype, regid, toss, numregs, i):
|
||||
elif hex_common.is_single(regid):
|
||||
f.write(f", {def_helper_types[regtype]}")
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
|
||||
##
|
||||
@ -86,6 +86,8 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
|
||||
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):
|
||||
@ -103,6 +105,8 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
|
||||
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):
|
||||
@ -156,10 +160,12 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
|
||||
for immlett, bits, immshift in imms:
|
||||
f.write(", s32")
|
||||
|
||||
## Add the arguments for the instruction pkt_has_multi_cof, slot and
|
||||
## part1 (if needed)
|
||||
## Add the arguments for the instruction pkt_has_multi_cof,
|
||||
## pkt_needs_commit, PC, next_PC, slot, and part1 (if needed)
|
||||
if hex_common.need_pkt_has_multi_cof(tag):
|
||||
f.write(", i32")
|
||||
if hex_common.need_pkt_need_commit(tag):
|
||||
f.write(', i32')
|
||||
if hex_common.need_PC(tag):
|
||||
f.write(", i32")
|
||||
if hex_common.helper_needs_next_PC(tag):
|
||||
|
@ -103,12 +103,29 @@ def main():
|
||||
continue
|
||||
if tag.startswith("V6_"):
|
||||
continue
|
||||
if tag.startswith("F"):
|
||||
if ( tag.startswith("F") and
|
||||
tag not in {
|
||||
"F2_sfimm_p",
|
||||
"F2_sfimm_n",
|
||||
"F2_dfimm_p",
|
||||
"F2_dfimm_n",
|
||||
"F2_dfmpyll",
|
||||
"F2_dfmpylh"
|
||||
}):
|
||||
continue
|
||||
if tag.endswith("_locked"):
|
||||
continue
|
||||
if "A_COF" in hex_common.attribdict[tag]:
|
||||
continue
|
||||
if ( tag.startswith('R6_release_') ):
|
||||
continue
|
||||
## Skip instructions that are incompatible with short-circuit
|
||||
## packet register writes
|
||||
if ( tag == 'S2_insert' or
|
||||
tag == 'S2_insert_rp' or
|
||||
tag == 'S2_asr_r_svw_trun' or
|
||||
tag == 'A2_swiz' ):
|
||||
continue
|
||||
|
||||
regs = tagregs[tag]
|
||||
imms = tagimms[tag]
|
||||
@ -130,7 +147,7 @@ def main():
|
||||
elif is_single_new:
|
||||
arguments.append(f"{prefix}{regtype}{regid}N")
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
for immlett, bits, immshift in imms:
|
||||
arguments.append(hex_common.imm_name(immlett))
|
||||
|
@ -500,6 +500,38 @@
|
||||
#define fGEN_TCG_Y2_icinva(SHORTCODE) \
|
||||
do { RsV = RsV; } while (0)
|
||||
|
||||
/*
|
||||
* allocframe(#uiV)
|
||||
* RxV == r29
|
||||
*/
|
||||
#define fGEN_TCG_S2_allocframe(SHORTCODE) \
|
||||
gen_allocframe(ctx, RxV, uiV)
|
||||
|
||||
/* sub-instruction version (no RxV, so handle it manually) */
|
||||
#define fGEN_TCG_SS2_allocframe(SHORTCODE) \
|
||||
do { \
|
||||
TCGv r29 = tcg_temp_new(); \
|
||||
tcg_gen_mov_tl(r29, hex_gpr[HEX_REG_SP]); \
|
||||
gen_allocframe(ctx, r29, uiV); \
|
||||
gen_log_reg_write(ctx, HEX_REG_SP, r29); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Rdd32 = deallocframe(Rs32):raw
|
||||
* RddV == r31:30
|
||||
* RsV == r30
|
||||
*/
|
||||
#define fGEN_TCG_L2_deallocframe(SHORTCODE) \
|
||||
gen_deallocframe(ctx, RddV, RsV)
|
||||
|
||||
/* sub-instruction version (no RddV/RsV, so handle it manually) */
|
||||
#define fGEN_TCG_SL2_deallocframe(SHORTCODE) \
|
||||
do { \
|
||||
TCGv_i64 r31_30 = tcg_temp_new_i64(); \
|
||||
gen_deallocframe(ctx, r31_30, hex_gpr[HEX_REG_FP]); \
|
||||
gen_log_reg_write_pair(ctx, HEX_REG_FP, r31_30); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* dealloc_return
|
||||
* Assembler mapped to
|
||||
@ -515,7 +547,7 @@
|
||||
do { \
|
||||
TCGv_i64 RddV = get_result_gpr_pair(ctx, HEX_REG_FP); \
|
||||
gen_return(ctx, RddV, hex_gpr[HEX_REG_FP]); \
|
||||
gen_log_reg_write_pair(HEX_REG_FP, RddV); \
|
||||
gen_log_reg_write_pair(ctx, HEX_REG_FP, RddV); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
@ -549,9 +581,9 @@
|
||||
#define fGEN_TCG_SL2_return_f(SHORTCODE) \
|
||||
gen_cond_return_subinsn(ctx, TCG_COND_NE, hex_pred[0])
|
||||
#define fGEN_TCG_SL2_return_tnew(SHORTCODE) \
|
||||
gen_cond_return_subinsn(ctx, TCG_COND_EQ, hex_new_pred_value[0])
|
||||
gen_cond_return_subinsn(ctx, TCG_COND_EQ, ctx->new_pred_value[0])
|
||||
#define fGEN_TCG_SL2_return_fnew(SHORTCODE) \
|
||||
gen_cond_return_subinsn(ctx, TCG_COND_NE, hex_new_pred_value[0])
|
||||
gen_cond_return_subinsn(ctx, TCG_COND_NE, ctx->new_pred_value[0])
|
||||
|
||||
/*
|
||||
* Mathematical operations with more than one definition require
|
||||
@ -560,7 +592,16 @@
|
||||
#define fGEN_TCG_A5_ACS(SHORTCODE) \
|
||||
do { \
|
||||
gen_helper_vacsh_pred(PeV, cpu_env, RxxV, RssV, RttV); \
|
||||
gen_helper_vacsh_val(RxxV, cpu_env, RxxV, RssV, RttV); \
|
||||
gen_helper_vacsh_val(RxxV, cpu_env, RxxV, RssV, RttV, \
|
||||
tcg_constant_tl(ctx->need_commit)); \
|
||||
} while (0)
|
||||
|
||||
#define fGEN_TCG_S2_cabacdecbin(SHORTCODE) \
|
||||
do { \
|
||||
TCGv p0 = tcg_temp_new(); \
|
||||
gen_helper_cabacdecbin_pred(p0, RssV, RttV); \
|
||||
gen_helper_cabacdecbin_val(RddV, RssV, RttV); \
|
||||
gen_log_pred_write(ctx, 0, p0); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
@ -653,6 +694,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)
|
||||
@ -663,6 +706,27 @@
|
||||
#define fGEN_TCG_J2_callrf(SHORTCODE) \
|
||||
gen_cond_callr(ctx, TCG_COND_NE, PuV, RsV)
|
||||
|
||||
#define fGEN_TCG_J2_loop0r(SHORTCODE) \
|
||||
gen_loop0r(ctx, RsV, riV)
|
||||
#define fGEN_TCG_J2_loop1r(SHORTCODE) \
|
||||
gen_loop1r(ctx, RsV, riV)
|
||||
#define fGEN_TCG_J2_loop0i(SHORTCODE) \
|
||||
gen_loop0i(ctx, UiV, riV)
|
||||
#define fGEN_TCG_J2_loop1i(SHORTCODE) \
|
||||
gen_loop1i(ctx, UiV, riV)
|
||||
#define fGEN_TCG_J2_ploop1sr(SHORTCODE) \
|
||||
gen_ploopNsr(ctx, 1, RsV, riV)
|
||||
#define fGEN_TCG_J2_ploop1si(SHORTCODE) \
|
||||
gen_ploopNsi(ctx, 1, UiV, riV)
|
||||
#define fGEN_TCG_J2_ploop2sr(SHORTCODE) \
|
||||
gen_ploopNsr(ctx, 2, RsV, riV)
|
||||
#define fGEN_TCG_J2_ploop2si(SHORTCODE) \
|
||||
gen_ploopNsi(ctx, 2, UiV, riV)
|
||||
#define fGEN_TCG_J2_ploop3sr(SHORTCODE) \
|
||||
gen_ploopNsr(ctx, 3, RsV, riV)
|
||||
#define fGEN_TCG_J2_ploop3si(SHORTCODE) \
|
||||
gen_ploopNsi(ctx, 3, UiV, riV)
|
||||
|
||||
#define fGEN_TCG_J2_endloop0(SHORTCODE) \
|
||||
gen_endloop0(ctx)
|
||||
#define fGEN_TCG_J2_endloop1(SHORTCODE) \
|
||||
@ -847,10 +911,20 @@
|
||||
#define fGEN_TCG_J4_tstbit0_fp1_jump_t(SHORTCODE) \
|
||||
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_NE, riV)
|
||||
|
||||
/* p0 = cmp.eq(r0, #7) */
|
||||
#define fGEN_TCG_SA1_cmpeqi(SHORTCODE) \
|
||||
do { \
|
||||
TCGv p0 = tcg_temp_new(); \
|
||||
gen_comparei(TCG_COND_EQ, p0, RsV, uiV); \
|
||||
gen_log_pred_write(ctx, 0, p0); \
|
||||
} while (0)
|
||||
|
||||
#define fGEN_TCG_J2_jump(SHORTCODE) \
|
||||
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); \
|
||||
@ -1044,6 +1118,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, \
|
||||
ctx->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, \
|
||||
ctx->new_pred_value[0], tcg_constant_tl(0), \
|
||||
RdV, tcg_constant_tl(0)); \
|
||||
} while (0)
|
||||
|
||||
#define fGEN_TCG_J2_pause(SHORTCODE) \
|
||||
do { \
|
||||
uiV = uiV; \
|
||||
@ -1067,9 +1157,9 @@
|
||||
gen_cond_jumpr31(ctx, TCG_COND_NE, hex_pred[0])
|
||||
|
||||
#define fGEN_TCG_SL2_jumpr31_tnew(SHORTCODE) \
|
||||
gen_cond_jumpr31(ctx, TCG_COND_EQ, hex_new_pred_value[0])
|
||||
gen_cond_jumpr31(ctx, TCG_COND_EQ, ctx->new_pred_value[0])
|
||||
#define fGEN_TCG_SL2_jumpr31_fnew(SHORTCODE) \
|
||||
gen_cond_jumpr31(ctx, TCG_COND_NE, hex_new_pred_value[0])
|
||||
gen_cond_jumpr31(ctx, TCG_COND_NE, ctx->new_pred_value[0])
|
||||
|
||||
/* Count trailing zeros/ones */
|
||||
#define fGEN_TCG_S2_ct0(SHORTCODE) \
|
||||
@ -1095,6 +1185,24 @@
|
||||
tcg_gen_extrl_i64_i32(RdV, tmp); \
|
||||
} while (0)
|
||||
|
||||
#define fGEN_TCG_S2_insert(SHORTCODE) \
|
||||
do { \
|
||||
int width = uiV; \
|
||||
int offset = UiV; \
|
||||
if (width != 0) { \
|
||||
if (offset + width > 32) { \
|
||||
width = 32 - offset; \
|
||||
} \
|
||||
tcg_gen_deposit_tl(RxV, RxV, RsV, offset, width); \
|
||||
} \
|
||||
} while (0)
|
||||
#define fGEN_TCG_S2_insert_rp(SHORTCODE) \
|
||||
gen_insert_rp(ctx, RxV, RsV, RttV)
|
||||
#define fGEN_TCG_S2_asr_r_svw_trun(SHORTCODE) \
|
||||
gen_asr_r_svw_trun(ctx, RdV, RssV, RtV)
|
||||
#define fGEN_TCG_A2_swiz(SHORTCODE) \
|
||||
tcg_gen_bswap_tl(RdV, RsV)
|
||||
|
||||
/* Floating point */
|
||||
#define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
|
||||
gen_helper_conv_sf2df(RddV, cpu_env, RsV)
|
||||
@ -1236,6 +1344,24 @@
|
||||
uiV = uiV; \
|
||||
} while (0)
|
||||
|
||||
#define fGEN_TCG_L2_loadw_aq(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_L4_loadd_aq(SHORTCODE) SHORTCODE
|
||||
|
||||
/* Nothing to do for these in qemu, need to suppress compiler warnings */
|
||||
#define fGEN_TCG_R6_release_at_vi(SHORTCODE) \
|
||||
do { \
|
||||
RsV = RsV; \
|
||||
} while (0)
|
||||
#define fGEN_TCG_R6_release_st_vi(SHORTCODE) \
|
||||
do { \
|
||||
RsV = RsV; \
|
||||
} while (0)
|
||||
|
||||
#define fGEN_TCG_S2_storew_rl_at_vi(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_S4_stored_rl_at_vi(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_S2_storew_rl_st_vi(SHORTCODE) SHORTCODE
|
||||
#define fGEN_TCG_S4_stored_rl_st_vi(SHORTCODE) SHORTCODE
|
||||
|
||||
#define fGEN_TCG_J2_trap0(SHORTCODE) \
|
||||
do { \
|
||||
uiV = uiV; \
|
||||
|
@ -37,7 +37,7 @@ def genptr_decl_pair_writable(f, tag, regtype, regid, regno):
|
||||
elif regtype == "C":
|
||||
f.write(f" const int {regN} = insn->regno[{regno}] + HEX_REG_SA0;\n")
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
f.write(f" TCGv_i64 {regtype}{regid}V = " f"get_result_gpr_pair(ctx, {regN});\n")
|
||||
|
||||
|
||||
@ -53,7 +53,7 @@ def genptr_decl_writable(f, tag, regtype, regid, regno):
|
||||
f.write(f" const int {regN} = insn->regno[{regno}];\n")
|
||||
f.write(f" TCGv {regtype}{regid}V = tcg_temp_new();\n")
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
|
||||
|
||||
def genptr_decl(f, tag, regtype, regid, regno):
|
||||
@ -71,7 +71,7 @@ def genptr_decl(f, tag, regtype, regid, regno):
|
||||
elif regid in {"d", "e", "x", "y"}:
|
||||
genptr_decl_writable(f, tag, regtype, regid, regno)
|
||||
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(
|
||||
@ -80,7 +80,7 @@ def genptr_decl(f, tag, regtype, regid, regno):
|
||||
elif regid in {"d", "e", "x"}:
|
||||
genptr_decl_writable(f, tag, regtype, regid, regno)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
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")
|
||||
@ -96,7 +96,7 @@ def genptr_decl(f, tag, regtype, regid, regno):
|
||||
elif regid == "d":
|
||||
genptr_decl_writable(f, tag, regtype, regid, regno)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
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")
|
||||
@ -105,7 +105,7 @@ def genptr_decl(f, tag, regtype, regid, regno):
|
||||
"HEX_REG_M0];\n"
|
||||
)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "V":
|
||||
if regid in {"dd"}:
|
||||
f.write(f" const int {regtype}{regid}N = " f"insn->regno[{regno}];\n")
|
||||
@ -159,7 +159,7 @@ def genptr_decl(f, tag, regtype, regid, regno):
|
||||
f"{regtype}{regid}V_off);\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 {regtype}{regid}N = " f"insn->regno[{regno}];\n")
|
||||
@ -180,9 +180,9 @@ def genptr_decl(f, tag, regtype, regid, regno):
|
||||
if not hex_common.skip_qemu_helper(tag):
|
||||
f.write(f" TCGv_ptr {regtype}{regid}V = " "tcg_temp_new_ptr();\n")
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
|
||||
|
||||
def genptr_decl_new(f, tag, regtype, regid, regno):
|
||||
@ -190,18 +190,18 @@ def genptr_decl_new(f, tag, regtype, regid, regno):
|
||||
if regid in {"s", "t"}:
|
||||
f.write(
|
||||
f" TCGv {regtype}{regid}N = "
|
||||
f"hex_new_value[insn->regno[{regno}]];\n"
|
||||
f"get_result_gpr(ctx, insn->regno[{regno}]);\n"
|
||||
)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "P":
|
||||
if regid in {"t", "u", "v"}:
|
||||
f.write(
|
||||
f" TCGv {regtype}{regid}N = "
|
||||
f"hex_new_pred_value[insn->regno[{regno}]];\n"
|
||||
f"ctx->new_pred_value[insn->regno[{regno}]];\n"
|
||||
)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "O":
|
||||
if regid == "s":
|
||||
f.write(
|
||||
@ -218,9 +218,9 @@ def genptr_decl_new(f, tag, regtype, regid, regno):
|
||||
f"tcg_constant_tl({regtype}{regid}N_num);\n"
|
||||
)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
|
||||
|
||||
def genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i):
|
||||
@ -232,9 +232,9 @@ def genptr_decl_opn(f, tag, regtype, regid, toss, numregs, i):
|
||||
elif hex_common.is_new_val(regtype, regid, tag):
|
||||
genptr_decl_new(f, tag, regtype, regid, i)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
|
||||
def genptr_decl_imm(f, immlett):
|
||||
@ -266,7 +266,7 @@ def genptr_src_read(f, tag, regtype, regid):
|
||||
f"hex_gpr[{regtype}{regid}N]);\n"
|
||||
)
|
||||
elif regid not in {"s", "t", "u", "v"}:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "P":
|
||||
if regid == "x":
|
||||
f.write(
|
||||
@ -274,7 +274,7 @@ def genptr_src_read(f, tag, regtype, regid):
|
||||
f"hex_pred[{regtype}{regid}N]);\n"
|
||||
)
|
||||
elif regid not in {"s", "t", "u", "v"}:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "C":
|
||||
if regid == "ss":
|
||||
f.write(
|
||||
@ -287,10 +287,10 @@ def genptr_src_read(f, tag, regtype, regid):
|
||||
f"{regtype}{regid}V);\n"
|
||||
)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "M":
|
||||
if regid != "u":
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "V":
|
||||
if regid in {"uu", "vv", "xx"}:
|
||||
f.write(f" tcg_gen_gvec_mov(MO_64, {regtype}{regid}V_off,\n")
|
||||
@ -311,7 +311,7 @@ def genptr_src_read(f, tag, regtype, regid):
|
||||
f.write(f" vreg_src_off(ctx, {regtype}{regid}N),\n")
|
||||
f.write(" sizeof(MMVector), sizeof(MMVector));\n")
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "Q":
|
||||
if regid in {"s", "t", "u", "v"}:
|
||||
if not hex_common.skip_qemu_helper(tag):
|
||||
@ -326,23 +326,23 @@ def genptr_src_read(f, tag, regtype, regid):
|
||||
)
|
||||
f.write(" sizeof(MMQReg), sizeof(MMQReg));\n")
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
|
||||
|
||||
def genptr_src_read_new(f, regtype, regid):
|
||||
if regtype == "N":
|
||||
if regid not in {"s", "t"}:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "P":
|
||||
if regid not in {"t", "u", "v"}:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "O":
|
||||
if regid != "s":
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
|
||||
|
||||
def genptr_src_read_opn(f, regtype, regid, tag):
|
||||
@ -354,9 +354,9 @@ def genptr_src_read_opn(f, regtype, regid, tag):
|
||||
elif hex_common.is_new_val(regtype, regid, tag):
|
||||
genptr_src_read_new(f, regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
|
||||
def gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i):
|
||||
@ -370,9 +370,9 @@ def gen_helper_call_opn(f, tag, regtype, regid, toss, numregs, i):
|
||||
elif hex_common.is_new_val(regtype, regid, tag):
|
||||
f.write(f"{regtype}{regid}N")
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
|
||||
def gen_helper_decl_imm(f, immlett):
|
||||
@ -387,7 +387,8 @@ def gen_helper_call_imm(f, immlett):
|
||||
|
||||
|
||||
def genptr_dst_write_pair(f, tag, regtype, regid):
|
||||
f.write(f" gen_log_reg_write_pair({regtype}{regid}N, " f"{regtype}{regid}V);\n")
|
||||
f.write(f" gen_log_reg_write_pair(ctx, {regtype}{regid}N, "
|
||||
f"{regtype}{regid}V);\n")
|
||||
|
||||
|
||||
def genptr_dst_write(f, tag, regtype, regid):
|
||||
@ -396,10 +397,11 @@ def genptr_dst_write(f, tag, regtype, regid):
|
||||
genptr_dst_write_pair(f, tag, regtype, regid)
|
||||
elif regid in {"d", "e", "x", "y"}:
|
||||
f.write(
|
||||
f" gen_log_reg_write({regtype}{regid}N, " f"{regtype}{regid}V);\n"
|
||||
f" gen_log_reg_write(ctx, {regtype}{regid}N, "
|
||||
f"{regtype}{regid}V);\n"
|
||||
)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "P":
|
||||
if regid in {"d", "e", "x"}:
|
||||
f.write(
|
||||
@ -407,7 +409,7 @@ def genptr_dst_write(f, tag, regtype, regid):
|
||||
f"{regtype}{regid}V);\n"
|
||||
)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "C":
|
||||
if regid == "dd":
|
||||
f.write(
|
||||
@ -420,9 +422,9 @@ def genptr_dst_write(f, tag, regtype, regid):
|
||||
f"{regtype}{regid}V);\n"
|
||||
)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
|
||||
|
||||
def genptr_dst_write_ext(f, tag, regtype, regid, newv="EXT_DFL"):
|
||||
@ -438,12 +440,12 @@ def genptr_dst_write_ext(f, tag, regtype, regid, newv="EXT_DFL"):
|
||||
f"{regtype}{regid}N, {newv});\n"
|
||||
)
|
||||
elif regid not in {"dd", "d", "x"}:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
elif regtype == "Q":
|
||||
if regid not in {"d", "e", "x"}:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid)
|
||||
hex_common.bad_register(regtype, regid)
|
||||
|
||||
|
||||
def genptr_dst_write_opn(f, regtype, regid, tag):
|
||||
@ -466,7 +468,7 @@ def genptr_dst_write_opn(f, regtype, regid, tag):
|
||||
else:
|
||||
genptr_dst_write(f, tag, regtype, regid)
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
|
||||
##
|
||||
@ -481,7 +483,7 @@ def genptr_dst_write_opn(f, regtype, regid, tag):
|
||||
## TCGv RsV = hex_gpr[insn->regno[1]];
|
||||
## TCGv RtV = hex_gpr[insn->regno[2]];
|
||||
## <GEN>
|
||||
## gen_log_reg_write(RdN, RdV);
|
||||
## gen_log_reg_write(ctx, RdN, RdV);
|
||||
## }
|
||||
##
|
||||
## where <GEN> depends on hex_common.skip_qemu_helper(tag)
|
||||
@ -530,7 +532,7 @@ def gen_tcg_func(f, tag, regs, imms):
|
||||
elif hex_common.is_new_val(regtype, regid, tag):
|
||||
declared.append(f"{regtype}{regid}N")
|
||||
else:
|
||||
print("Bad register parse: ", regtype, regid, toss, numregs)
|
||||
hex_common.bad_register(regtype, regid, toss, numregs)
|
||||
|
||||
## Handle immediates
|
||||
for immlett, bits, immshift in imms:
|
||||
@ -548,10 +550,13 @@ def gen_tcg_func(f, tag, regs, imms):
|
||||
if hex_common.need_pkt_has_multi_cof(tag):
|
||||
f.write(" TCGv pkt_has_multi_cof = ")
|
||||
f.write("tcg_constant_tl(ctx->pkt->pkt_has_multi_cof);\n")
|
||||
if hex_common.need_pkt_need_commit(tag):
|
||||
f.write(" TCGv pkt_need_commit = ")
|
||||
f.write("tcg_constant_tl(ctx->need_commit);\n")
|
||||
if hex_common.need_part1(tag):
|
||||
f.write(" TCGv part1 = tcg_constant_tl(insn->part1);\n")
|
||||
if hex_common.need_slot(tag):
|
||||
f.write(" TCGv slot = tcg_constant_tl(insn->slot);\n")
|
||||
f.write(" TCGv slotval = gen_slotval(ctx);\n")
|
||||
if hex_common.need_PC(tag):
|
||||
f.write(" TCGv PC = tcg_constant_tl(ctx->pkt->pc);\n")
|
||||
if hex_common.helper_needs_next_PC(tag):
|
||||
@ -594,12 +599,14 @@ def gen_tcg_func(f, tag, regs, imms):
|
||||
|
||||
if hex_common.need_pkt_has_multi_cof(tag):
|
||||
f.write(", pkt_has_multi_cof")
|
||||
if hex_common.need_pkt_need_commit(tag):
|
||||
f.write(", pkt_need_commit")
|
||||
if hex_common.need_PC(tag):
|
||||
f.write(", PC")
|
||||
if hex_common.helper_needs_next_PC(tag):
|
||||
f.write(", next_PC")
|
||||
if hex_common.need_slot(tag):
|
||||
f.write(", slot")
|
||||
f.write(", slotval")
|
||||
if hex_common.need_part1(tag):
|
||||
f.write(", part1")
|
||||
f.write(");\n")
|
||||
|
@ -128,6 +128,41 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
|
||||
tcg_gen_gvec_mov(MO_64, VdV_off, VuV_off, \
|
||||
sizeof(MMVector), sizeof(MMVector))
|
||||
|
||||
#define fGEN_TCG_V6_vassign_tmp(SHORTCODE) \
|
||||
tcg_gen_gvec_mov(MO_64, VdV_off, VuV_off, \
|
||||
sizeof(MMVector), sizeof(MMVector))
|
||||
|
||||
#define fGEN_TCG_V6_vcombine_tmp(SHORTCODE) \
|
||||
do { \
|
||||
tcg_gen_gvec_mov(MO_64, VddV_off, VvV_off, \
|
||||
sizeof(MMVector), sizeof(MMVector)); \
|
||||
tcg_gen_gvec_mov(MO_64, VddV_off + sizeof(MMVector), VuV_off, \
|
||||
sizeof(MMVector), sizeof(MMVector)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Vector combine
|
||||
*
|
||||
* Be careful that the source and dest don't overlap
|
||||
*/
|
||||
#define fGEN_TCG_V6_vcombine(SHORTCODE) \
|
||||
do { \
|
||||
if (VddV_off != VuV_off) { \
|
||||
tcg_gen_gvec_mov(MO_64, VddV_off, VvV_off, \
|
||||
sizeof(MMVector), sizeof(MMVector)); \
|
||||
tcg_gen_gvec_mov(MO_64, VddV_off + sizeof(MMVector), VuV_off, \
|
||||
sizeof(MMVector), sizeof(MMVector)); \
|
||||
} else { \
|
||||
intptr_t tmpoff = offsetof(CPUHexagonState, vtmp); \
|
||||
tcg_gen_gvec_mov(MO_64, tmpoff, VuV_off, \
|
||||
sizeof(MMVector), sizeof(MMVector)); \
|
||||
tcg_gen_gvec_mov(MO_64, VddV_off, VvV_off, \
|
||||
sizeof(MMVector), sizeof(MMVector)); \
|
||||
tcg_gen_gvec_mov(MO_64, VddV_off + sizeof(MMVector), tmpoff, \
|
||||
sizeof(MMVector), sizeof(MMVector)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* Vector conditional move */
|
||||
#define fGEN_TCG_VEC_CMOV(PRED) \
|
||||
do { \
|
||||
|
@ -45,7 +45,7 @@ TCGv gen_read_preg(TCGv pred, uint8_t num)
|
||||
|
||||
#define IMMUTABLE (~0)
|
||||
|
||||
static const target_ulong reg_immut_masks[TOTAL_PER_THREAD_REGS] = {
|
||||
const target_ulong reg_immut_masks[TOTAL_PER_THREAD_REGS] = {
|
||||
[HEX_REG_USR] = 0xc13000c0,
|
||||
[HEX_REG_PC] = IMMUTABLE,
|
||||
[HEX_REG_GP] = 0x3f,
|
||||
@ -68,58 +68,72 @@ static inline void gen_masked_reg_write(TCGv new_val, TCGv cur_val,
|
||||
}
|
||||
}
|
||||
|
||||
static TCGv get_result_gpr(DisasContext *ctx, int rnum)
|
||||
TCGv get_result_gpr(DisasContext *ctx, int rnum)
|
||||
{
|
||||
return hex_new_value[rnum];
|
||||
if (ctx->need_commit) {
|
||||
if (rnum == HEX_REG_USR) {
|
||||
return hex_new_value_usr;
|
||||
} else {
|
||||
if (ctx->new_value[rnum] == NULL) {
|
||||
ctx->new_value[rnum] = tcg_temp_new();
|
||||
tcg_gen_movi_tl(ctx->new_value[rnum], 0);
|
||||
}
|
||||
return ctx->new_value[rnum];
|
||||
}
|
||||
} else {
|
||||
return hex_gpr[rnum];
|
||||
}
|
||||
}
|
||||
|
||||
static TCGv_i64 get_result_gpr_pair(DisasContext *ctx, int rnum)
|
||||
{
|
||||
TCGv_i64 result = tcg_temp_new_i64();
|
||||
tcg_gen_concat_i32_i64(result, hex_new_value[rnum],
|
||||
hex_new_value[rnum + 1]);
|
||||
tcg_gen_concat_i32_i64(result, get_result_gpr(ctx, rnum),
|
||||
get_result_gpr(ctx, rnum + 1));
|
||||
return result;
|
||||
}
|
||||
|
||||
void gen_log_reg_write(int rnum, TCGv val)
|
||||
void gen_log_reg_write(DisasContext *ctx, int rnum, TCGv val)
|
||||
{
|
||||
const target_ulong reg_mask = reg_immut_masks[rnum];
|
||||
|
||||
gen_masked_reg_write(val, hex_gpr[rnum], reg_mask);
|
||||
tcg_gen_mov_tl(hex_new_value[rnum], val);
|
||||
tcg_gen_mov_tl(get_result_gpr(ctx, rnum), val);
|
||||
if (HEX_DEBUG) {
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
tcg_gen_movi_tl(hex_reg_written[rnum], 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void gen_log_reg_write_pair(int rnum, TCGv_i64 val)
|
||||
static void gen_log_reg_write_pair(DisasContext *ctx, int rnum, TCGv_i64 val)
|
||||
{
|
||||
const target_ulong reg_mask_low = reg_immut_masks[rnum];
|
||||
const target_ulong reg_mask_high = reg_immut_masks[rnum + 1];
|
||||
TCGv val32 = tcg_temp_new();
|
||||
|
||||
/* Low word */
|
||||
tcg_gen_extrl_i64_i32(val32, val);
|
||||
gen_masked_reg_write(val32, hex_gpr[rnum], reg_mask_low);
|
||||
tcg_gen_mov_tl(hex_new_value[rnum], val32);
|
||||
if (HEX_DEBUG) {
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
tcg_gen_movi_tl(hex_reg_written[rnum], 1);
|
||||
}
|
||||
gen_log_reg_write(ctx, rnum, val32);
|
||||
|
||||
/* High word */
|
||||
tcg_gen_extrh_i64_i32(val32, val);
|
||||
gen_masked_reg_write(val32, hex_gpr[rnum + 1], reg_mask_high);
|
||||
tcg_gen_mov_tl(hex_new_value[rnum + 1], val32);
|
||||
if (HEX_DEBUG) {
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
tcg_gen_movi_tl(hex_reg_written[rnum + 1], 1);
|
||||
gen_log_reg_write(ctx, rnum + 1, val32);
|
||||
}
|
||||
|
||||
TCGv get_result_pred(DisasContext *ctx, int pnum)
|
||||
{
|
||||
if (ctx->need_commit) {
|
||||
if (ctx->new_pred_value[pnum] == NULL) {
|
||||
ctx->new_pred_value[pnum] = tcg_temp_new();
|
||||
tcg_gen_movi_tl(ctx->new_pred_value[pnum], 0);
|
||||
}
|
||||
return ctx->new_pred_value[pnum];
|
||||
} else {
|
||||
return hex_pred[pnum];
|
||||
}
|
||||
}
|
||||
|
||||
void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val)
|
||||
{
|
||||
TCGv pred = get_result_pred(ctx, pnum);
|
||||
TCGv base_val = tcg_temp_new();
|
||||
|
||||
tcg_gen_andi_tl(base_val, val, 0xff);
|
||||
@ -132,12 +146,13 @@ void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val)
|
||||
* straight assignment. Otherwise, do an and.
|
||||
*/
|
||||
if (!test_bit(pnum, ctx->pregs_written)) {
|
||||
tcg_gen_mov_tl(hex_new_pred_value[pnum], base_val);
|
||||
tcg_gen_mov_tl(pred, base_val);
|
||||
} else {
|
||||
tcg_gen_and_tl(hex_new_pred_value[pnum],
|
||||
hex_new_pred_value[pnum], base_val);
|
||||
tcg_gen_and_tl(pred, pred, base_val);
|
||||
}
|
||||
if (HEX_DEBUG) {
|
||||
tcg_gen_ori_tl(ctx->pred_written, ctx->pred_written, 1 << pnum);
|
||||
}
|
||||
tcg_gen_ori_tl(hex_pred_written, hex_pred_written, 1 << pnum);
|
||||
set_bit(pnum, ctx->pregs_written);
|
||||
}
|
||||
|
||||
@ -231,7 +246,7 @@ static inline void gen_write_ctrl_reg(DisasContext *ctx, int reg_num,
|
||||
if (reg_num == HEX_REG_P3_0_ALIASED) {
|
||||
gen_write_p3_0(ctx, val);
|
||||
} else {
|
||||
gen_log_reg_write(reg_num, val);
|
||||
gen_log_reg_write(ctx, reg_num, val);
|
||||
if (reg_num == HEX_REG_QEMU_PKT_CNT) {
|
||||
ctx->num_packets = 0;
|
||||
}
|
||||
@ -255,7 +270,7 @@ static inline void gen_write_ctrl_reg_pair(DisasContext *ctx, int reg_num,
|
||||
tcg_gen_extrh_i64_i32(val32, val);
|
||||
tcg_gen_mov_tl(result, val32);
|
||||
} else {
|
||||
gen_log_reg_write_pair(reg_num, val);
|
||||
gen_log_reg_write_pair(ctx, reg_num, val);
|
||||
if (reg_num == HEX_REG_QEMU_PKT_CNT) {
|
||||
ctx->num_packets = 0;
|
||||
ctx->num_insns = 0;
|
||||
@ -383,6 +398,14 @@ static inline void gen_store_conditional8(DisasContext *ctx,
|
||||
tcg_gen_movi_tl(hex_llsc_addr, ~0);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_HEXAGON_IDEF_PARSER
|
||||
static TCGv gen_slotval(DisasContext *ctx)
|
||||
{
|
||||
int slotval = (ctx->pkt->pkt_has_store_s1 & 1) | (ctx->insn->slot << 1);
|
||||
return tcg_constant_tl(slotval);
|
||||
}
|
||||
#endif
|
||||
|
||||
void gen_store32(TCGv vaddr, TCGv src, int width, uint32_t slot)
|
||||
{
|
||||
tcg_gen_mov_tl(hex_store_addr[slot], vaddr);
|
||||
@ -457,9 +480,9 @@ static void gen_write_new_pc_addr(DisasContext *ctx, TCGv addr,
|
||||
if (ctx->pkt->pkt_has_multi_cof) {
|
||||
/* If there are multiple branches in a packet, ignore the second one */
|
||||
tcg_gen_movcond_tl(TCG_COND_NE, hex_gpr[HEX_REG_PC],
|
||||
hex_branch_taken, tcg_constant_tl(0),
|
||||
ctx->branch_taken, tcg_constant_tl(0),
|
||||
hex_gpr[HEX_REG_PC], addr);
|
||||
tcg_gen_movi_tl(hex_branch_taken, 1);
|
||||
tcg_gen_movi_tl(ctx->branch_taken, 1);
|
||||
} else {
|
||||
tcg_gen_mov_tl(hex_gpr[HEX_REG_PC], addr);
|
||||
}
|
||||
@ -480,7 +503,7 @@ static void gen_write_new_pc_pcrel(DisasContext *ctx, int pc_off,
|
||||
ctx->branch_cond = TCG_COND_ALWAYS;
|
||||
if (pred != NULL) {
|
||||
ctx->branch_cond = cond;
|
||||
tcg_gen_mov_tl(hex_branch_taken, pred);
|
||||
tcg_gen_mov_tl(ctx->branch_taken, pred);
|
||||
}
|
||||
ctx->branch_dest = dest;
|
||||
}
|
||||
@ -518,6 +541,55 @@ static void gen_compare(TCGCond cond, TCGv res, TCGv arg1, TCGv arg2)
|
||||
tcg_gen_movcond_tl(cond, res, arg1, arg2, one, zero);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_HEXAGON_IDEF_PARSER
|
||||
static inline void gen_loop0r(DisasContext *ctx, TCGv RsV, int riV)
|
||||
{
|
||||
fIMMEXT(riV);
|
||||
fPCALIGN(riV);
|
||||
gen_log_reg_write(ctx, HEX_REG_LC0, RsV);
|
||||
gen_log_reg_write(ctx, HEX_REG_SA0, tcg_constant_tl(ctx->pkt->pc + riV));
|
||||
gen_set_usr_fieldi(ctx, USR_LPCFG, 0);
|
||||
}
|
||||
|
||||
static void gen_loop0i(DisasContext *ctx, int count, int riV)
|
||||
{
|
||||
gen_loop0r(ctx, tcg_constant_tl(count), riV);
|
||||
}
|
||||
|
||||
static inline void gen_loop1r(DisasContext *ctx, TCGv RsV, int riV)
|
||||
{
|
||||
fIMMEXT(riV);
|
||||
fPCALIGN(riV);
|
||||
gen_log_reg_write(ctx, HEX_REG_LC1, RsV);
|
||||
gen_log_reg_write(ctx, HEX_REG_SA1, tcg_constant_tl(ctx->pkt->pc + riV));
|
||||
}
|
||||
|
||||
static void gen_loop1i(DisasContext *ctx, int count, int riV)
|
||||
{
|
||||
gen_loop1r(ctx, tcg_constant_tl(count), riV);
|
||||
}
|
||||
|
||||
static void gen_ploopNsr(DisasContext *ctx, int N, TCGv RsV, int riV)
|
||||
{
|
||||
fIMMEXT(riV);
|
||||
fPCALIGN(riV);
|
||||
gen_log_reg_write(ctx, HEX_REG_LC0, RsV);
|
||||
gen_log_reg_write(ctx, HEX_REG_SA0, tcg_constant_tl(ctx->pkt->pc + riV));
|
||||
gen_set_usr_fieldi(ctx, USR_LPCFG, N);
|
||||
gen_log_pred_write(ctx, 3, tcg_constant_tl(0));
|
||||
}
|
||||
|
||||
static void gen_ploopNsi(DisasContext *ctx, int N, int count, int riV)
|
||||
{
|
||||
gen_ploopNsr(ctx, N, tcg_constant_tl(count), riV);
|
||||
}
|
||||
|
||||
static inline void gen_comparei(TCGCond cond, TCGv res, TCGv arg1, int arg2)
|
||||
{
|
||||
gen_compare(cond, res, arg1, tcg_constant_tl(arg2));
|
||||
}
|
||||
#endif
|
||||
|
||||
static void gen_cond_jumpr(DisasContext *ctx, TCGv dst_pc,
|
||||
TCGCond cond, TCGv pred)
|
||||
{
|
||||
@ -547,7 +619,7 @@ static void gen_cmpnd_cmp_jmp(DisasContext *ctx,
|
||||
gen_log_pred_write(ctx, pnum, pred);
|
||||
} else {
|
||||
TCGv pred = tcg_temp_new();
|
||||
tcg_gen_mov_tl(pred, hex_new_pred_value[pnum]);
|
||||
tcg_gen_mov_tl(pred, ctx->new_pred_value[pnum]);
|
||||
gen_cond_jump(ctx, cond2, pred, pc_off);
|
||||
}
|
||||
}
|
||||
@ -604,7 +676,7 @@ static void gen_cmpnd_tstbit0_jmp(DisasContext *ctx,
|
||||
gen_log_pred_write(ctx, pnum, pred);
|
||||
} else {
|
||||
TCGv pred = tcg_temp_new();
|
||||
tcg_gen_mov_tl(pred, hex_new_pred_value[pnum]);
|
||||
tcg_gen_mov_tl(pred, ctx->new_pred_value[pnum]);
|
||||
gen_cond_jump(ctx, cond, pred, pc_off);
|
||||
}
|
||||
}
|
||||
@ -665,6 +737,18 @@ static void gen_cond_callr(DisasContext *ctx,
|
||||
gen_set_label(skip);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_HEXAGON_IDEF_PARSER
|
||||
/* frame = ((LR << 32) | FP) ^ (FRAMEKEY << 32)) */
|
||||
static TCGv_i64 gen_frame_scramble(void)
|
||||
{
|
||||
TCGv_i64 frame = tcg_temp_new_i64();
|
||||
TCGv tmp = tcg_temp_new();
|
||||
tcg_gen_xor_tl(tmp, hex_gpr[HEX_REG_LR], hex_gpr[HEX_REG_FRAMEKEY]);
|
||||
tcg_gen_concat_i32_i64(frame, hex_gpr[HEX_REG_FP], tmp);
|
||||
return frame;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* frame ^= (int64_t)FRAMEKEY << 32 */
|
||||
static void gen_frame_unscramble(TCGv_i64 frame)
|
||||
{
|
||||
@ -681,6 +765,41 @@ static void gen_load_frame(DisasContext *ctx, TCGv_i64 frame, TCGv EA)
|
||||
tcg_gen_qemu_ld_i64(frame, EA, ctx->mem_idx, MO_TEUQ);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_HEXAGON_IDEF_PARSER
|
||||
/* Stack overflow check */
|
||||
static void gen_framecheck(TCGv EA, int framesize)
|
||||
{
|
||||
/* Not modelled in linux-user mode */
|
||||
/* Placeholder for system mode */
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
g_assert_not_reached();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void gen_allocframe(DisasContext *ctx, TCGv r29, int framesize)
|
||||
{
|
||||
TCGv r30 = tcg_temp_new();
|
||||
TCGv_i64 frame;
|
||||
tcg_gen_addi_tl(r30, r29, -8);
|
||||
frame = gen_frame_scramble();
|
||||
gen_store8(cpu_env, r30, frame, ctx->insn->slot);
|
||||
gen_log_reg_write(ctx, HEX_REG_FP, r30);
|
||||
gen_framecheck(r30, framesize);
|
||||
tcg_gen_subi_tl(r29, r30, framesize);
|
||||
}
|
||||
|
||||
static void gen_deallocframe(DisasContext *ctx, TCGv_i64 r31_30, TCGv r30)
|
||||
{
|
||||
TCGv r29 = tcg_temp_new();
|
||||
TCGv_i64 frame = tcg_temp_new_i64();
|
||||
gen_load_frame(ctx, frame, r30);
|
||||
gen_frame_unscramble(frame);
|
||||
tcg_gen_mov_i64(r31_30, frame);
|
||||
tcg_gen_addi_tl(r29, r30, 8);
|
||||
gen_log_reg_write(ctx, HEX_REG_SP, r29);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void gen_return(DisasContext *ctx, TCGv_i64 dst, TCGv src)
|
||||
{
|
||||
/*
|
||||
@ -719,7 +838,7 @@ static void gen_cond_return_subinsn(DisasContext *ctx, TCGCond cond, TCGv pred)
|
||||
{
|
||||
TCGv_i64 RddV = get_result_gpr_pair(ctx, HEX_REG_FP);
|
||||
gen_cond_return(ctx, RddV, hex_gpr[HEX_REG_FP], pred, cond);
|
||||
gen_log_reg_write_pair(HEX_REG_FP, RddV);
|
||||
gen_log_reg_write_pair(ctx, HEX_REG_FP, RddV);
|
||||
}
|
||||
|
||||
static void gen_endloop0(DisasContext *ctx)
|
||||
@ -730,15 +849,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);
|
||||
|
||||
@ -807,14 +924,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);
|
||||
|
||||
@ -877,6 +992,7 @@ static void gen_cmpi_jumpnv(DisasContext *ctx,
|
||||
/* Shift left with saturation */
|
||||
static void gen_shl_sat(DisasContext *ctx, TCGv dst, TCGv src, TCGv shift_amt)
|
||||
{
|
||||
TCGv tmp = tcg_temp_new(); /* In case dst == src */
|
||||
TCGv usr = get_result_gpr(ctx, HEX_REG_USR);
|
||||
TCGv sh32 = tcg_temp_new();
|
||||
TCGv dst_sar = tcg_temp_new();
|
||||
@ -901,17 +1017,17 @@ static void gen_shl_sat(DisasContext *ctx, TCGv dst, TCGv src, TCGv shift_amt)
|
||||
*/
|
||||
|
||||
tcg_gen_andi_tl(sh32, shift_amt, 31);
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, dst, sh32, shift_amt,
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, tmp, sh32, shift_amt,
|
||||
src, tcg_constant_tl(0));
|
||||
tcg_gen_shl_tl(dst, dst, sh32);
|
||||
tcg_gen_sar_tl(dst_sar, dst, sh32);
|
||||
tcg_gen_shl_tl(tmp, tmp, sh32);
|
||||
tcg_gen_sar_tl(dst_sar, tmp, sh32);
|
||||
tcg_gen_movcond_tl(TCG_COND_LT, satval, src, tcg_constant_tl(0), min, max);
|
||||
|
||||
tcg_gen_setcond_tl(TCG_COND_NE, ovf, dst_sar, src);
|
||||
tcg_gen_shli_tl(ovf, ovf, reg_field_info[USR_OVF].offset);
|
||||
tcg_gen_or_tl(usr, usr, ovf);
|
||||
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, dst, dst_sar, src, dst, satval);
|
||||
tcg_gen_movcond_tl(TCG_COND_EQ, dst, dst_sar, src, tmp, satval);
|
||||
}
|
||||
|
||||
static void gen_sar(TCGv dst, TCGv src, TCGv shift_amt)
|
||||
@ -969,6 +1085,105 @@ static void gen_asl_r_r_sat(DisasContext *ctx, TCGv RdV, TCGv RsV, TCGv RtV)
|
||||
gen_set_label(done);
|
||||
}
|
||||
|
||||
static void gen_insert_rp(DisasContext *ctx, TCGv RxV, TCGv RsV, TCGv_i64 RttV)
|
||||
{
|
||||
/*
|
||||
* int width = fZXTN(6, 32, (fGETWORD(1, RttV)));
|
||||
* int offset = fSXTN(7, 32, (fGETWORD(0, RttV)));
|
||||
* size8u_t mask = ((fCONSTLL(1) << width) - 1);
|
||||
* if (offset < 0) {
|
||||
* RxV = 0;
|
||||
* } else {
|
||||
* RxV &= ~(mask << offset);
|
||||
* RxV |= ((RsV & mask) << offset);
|
||||
* }
|
||||
*/
|
||||
|
||||
TCGv width = tcg_temp_new();
|
||||
TCGv offset = tcg_temp_new();
|
||||
TCGv_i64 mask = tcg_temp_new_i64();
|
||||
TCGv_i64 result = tcg_temp_new_i64();
|
||||
TCGv_i64 tmp = tcg_temp_new_i64();
|
||||
TCGv_i64 offset64 = tcg_temp_new_i64();
|
||||
TCGLabel *label = gen_new_label();
|
||||
TCGLabel *done = gen_new_label();
|
||||
|
||||
tcg_gen_extrh_i64_i32(width, RttV);
|
||||
tcg_gen_extract_tl(width, width, 0, 6);
|
||||
tcg_gen_extrl_i64_i32(offset, RttV);
|
||||
tcg_gen_sextract_tl(offset, offset, 0, 7);
|
||||
/* Possible values for offset are -64 .. 63 */
|
||||
tcg_gen_brcondi_tl(TCG_COND_GE, offset, 0, label);
|
||||
/* For negative offsets, zero out the result */
|
||||
tcg_gen_movi_tl(RxV, 0);
|
||||
tcg_gen_br(done);
|
||||
gen_set_label(label);
|
||||
/* At this point, possible values of offset are 0 .. 63 */
|
||||
tcg_gen_ext_i32_i64(mask, width);
|
||||
tcg_gen_shl_i64(mask, tcg_constant_i64(1), mask);
|
||||
tcg_gen_subi_i64(mask, mask, 1);
|
||||
tcg_gen_extu_i32_i64(result, RxV);
|
||||
tcg_gen_ext_i32_i64(tmp, offset);
|
||||
tcg_gen_shl_i64(tmp, mask, tmp);
|
||||
tcg_gen_andc_i64(result, result, tmp);
|
||||
tcg_gen_extu_i32_i64(tmp, RsV);
|
||||
tcg_gen_and_i64(tmp, tmp, mask);
|
||||
tcg_gen_extu_i32_i64(offset64, offset);
|
||||
tcg_gen_shl_i64(tmp, tmp, offset64);
|
||||
tcg_gen_or_i64(result, result, tmp);
|
||||
tcg_gen_extrl_i64_i32(RxV, result);
|
||||
gen_set_label(done);
|
||||
}
|
||||
|
||||
static void gen_asr_r_svw_trun(DisasContext *ctx, TCGv RdV,
|
||||
TCGv_i64 RssV, TCGv RtV)
|
||||
{
|
||||
/*
|
||||
* for (int i = 0; i < 2; i++) {
|
||||
* fSETHALF(i, RdV, fGETHALF(0, ((fSXTN(7, 32, RtV) > 0) ?
|
||||
* (fCAST4_8s(fGETWORD(i, RssV)) >> fSXTN(7, 32, RtV)) :
|
||||
* (fCAST4_8s(fGETWORD(i, RssV)) << -fSXTN(7, 32, RtV)))));
|
||||
* }
|
||||
*/
|
||||
TCGv shift_amt32 = tcg_temp_new();
|
||||
TCGv_i64 shift_amt64 = tcg_temp_new_i64();
|
||||
TCGv_i64 tmp64 = tcg_temp_new_i64();
|
||||
TCGv tmp32 = tcg_temp_new();
|
||||
TCGLabel *label = gen_new_label();
|
||||
TCGLabel *zero = gen_new_label();
|
||||
TCGLabel *done = gen_new_label();
|
||||
|
||||
tcg_gen_sextract_tl(shift_amt32, RtV, 0, 7);
|
||||
/* Possible values of shift_amt32 are -64 .. 63 */
|
||||
tcg_gen_brcondi_tl(TCG_COND_LE, shift_amt32, 0, label);
|
||||
/* After branch, possible values of shift_amt32 are 1 .. 63 */
|
||||
tcg_gen_ext_i32_i64(shift_amt64, shift_amt32);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
tcg_gen_sextract_i64(tmp64, RssV, i * 32, 32);
|
||||
tcg_gen_sar_i64(tmp64, tmp64, shift_amt64);
|
||||
tcg_gen_extrl_i64_i32(tmp32, tmp64);
|
||||
tcg_gen_deposit_tl(RdV, RdV, tmp32, i * 16, 16);
|
||||
}
|
||||
tcg_gen_br(done);
|
||||
gen_set_label(label);
|
||||
tcg_gen_neg_tl(shift_amt32, shift_amt32);
|
||||
/*At this point, possible values of shift_amt32 are 0 .. 64 */
|
||||
tcg_gen_brcondi_tl(TCG_COND_GT, shift_amt32, 63, zero);
|
||||
/*At this point, possible values of shift_amt32 are 0 .. 63 */
|
||||
tcg_gen_ext_i32_i64(shift_amt64, shift_amt32);
|
||||
for (int i = 0; i < 2; i++) {
|
||||
tcg_gen_sextract_i64(tmp64, RssV, i * 32, 32);
|
||||
tcg_gen_shl_i64(tmp64, tmp64, shift_amt64);
|
||||
tcg_gen_extrl_i64_i32(tmp32, tmp64);
|
||||
tcg_gen_deposit_tl(RdV, RdV, tmp32, i * 16, 16);
|
||||
}
|
||||
tcg_gen_br(done);
|
||||
gen_set_label(zero);
|
||||
/* When the shift_amt is 64, zero out the result */
|
||||
tcg_gen_movi_tl(RdV, 0);
|
||||
gen_set_label(done);
|
||||
}
|
||||
|
||||
static intptr_t vreg_src_off(DisasContext *ctx, int num)
|
||||
{
|
||||
intptr_t offset = offsetof(CPUHexagonState, VRegs[num]);
|
||||
@ -1008,7 +1223,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,
|
||||
@ -1134,22 +1353,28 @@ void gen_sat_i32(TCGv dest, TCGv source, int width)
|
||||
|
||||
void gen_sat_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width)
|
||||
{
|
||||
gen_sat_i32(dest, source, width);
|
||||
tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, dest);
|
||||
TCGv tmp = tcg_temp_new(); /* In case dest == source */
|
||||
gen_sat_i32(tmp, source, width);
|
||||
tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, tmp);
|
||||
tcg_gen_mov_tl(dest, tmp);
|
||||
}
|
||||
|
||||
void gen_satu_i32(TCGv dest, TCGv source, int width)
|
||||
{
|
||||
TCGv tmp = tcg_temp_new(); /* In case dest == source */
|
||||
TCGv max_val = tcg_constant_tl((1 << width) - 1);
|
||||
TCGv zero = tcg_constant_tl(0);
|
||||
tcg_gen_movcond_tl(TCG_COND_GTU, dest, source, max_val, max_val, source);
|
||||
tcg_gen_movcond_tl(TCG_COND_LT, dest, source, zero, zero, dest);
|
||||
tcg_gen_movcond_tl(TCG_COND_GTU, tmp, source, max_val, max_val, source);
|
||||
tcg_gen_movcond_tl(TCG_COND_LT, tmp, source, zero, zero, tmp);
|
||||
tcg_gen_mov_tl(dest, tmp);
|
||||
}
|
||||
|
||||
void gen_satu_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width)
|
||||
{
|
||||
gen_satu_i32(dest, source, width);
|
||||
tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, dest);
|
||||
TCGv tmp = tcg_temp_new(); /* In case dest == source */
|
||||
gen_satu_i32(tmp, source, width);
|
||||
tcg_gen_setcond_tl(TCG_COND_NE, ovfl, source, tmp);
|
||||
tcg_gen_mov_tl(dest, tmp);
|
||||
}
|
||||
|
||||
void gen_sat_i64(TCGv_i64 dest, TCGv_i64 source, int width)
|
||||
@ -1162,27 +1387,33 @@ void gen_sat_i64(TCGv_i64 dest, TCGv_i64 source, int width)
|
||||
|
||||
void gen_sat_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width)
|
||||
{
|
||||
TCGv_i64 tmp = tcg_temp_new_i64(); /* In case dest == source */
|
||||
TCGv_i64 ovfl_64;
|
||||
gen_sat_i64(dest, source, width);
|
||||
gen_sat_i64(tmp, source, width);
|
||||
ovfl_64 = tcg_temp_new_i64();
|
||||
tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, dest, source);
|
||||
tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, tmp, source);
|
||||
tcg_gen_mov_i64(dest, tmp);
|
||||
tcg_gen_trunc_i64_tl(ovfl, ovfl_64);
|
||||
}
|
||||
|
||||
void gen_satu_i64(TCGv_i64 dest, TCGv_i64 source, int width)
|
||||
{
|
||||
TCGv_i64 tmp = tcg_temp_new_i64(); /* In case dest == source */
|
||||
TCGv_i64 max_val = tcg_constant_i64((1LL << width) - 1LL);
|
||||
TCGv_i64 zero = tcg_constant_i64(0);
|
||||
tcg_gen_movcond_i64(TCG_COND_GTU, dest, source, max_val, max_val, source);
|
||||
tcg_gen_movcond_i64(TCG_COND_LT, dest, source, zero, zero, dest);
|
||||
tcg_gen_movcond_i64(TCG_COND_GTU, tmp, source, max_val, max_val, source);
|
||||
tcg_gen_movcond_i64(TCG_COND_LT, tmp, source, zero, zero, tmp);
|
||||
tcg_gen_mov_i64(dest, tmp);
|
||||
}
|
||||
|
||||
void gen_satu_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width)
|
||||
{
|
||||
TCGv_i64 tmp = tcg_temp_new_i64(); /* In case dest == source */
|
||||
TCGv_i64 ovfl_64;
|
||||
gen_satu_i64(dest, source, width);
|
||||
gen_satu_i64(tmp, source, width);
|
||||
ovfl_64 = tcg_temp_new_i64();
|
||||
tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, dest, source);
|
||||
tcg_gen_setcond_i64(TCG_COND_NE, ovfl_64, tmp, source);
|
||||
tcg_gen_mov_i64(dest, tmp);
|
||||
tcg_gen_trunc_i64_tl(ovfl, ovfl_64);
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,9 @@ void gen_store4i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot);
|
||||
void gen_store8i(TCGv_env cpu_env, TCGv vaddr, int64_t src, uint32_t slot);
|
||||
TCGv gen_read_reg(TCGv result, int num);
|
||||
TCGv gen_read_preg(TCGv pred, uint8_t num);
|
||||
void gen_log_reg_write(int rnum, TCGv val);
|
||||
TCGv get_result_gpr(DisasContext *ctx, int rnum);
|
||||
TCGv get_result_pred(DisasContext *ctx, int pnum);
|
||||
void gen_log_reg_write(DisasContext *ctx, int rnum, TCGv val);
|
||||
void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val);
|
||||
void gen_set_usr_field(DisasContext *ctx, int field, TCGv val);
|
||||
void gen_set_usr_fieldi(DisasContext *ctx, int field, int x);
|
||||
@ -58,4 +60,6 @@ void gen_set_half(int N, TCGv result, TCGv src);
|
||||
void gen_set_half_i64(int N, TCGv_i64 result, TCGv src);
|
||||
void probe_noshuf_load(TCGv va, int s, int mi);
|
||||
|
||||
extern const target_ulong reg_immut_masks[TOTAL_PER_THREAD_REGS];
|
||||
|
||||
#endif
|
||||
|
@ -21,7 +21,7 @@
|
||||
DEF_HELPER_FLAGS_2(raise_exception, TCG_CALL_NO_RETURN, noreturn, env, i32)
|
||||
DEF_HELPER_1(debug_start_packet, void, env)
|
||||
DEF_HELPER_FLAGS_3(debug_check_store_width, TCG_CALL_NO_WG, void, env, int, int)
|
||||
DEF_HELPER_FLAGS_3(debug_commit_end, TCG_CALL_NO_WG, void, env, int, int)
|
||||
DEF_HELPER_FLAGS_5(debug_commit_end, TCG_CALL_NO_WG, void, env, i32, int, int, int)
|
||||
DEF_HELPER_2(commit_store, void, env, int)
|
||||
DEF_HELPER_3(gather_store, void, env, i32, int)
|
||||
DEF_HELPER_1(commit_hvx_stores, void, env)
|
||||
@ -29,8 +29,10 @@ DEF_HELPER_FLAGS_4(fcircadd, TCG_CALL_NO_RWG_SE, s32, s32, s32, s32, s32)
|
||||
DEF_HELPER_FLAGS_1(fbrev, TCG_CALL_NO_RWG_SE, i32, i32)
|
||||
DEF_HELPER_3(sfrecipa, i64, env, f32, f32)
|
||||
DEF_HELPER_2(sfinvsqrta, i64, env, f32)
|
||||
DEF_HELPER_4(vacsh_val, s64, env, s64, s64, s64)
|
||||
DEF_HELPER_5(vacsh_val, s64, env, s64, s64, s64, i32)
|
||||
DEF_HELPER_FLAGS_4(vacsh_pred, TCG_CALL_NO_RWG_SE, s32, env, s64, s64, s64)
|
||||
DEF_HELPER_FLAGS_2(cabacdecbin_val, TCG_CALL_NO_RWG_SE, s64, s64, s64)
|
||||
DEF_HELPER_FLAGS_2(cabacdecbin_pred, TCG_CALL_NO_RWG_SE, s32, s64, s64)
|
||||
|
||||
/* Floating point */
|
||||
DEF_HELPER_2(conv_sf2df, f64, env, f32)
|
||||
|
@ -30,6 +30,9 @@ tags = [] # list of all tags
|
||||
overrides = {} # tags with helper overrides
|
||||
idef_parser_enabled = {} # tags enabled for idef-parser
|
||||
|
||||
def bad_register(*args):
|
||||
args_str = ", ".join(map(str, args))
|
||||
raise Exception(f"Bad register parse: {args_str}")
|
||||
|
||||
# We should do this as a hash for performance,
|
||||
# but to keep order let's keep it as a list.
|
||||
@ -97,6 +100,12 @@ def calculate_attribs():
|
||||
add_qemu_macro_attrib("fSET_LPCFG", "A_IMPLICIT_WRITES_USR")
|
||||
add_qemu_macro_attrib("fLOAD", "A_SCALAR_LOAD")
|
||||
add_qemu_macro_attrib("fSTORE", "A_SCALAR_STORE")
|
||||
add_qemu_macro_attrib('fLSBNEW0', 'A_IMPLICIT_READS_P0')
|
||||
add_qemu_macro_attrib('fLSBNEW0NOT', 'A_IMPLICIT_READS_P0')
|
||||
add_qemu_macro_attrib('fREAD_P0', 'A_IMPLICIT_READS_P0')
|
||||
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')
|
||||
|
||||
# Recurse down macros, find attributes from sub-macros
|
||||
macroValues = list(macros.values())
|
||||
@ -241,9 +250,10 @@ def is_new_val(regtype, regid, tag):
|
||||
|
||||
def need_slot(tag):
|
||||
if (
|
||||
("A_CONDEXEC" in attribdict[tag] and "A_JUMP" not in attribdict[tag])
|
||||
or "A_STORE" in attribdict[tag]
|
||||
or "A_LOAD" in attribdict[tag]
|
||||
"A_CVI_SCATTER" not in attribdict[tag]
|
||||
and "A_CVI_GATHER" not in attribdict[tag]
|
||||
and ("A_STORE" in attribdict[tag]
|
||||
or "A_LOAD" in attribdict[tag])
|
||||
):
|
||||
return 1
|
||||
else:
|
||||
@ -270,6 +280,9 @@ def need_pkt_has_multi_cof(tag):
|
||||
return "A_COF" in attribdict[tag]
|
||||
|
||||
|
||||
def need_pkt_need_commit(tag):
|
||||
return 'A_IMPLICIT_WRITES_USR' in attribdict[tag]
|
||||
|
||||
def need_condexec_reg(tag, regs):
|
||||
if "A_CONDEXEC" in attribdict[tag]:
|
||||
for regtype, regid, toss, numregs in regs:
|
||||
|
@ -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
|
||||
@ -51,8 +51,10 @@ SlotMask find_iclass_slots(Opcode opcode, int itype)
|
||||
return SLOTS_0;
|
||||
} else if ((opcode == J2_trap0) ||
|
||||
(opcode == Y2_isync) ||
|
||||
(opcode == J2_pause) || (opcode == J4_hintjumpr)) {
|
||||
(opcode == J2_pause)) {
|
||||
return SLOTS_2;
|
||||
} else if (opcode == J4_hintjumpr) {
|
||||
return SLOTS_23;
|
||||
} else if (GET_ATTRIB(opcode, A_CRSLOT23)) {
|
||||
return SLOTS_23;
|
||||
} else if (GET_ATTRIB(opcode, A_RESTRICT_PREFERSLOT0)) {
|
||||
|
@ -401,12 +401,39 @@ STRING_LIT \"(\\.|[^"\\])*\"
|
||||
}
|
||||
return SIGN;
|
||||
}
|
||||
"0x"{HEX_DIGIT}+ |
|
||||
{DIGIT}+ { yylval->rvalue.type = IMMEDIATE;
|
||||
yylval->rvalue.bit_width = 32;
|
||||
yylval->rvalue.signedness = SIGNED;
|
||||
"0x"{HEX_DIGIT}+ { uint64_t value = strtoull(yytext, NULL, 0);
|
||||
yylval->rvalue.type = IMMEDIATE;
|
||||
yylval->rvalue.imm.type = VALUE;
|
||||
yylval->rvalue.imm.value = strtoull(yytext, NULL, 0);
|
||||
yylval->rvalue.imm.value = value;
|
||||
if (value <= INT_MAX) {
|
||||
yylval->rvalue.bit_width = sizeof(int) * 8;
|
||||
yylval->rvalue.signedness = SIGNED;
|
||||
} else if (value <= UINT_MAX) {
|
||||
yylval->rvalue.bit_width = sizeof(unsigned int) * 8;
|
||||
yylval->rvalue.signedness = UNSIGNED;
|
||||
} else if (value <= LONG_MAX) {
|
||||
yylval->rvalue.bit_width = sizeof(long) * 8;
|
||||
yylval->rvalue.signedness = SIGNED;
|
||||
} else if (value <= ULONG_MAX) {
|
||||
yylval->rvalue.bit_width = sizeof(unsigned long) * 8;
|
||||
yylval->rvalue.signedness = UNSIGNED;
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return IMM; }
|
||||
{DIGIT}+ { int64_t value = strtoll(yytext, NULL, 0);
|
||||
yylval->rvalue.type = IMMEDIATE;
|
||||
yylval->rvalue.imm.type = VALUE;
|
||||
yylval->rvalue.imm.value = value;
|
||||
if (value >= INT_MIN && value <= INT_MAX) {
|
||||
yylval->rvalue.bit_width = sizeof(int) * 8;
|
||||
yylval->rvalue.signedness = SIGNED;
|
||||
} else if (value >= LONG_MIN && value <= LONG_MAX) {
|
||||
yylval->rvalue.bit_width = sizeof(long) * 8;
|
||||
yylval->rvalue.signedness = SIGNED;
|
||||
} else {
|
||||
g_assert_not_reached();
|
||||
}
|
||||
return IMM; }
|
||||
"0x"{HEX_DIGIT}+"ULL" |
|
||||
{DIGIT}+"ULL" { yylval->rvalue.type = IMMEDIATE;
|
||||
|
@ -594,8 +594,6 @@ rvalue : FAIL
|
||||
| CAST rvalue
|
||||
{
|
||||
@1.last_column = @2.last_column;
|
||||
/* Assign target signedness */
|
||||
$2.signedness = $1.signedness;
|
||||
$$ = gen_cast_op(c, &@1, &$2, $1.bit_width, $1.signedness);
|
||||
}
|
||||
| rvalue EQ rvalue
|
||||
@ -685,7 +683,7 @@ rvalue : FAIL
|
||||
yyassert(c, &@1, $5.type == IMMEDIATE &&
|
||||
$5.imm.type == VALUE,
|
||||
"SXT expects immediate values\n");
|
||||
$$ = gen_extend_op(c, &@1, &$3, $5.imm.value, &$7, SIGNED);
|
||||
$$ = gen_extend_op(c, &@1, &$3, 64, &$7, SIGNED);
|
||||
}
|
||||
| ZXT '(' rvalue ',' IMM ',' rvalue ')'
|
||||
{
|
||||
@ -693,7 +691,7 @@ rvalue : FAIL
|
||||
yyassert(c, &@1, $5.type == IMMEDIATE &&
|
||||
$5.imm.type == VALUE,
|
||||
"ZXT expects immediate values\n");
|
||||
$$ = gen_extend_op(c, &@1, &$3, $5.imm.value, &$7, UNSIGNED);
|
||||
$$ = gen_extend_op(c, &@1, &$3, 64, &$7, UNSIGNED);
|
||||
}
|
||||
| '(' rvalue ')'
|
||||
{
|
||||
|
@ -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 = &rvalue->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, &rvalue->tmp);
|
||||
break;
|
||||
case IMMEDIATE:
|
||||
imm_print(c, locp, &rvalue->imm);
|
||||
imm_print(c, locp, rvalue);
|
||||
break;
|
||||
case VARID:
|
||||
var_print(c, locp, &rvalue->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, " ", &res, " = ");
|
||||
OUT(c, locp, "(", sign_suffix, "int64_t) ");
|
||||
OUT(c, locp, "(", sign_suffix, "int32_t) ");
|
||||
OUT(c, locp, rvalue, ";\n");
|
||||
OUT(c, locp, " ", &res, " = (");
|
||||
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,
|
||||
HexSignedness signedness)
|
||||
{
|
||||
HexValue res;
|
||||
assert_signedness(c, locp, src->signedness);
|
||||
if (src->bit_width == target_width) {
|
||||
return *src;
|
||||
} else if (src->type == IMMEDIATE) {
|
||||
HexValue res = *src;
|
||||
res.bit_width = target_width;
|
||||
res.signedness = signedness;
|
||||
return res;
|
||||
res = *src;
|
||||
} else if (src->bit_width < target_width) {
|
||||
res = gen_rvalue_extend(c, locp, src);
|
||||
} else {
|
||||
HexValue res = gen_tmp(c, locp, target_width, signedness);
|
||||
/* Truncate */
|
||||
if (src->bit_width > target_width) {
|
||||
OUT(c, locp, "tcg_gen_trunc_i64_tl(", &res, ", ", src, ");\n");
|
||||
} else {
|
||||
assert_signedness(c, locp, src->signedness);
|
||||
if (src->signedness == UNSIGNED) {
|
||||
/* Extend unsigned */
|
||||
OUT(c, locp, "tcg_gen_extu_i32_i64(",
|
||||
&res, ", ", src, ");\n");
|
||||
} else {
|
||||
/* Extend signed */
|
||||
OUT(c, locp, "tcg_gen_ext_i32_i64(",
|
||||
&res, ", ", src, ");\n");
|
||||
}
|
||||
}
|
||||
return res;
|
||||
/* src->bit_width > target_width */
|
||||
res = gen_rvalue_truncate(c, locp, src);
|
||||
}
|
||||
res.signedness = signedness;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@ -1123,7 +1120,7 @@ HexValue gen_extend_op(Context *c,
|
||||
HexValue *value,
|
||||
HexSignedness signedness)
|
||||
{
|
||||
unsigned bit_width = (dst_width = 64) ? 64 : 32;
|
||||
unsigned bit_width = (dst_width == 64) ? 64 : 32;
|
||||
HexValue value_m = *value;
|
||||
HexValue src_width_m = *src_width;
|
||||
|
||||
@ -1318,7 +1315,7 @@ void gen_write_reg(Context *c, YYLTYPE *locp, HexValue *reg, HexValue *value)
|
||||
value_m = rvalue_materialize(c, locp, &value_m);
|
||||
OUT(c,
|
||||
locp,
|
||||
"gen_log_reg_write(", ®->reg.id, ", ",
|
||||
"gen_log_reg_write(ctx, ", ®->reg.id, ", ",
|
||||
&value_m, ");\n");
|
||||
}
|
||||
|
||||
@ -1854,7 +1851,7 @@ HexValue gen_rvalue_pred(Context *c, YYLTYPE *locp, HexValue *pred)
|
||||
*pred = gen_tmp(c, locp, 32, UNSIGNED);
|
||||
if (is_dotnew) {
|
||||
OUT(c, locp, "tcg_gen_mov_i32(", pred,
|
||||
", hex_new_pred_value[");
|
||||
", ctx->new_pred_value[");
|
||||
OUT(c, locp, pred_str, "]);\n");
|
||||
} else {
|
||||
OUT(c, locp, "gen_read_preg(", pred, ", ", pred_str, ");\n");
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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); })
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
||||
@ -382,14 +382,23 @@ DEF_ENC32(L4_return_fnew_pt, ICLASS_LD" 011 0 000 sssss PP1110vv ---ddddd")
|
||||
DEF_ENC32(L4_return_tnew_pnt, ICLASS_LD" 011 0 000 sssss PP0010vv ---ddddd")
|
||||
DEF_ENC32(L4_return_fnew_pnt, ICLASS_LD" 011 0 000 sssss PP1010vv ---ddddd")
|
||||
|
||||
DEF_ENC32(L2_loadw_locked,ICLASS_LD" 001 0 000 sssss PP00---- -00ddddd")
|
||||
DEF_ENC32(L2_loadw_locked,ICLASS_LD" 001 0 000 sssss PP000--- 000ddddd")
|
||||
|
||||
|
||||
|
||||
DEF_ENC32(L2_loadw_aq, ICLASS_LD" 001 0 000 sssss PP001--- 000ddddd")
|
||||
DEF_ENC32(L4_loadd_aq, ICLASS_LD" 001 0 000 sssss PP011--- 000ddddd")
|
||||
|
||||
DEF_ENC32(R6_release_at_vi, ICLASS_ST" 000 01 11sssss PP0ttttt --0011dd")
|
||||
DEF_ENC32(R6_release_st_vi, ICLASS_ST" 000 01 11sssss PP0ttttt --1011dd")
|
||||
|
||||
DEF_ENC32(S2_storew_rl_at_vi, ICLASS_ST" 000 01 01sssss PP-ttttt --0010dd")
|
||||
DEF_ENC32(S2_storew_rl_st_vi, ICLASS_ST" 000 01 01sssss PP-ttttt --1010dd")
|
||||
|
||||
DEF_ENC32(L4_loadd_locked,ICLASS_LD" 001 0 000 sssss PP01---- -00ddddd")
|
||||
DEF_ENC32(S4_stored_rl_at_vi, ICLASS_ST" 000 01 11sssss PP0ttttt --0010dd")
|
||||
DEF_ENC32(S4_stored_rl_st_vi, ICLASS_ST" 000 01 11sssss PP0ttttt --1010dd")
|
||||
|
||||
DEF_ENC32(L4_loadd_locked,ICLASS_LD" 001 0 000 sssss PP010--- 000ddddd")
|
||||
DEF_EXT_SPACE(EXTRACTW, ICLASS_LD" 001 0 000 iiiii PP0iiiii -01iiiii")
|
||||
DEF_ENC32(Y2_dcfetchbo, ICLASS_LD" 010 0 000 sssss PP0--iii iiiiiiii")
|
||||
|
||||
@ -479,8 +488,8 @@ STD_PST_ENC(rinew, "1 101","10ttt")
|
||||
/* x bus/cache */
|
||||
/* x store/cache */
|
||||
DEF_ENC32(S2_allocframe, ICLASS_ST" 000 01 00xxxxx PP000iii iiiiiiii")
|
||||
DEF_ENC32(S2_storew_locked,ICLASS_ST" 000 01 01sssss PP-ttttt ------dd")
|
||||
DEF_ENC32(S4_stored_locked,ICLASS_ST" 000 01 11sssss PP0ttttt ------dd")
|
||||
DEF_ENC32(S2_storew_locked,ICLASS_ST" 000 01 01sssss PP-ttttt ----00dd")
|
||||
DEF_ENC32(S4_stored_locked,ICLASS_ST" 000 01 11sssss PP0ttttt ----00dd")
|
||||
DEF_ENC32(Y2_dczeroa, ICLASS_ST" 000 01 10sssss PP0----- --------")
|
||||
|
||||
|
||||
@ -515,6 +524,7 @@ DEF_FIELD32(ICLASS_J" 110- -------- PP-!---- --------",J_PT,"Predict-taken")
|
||||
|
||||
DEF_FIELDROW_DESC32(ICLASS_J" 0000 -------- PP------ --------","[#0] PC=(Rs), R31=return")
|
||||
DEF_ENC32(J2_callr, ICLASS_J" 0000 101sssss PP------ --------")
|
||||
DEF_ENC32(J2_callrh, ICLASS_J" 0000 110sssss PP------ --------")
|
||||
|
||||
DEF_FIELDROW_DESC32(ICLASS_J" 0001 -------- PP------ --------","[#1] if (Pu) PC=(Rs), R31=return")
|
||||
DEF_ENC32(J2_callrt, ICLASS_J" 0001 000sssss PP----uu --------")
|
||||
@ -522,6 +532,7 @@ DEF_ENC32(J2_callrf, ICLASS_J" 0001 001sssss PP----uu --------")
|
||||
|
||||
DEF_FIELDROW_DESC32(ICLASS_J" 0010 -------- PP------ --------","[#2] PC=(Rs); ")
|
||||
DEF_ENC32(J2_jumpr, ICLASS_J" 0010 100sssss PP------ --------")
|
||||
DEF_ENC32(J2_jumprh, ICLASS_J" 0010 110sssss PP------ --------")
|
||||
DEF_ENC32(J4_hintjumpr, ICLASS_J" 0010 101sssss PP------ --------")
|
||||
|
||||
DEF_FIELDROW_DESC32(ICLASS_J" 0011 -------- PP------ --------","[#3] if (Pu) PC=(Rs) ")
|
||||
|
@ -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
|
||||
@ -128,6 +128,24 @@ Q6INSN(S2_allocframe,"allocframe(Rx32,#u11:3):raw", ATTRIBS(A_REGWRSIZE_8B,A_MEM
|
||||
|
||||
#define A_RETURN A_RESTRICT_COF_MAX1,A_RESTRICT_SLOT0ONLY,A_RESTRICT_NOSLOT1_STORE,A_RET_TYPE,A_DEALLOCRET
|
||||
|
||||
/**** Load Acquire Store Release Instructions****/
|
||||
|
||||
|
||||
|
||||
Q6INSN(L2_loadw_aq,"Rd32=memw_aq(Rs32)",ATTRIBS(A_REGWRSIZE_4B,A_ACQUIRE,A_RESTRICT_SLOT0ONLY,A_MEMSIZE_4B,A_LOAD),"Load Acquire Word",
|
||||
{ fEA_REG(RsV); fLOAD(1,4,u,EA,RdV); })
|
||||
Q6INSN(L4_loadd_aq,"Rdd32=memd_aq(Rs32)",ATTRIBS(A_REGWRSIZE_8B,A_ACQUIRE,A_RESTRICT_SLOT0ONLY,A_MEMSIZE_8B,A_LOAD),"Load Acquire Double integer",
|
||||
{ fEA_REG(RsV); fLOAD(1,8,u,EA,RddV); })
|
||||
|
||||
Q6INSN(R6_release_at_vi,"release(Rs32):at",ATTRIBS(A_MEMSIZE_0B,A_RELEASE,A_STORE,A_VTCM_ALLBANK_ACCESS,A_RLS_INNER,A_RLS_ALL_THREAD,A_RESTRICT_NOPACKET,A_RESTRICT_SLOT0ONLY), "Release lock", {fEA_REG(RsV); fSTORE(1,0,EA,RsV); })
|
||||
Q6INSN(R6_release_st_vi,"release(Rs32):st",ATTRIBS(A_MEMSIZE_0B,A_RELEASE,A_STORE,A_VTCM_ALLBANK_ACCESS,A_RLS_INNER,A_RLS_SAME_THREAD,A_RESTRICT_NOPACKET,A_RESTRICT_SLOT0ONLY), "Release lock", {fEA_REG(RsV); fSTORE(1,0,EA,RsV); })
|
||||
|
||||
Q6INSN(S2_storew_rl_at_vi,"memw_rl(Rs32):at=Rt32",ATTRIBS(A_REGWRSIZE_4B,A_RELEASE,A_VTCM_ALLBANK_ACCESS,A_RLS_INNER,A_RLS_ALL_THREAD,A_RESTRICT_NOPACKET,A_MEMSIZE_4B,A_STORE,A_RESTRICT_SLOT0ONLY),"Store Release Word", { fEA_REG(RsV); fSTORE(1,4,EA,RtV); })
|
||||
Q6INSN(S4_stored_rl_at_vi,"memd_rl(Rs32):at=Rtt32",ATTRIBS(A_REGWRSIZE_8B,A_RELEASE,A_VTCM_ALLBANK_ACCESS,A_RLS_INNER,A_RLS_ALL_THREAD,A_RESTRICT_NOPACKET,A_MEMSIZE_8B,A_STORE,A_RESTRICT_SLOT0ONLY),"Store Release Double integer", { fEA_REG(RsV); fSTORE(1,8,EA,RttV); })
|
||||
|
||||
Q6INSN(S2_storew_rl_st_vi,"memw_rl(Rs32):st=Rt32",ATTRIBS(A_REGWRSIZE_4B,A_RELEASE,A_VTCM_ALLBANK_ACCESS,A_RLS_INNER,A_RLS_SAME_THREAD,A_RESTRICT_NOPACKET,A_MEMSIZE_4B,A_STORE,A_RESTRICT_SLOT0ONLY),"Store Release Word", { fEA_REG(RsV); fSTORE(1,4,EA,RtV); })
|
||||
Q6INSN(S4_stored_rl_st_vi,"memd_rl(Rs32):st=Rtt32",ATTRIBS(A_REGWRSIZE_8B,A_RELEASE,A_VTCM_ALLBANK_ACCESS,A_RLS_INNER,A_RLS_SAME_THREAD,A_RESTRICT_NOPACKET,A_MEMSIZE_8B,A_STORE,A_RESTRICT_SLOT0ONLY),"Store Release Double integer", { fEA_REG(RsV); fSTORE(1,8,EA,RttV); })
|
||||
|
||||
Q6INSN(L2_deallocframe,"Rdd32=deallocframe(Rs32):raw", ATTRIBS(A_REGWRSIZE_8B,A_MEMSIZE_8B,A_LOAD,A_DEALLOCFRAME), "Deallocate stack frame",
|
||||
{ fHIDE(size8u_t tmp;) fEA_REG(RsV);
|
||||
fLOAD(1,8,u,EA,tmp);
|
||||
|
@ -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
|
||||
@ -257,6 +257,11 @@ DEF_ENC(V6_vasruhubrndsat, ICLASS_CJ" 1 000 vvv vvttt PP 0 uuuuu 111 ddd
|
||||
DEF_ENC(V6_vasruwuhsat, ICLASS_CJ" 1 000 vvv vvttt PP 1 uuuuu 100 ddddd") //
|
||||
DEF_ENC(V6_vasruhubsat, ICLASS_CJ" 1 000 vvv vvttt PP 1 uuuuu 101 ddddd") //
|
||||
|
||||
DEF_ENC(V6_vasrvuhubrndsat,"00011101000vvvvvPP0uuuuu011ddddd")
|
||||
DEF_ENC(V6_vasrvuhubsat,"00011101000vvvvvPP0uuuuu010ddddd")
|
||||
DEF_ENC(V6_vasrvwuhrndsat,"00011101000vvvvvPP0uuuuu001ddddd")
|
||||
DEF_ENC(V6_vasrvwuhsat,"00011101000vvvvvPP0uuuuu000ddddd")
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Group #1, Uses Q6 Rt32
|
||||
@ -716,6 +721,7 @@ DEF_ENC(V6_vaddclbw, ICLASS_CJ" 1 111 000 vvvvv PP 1 uuuuu 001 ddddd") //
|
||||
|
||||
DEF_ENC(V6_vavguw, ICLASS_CJ" 1 111 000 vvvvv PP 1 uuuuu 010 ddddd") //
|
||||
DEF_ENC(V6_vavguwrnd, ICLASS_CJ" 1 111 000 vvvvv PP 1 uuuuu 011 ddddd") //
|
||||
DEF_ENC(V6_vassign_tmp,"00011110--0---01PP0uuuuu110ddddd")
|
||||
DEF_ENC(V6_vavgb, ICLASS_CJ" 1 111 000 vvvvv PP 1 uuuuu 100 ddddd") //
|
||||
DEF_ENC(V6_vavgbrnd, ICLASS_CJ" 1 111 000 vvvvv PP 1 uuuuu 101 ddddd") //
|
||||
DEF_ENC(V6_vnavgb, ICLASS_CJ" 1 111 000 vvvvv PP 1 uuuuu 110 ddddd") //
|
||||
@ -730,6 +736,8 @@ DEF_ENC(V6_vmaxb, ICLASS_CJ" 1 111 001 vvvvv PP 0 uuuuu 101 ddddd") //
|
||||
DEF_ENC(V6_vsatuwuh, ICLASS_CJ" 1 111 001 vvvvv PP 0 uuuuu 110 ddddd") //
|
||||
DEF_ENC(V6_vdealb4w, ICLASS_CJ" 1 111 001 vvvvv PP 0 uuuuu 111 ddddd") //
|
||||
|
||||
DEF_ENC(V6_v6mpyvubs10_vxx, ICLASS_CJ" 1 111 001 vvvvv PP 1 uuuuu 0ii xxxxx")
|
||||
DEF_ENC(V6_v6mpyhubs10_vxx, ICLASS_CJ" 1 111 001 vvvvv PP 1 uuuuu 1ii xxxxx")
|
||||
|
||||
DEF_ENC(V6_vmpyowh_rnd, ICLASS_CJ" 1 111 010 vvvvv PP 0 uuuuu 000 ddddd") //
|
||||
DEF_ENC(V6_vshuffeb, ICLASS_CJ" 1 111 010 vvvvv PP 0 uuuuu 001 ddddd") //
|
||||
@ -739,6 +747,11 @@ DEF_ENC(V6_vshufoh, ICLASS_CJ" 1 111 010 vvvvv PP 0 uuuuu 100 ddddd") //
|
||||
DEF_ENC(V6_vshufoeh, ICLASS_CJ" 1 111 010 vvvvv PP 0 uuuuu 101 ddddd") //
|
||||
DEF_ENC(V6_vshufoeb, ICLASS_CJ" 1 111 010 vvvvv PP 0 uuuuu 110 ddddd") //
|
||||
DEF_ENC(V6_vcombine, ICLASS_CJ" 1 111 010 vvvvv PP 0 uuuuu 111 ddddd") //
|
||||
DEF_ENC(V6_vcombine_tmp,"00011110101vvvvvPP0uuuuu111ddddd")
|
||||
|
||||
DEF_ENC(V6_v6mpyvubs10, ICLASS_CJ" 1 111 010 vvvvv PP 1 uuuuu 0ii ddddd")
|
||||
DEF_ENC(V6_v6mpyhubs10, ICLASS_CJ" 1 111 010 vvvvv PP 1 uuuuu 1ii ddddd")
|
||||
|
||||
|
||||
DEF_ENC(V6_vmpyieoh, ICLASS_CJ" 1 111 011 vvvvv PP 0 uuuuu 000 ddddd") //
|
||||
DEF_ENC(V6_vadduwsat, ICLASS_CJ" 1 111 011 vvvvv PP 0 uuuuu 001 ddddd") //
|
||||
@ -789,6 +802,7 @@ DEF_ENC(V6_vrounduhub, ICLASS_CJ" 1 111 111 vvvvv PP 0 uuuuu 011 ddddd") //
|
||||
DEF_ENC(V6_vrounduwuh, ICLASS_CJ" 1 111 111 vvvvv PP 0 uuuuu 100 ddddd") //
|
||||
DEF_ENC(V6_vmpyewuh, ICLASS_CJ" 1 111 111 vvvvv PP 0 uuuuu 101 ddddd")
|
||||
DEF_ENC(V6_vmpyowh, ICLASS_CJ" 1 111 111 vvvvv PP 0 uuuuu 111 ddddd")
|
||||
DEF_ENC(V6_vmpyuhvs,"00011111110vvvvvPP1uuuuu111ddddd")
|
||||
|
||||
|
||||
#endif /* NO MMVEC */
|
||||
|
@ -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
|
||||
@ -62,6 +62,9 @@ EXTINSN(V6_##TAG, SYNTAX, ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VS), \
|
||||
DESCR, DO_FOR_EACH_CODE(WIDTH, CODE))
|
||||
|
||||
|
||||
#define ITERATOR_INSN_SHIFT3_SLOT(WIDTH,TAG,SYNTAX,DESCR,CODE) \
|
||||
EXTINSN(V6_##TAG, SYNTAX, ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VS,A_CVI_VS_3SRC,A_NOTE_SHIFT_RESOURCE,A_NOTE_NOVP,A_NOTE_VA_UNARY), \
|
||||
DESCR, DO_FOR_EACH_CODE(WIDTH, CODE))
|
||||
|
||||
#define ITERATOR_INSN_SHIFT_SLOT_VV_LATE(WIDTH,TAG,SYNTAX,DESCR,CODE) \
|
||||
EXTINSN(V6_##TAG, SYNTAX, ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VS), \
|
||||
@ -116,6 +119,10 @@ ITERATOR_INSN_MPY_SLOT_LATE(WIDTH,TAG, SYNTAX2,DESCR,CODE)
|
||||
EXTINSN(V6_##TAG, SYNTAX, ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VX_DV), \
|
||||
DESCR, DO_FOR_EACH_CODE(WIDTH, CODE))
|
||||
|
||||
#define ITERATOR_INSN_MPY_SLOT_DOUBLE_VEC_VX_FWD(WIDTH,TAG,SYNTAX,DESCR,CODE) \
|
||||
EXTINSN(V6_##TAG, SYNTAX, ATTRIBS(A_EXTENSION,A_CVI,A_CVI_VX_DV), \
|
||||
DESCR, DO_FOR_EACH_CODE(WIDTH, CODE))
|
||||
|
||||
#define ITERATOR_INSN2_MPY_SLOT_DOUBLE_VEC(WIDTH,TAG,SYNTAX,SYNTAX2,DESCR,CODE) \
|
||||
ITERATOR_INSN_MPY_SLOT_DOUBLE_VEC(WIDTH,TAG,SYNTAX2,DESCR,CODE)
|
||||
|
||||
@ -976,6 +983,22 @@ NARROWING_SHIFT(16,vasrhubrndsat,fSETBYTE,ub,h,:rnd:sat,fVSATUB,fVROUND,0x7)
|
||||
NARROWING_SHIFT(16,vasrhbsat,fSETBYTE,b,h,:sat,fVSATB,fVNOROUND,0x7)
|
||||
NARROWING_SHIFT(16,vasrhbrndsat,fSETBYTE,b,h,:rnd:sat,fVSATB,fVROUND,0x7)
|
||||
|
||||
#define NARROWING_VECTOR_SHIFT(ITERSIZE,TAG,DSTM,DSTTYPE,SRCTYPE,SRCTYPE2,SYNOPTS,SATFUNC,RNDFUNC,SHAMTMASK) \
|
||||
ITERATOR_INSN_SHIFT3_SLOT(ITERSIZE,TAG, \
|
||||
"Vd32." #DSTTYPE "=vasr(Vuu32." #SRCTYPE ",Vv32." #SRCTYPE2 ")" #SYNOPTS, \
|
||||
"Vector shift by vector right and shuffle", \
|
||||
fHIDE(int )shamt = VvV.SRCTYPE2[2*i+0] & SHAMTMASK; \
|
||||
DSTM(0,VdV.SRCTYPE[i],SATFUNC(RNDFUNC(VuuV.v[0].SRCTYPE[i],shamt) >> shamt)); \
|
||||
shamt = VvV.SRCTYPE2[2*i+1] & SHAMTMASK; \
|
||||
DSTM(1,VdV.SRCTYPE[i],SATFUNC(RNDFUNC(VuuV.v[1].SRCTYPE[i],shamt) >> shamt)))
|
||||
|
||||
/* WORD TO HALF*/
|
||||
NARROWING_VECTOR_SHIFT(32,vasrvwuhsat,fSETHALF,uh,w,uh,:sat,fVSATUH,fVNOROUND,0xF)
|
||||
NARROWING_VECTOR_SHIFT(32,vasrvwuhrndsat,fSETHALF,uh,w,uh,:rnd:sat,fVSATUH,fVROUND,0xF)
|
||||
/* HALF TO BYTE*/
|
||||
NARROWING_VECTOR_SHIFT(16,vasrvuhubsat,fSETBYTE,ub,uh,ub,:sat,fVSATUB,fVNOROUND,0x7)
|
||||
NARROWING_VECTOR_SHIFT(16,vasrvuhubrndsat,fSETBYTE,ub,uh,ub,:rnd:sat,fVSATUB,fVROUND,0x7)
|
||||
|
||||
NARROWING_SHIFT_NOV1(16,vasruhubsat,fSETBYTE,ub,uh,:sat,fVSATUB,fVNOROUND,0x7)
|
||||
NARROWING_SHIFT_NOV1(16,vasruhubrndsat,fSETBYTE,ub,uh,:rnd:sat,fVSATUB,fVROUND,0x7)
|
||||
|
||||
@ -1360,6 +1383,9 @@ ITERATOR_INSN2_MPY_SLOT_DOUBLE_VEC(16,vmpyhvsrs,"Vd32=vmpyh(Vu32,Vv32):<<1:rnd:s
|
||||
|
||||
|
||||
|
||||
ITERATOR_INSN_MPY_SLOT(16,vmpyuhvs, "Vd32.uh=vmpy(Vu32.uh,Vv32.uh):>>16",
|
||||
"Vector by Vector Unsigned Halfword Multiply with 16 bit rightshift",
|
||||
VdV.uh[i] = fGETUHALF(1,fMPY16UU(VuV.uh[i],VvV.uh[i])))
|
||||
|
||||
|
||||
ITERATOR_INSN2_MPY_SLOT_DOUBLE_VEC(32,vmpyhus, "Vdd32=vmpyhus(Vu32,Vv32)","Vdd32.w=vmpy(Vu32.h,Vv32.uh)",
|
||||
@ -2038,6 +2064,24 @@ ITERATOR_INSN_ANY_SLOT_DOUBLE_VEC(8,vcombine,"Vdd32=vcombine(Vu32,Vv32)",
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EXTINSN(V6_vcombine_tmp, "Vdd32.tmp=vcombine(Vu32,Vv32)", ATTRIBS(A_EXTENSION,A_CVI,A_CVI_REMAP,A_CVI_TMP,A_NO_INTRINSIC),
|
||||
"Vector assign tmp, Any two to Vector Pair ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
fVFOREACH(8, i) {
|
||||
VddV.v[0].ub[i] = VvV.ub[i];
|
||||
VddV.v[1].ub[i] = VuV.ub[i];
|
||||
}
|
||||
})
|
||||
|
||||
EXTINSN(V6_vassign_tmp, "Vd32.tmp=Vu32", ATTRIBS(A_EXTENSION,A_CVI,A_CVI_REMAP,A_CVI_TMP,A_NO_INTRINSIC),
|
||||
"Vector assign tmp, Any two to Vector Pair ",
|
||||
{
|
||||
fHIDE(int i;)
|
||||
fVFOREACH(32, i) {
|
||||
VdV.w[i]=VuV.w[i];
|
||||
}
|
||||
})
|
||||
|
||||
/*********************************************************
|
||||
* GENERAL PERMUTE NETWORKS
|
||||
@ -2507,6 +2551,281 @@ EXTINSN(V6_vscattermhw , "vscatter(Rt32,Mu2,Vvv32.w).h=Vw32", ATTRIBS(A_EXTENSIO
|
||||
})
|
||||
|
||||
|
||||
ITERATOR_INSN_MPY_SLOT_DOUBLE_VEC_VX_FWD(32, v6mpyvubs10_vxx, "Vxx32.w+=v6mpy(Vuu32.ub,Vvv32.b,#u2):v", "",
|
||||
fHIDE(size2s_t c00;)
|
||||
fGET10BIT(c00, VvvV.v[0].uw[i], 0)
|
||||
fHIDE(size2s_t c01;)
|
||||
fGET10BIT(c01, VvvV.v[0].uw[i], 1)
|
||||
fHIDE(size2s_t c02;)
|
||||
fGET10BIT(c02, VvvV.v[0].uw[i], 2)
|
||||
|
||||
fHIDE(size2s_t c10;)
|
||||
fGET10BIT(c10, VvvV.v[1].uw[i], 0)
|
||||
fHIDE(size2s_t c11;)
|
||||
fGET10BIT(c11, VvvV.v[1].uw[i], 1)
|
||||
fHIDE(size2s_t c12;)
|
||||
fGET10BIT(c12, VvvV.v[1].uw[i], 2)
|
||||
|
||||
if (uiV == 0) {
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c10);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c11);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c00);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c01);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c02);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c10);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c11);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
} else if (uiV == 1) {
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c00);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c01);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c02);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c10);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c11);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c00);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c01);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c02);
|
||||
|
||||
} else if (uiV == 2) {
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c10);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c11);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c00);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c01);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c02);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c10);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c11);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
} else if (uiV == 3) {
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c00);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c01);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c02);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c10);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c11);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c00);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c01);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c02);
|
||||
}
|
||||
)
|
||||
ITERATOR_INSN_MPY_SLOT_DOUBLE_VEC_VX_FWD(32, v6mpyhubs10_vxx, "Vxx32.w+=v6mpy(Vuu32.ub,Vvv32.b,#u2):h", "",
|
||||
fHIDE(size2s_t c00;)
|
||||
fGET10BIT(c00, VvvV.v[0].uw[i], 0)
|
||||
fHIDE(size2s_t c01;)
|
||||
fGET10BIT(c01, VvvV.v[0].uw[i], 1)
|
||||
fHIDE(size2s_t c02;)
|
||||
fGET10BIT(c02, VvvV.v[0].uw[i], 2)
|
||||
fHIDE(size2s_t c10;)
|
||||
fGET10BIT(c10, VvvV.v[1].uw[i], 0)
|
||||
fHIDE(size2s_t c11;)
|
||||
fGET10BIT(c11, VvvV.v[1].uw[i], 1)
|
||||
fHIDE(size2s_t c12;)
|
||||
fGET10BIT(c12, VvvV.v[1].uw[i], 2)
|
||||
|
||||
if (uiV == 0) {
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c10);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c11);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c00);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c01);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c02);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c10);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c11);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
} else if (uiV == 1) {
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c00);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c01);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c02);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c10);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c11);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c00);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c01);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c02);
|
||||
|
||||
} else if (uiV == 2) {
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c10);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c11);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c00);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c01);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c02);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c10);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c11);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
} else if (uiV == 3) {
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c00);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c01);
|
||||
VxxV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c02);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c10);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c11);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c00);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c01);
|
||||
VxxV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c02);
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
ITERATOR_INSN_MPY_SLOT_DOUBLE_VEC(32, v6mpyvubs10, "Vdd32.w=v6mpy(Vuu32.ub,Vvv32.b,#u2):v", "",
|
||||
fHIDE(short c00;)
|
||||
fGET10BIT(c00, VvvV.v[0].uw[i], 0)
|
||||
fHIDE(short c01;)
|
||||
fGET10BIT(c01, VvvV.v[0].uw[i], 1)
|
||||
fHIDE(short c02;)
|
||||
fGET10BIT(c02, VvvV.v[0].uw[i], 2)
|
||||
fHIDE(short c10;)
|
||||
fGET10BIT(c10, VvvV.v[1].uw[i], 0)
|
||||
fHIDE(short c11;)
|
||||
fGET10BIT(c11, VvvV.v[1].uw[i], 1)
|
||||
fHIDE(short c12;)
|
||||
fGET10BIT(c12, VvvV.v[1].uw[i], 2)
|
||||
|
||||
|
||||
|
||||
if (uiV == 0) {
|
||||
VddV.v[1].w[i] = fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c10);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c11);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c00);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c01);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c02);
|
||||
|
||||
VddV.v[0].w[i] = fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c10);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c11);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
} else if (uiV == 1) {
|
||||
VddV.v[1].w[i] = fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c00);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c01);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c02);
|
||||
|
||||
VddV.v[0].w[i] = fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c10);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c11);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c00);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c01);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c02);
|
||||
|
||||
} else if (uiV == 2) {
|
||||
VddV.v[1].w[i] = fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c10);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c11);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c00);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c01);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c02);
|
||||
|
||||
VddV.v[0].w[i] = fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c10);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c11);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
} else if (uiV == 3) {
|
||||
VddV.v[1].w[i] = fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c00);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c01);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c02);
|
||||
|
||||
VddV.v[0].w[i] = fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c10);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c11);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c12);
|
||||
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c00);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c01);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c02);
|
||||
}
|
||||
)
|
||||
|
||||
ITERATOR_INSN_MPY_SLOT_DOUBLE_VEC(32, v6mpyhubs10, "Vdd32.w=v6mpy(Vuu32.ub,Vvv32.b,#u2):h", "",
|
||||
fHIDE(short c00;)
|
||||
fGET10BIT(c00, VvvV.v[0].uw[i], 0)
|
||||
fHIDE(short c01;)
|
||||
fGET10BIT(c01, VvvV.v[0].uw[i], 1)
|
||||
fHIDE(short c02;)
|
||||
fGET10BIT(c02, VvvV.v[0].uw[i], 2)
|
||||
fHIDE(short c10;)
|
||||
fGET10BIT(c10, VvvV.v[1].uw[i], 0)
|
||||
fHIDE(short c11;)
|
||||
fGET10BIT(c11, VvvV.v[1].uw[i], 1)
|
||||
fHIDE(short c12;)
|
||||
fGET10BIT(c12, VvvV.v[1].uw[i], 2)
|
||||
|
||||
if (uiV == 0) {
|
||||
VddV.v[1].w[i] = fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c10);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c11);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c00);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c01);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c02);
|
||||
|
||||
VddV.v[0].w[i] = fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c10);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c11);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
} else if (uiV == 1) {
|
||||
VddV.v[1].w[i] = fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c00);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c01);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c02);
|
||||
|
||||
VddV.v[0].w[i] = fMPY16US(fGETUBYTE(3,VuuV.v[1].uw[i]), c10);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c11);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[1].uw[i]), c00);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c01);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c02);
|
||||
|
||||
} else if (uiV == 2) {
|
||||
VddV.v[1].w[i] = fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c10);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c11);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c00);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c01);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c02);
|
||||
|
||||
VddV.v[0].w[i] = fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c10);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c11);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
} else if (uiV == 3) {
|
||||
VddV.v[1].w[i] = fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c00);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c01);
|
||||
VddV.v[1].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c02);
|
||||
|
||||
VddV.v[0].w[i] = fMPY16US(fGETUBYTE(1,VuuV.v[1].uw[i]), c10);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(3,VuuV.v[0].uw[i]), c11);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(1,VuuV.v[0].uw[i]), c12);
|
||||
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[1].uw[i]), c00);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(2,VuuV.v[0].uw[i]), c01);
|
||||
VddV.v[0].w[i] += fMPY16US(fGETUBYTE(0,VuuV.v[0].uw[i]), c02);
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
EXTINSN(V6_vscattermhwq, "if (Qs4) vscatter(Rt32,Mu2,Vvv32.w).h=Vw32", ATTRIBS(A_EXTENSION,A_CVI,A_CVI_SCATTER,A_CVI_VA_DV,A_CVI_VM,A_MEMLIKE), "Scatter halfwords conditional",
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -44,8 +44,17 @@
|
||||
reg_field_info[FIELD].offset)
|
||||
|
||||
#define SET_USR_FIELD(FIELD, VAL) \
|
||||
fINSERT_BITS(env->new_value[HEX_REG_USR], reg_field_info[FIELD].width, \
|
||||
reg_field_info[FIELD].offset, (VAL))
|
||||
do { \
|
||||
if (pkt_need_commit) { \
|
||||
fINSERT_BITS(env->new_value_usr, \
|
||||
reg_field_info[FIELD].width, \
|
||||
reg_field_info[FIELD].offset, (VAL)); \
|
||||
} else { \
|
||||
fINSERT_BITS(env->gpr[HEX_REG_USR], \
|
||||
reg_field_info[FIELD].width, \
|
||||
reg_field_info[FIELD].offset, (VAL)); \
|
||||
} \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
@ -164,14 +173,14 @@
|
||||
#define MEM_STORE8(VA, DATA, SLOT) \
|
||||
MEM_STORE8_FUNC(DATA)(cpu_env, VA, DATA, SLOT)
|
||||
#else
|
||||
#define MEM_LOAD1s(VA) ((int8_t)mem_load1(env, slot, VA))
|
||||
#define MEM_LOAD1u(VA) ((uint8_t)mem_load1(env, slot, VA))
|
||||
#define MEM_LOAD2s(VA) ((int16_t)mem_load2(env, slot, VA))
|
||||
#define MEM_LOAD2u(VA) ((uint16_t)mem_load2(env, slot, VA))
|
||||
#define MEM_LOAD4s(VA) ((int32_t)mem_load4(env, slot, VA))
|
||||
#define MEM_LOAD4u(VA) ((uint32_t)mem_load4(env, slot, VA))
|
||||
#define MEM_LOAD8s(VA) ((int64_t)mem_load8(env, slot, VA))
|
||||
#define MEM_LOAD8u(VA) ((uint64_t)mem_load8(env, slot, VA))
|
||||
#define MEM_LOAD1s(VA) ((int8_t)mem_load1(env, pkt_has_store_s1, slot, VA))
|
||||
#define MEM_LOAD1u(VA) ((uint8_t)mem_load1(env, pkt_has_store_s1, slot, VA))
|
||||
#define MEM_LOAD2s(VA) ((int16_t)mem_load2(env, pkt_has_store_s1, slot, VA))
|
||||
#define MEM_LOAD2u(VA) ((uint16_t)mem_load2(env, pkt_has_store_s1, slot, VA))
|
||||
#define MEM_LOAD4s(VA) ((int32_t)mem_load4(env, pkt_has_store_s1, slot, VA))
|
||||
#define MEM_LOAD4u(VA) ((uint32_t)mem_load4(env, pkt_has_store_s1, slot, VA))
|
||||
#define MEM_LOAD8s(VA) ((int64_t)mem_load8(env, pkt_has_store_s1, slot, VA))
|
||||
#define MEM_LOAD8u(VA) ((uint64_t)mem_load8(env, pkt_has_store_s1, slot, VA))
|
||||
|
||||
#define MEM_STORE1(VA, DATA, SLOT) log_store32(env, VA, DATA, 1, SLOT)
|
||||
#define MEM_STORE2(VA, DATA, SLOT) log_store32(env, VA, DATA, 2, SLOT)
|
||||
@ -227,12 +236,8 @@ static inline void gen_cancel(uint32_t slot)
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
#define fLSBNEW(PVAL) tcg_gen_andi_tl(LSB, (PVAL), 1)
|
||||
#define fLSBNEW0 tcg_gen_andi_tl(LSB, hex_new_pred_value[0], 1)
|
||||
#define fLSBNEW1 tcg_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
|
||||
@ -347,10 +352,6 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
|
||||
|
||||
#define fREAD_LR() (env->gpr[HEX_REG_LR])
|
||||
|
||||
#define fWRITE_LR(A) log_reg_write(env, HEX_REG_LR, A)
|
||||
#define fWRITE_FP(A) log_reg_write(env, HEX_REG_FP, A)
|
||||
#define fWRITE_SP(A) log_reg_write(env, HEX_REG_SP, A)
|
||||
|
||||
#define fREAD_SP() (env->gpr[HEX_REG_SP])
|
||||
#define fREAD_LC0 (env->gpr[HEX_REG_LC0])
|
||||
#define fREAD_LC1 (env->gpr[HEX_REG_LC1])
|
||||
@ -375,24 +376,10 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
|
||||
#define fBRANCH(LOC, TYPE) fWRITE_NPC(LOC)
|
||||
#define fJUMPR(REGNO, TARGET, TYPE) fBRANCH(TARGET, COF_TYPE_JUMPR)
|
||||
#define fHINTJR(TARGET) { /* Not modelled in qemu */}
|
||||
#define fWRITE_LOOP_REGS0(START, COUNT) \
|
||||
do { \
|
||||
log_reg_write(env, HEX_REG_LC0, COUNT); \
|
||||
log_reg_write(env, HEX_REG_SA0, START); \
|
||||
} while (0)
|
||||
#define fWRITE_LOOP_REGS1(START, COUNT) \
|
||||
do { \
|
||||
log_reg_write(env, HEX_REG_LC1, COUNT); \
|
||||
log_reg_write(env, HEX_REG_SA1, START);\
|
||||
} while (0)
|
||||
|
||||
#define fSET_OVERFLOW() SET_USR_FIELD(USR_OVF, 1)
|
||||
#define fSET_LPCFG(VAL) SET_USR_FIELD(USR_LPCFG, (VAL))
|
||||
#define fGET_LPCFG (GET_USR_FIELD(USR_LPCFG))
|
||||
#define fWRITE_P0(VAL) log_pred_write(env, 0, VAL)
|
||||
#define fWRITE_P1(VAL) log_pred_write(env, 1, VAL)
|
||||
#define fWRITE_P2(VAL) log_pred_write(env, 2, VAL)
|
||||
#define fWRITE_P3(VAL) log_pred_write(env, 3, VAL)
|
||||
#define fPART1(WORK) if (part1) { WORK; return; }
|
||||
#define fCAST4u(A) ((uint32_t)(A))
|
||||
#define fCAST4s(A) ((int32_t)(A))
|
||||
@ -661,7 +648,11 @@ static inline TCGv gen_read_ireg(TCGv result, TCGv val, int shift)
|
||||
reg_field_info[FIELD].offset)
|
||||
|
||||
#ifdef QEMU_GENERATE
|
||||
#define fDCZEROA(REG) tcg_gen_mov_tl(hex_dczero_addr, (REG))
|
||||
#define fDCZEROA(REG) \
|
||||
do { \
|
||||
ctx->dczero_addr = tcg_temp_new(); \
|
||||
tcg_gen_mov_tl(ctx->dczero_addr, (REG)); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#define fBRANCH_SPECULATE_STALL(DOTNEWVAL, JUMP_COND, SPEC_DIR, HINTBITNUM, \
|
||||
|
@ -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
|
||||
@ -346,4 +346,11 @@
|
||||
#define fUARCH_NOTE_PUMP_2X()
|
||||
|
||||
#define IV1DEAD()
|
||||
|
||||
#define fGET10BIT(COE, VAL, POS) \
|
||||
do { \
|
||||
COE = (sextract32(VAL, 24 + 2 * POS, 2) << 8) | \
|
||||
extract32(VAL, POS * 8, 8); \
|
||||
} while (0);
|
||||
|
||||
#endif
|
||||
|
@ -52,38 +52,6 @@ G_NORETURN void HELPER(raise_exception)(CPUHexagonState *env, uint32_t excp)
|
||||
do_raise_exception_err(env, excp, 0);
|
||||
}
|
||||
|
||||
void log_reg_write(CPUHexagonState *env, int rnum,
|
||||
target_ulong val)
|
||||
{
|
||||
HEX_DEBUG_LOG("log_reg_write[%d] = " TARGET_FMT_ld " (0x" TARGET_FMT_lx ")",
|
||||
rnum, val, val);
|
||||
if (val == env->gpr[rnum]) {
|
||||
HEX_DEBUG_LOG(" NO CHANGE");
|
||||
}
|
||||
HEX_DEBUG_LOG("\n");
|
||||
|
||||
env->new_value[rnum] = val;
|
||||
if (HEX_DEBUG) {
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
env->reg_written[rnum] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void log_pred_write(CPUHexagonState *env, int pnum, target_ulong val)
|
||||
{
|
||||
HEX_DEBUG_LOG("log_pred_write[%d] = " TARGET_FMT_ld
|
||||
" (0x" TARGET_FMT_lx ")\n",
|
||||
pnum, val, val);
|
||||
|
||||
/* Multiple writes to the same preg are and'ed together */
|
||||
if (env->pred_written & (1 << pnum)) {
|
||||
env->new_pred_value[pnum] &= val & 0xff;
|
||||
} else {
|
||||
env->new_pred_value[pnum] = val & 0xff;
|
||||
env->pred_written |= 1 << pnum;
|
||||
}
|
||||
}
|
||||
|
||||
void log_store32(CPUHexagonState *env, target_ulong addr,
|
||||
target_ulong val, int width, int slot)
|
||||
{
|
||||
@ -235,14 +203,14 @@ static void print_store(CPUHexagonState *env, int slot)
|
||||
}
|
||||
|
||||
/* This function is a handy place to set a breakpoint */
|
||||
void HELPER(debug_commit_end)(CPUHexagonState *env, int has_st0, int has_st1)
|
||||
void HELPER(debug_commit_end)(CPUHexagonState *env, uint32_t this_PC,
|
||||
int pred_written, int has_st0, int has_st1)
|
||||
{
|
||||
bool reg_printed = false;
|
||||
bool pred_printed = false;
|
||||
int i;
|
||||
|
||||
HEX_DEBUG_LOG("Packet committed: pc = 0x" TARGET_FMT_lx "\n",
|
||||
env->this_PC);
|
||||
HEX_DEBUG_LOG("Packet committed: pc = 0x" TARGET_FMT_lx "\n", this_PC);
|
||||
HEX_DEBUG_LOG("slot_cancelled = %d\n", env->slot_cancelled);
|
||||
|
||||
for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
|
||||
@ -252,18 +220,18 @@ void HELPER(debug_commit_end)(CPUHexagonState *env, int has_st0, int has_st1)
|
||||
reg_printed = true;
|
||||
}
|
||||
HEX_DEBUG_LOG("\tr%d = " TARGET_FMT_ld " (0x" TARGET_FMT_lx ")\n",
|
||||
i, env->new_value[i], env->new_value[i]);
|
||||
i, env->gpr[i], env->gpr[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_PREGS; i++) {
|
||||
if (env->pred_written & (1 << i)) {
|
||||
if (pred_written & (1 << i)) {
|
||||
if (!pred_printed) {
|
||||
HEX_DEBUG_LOG("Predicates written\n");
|
||||
pred_printed = true;
|
||||
}
|
||||
HEX_DEBUG_LOG("\tp%d = 0x" TARGET_FMT_lx "\n",
|
||||
i, env->new_pred_value[i]);
|
||||
i, env->pred[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,7 +352,8 @@ uint64_t HELPER(sfinvsqrta)(CPUHexagonState *env, float32 RsV)
|
||||
}
|
||||
|
||||
int64_t HELPER(vacsh_val)(CPUHexagonState *env,
|
||||
int64_t RxxV, int64_t RssV, int64_t RttV)
|
||||
int64_t RxxV, int64_t RssV, int64_t RttV,
|
||||
uint32_t pkt_need_commit)
|
||||
{
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int xv = sextract64(RxxV, i * 16, 16);
|
||||
@ -416,6 +385,87 @@ int32_t HELPER(vacsh_pred)(CPUHexagonState *env,
|
||||
return PeV;
|
||||
}
|
||||
|
||||
int64_t HELPER(cabacdecbin_val)(int64_t RssV, int64_t RttV)
|
||||
{
|
||||
int64_t RddV = 0;
|
||||
size4u_t state;
|
||||
size4u_t valMPS;
|
||||
size4u_t bitpos;
|
||||
size4u_t range;
|
||||
size4u_t offset;
|
||||
size4u_t rLPS;
|
||||
size4u_t rMPS;
|
||||
|
||||
state = fEXTRACTU_RANGE(fGETWORD(1, RttV), 5, 0);
|
||||
valMPS = fEXTRACTU_RANGE(fGETWORD(1, RttV), 8, 8);
|
||||
bitpos = fEXTRACTU_RANGE(fGETWORD(0, RttV), 4, 0);
|
||||
range = fGETWORD(0, RssV);
|
||||
offset = fGETWORD(1, RssV);
|
||||
|
||||
/* calculate rLPS */
|
||||
range <<= bitpos;
|
||||
offset <<= bitpos;
|
||||
rLPS = rLPS_table_64x4[state][(range >> 29) & 3];
|
||||
rLPS = rLPS << 23; /* left aligned */
|
||||
|
||||
/* calculate rMPS */
|
||||
rMPS = (range & 0xff800000) - rLPS;
|
||||
|
||||
/* most probable region */
|
||||
if (offset < rMPS) {
|
||||
RddV = AC_next_state_MPS_64[state];
|
||||
fINSERT_RANGE(RddV, 8, 8, valMPS);
|
||||
fINSERT_RANGE(RddV, 31, 23, (rMPS >> 23));
|
||||
fSETWORD(1, RddV, offset);
|
||||
}
|
||||
/* least probable region */
|
||||
else {
|
||||
RddV = AC_next_state_LPS_64[state];
|
||||
fINSERT_RANGE(RddV, 8, 8, ((!state) ? (1 - valMPS) : (valMPS)));
|
||||
fINSERT_RANGE(RddV, 31, 23, (rLPS >> 23));
|
||||
fSETWORD(1, RddV, (offset - rMPS));
|
||||
}
|
||||
return RddV;
|
||||
}
|
||||
|
||||
int32_t HELPER(cabacdecbin_pred)(int64_t RssV, int64_t RttV)
|
||||
{
|
||||
int32_t p0 = 0;
|
||||
size4u_t state;
|
||||
size4u_t valMPS;
|
||||
size4u_t bitpos;
|
||||
size4u_t range;
|
||||
size4u_t offset;
|
||||
size4u_t rLPS;
|
||||
size4u_t rMPS;
|
||||
|
||||
state = fEXTRACTU_RANGE(fGETWORD(1, RttV), 5, 0);
|
||||
valMPS = fEXTRACTU_RANGE(fGETWORD(1, RttV), 8, 8);
|
||||
bitpos = fEXTRACTU_RANGE(fGETWORD(0, RttV), 4, 0);
|
||||
range = fGETWORD(0, RssV);
|
||||
offset = fGETWORD(1, RssV);
|
||||
|
||||
/* calculate rLPS */
|
||||
range <<= bitpos;
|
||||
offset <<= bitpos;
|
||||
rLPS = rLPS_table_64x4[state][(range >> 29) & 3];
|
||||
rLPS = rLPS << 23; /* left aligned */
|
||||
|
||||
/* calculate rMPS */
|
||||
rMPS = (range & 0xff800000) - rLPS;
|
||||
|
||||
/* most probable region */
|
||||
if (offset < rMPS) {
|
||||
p0 = valMPS;
|
||||
|
||||
}
|
||||
/* least probable region */
|
||||
else {
|
||||
p0 = valMPS ^ 1;
|
||||
}
|
||||
return p0;
|
||||
}
|
||||
|
||||
static void probe_store(CPUHexagonState *env, int slot, int mmu_idx,
|
||||
bool is_predicated)
|
||||
{
|
||||
@ -516,41 +566,45 @@ void HELPER(probe_pkt_scalar_hvx_stores)(CPUHexagonState *env, int mask)
|
||||
* If the load is in slot 0 and there is a store in slot1 (that
|
||||
* wasn't cancelled), we have to do the store first.
|
||||
*/
|
||||
static void check_noshuf(CPUHexagonState *env, uint32_t slot,
|
||||
target_ulong vaddr, int size)
|
||||
static void check_noshuf(CPUHexagonState *env, bool pkt_has_store_s1,
|
||||
uint32_t slot, target_ulong vaddr, int size)
|
||||
{
|
||||
if (slot == 0 && env->pkt_has_store_s1 &&
|
||||
if (slot == 0 && pkt_has_store_s1 &&
|
||||
((env->slot_cancelled & (1 << 1)) == 0)) {
|
||||
HELPER(probe_noshuf_load)(env, vaddr, size, MMU_USER_IDX);
|
||||
HELPER(commit_store)(env, 1);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t mem_load1(CPUHexagonState *env, uint32_t slot, target_ulong vaddr)
|
||||
uint8_t mem_load1(CPUHexagonState *env, bool pkt_has_store_s1,
|
||||
uint32_t slot, target_ulong vaddr)
|
||||
{
|
||||
uintptr_t ra = GETPC();
|
||||
check_noshuf(env, slot, vaddr, 1);
|
||||
check_noshuf(env, pkt_has_store_s1, slot, vaddr, 1);
|
||||
return cpu_ldub_data_ra(env, vaddr, ra);
|
||||
}
|
||||
|
||||
uint16_t mem_load2(CPUHexagonState *env, uint32_t slot, target_ulong vaddr)
|
||||
uint16_t mem_load2(CPUHexagonState *env, bool pkt_has_store_s1,
|
||||
uint32_t slot, target_ulong vaddr)
|
||||
{
|
||||
uintptr_t ra = GETPC();
|
||||
check_noshuf(env, slot, vaddr, 2);
|
||||
check_noshuf(env, pkt_has_store_s1, slot, vaddr, 2);
|
||||
return cpu_lduw_data_ra(env, vaddr, ra);
|
||||
}
|
||||
|
||||
uint32_t mem_load4(CPUHexagonState *env, uint32_t slot, target_ulong vaddr)
|
||||
uint32_t mem_load4(CPUHexagonState *env, bool pkt_has_store_s1,
|
||||
uint32_t slot, target_ulong vaddr)
|
||||
{
|
||||
uintptr_t ra = GETPC();
|
||||
check_noshuf(env, slot, vaddr, 4);
|
||||
check_noshuf(env, pkt_has_store_s1, slot, vaddr, 4);
|
||||
return cpu_ldl_data_ra(env, vaddr, ra);
|
||||
}
|
||||
|
||||
uint64_t mem_load8(CPUHexagonState *env, uint32_t slot, target_ulong vaddr)
|
||||
uint64_t mem_load8(CPUHexagonState *env, bool pkt_has_store_s1,
|
||||
uint32_t slot, target_ulong vaddr)
|
||||
{
|
||||
uintptr_t ra = GETPC();
|
||||
check_noshuf(env, slot, vaddr, 8);
|
||||
check_noshuf(env, pkt_has_store_s1, slot, vaddr, 8);
|
||||
return cpu_ldq_data_ra(env, vaddr, ra);
|
||||
}
|
||||
|
||||
|
@ -19,15 +19,15 @@
|
||||
#define HEXAGON_OP_HELPER_H
|
||||
|
||||
/* Misc functions */
|
||||
void write_new_pc(CPUHexagonState *env, bool pkt_has_multi_cof, target_ulong addr);
|
||||
uint8_t mem_load1(CPUHexagonState *env, bool pkt_has_store_s1,
|
||||
uint32_t slot, target_ulong vaddr);
|
||||
uint16_t mem_load2(CPUHexagonState *env, bool pkt_has_store_s1,
|
||||
uint32_t slot, target_ulong vaddr);
|
||||
uint32_t mem_load4(CPUHexagonState *env, bool pkt_has_store_s1,
|
||||
uint32_t slot, target_ulong vaddr);
|
||||
uint64_t mem_load8(CPUHexagonState *env, bool pkt_has_store_s1,
|
||||
uint32_t slot, target_ulong vaddr);
|
||||
|
||||
uint8_t mem_load1(CPUHexagonState *env, uint32_t slot, target_ulong vaddr);
|
||||
uint16_t mem_load2(CPUHexagonState *env, uint32_t slot, target_ulong vaddr);
|
||||
uint32_t mem_load4(CPUHexagonState *env, uint32_t slot, target_ulong vaddr);
|
||||
uint64_t mem_load8(CPUHexagonState *env, uint32_t slot, target_ulong vaddr);
|
||||
|
||||
void log_reg_write(CPUHexagonState *env, int rnum,
|
||||
target_ulong val);
|
||||
void log_store64(CPUHexagonState *env, target_ulong addr,
|
||||
int64_t val, int width, int slot);
|
||||
void log_store32(CPUHexagonState *env, target_ulong addr,
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "insn.h"
|
||||
#include "decode.h"
|
||||
#include "translate.h"
|
||||
#include "genptr.h"
|
||||
#include "printinsn.h"
|
||||
|
||||
#include "analyze_funcs_generated.c.inc"
|
||||
@ -40,19 +41,13 @@ static const AnalyzeInsn opcode_analyze[XX_LAST_OPCODE] = {
|
||||
|
||||
TCGv hex_gpr[TOTAL_PER_THREAD_REGS];
|
||||
TCGv hex_pred[NUM_PREGS];
|
||||
TCGv hex_this_PC;
|
||||
TCGv hex_slot_cancelled;
|
||||
TCGv hex_branch_taken;
|
||||
TCGv hex_new_value[TOTAL_PER_THREAD_REGS];
|
||||
TCGv hex_new_value_usr;
|
||||
TCGv hex_reg_written[TOTAL_PER_THREAD_REGS];
|
||||
TCGv hex_new_pred_value[NUM_PREGS];
|
||||
TCGv hex_pred_written;
|
||||
TCGv hex_store_addr[STORES_MAX];
|
||||
TCGv hex_store_width[STORES_MAX];
|
||||
TCGv hex_store_val32[STORES_MAX];
|
||||
TCGv_i64 hex_store_val64[STORES_MAX];
|
||||
TCGv hex_pkt_has_store_s1;
|
||||
TCGv hex_dczero_addr;
|
||||
TCGv hex_llsc_addr;
|
||||
TCGv hex_llsc_val;
|
||||
TCGv_i64 hex_llsc_val_i64;
|
||||
@ -69,6 +64,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) {
|
||||
@ -154,7 +153,7 @@ static void gen_end_tb(DisasContext *ctx)
|
||||
if (ctx->branch_cond != TCG_COND_NEVER) {
|
||||
if (ctx->branch_cond != TCG_COND_ALWAYS) {
|
||||
TCGLabel *skip = gen_new_label();
|
||||
tcg_gen_brcondi_tl(ctx->branch_cond, hex_branch_taken, 0, skip);
|
||||
tcg_gen_brcondi_tl(ctx->branch_cond, ctx->branch_taken, 0, skip);
|
||||
gen_goto_tb(ctx, 0, ctx->branch_dest, true);
|
||||
gen_set_label(skip);
|
||||
gen_goto_tb(ctx, 1, ctx->next_PC, false);
|
||||
@ -262,11 +261,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;
|
||||
@ -341,10 +335,131 @@ static void mark_implicit_pred_writes(DisasContext *ctx)
|
||||
mark_implicit_pred_write(ctx, A_IMPLICIT_WRITES_P3, 3);
|
||||
}
|
||||
|
||||
static bool pkt_raises_exception(Packet *pkt)
|
||||
{
|
||||
if (check_for_attrib(pkt, A_LOAD) ||
|
||||
check_for_attrib(pkt, A_STORE)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool need_commit(DisasContext *ctx)
|
||||
{
|
||||
Packet *pkt = ctx->pkt;
|
||||
|
||||
/*
|
||||
* If the short-circuit property is set to false, we'll always do the commit
|
||||
*/
|
||||
if (!ctx->short_circuit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pkt_raises_exception(pkt)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Registers with immutability flags require new_value */
|
||||
for (int i = 0; i < ctx->reg_log_idx; i++) {
|
||||
int rnum = ctx->reg_log[i];
|
||||
if (reg_immut_masks[rnum]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Floating point instructions are hard-coded to use new_value */
|
||||
if (check_for_attrib(pkt, A_FPOP)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pkt->num_insns == 1) {
|
||||
if (pkt->pkt_has_hvx) {
|
||||
/*
|
||||
* The HVX instructions with generated helpers use
|
||||
* pass-by-reference, so they need the read/write overlap
|
||||
* check below.
|
||||
* The HVX instructions with overrides are OK.
|
||||
*/
|
||||
if (!ctx->has_hvx_helper) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static void mark_implicit_pred_read(DisasContext *ctx, int attrib, int pnum)
|
||||
{
|
||||
if (GET_ATTRIB(ctx->insn->opcode, attrib)) {
|
||||
ctx_log_pred_read(ctx, pnum);
|
||||
}
|
||||
}
|
||||
|
||||
static void mark_implicit_pred_reads(DisasContext *ctx)
|
||||
{
|
||||
mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P0, 0);
|
||||
mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P1, 1);
|
||||
mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P3, 2);
|
||||
mark_implicit_pred_read(ctx, A_IMPLICIT_READS_P3, 3);
|
||||
}
|
||||
|
||||
static void analyze_packet(DisasContext *ctx)
|
||||
{
|
||||
Packet *pkt = ctx->pkt;
|
||||
ctx->need_pkt_has_store_s1 = false;
|
||||
ctx->has_hvx_helper = false;
|
||||
for (int i = 0; i < pkt->num_insns; i++) {
|
||||
Insn *insn = &pkt->insn[i];
|
||||
ctx->insn = insn;
|
||||
@ -353,7 +468,10 @@ static void analyze_packet(DisasContext *ctx)
|
||||
}
|
||||
mark_implicit_reg_writes(ctx);
|
||||
mark_implicit_pred_writes(ctx);
|
||||
mark_implicit_pred_reads(ctx);
|
||||
}
|
||||
|
||||
ctx->need_commit = need_commit(ctx);
|
||||
}
|
||||
|
||||
static void gen_start_packet(DisasContext *ctx)
|
||||
@ -366,9 +484,11 @@ static void gen_start_packet(DisasContext *ctx)
|
||||
ctx->next_PC = next_PC;
|
||||
ctx->reg_log_idx = 0;
|
||||
bitmap_zero(ctx->regs_written, TOTAL_PER_THREAD_REGS);
|
||||
bitmap_zero(ctx->regs_read, TOTAL_PER_THREAD_REGS);
|
||||
bitmap_zero(ctx->predicated_regs, TOTAL_PER_THREAD_REGS);
|
||||
ctx->preg_log_idx = 0;
|
||||
bitmap_zero(ctx->pregs_written, NUM_PREGS);
|
||||
bitmap_zero(ctx->pregs_read, NUM_PREGS);
|
||||
ctx->future_vregs_idx = 0;
|
||||
ctx->tmp_vregs_idx = 0;
|
||||
ctx->vreg_log_idx = 0;
|
||||
@ -377,19 +497,23 @@ static void gen_start_packet(DisasContext *ctx)
|
||||
bitmap_zero(ctx->vregs_select, NUM_VREGS);
|
||||
bitmap_zero(ctx->predicated_future_vregs, NUM_VREGS);
|
||||
bitmap_zero(ctx->predicated_tmp_vregs, NUM_VREGS);
|
||||
bitmap_zero(ctx->vregs_read, NUM_VREGS);
|
||||
bitmap_zero(ctx->qregs_read, NUM_QREGS);
|
||||
ctx->qreg_log_idx = 0;
|
||||
for (i = 0; i < STORES_MAX; i++) {
|
||||
ctx->store_width[i] = 0;
|
||||
}
|
||||
ctx->s1_store_processed = false;
|
||||
ctx->pre_commit = true;
|
||||
for (i = 0; i < TOTAL_PER_THREAD_REGS; i++) {
|
||||
ctx->new_value[i] = NULL;
|
||||
}
|
||||
for (i = 0; i < NUM_PREGS; i++) {
|
||||
ctx->new_pred_value[i] = NULL;
|
||||
}
|
||||
|
||||
analyze_packet(ctx);
|
||||
|
||||
if (ctx->need_pkt_has_store_s1) {
|
||||
tcg_gen_movi_tl(hex_pkt_has_store_s1, pkt->pkt_has_store_s1);
|
||||
}
|
||||
|
||||
/*
|
||||
* pregs_written is used both in the analyze phase as well as the code
|
||||
* gen phase, so clear it again.
|
||||
@ -399,35 +523,50 @@ static void gen_start_packet(DisasContext *ctx)
|
||||
if (HEX_DEBUG) {
|
||||
/* Handy place to set a breakpoint before the packet executes */
|
||||
gen_helper_debug_start_packet(cpu_env);
|
||||
tcg_gen_movi_tl(hex_this_PC, ctx->base.pc_next);
|
||||
}
|
||||
|
||||
/* Initialize the runtime state for packet semantics */
|
||||
if (need_slot_cancelled(pkt)) {
|
||||
tcg_gen_movi_tl(hex_slot_cancelled, 0);
|
||||
}
|
||||
ctx->branch_taken = NULL;
|
||||
if (pkt->pkt_has_cof) {
|
||||
ctx->branch_taken = tcg_temp_new();
|
||||
if (pkt->pkt_has_multi_cof) {
|
||||
tcg_gen_movi_tl(hex_branch_taken, 0);
|
||||
tcg_gen_movi_tl(ctx->branch_taken, 0);
|
||||
}
|
||||
if (need_next_PC(ctx)) {
|
||||
tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], next_PC);
|
||||
}
|
||||
}
|
||||
if (need_pred_written(pkt)) {
|
||||
tcg_gen_movi_tl(hex_pred_written, 0);
|
||||
if (HEX_DEBUG) {
|
||||
ctx->pred_written = tcg_temp_new();
|
||||
tcg_gen_movi_tl(ctx->pred_written, 0);
|
||||
}
|
||||
|
||||
/* Preload the predicated registers into hex_new_value[i] */
|
||||
if (!bitmap_empty(ctx->predicated_regs, TOTAL_PER_THREAD_REGS)) {
|
||||
/* Preload the predicated registers into get_result_gpr(ctx, i) */
|
||||
if (ctx->need_commit &&
|
||||
!bitmap_empty(ctx->predicated_regs, TOTAL_PER_THREAD_REGS)) {
|
||||
int i = find_first_bit(ctx->predicated_regs, TOTAL_PER_THREAD_REGS);
|
||||
while (i < TOTAL_PER_THREAD_REGS) {
|
||||
tcg_gen_mov_tl(hex_new_value[i], hex_gpr[i]);
|
||||
tcg_gen_mov_tl(get_result_gpr(ctx, i), hex_gpr[i]);
|
||||
i = find_next_bit(ctx->predicated_regs, TOTAL_PER_THREAD_REGS,
|
||||
i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Preload the predicated pred registers into hex_new_pred_value[pred_num]
|
||||
* Only endloop instructions conditionally write to pred registers
|
||||
*/
|
||||
if (ctx->need_commit && pkt->pkt_has_endloop) {
|
||||
for (int i = 0; i < ctx->preg_log_idx; i++) {
|
||||
int pred_num = ctx->preg_log[i];
|
||||
ctx->new_pred_value[pred_num] = tcg_temp_new();
|
||||
tcg_gen_mov_tl(ctx->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);
|
||||
@ -481,6 +620,9 @@ static void mark_store_width(DisasContext *ctx)
|
||||
uint8_t width = 0;
|
||||
|
||||
if (GET_ATTRIB(opcode, A_SCALAR_STORE)) {
|
||||
if (GET_ATTRIB(opcode, A_MEMSIZE_0B)) {
|
||||
return;
|
||||
}
|
||||
if (GET_ATTRIB(opcode, A_MEMSIZE_1B)) {
|
||||
width |= 1;
|
||||
}
|
||||
@ -515,10 +657,15 @@ static void gen_reg_writes(DisasContext *ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* Early exit if not needed */
|
||||
if (!ctx->need_commit) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < ctx->reg_log_idx; i++) {
|
||||
int reg_num = ctx->reg_log[i];
|
||||
|
||||
tcg_gen_mov_tl(hex_gpr[reg_num], hex_new_value[reg_num]);
|
||||
tcg_gen_mov_tl(hex_gpr[reg_num], get_result_gpr(ctx, reg_num));
|
||||
|
||||
/*
|
||||
* ctx->is_tight_loop is set when SA0 points to the beginning of the TB.
|
||||
@ -532,41 +679,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) {
|
||||
/* Early exit if not needed or the log is empty */
|
||||
if (!ctx->need_commit || !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],
|
||||
pred_written, zero,
|
||||
hex_new_pred_value[pred_num],
|
||||
hex_pred[pred_num]);
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ctx->preg_log_idx; i++) {
|
||||
int pred_num = ctx->preg_log[i];
|
||||
tcg_gen_mov_tl(hex_pred[pred_num], hex_new_pred_value[pred_num]);
|
||||
if (HEX_DEBUG) {
|
||||
/* Do this so HELPER(debug_commit_end) will know */
|
||||
tcg_gen_ori_tl(hex_pred_written, hex_pred_written,
|
||||
1 << pred_num);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < ctx->preg_log_idx; i++) {
|
||||
int pred_num = ctx->preg_log[i];
|
||||
tcg_gen_mov_tl(hex_pred[pred_num], ctx->new_pred_value[pred_num]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -692,7 +812,7 @@ static void process_dczeroa(DisasContext *ctx)
|
||||
TCGv addr = tcg_temp_new();
|
||||
TCGv_i64 zero = tcg_constant_i64(0);
|
||||
|
||||
tcg_gen_andi_tl(addr, hex_dczero_addr, ~0x1f);
|
||||
tcg_gen_andi_tl(addr, ctx->dczero_addr, ~0x1f);
|
||||
tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
|
||||
tcg_gen_addi_tl(addr, addr, 8);
|
||||
tcg_gen_qemu_st_i64(zero, addr, ctx->mem_idx, MO_UQ);
|
||||
@ -719,6 +839,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];
|
||||
@ -873,7 +999,8 @@ static void gen_commit_packet(DisasContext *ctx)
|
||||
tcg_constant_tl(pkt->pkt_has_store_s1 && !pkt->pkt_has_dczeroa);
|
||||
|
||||
/* Handy place to set a breakpoint at the end of execution */
|
||||
gen_helper_debug_commit_end(cpu_env, has_st0, has_st1);
|
||||
gen_helper_debug_commit_end(cpu_env, tcg_constant_tl(ctx->pkt->pc),
|
||||
ctx->pred_written, has_st0, has_st1);
|
||||
}
|
||||
|
||||
if (pkt->vhist_insn != NULL) {
|
||||
@ -920,6 +1047,7 @@ static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
|
||||
CPUState *cs)
|
||||
{
|
||||
DisasContext *ctx = container_of(dcbase, DisasContext, base);
|
||||
HexagonCPU *hex_cpu = env_archcpu(cs->env_ptr);
|
||||
uint32_t hex_flags = dcbase->tb->flags;
|
||||
|
||||
ctx->mem_idx = MMU_USER_IDX;
|
||||
@ -928,6 +1056,7 @@ static void hexagon_tr_init_disas_context(DisasContextBase *dcbase,
|
||||
ctx->num_hvx_insns = 0;
|
||||
ctx->branch_cond = TCG_COND_NEVER;
|
||||
ctx->is_tight_loop = FIELD_EX32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP);
|
||||
ctx->short_circuit = hex_cpu->short_circuit;
|
||||
}
|
||||
|
||||
static void hexagon_tr_tb_start(DisasContextBase *db, CPUState *cpu)
|
||||
@ -1028,9 +1157,7 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
|
||||
}
|
||||
|
||||
#define NAME_LEN 64
|
||||
static char new_value_names[TOTAL_PER_THREAD_REGS][NAME_LEN];
|
||||
static char reg_written_names[TOTAL_PER_THREAD_REGS][NAME_LEN];
|
||||
static char new_pred_value_names[NUM_PREGS][NAME_LEN];
|
||||
static char store_addr_names[STORES_MAX][NAME_LEN];
|
||||
static char store_width_names[STORES_MAX][NAME_LEN];
|
||||
static char store_val32_names[STORES_MAX][NAME_LEN];
|
||||
@ -1050,11 +1177,6 @@ void hexagon_translate_init(void)
|
||||
offsetof(CPUHexagonState, gpr[i]),
|
||||
hexagon_regnames[i]);
|
||||
|
||||
snprintf(new_value_names[i], NAME_LEN, "new_%s", hexagon_regnames[i]);
|
||||
hex_new_value[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, new_value[i]),
|
||||
new_value_names[i]);
|
||||
|
||||
if (HEX_DEBUG) {
|
||||
snprintf(reg_written_names[i], NAME_LEN, "reg_written_%s",
|
||||
hexagon_regnames[i]);
|
||||
@ -1063,29 +1185,16 @@ void hexagon_translate_init(void)
|
||||
reg_written_names[i]);
|
||||
}
|
||||
}
|
||||
hex_new_value_usr = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, new_value_usr), "new_value_usr");
|
||||
|
||||
for (i = 0; i < NUM_PREGS; i++) {
|
||||
hex_pred[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, pred[i]),
|
||||
hexagon_prednames[i]);
|
||||
|
||||
snprintf(new_pred_value_names[i], NAME_LEN, "new_pred_%s",
|
||||
hexagon_prednames[i]);
|
||||
hex_new_pred_value[i] = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, new_pred_value[i]),
|
||||
new_pred_value_names[i]);
|
||||
}
|
||||
hex_pred_written = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, pred_written), "pred_written");
|
||||
hex_this_PC = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, this_PC), "this_PC");
|
||||
hex_slot_cancelled = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, slot_cancelled), "slot_cancelled");
|
||||
hex_branch_taken = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, branch_taken), "branch_taken");
|
||||
hex_pkt_has_store_s1 = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, pkt_has_store_s1), "pkt_has_store_s1");
|
||||
hex_dczero_addr = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, dczero_addr), "dczero_addr");
|
||||
hex_llsc_addr = tcg_global_mem_new(cpu_env,
|
||||
offsetof(CPUHexagonState, llsc_addr), "llsc_addr");
|
||||
hex_llsc_val = tcg_global_mem_new(cpu_env,
|
||||
|
@ -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,13 +57,22 @@ 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;
|
||||
bool need_commit;
|
||||
TCGCond branch_cond;
|
||||
target_ulong branch_dest;
|
||||
bool is_tight_loop;
|
||||
bool need_pkt_has_store_s1;
|
||||
bool short_circuit;
|
||||
bool has_hvx_helper;
|
||||
TCGv new_value[TOTAL_PER_THREAD_REGS];
|
||||
TCGv new_pred_value[NUM_PREGS];
|
||||
TCGv pred_written;
|
||||
TCGv branch_taken;
|
||||
TCGv dczero_addr;
|
||||
} DisasContext;
|
||||
|
||||
static inline void ctx_log_pred_write(DisasContext *ctx, int pnum)
|
||||
@ -73,6 +84,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 +115,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 +166,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,20 +184,20 @@ 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;
|
||||
extern TCGv hex_slot_cancelled;
|
||||
extern TCGv hex_branch_taken;
|
||||
extern TCGv hex_new_value[TOTAL_PER_THREAD_REGS];
|
||||
extern TCGv hex_new_value_usr;
|
||||
extern TCGv hex_reg_written[TOTAL_PER_THREAD_REGS];
|
||||
extern TCGv hex_new_pred_value[NUM_PREGS];
|
||||
extern TCGv hex_pred_written;
|
||||
extern TCGv hex_store_addr[STORES_MAX];
|
||||
extern TCGv hex_store_width[STORES_MAX];
|
||||
extern TCGv hex_store_val32[STORES_MAX];
|
||||
extern TCGv_i64 hex_store_val64[STORES_MAX];
|
||||
extern TCGv hex_dczero_addr;
|
||||
extern TCGv hex_llsc_addr;
|
||||
extern TCGv hex_llsc_val;
|
||||
extern TCGv_i64 hex_llsc_val_i64;
|
||||
|
@ -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 @@ if __name__ == '__main__':
|
||||
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 @@ if __name__ == '__main__':
|
||||
|
||||
# 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 @@ if __name__ == '__main__':
|
||||
# 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
|
||||
|
@ -45,10 +45,18 @@ HEX_TESTS += fpstuff
|
||||
HEX_TESTS += overflow
|
||||
HEX_TESTS += signal_context
|
||||
HEX_TESTS += reg_mut
|
||||
HEX_TESTS += read_write_overlap
|
||||
HEX_TESTS += vector_add_int
|
||||
HEX_TESTS += scatter_gather
|
||||
HEX_TESTS += hvx_misc
|
||||
HEX_TESTS += hvx_histogram
|
||||
HEX_TESTS += invalid-slots
|
||||
|
||||
run-and-check-exception = $(call run-test,$2,$3 2>$2.stderr; \
|
||||
test $$? -eq 1 && grep -q "exception $(strip $1)" $2.stderr)
|
||||
|
||||
run-invalid-slots: invalid-slots
|
||||
$(call run-and-check-exception, 0x15, $@, $(QEMU) $(QEMU_OPTS) $<)
|
||||
|
||||
HEX_TESTS += test_abs
|
||||
HEX_TESTS += test_bitcnt
|
||||
@ -76,17 +84,30 @@ HEX_TESTS += test_vminh
|
||||
HEX_TESTS += test_vpmpyh
|
||||
HEX_TESTS += test_vspliceb
|
||||
|
||||
HEX_TESTS += v68_scalar
|
||||
HEX_TESTS += v68_hvx
|
||||
HEX_TESTS += v69_hvx
|
||||
HEX_TESTS += v73_scalar
|
||||
|
||||
TESTS += $(HEX_TESTS)
|
||||
|
||||
# This test has to be compiled for the -mv67t target
|
||||
usr: usr.c
|
||||
$(CC) $(CFLAGS) -mv67t -O2 -Wno-inline-asm -Wno-expansion-to-defined $< -o $@ $(LDFLAGS)
|
||||
|
||||
# Build this test with -mv71 to exercise the CABAC instruction
|
||||
misc: misc.c
|
||||
$(CC) $(CFLAGS) -mv71 -O2 $< -o $@ $(LDFLAGS)
|
||||
scatter_gather: CFLAGS += -mhvx
|
||||
vector_add_int: CFLAGS += -mhvx -fvectorize
|
||||
hvx_misc: hvx_misc.c hvx_misc.h
|
||||
hvx_misc: CFLAGS += -mhvx
|
||||
hvx_histogram: CFLAGS += -mhvx -Wno-gnu-folding-constant
|
||||
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)
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <float.h>
|
||||
|
||||
const int FPINVF_BIT = 1; /* Invalid */
|
||||
const int FPINVF = 1 << FPINVF_BIT;
|
||||
@ -706,6 +707,57 @@ static void check_float2int_convs()
|
||||
check_fpstatus(usr, FPINVF);
|
||||
}
|
||||
|
||||
static void check_float_consts(void)
|
||||
{
|
||||
int res32;
|
||||
unsigned long long res64;
|
||||
|
||||
asm("%0 = sfmake(#%1):neg\n\t" : "=r"(res32) : "i"(0xf));
|
||||
check32(res32, 0xbc9e0000);
|
||||
|
||||
asm("%0 = sfmake(#%1):pos\n\t" : "=r"(res32) : "i"(0xf));
|
||||
check32(res32, 0x3c9e0000);
|
||||
|
||||
asm("%0 = dfmake(#%1):neg\n\t" : "=r"(res64) : "i"(0xf));
|
||||
check64(res64, 0xbf93c00000000000ULL);
|
||||
|
||||
asm("%0 = dfmake(#%1):pos\n\t" : "=r"(res64) : "i"(0xf));
|
||||
check64(res64, 0x3f93c00000000000ULL);
|
||||
}
|
||||
|
||||
static inline unsigned long long dfmpyll(double x, double y)
|
||||
{
|
||||
unsigned long long res64;
|
||||
asm("%0 = dfmpyll(%1, %2)" : "=r"(res64) : "r"(x), "r"(y));
|
||||
return res64;
|
||||
}
|
||||
|
||||
static inline unsigned long long dfmpylh(double acc, double x, double y)
|
||||
{
|
||||
unsigned long long res64 = *(unsigned long long *)&acc;
|
||||
asm("%0 += dfmpylh(%1, %2)" : "+r"(res64) : "r"(x), "r"(y));
|
||||
return res64;
|
||||
}
|
||||
|
||||
static void check_dfmpyxx(void)
|
||||
{
|
||||
unsigned long long res64;
|
||||
|
||||
res64 = dfmpyll(DBL_MIN, DBL_MIN);
|
||||
check64(res64, 0ULL);
|
||||
res64 = dfmpyll(-1.0, DBL_MIN);
|
||||
check64(res64, 0ULL);
|
||||
res64 = dfmpyll(DBL_MAX, DBL_MAX);
|
||||
check64(res64, 0x1fffffffdULL);
|
||||
|
||||
res64 = dfmpylh(DBL_MIN, DBL_MIN, DBL_MIN);
|
||||
check64(res64, 0x10000000000000ULL);
|
||||
res64 = dfmpylh(-1.0, DBL_MAX, DBL_MIN);
|
||||
check64(res64, 0xc00fffffffe00000ULL);
|
||||
res64 = dfmpylh(DBL_MAX, 0.0, -1.0);
|
||||
check64(res64, 0x7fefffffffffffffULL);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
check_compare_exception();
|
||||
@ -718,6 +770,8 @@ int main()
|
||||
check_sffixupd();
|
||||
check_sffms();
|
||||
check_float2int_convs();
|
||||
check_float_consts();
|
||||
check_dfmpyxx();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err ? 1 : 0;
|
||||
|
@ -342,49 +342,6 @@ static void test_vsubuwsat_dv(void)
|
||||
check_output_w(__LINE__, 2);
|
||||
}
|
||||
|
||||
static void test_vshuff(void)
|
||||
{
|
||||
/* Test that vshuff works when the two operands are the same register */
|
||||
const uint32_t splat = 0x089be55c;
|
||||
const uint32_t shuff = 0x454fa926;
|
||||
MMVector v0, v1;
|
||||
|
||||
memset(expect, 0x12, sizeof(MMVector));
|
||||
memset(output, 0x34, sizeof(MMVector));
|
||||
|
||||
asm volatile("v25 = vsplat(%0)\n\t"
|
||||
"vshuff(v25, v25, %1)\n\t"
|
||||
"vmem(%2 + #0) = v25\n\t"
|
||||
: /* no outputs */
|
||||
: "r"(splat), "r"(shuff), "r"(output)
|
||||
: "v25", "memory");
|
||||
|
||||
/*
|
||||
* The semantics of Hexagon are the operands are pass-by-value, so create
|
||||
* two copies of the vsplat result.
|
||||
*/
|
||||
for (int i = 0; i < MAX_VEC_SIZE_BYTES / 4; i++) {
|
||||
v0.uw[i] = splat;
|
||||
v1.uw[i] = splat;
|
||||
}
|
||||
/* Do the vshuff operation */
|
||||
for (int offset = 1; offset < MAX_VEC_SIZE_BYTES; offset <<= 1) {
|
||||
if (shuff & offset) {
|
||||
for (int k = 0; k < MAX_VEC_SIZE_BYTES; k++) {
|
||||
if (!(k & offset)) {
|
||||
uint8_t tmp = v0.ub[k];
|
||||
v0.ub[k] = v1.ub[k + offset];
|
||||
v1.ub[k + offset] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Put the result in the expect buffer for verification */
|
||||
expect[0] = v1;
|
||||
|
||||
check_output_b(__LINE__, 1);
|
||||
}
|
||||
|
||||
static void test_load_tmp_predicated(void)
|
||||
{
|
||||
void *p0 = buffer0;
|
||||
@ -454,6 +411,25 @@ static void test_load_cur_predicated(void)
|
||||
check_output_w(__LINE__, BUFSIZE);
|
||||
}
|
||||
|
||||
static void test_vcombine(void)
|
||||
{
|
||||
for (int i = 0; i < BUFSIZE / 2; i++) {
|
||||
asm volatile("v2 = vsplat(%0)\n\t"
|
||||
"v3 = vsplat(%1)\n\t"
|
||||
"v3:2 = vcombine(v2, v3)\n\t"
|
||||
"vmem(%2+#0) = v2\n\t"
|
||||
"vmem(%2+#1) = v3\n\t"
|
||||
:
|
||||
: "r"(2 * i), "r"(2 * i + 1), "r"(&output[2 * i])
|
||||
: "v2", "v3", "memory");
|
||||
for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
|
||||
expect[2 * i].w[j] = 2 * i + 1;
|
||||
expect[2 * i + 1].w[j] = 2 * i;
|
||||
}
|
||||
}
|
||||
check_output_w(__LINE__, BUFSIZE);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
init_buffers();
|
||||
@ -489,11 +465,11 @@ int main()
|
||||
test_vadduwsat();
|
||||
test_vsubuwsat_dv();
|
||||
|
||||
test_vshuff();
|
||||
|
||||
test_load_tmp_predicated();
|
||||
test_load_cur_predicated();
|
||||
|
||||
test_vcombine();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err ? 1 : 0;
|
||||
}
|
||||
|
29
tests/tcg/hexagon/invalid-slots.c
Normal file
29
tests/tcg/hexagon/invalid-slots.c
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
char mem[8] __attribute__((aligned(8)));
|
||||
|
||||
int main()
|
||||
{
|
||||
asm volatile(
|
||||
"r0 = #mem\n"
|
||||
/* Invalid packet (2 instructions at slot 0): */
|
||||
".word 0xa1804100\n" /* { memw(r0) = r1; */
|
||||
".word 0x28032804\n" /* r3 = #0; r4 = #0 } */
|
||||
: : : "r0", "r3", "r4", "memory");
|
||||
return 0;
|
||||
}
|
@ -18,6 +18,8 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CORE_HAS_CABAC (__HEXAGON_ARCH__ <= 71)
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
@ -245,6 +247,7 @@ static void check(int val, int expect)
|
||||
}
|
||||
}
|
||||
|
||||
#if CORE_HAS_CABAC
|
||||
static void check64(long long val, long long expect)
|
||||
{
|
||||
if (val != expect) {
|
||||
@ -252,6 +255,7 @@ static void check64(long long val, long long expect)
|
||||
err++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t init[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
|
||||
uint32_t array[10];
|
||||
@ -286,6 +290,7 @@ static long long creg_pair(int x, int y)
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if CORE_HAS_CABAC
|
||||
static long long decbin(long long x, long long y, int *pred)
|
||||
{
|
||||
long long retval;
|
||||
@ -295,6 +300,7 @@ static long long decbin(long long x, long long y, int *pred)
|
||||
: "r"(x), "r"(y));
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Check that predicates are auto-and'ed in a packet */
|
||||
static int auto_and(void)
|
||||
@ -385,11 +391,46 @@ void test_count_trailing_zeros_ones(void)
|
||||
check(ct1p(0xffffff0fffffffffULL), 36);
|
||||
}
|
||||
|
||||
static inline int dpmpyss_rnd_s0(int x, int y)
|
||||
{
|
||||
int res;
|
||||
asm("%0 = mpy(%1, %2):rnd\n\t" : "=r"(res) : "r"(x), "r"(y));
|
||||
return res;
|
||||
}
|
||||
|
||||
void test_dpmpyss_rnd_s0(void)
|
||||
{
|
||||
check(dpmpyss_rnd_s0(-1, 0x80000000), 1);
|
||||
check(dpmpyss_rnd_s0(0, 0x80000000), 0);
|
||||
check(dpmpyss_rnd_s0(1, 0x80000000), 0);
|
||||
check(dpmpyss_rnd_s0(0x7fffffff, 0x80000000), 0xc0000001);
|
||||
check(dpmpyss_rnd_s0(0x80000000, -1), 1);
|
||||
check(dpmpyss_rnd_s0(-1, -1), 0);
|
||||
check(dpmpyss_rnd_s0(0, -1), 0);
|
||||
check(dpmpyss_rnd_s0(1, -1), 0);
|
||||
check(dpmpyss_rnd_s0(0x7fffffff, -1), 0);
|
||||
check(dpmpyss_rnd_s0(0x80000000, 0), 0);
|
||||
check(dpmpyss_rnd_s0(-1, 0), 0);
|
||||
check(dpmpyss_rnd_s0(0, 0), 0);
|
||||
check(dpmpyss_rnd_s0(1, 0), 0);
|
||||
check(dpmpyss_rnd_s0(-1, -1), 0);
|
||||
check(dpmpyss_rnd_s0(0, -1), 0);
|
||||
check(dpmpyss_rnd_s0(1, -1), 0);
|
||||
check(dpmpyss_rnd_s0(0x7fffffff, 1), 0);
|
||||
check(dpmpyss_rnd_s0(0x80000000, 0x7fffffff), 0xc0000001);
|
||||
check(dpmpyss_rnd_s0(-1, 0x7fffffff), 0);
|
||||
check(dpmpyss_rnd_s0(0, 0x7fffffff), 0);
|
||||
check(dpmpyss_rnd_s0(1, 0x7fffffff), 0);
|
||||
check(dpmpyss_rnd_s0(0x7fffffff, 0x7fffffff), 0x3fffffff);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
int res;
|
||||
#if CORE_HAS_CABAC
|
||||
long long res64;
|
||||
int pred;
|
||||
#endif
|
||||
|
||||
memcpy(array, init, sizeof(array));
|
||||
S4_storerhnew_rr(array, 4, 0xffff);
|
||||
@ -505,6 +546,7 @@ int main()
|
||||
res = test_clrtnew(2, 7);
|
||||
check(res, 7);
|
||||
|
||||
#if CORE_HAS_CABAC
|
||||
res64 = decbin(0xf0f1f2f3f4f5f6f7LL, 0x7f6f5f4f3f2f1f0fLL, &pred);
|
||||
check64(res64, 0x357980003700010cLL);
|
||||
check(pred, 0);
|
||||
@ -512,6 +554,9 @@ int main()
|
||||
res64 = decbin(0xfLL, 0x1bLL, &pred);
|
||||
check64(res64, 0x78000100LL);
|
||||
check(pred, 1);
|
||||
#else
|
||||
puts("Skipping cabac tests");
|
||||
#endif
|
||||
|
||||
res = auto_and();
|
||||
check(res, 0);
|
||||
@ -522,6 +567,8 @@ int main()
|
||||
|
||||
test_count_trailing_zeros_ones();
|
||||
|
||||
test_dpmpyss_rnd_s0();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err;
|
||||
}
|
||||
|
136
tests/tcg/hexagon/read_write_overlap.c
Normal file
136
tests/tcg/hexagon/read_write_overlap.c
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Test instructions where the semantics write to the destination
|
||||
* before all the operand reads have been completed.
|
||||
*
|
||||
* These instructions are problematic when we short-circuit the
|
||||
* register writes because the destination and source operands could
|
||||
* be the same TCGv.
|
||||
*
|
||||
* We test by forcing the read and write to be register r7.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int err;
|
||||
|
||||
static void __check(const char *filename, int line, int x, int expect)
|
||||
{
|
||||
if (x != expect) {
|
||||
printf("ERROR %s:%d - 0x%08x != 0x%08x\n",
|
||||
filename, line, x, expect);
|
||||
err++;
|
||||
}
|
||||
}
|
||||
|
||||
#define check(x, expect) __check(__FILE__, __LINE__, (x), (expect))
|
||||
|
||||
#define insert(RES, X, WIDTH, OFFSET) \
|
||||
asm("r7 = %1\n\t" \
|
||||
"r7 = insert(r7, #" #WIDTH ", #" #OFFSET ")\n\t" \
|
||||
"%0 = r7\n\t" \
|
||||
: "=r"(RES) : "r"(X) : "r7")
|
||||
|
||||
static void test_insert(void)
|
||||
{
|
||||
uint32_t res;
|
||||
|
||||
insert(res, 0x12345678, 8, 1);
|
||||
check(res, 0x123456f0);
|
||||
insert(res, 0x12345678, 0, 1);
|
||||
check(res, 0x12345678);
|
||||
insert(res, 0x12345678, 20, 16);
|
||||
check(res, 0x56785678);
|
||||
}
|
||||
|
||||
static inline uint32_t insert_rp(uint32_t x, uint32_t width, uint32_t offset)
|
||||
{
|
||||
uint64_t width_offset = (uint64_t)width << 32 | offset;
|
||||
uint32_t res;
|
||||
asm("r7 = %1\n\t"
|
||||
"r7 = insert(r7, %2)\n\t"
|
||||
"%0 = r7\n\t"
|
||||
: "=r"(res) : "r"(x), "r"(width_offset) : "r7");
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
static void test_insert_rp(void)
|
||||
{
|
||||
check(insert_rp(0x12345678, 8, 1), 0x123456f0);
|
||||
check(insert_rp(0x12345678, 63, 8), 0x34567878);
|
||||
check(insert_rp(0x12345678, 127, 8), 0x34567878);
|
||||
check(insert_rp(0x12345678, 8, 24), 0x78345678);
|
||||
check(insert_rp(0x12345678, 8, 63), 0x12345678);
|
||||
check(insert_rp(0x12345678, 8, 64), 0x00000000);
|
||||
}
|
||||
|
||||
static inline uint32_t asr_r_svw_trun(uint64_t x, uint32_t y)
|
||||
{
|
||||
uint32_t res;
|
||||
asm("r7 = %2\n\t"
|
||||
"r7 = vasrw(%1, r7)\n\t"
|
||||
"%0 = r7\n\t"
|
||||
: "=r"(res) : "r"(x), "r"(y) : "r7");
|
||||
return res;
|
||||
}
|
||||
|
||||
static void test_asr_r_svw_trun(void)
|
||||
{
|
||||
check(asr_r_svw_trun(0x1111111122222222ULL, 5),
|
||||
0x88881111);
|
||||
check(asr_r_svw_trun(0x1111111122222222ULL, 63),
|
||||
0x00000000);
|
||||
check(asr_r_svw_trun(0x1111111122222222ULL, 64),
|
||||
0x00000000);
|
||||
check(asr_r_svw_trun(0x1111111122222222ULL, 127),
|
||||
0x22224444);
|
||||
check(asr_r_svw_trun(0x1111111122222222ULL, 128),
|
||||
0x11112222);
|
||||
check(asr_r_svw_trun(0xffffffff22222222ULL, 128),
|
||||
0xffff2222);
|
||||
}
|
||||
|
||||
static inline uint32_t swiz(uint32_t x)
|
||||
{
|
||||
uint32_t res;
|
||||
asm("r7 = %1\n\t"
|
||||
"r7 = swiz(r7)\n\t"
|
||||
"%0 = r7\n\t"
|
||||
: "=r"(res) : "r"(x) : "r7");
|
||||
return res;
|
||||
}
|
||||
|
||||
static void test_swiz(void)
|
||||
{
|
||||
check(swiz(0x11223344), 0x44332211);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_insert();
|
||||
test_insert_rp();
|
||||
test_asr_r_svw_trun();
|
||||
test_swiz();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err ? EXIT_FAILURE : EXIT_SUCCESS;
|
||||
}
|
90
tests/tcg/hexagon/v68_hvx.c
Normal file
90
tests/tcg/hexagon/v68_hvx.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright(c) 2022-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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
int err;
|
||||
|
||||
#include "hvx_misc.h"
|
||||
|
||||
MMVector v6mpy_buffer0[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES)));
|
||||
MMVector v6mpy_buffer1[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES)));
|
||||
|
||||
static void init_v6mpy_buffers(void)
|
||||
{
|
||||
int counter0 = 0;
|
||||
int counter1 = 17;
|
||||
for (int i = 0; i < BUFSIZE; i++) {
|
||||
for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
|
||||
v6mpy_buffer0[i].w[j] = counter0++;
|
||||
v6mpy_buffer1[i].w[j] = counter1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int v6mpy_ref[BUFSIZE][MAX_VEC_SIZE_BYTES / 4] = {
|
||||
#include "v6mpy_ref.c.inc"
|
||||
};
|
||||
|
||||
static void test_v6mpy(void)
|
||||
{
|
||||
void *p00 = buffer0;
|
||||
void *p01 = v6mpy_buffer0;
|
||||
void *p10 = buffer1;
|
||||
void *p11 = v6mpy_buffer1;
|
||||
void *pout = output;
|
||||
|
||||
memset(expect, 0xff, sizeof(expect));
|
||||
memset(output, 0xff, sizeof(expect));
|
||||
|
||||
for (int i = 0; i < BUFSIZE; i++) {
|
||||
asm("v2 = vmem(%0 + #0)\n\t"
|
||||
"v3 = vmem(%1 + #0)\n\t"
|
||||
"v4 = vmem(%2 + #0)\n\t"
|
||||
"v5 = vmem(%3 + #0)\n\t"
|
||||
"v5:4.w = v6mpy(v5:4.ub, v3:2.b, #1):v\n\t"
|
||||
"vmem(%4 + #0) = v4\n\t"
|
||||
: : "r"(p00), "r"(p01), "r"(p10), "r"(p11), "r"(pout)
|
||||
: "v2", "v3", "v4", "v5", "memory");
|
||||
p00 += sizeof(MMVector);
|
||||
p01 += sizeof(MMVector);
|
||||
p10 += sizeof(MMVector);
|
||||
p11 += sizeof(MMVector);
|
||||
pout += sizeof(MMVector);
|
||||
|
||||
for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
|
||||
expect[i].w[j] = v6mpy_ref[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
check_output_w(__LINE__, BUFSIZE);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
init_buffers();
|
||||
init_v6mpy_buffers();
|
||||
|
||||
test_v6mpy();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err ? 1 : 0;
|
||||
}
|
186
tests/tcg/hexagon/v68_scalar.c
Normal file
186
tests/tcg/hexagon/v68_scalar.c
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* Test the scalar core instructions that are new in v68
|
||||
*/
|
||||
|
||||
int err;
|
||||
|
||||
static int buffer32[] = { 1, 2, 3, 4 };
|
||||
static long long buffer64[] = { 5, 6, 7, 8 };
|
||||
|
||||
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 inline int loadw_aq(int *p)
|
||||
{
|
||||
int res;
|
||||
asm volatile("%0 = memw_aq(%1)\n\t"
|
||||
: "=r"(res) : "r"(p));
|
||||
return res;
|
||||
}
|
||||
|
||||
static void test_loadw_aq(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
res = loadw_aq(&buffer32[0]);
|
||||
check32(res, 1);
|
||||
res = loadw_aq(&buffer32[1]);
|
||||
check32(res, 2);
|
||||
}
|
||||
|
||||
static inline long long loadd_aq(long long *p)
|
||||
{
|
||||
long long res;
|
||||
asm volatile("%0 = memd_aq(%1)\n\t"
|
||||
: "=r"(res) : "r"(p));
|
||||
return res;
|
||||
}
|
||||
|
||||
static void test_loadd_aq(void)
|
||||
{
|
||||
long long res;
|
||||
|
||||
res = loadd_aq(&buffer64[2]);
|
||||
check64(res, 7);
|
||||
res = loadd_aq(&buffer64[3]);
|
||||
check64(res, 8);
|
||||
}
|
||||
|
||||
static inline void release_at(int *p)
|
||||
{
|
||||
asm volatile("release(%0):at\n\t"
|
||||
: : "r"(p));
|
||||
}
|
||||
|
||||
static void test_release_at(void)
|
||||
{
|
||||
release_at(&buffer32[2]);
|
||||
check64(buffer32[2], 3);
|
||||
release_at(&buffer32[3]);
|
||||
check64(buffer32[3], 4);
|
||||
}
|
||||
|
||||
static inline void release_st(int *p)
|
||||
{
|
||||
asm volatile("release(%0):st\n\t"
|
||||
: : "r"(p));
|
||||
}
|
||||
|
||||
static void test_release_st(void)
|
||||
{
|
||||
release_st(&buffer32[2]);
|
||||
check64(buffer32[2], 3);
|
||||
release_st(&buffer32[3]);
|
||||
check64(buffer32[3], 4);
|
||||
}
|
||||
|
||||
static inline void storew_rl_at(int *p, int val)
|
||||
{
|
||||
asm volatile("memw_rl(%0):at = %1\n\t"
|
||||
: : "r"(p), "r"(val) : "memory");
|
||||
}
|
||||
|
||||
static void test_storew_rl_at(void)
|
||||
{
|
||||
storew_rl_at(&buffer32[2], 9);
|
||||
check64(buffer32[2], 9);
|
||||
storew_rl_at(&buffer32[3], 10);
|
||||
check64(buffer32[3], 10);
|
||||
}
|
||||
|
||||
static inline void stored_rl_at(long long *p, long long val)
|
||||
{
|
||||
asm volatile("memd_rl(%0):at = %1\n\t"
|
||||
: : "r"(p), "r"(val) : "memory");
|
||||
}
|
||||
|
||||
static void test_stored_rl_at(void)
|
||||
{
|
||||
stored_rl_at(&buffer64[2], 11);
|
||||
check64(buffer64[2], 11);
|
||||
stored_rl_at(&buffer64[3], 12);
|
||||
check64(buffer64[3], 12);
|
||||
}
|
||||
|
||||
static inline void storew_rl_st(int *p, int val)
|
||||
{
|
||||
asm volatile("memw_rl(%0):st = %1\n\t"
|
||||
: : "r"(p), "r"(val) : "memory");
|
||||
}
|
||||
|
||||
static void test_storew_rl_st(void)
|
||||
{
|
||||
storew_rl_st(&buffer32[0], 13);
|
||||
check64(buffer32[0], 13);
|
||||
storew_rl_st(&buffer32[1], 14);
|
||||
check64(buffer32[1], 14);
|
||||
}
|
||||
|
||||
static inline void stored_rl_st(long long *p, long long val)
|
||||
{
|
||||
asm volatile("memd_rl(%0):st = %1\n\t"
|
||||
: : "r"(p), "r"(val) : "memory");
|
||||
}
|
||||
|
||||
static void test_stored_rl_st(void)
|
||||
{
|
||||
stored_rl_st(&buffer64[0], 15);
|
||||
check64(buffer64[0], 15);
|
||||
stored_rl_st(&buffer64[1], 15);
|
||||
check64(buffer64[1], 15);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test_loadw_aq();
|
||||
test_loadd_aq();
|
||||
test_release_at();
|
||||
test_release_st();
|
||||
test_storew_rl_at();
|
||||
test_stored_rl_at();
|
||||
test_storew_rl_st();
|
||||
test_stored_rl_st();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err ? 1 : 0;
|
||||
}
|
318
tests/tcg/hexagon/v69_hvx.c
Normal file
318
tests/tcg/hexagon/v69_hvx.c
Normal file
@ -0,0 +1,318 @@
|
||||
/*
|
||||
* 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 <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
int err;
|
||||
|
||||
#include "hvx_misc.h"
|
||||
|
||||
#define fVROUND(VAL, SHAMT) \
|
||||
((VAL) + (((SHAMT) > 0) ? (1LL << ((SHAMT) - 1)) : 0))
|
||||
|
||||
#define fVSATUB(VAL) \
|
||||
((((VAL) & 0xffLL) == (VAL)) ? \
|
||||
(VAL) : \
|
||||
((((int32_t)(VAL)) < 0) ? 0 : 0xff))
|
||||
|
||||
#define fVSATUH(VAL) \
|
||||
((((VAL) & 0xffffLL) == (VAL)) ? \
|
||||
(VAL) : \
|
||||
((((int32_t)(VAL)) < 0) ? 0 : 0xffff))
|
||||
|
||||
static void test_vasrvuhubrndsat(void)
|
||||
{
|
||||
void *p0 = buffer0;
|
||||
void *p1 = buffer1;
|
||||
void *pout = output;
|
||||
|
||||
memset(expect, 0xaa, sizeof(expect));
|
||||
memset(output, 0xbb, sizeof(output));
|
||||
|
||||
for (int i = 0; i < BUFSIZE / 2; i++) {
|
||||
asm("v4 = vmem(%0 + #0)\n\t"
|
||||
"v5 = vmem(%0 + #1)\n\t"
|
||||
"v6 = vmem(%1 + #0)\n\t"
|
||||
"v5.ub = vasr(v5:4.uh, v6.ub):rnd:sat\n\t"
|
||||
"vmem(%2) = v5\n\t"
|
||||
: : "r"(p0), "r"(p1), "r"(pout)
|
||||
: "v4", "v5", "v6", "memory");
|
||||
p0 += sizeof(MMVector) * 2;
|
||||
p1 += sizeof(MMVector);
|
||||
pout += sizeof(MMVector);
|
||||
|
||||
for (int j = 0; j < MAX_VEC_SIZE_BYTES / 2; j++) {
|
||||
int shamt;
|
||||
uint8_t byte0;
|
||||
uint8_t byte1;
|
||||
|
||||
shamt = buffer1[i].ub[2 * j + 0] & 0x7;
|
||||
byte0 = fVSATUB(fVROUND(buffer0[2 * i + 0].uh[j], shamt) >> shamt);
|
||||
shamt = buffer1[i].ub[2 * j + 1] & 0x7;
|
||||
byte1 = fVSATUB(fVROUND(buffer0[2 * i + 1].uh[j], shamt) >> shamt);
|
||||
expect[i].uh[j] = (byte1 << 8) | (byte0 & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
check_output_h(__LINE__, BUFSIZE / 2);
|
||||
}
|
||||
|
||||
static void test_vasrvuhubsat(void)
|
||||
{
|
||||
void *p0 = buffer0;
|
||||
void *p1 = buffer1;
|
||||
void *pout = output;
|
||||
|
||||
memset(expect, 0xaa, sizeof(expect));
|
||||
memset(output, 0xbb, sizeof(output));
|
||||
|
||||
for (int i = 0; i < BUFSIZE / 2; i++) {
|
||||
asm("v4 = vmem(%0 + #0)\n\t"
|
||||
"v5 = vmem(%0 + #1)\n\t"
|
||||
"v6 = vmem(%1 + #0)\n\t"
|
||||
"v5.ub = vasr(v5:4.uh, v6.ub):sat\n\t"
|
||||
"vmem(%2) = v5\n\t"
|
||||
: : "r"(p0), "r"(p1), "r"(pout)
|
||||
: "v4", "v5", "v6", "memory");
|
||||
p0 += sizeof(MMVector) * 2;
|
||||
p1 += sizeof(MMVector);
|
||||
pout += sizeof(MMVector);
|
||||
|
||||
for (int j = 0; j < MAX_VEC_SIZE_BYTES / 2; j++) {
|
||||
int shamt;
|
||||
uint8_t byte0;
|
||||
uint8_t byte1;
|
||||
|
||||
shamt = buffer1[i].ub[2 * j + 0] & 0x7;
|
||||
byte0 = fVSATUB(buffer0[2 * i + 0].uh[j] >> shamt);
|
||||
shamt = buffer1[i].ub[2 * j + 1] & 0x7;
|
||||
byte1 = fVSATUB(buffer0[2 * i + 1].uh[j] >> shamt);
|
||||
expect[i].uh[j] = (byte1 << 8) | (byte0 & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
check_output_h(__LINE__, BUFSIZE / 2);
|
||||
}
|
||||
|
||||
static void test_vasrvwuhrndsat(void)
|
||||
{
|
||||
void *p0 = buffer0;
|
||||
void *p1 = buffer1;
|
||||
void *pout = output;
|
||||
|
||||
memset(expect, 0xaa, sizeof(expect));
|
||||
memset(output, 0xbb, sizeof(output));
|
||||
|
||||
for (int i = 0; i < BUFSIZE / 2; i++) {
|
||||
asm("v4 = vmem(%0 + #0)\n\t"
|
||||
"v5 = vmem(%0 + #1)\n\t"
|
||||
"v6 = vmem(%1 + #0)\n\t"
|
||||
"v5.uh = vasr(v5:4.w, v6.uh):rnd:sat\n\t"
|
||||
"vmem(%2) = v5\n\t"
|
||||
: : "r"(p0), "r"(p1), "r"(pout)
|
||||
: "v4", "v5", "v6", "memory");
|
||||
p0 += sizeof(MMVector) * 2;
|
||||
p1 += sizeof(MMVector);
|
||||
pout += sizeof(MMVector);
|
||||
|
||||
for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
|
||||
int shamt;
|
||||
uint16_t half0;
|
||||
uint16_t half1;
|
||||
|
||||
shamt = buffer1[i].uh[2 * j + 0] & 0xf;
|
||||
half0 = fVSATUH(fVROUND(buffer0[2 * i + 0].w[j], shamt) >> shamt);
|
||||
shamt = buffer1[i].uh[2 * j + 1] & 0xf;
|
||||
half1 = fVSATUH(fVROUND(buffer0[2 * i + 1].w[j], shamt) >> shamt);
|
||||
expect[i].w[j] = (half1 << 16) | (half0 & 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
check_output_w(__LINE__, BUFSIZE / 2);
|
||||
}
|
||||
|
||||
static void test_vasrvwuhsat(void)
|
||||
{
|
||||
void *p0 = buffer0;
|
||||
void *p1 = buffer1;
|
||||
void *pout = output;
|
||||
|
||||
memset(expect, 0xaa, sizeof(expect));
|
||||
memset(output, 0xbb, sizeof(output));
|
||||
|
||||
for (int i = 0; i < BUFSIZE / 2; i++) {
|
||||
asm("v4 = vmem(%0 + #0)\n\t"
|
||||
"v5 = vmem(%0 + #1)\n\t"
|
||||
"v6 = vmem(%1 + #0)\n\t"
|
||||
"v5.uh = vasr(v5:4.w, v6.uh):sat\n\t"
|
||||
"vmem(%2) = v5\n\t"
|
||||
: : "r"(p0), "r"(p1), "r"(pout)
|
||||
: "v4", "v5", "v6", "memory");
|
||||
p0 += sizeof(MMVector) * 2;
|
||||
p1 += sizeof(MMVector);
|
||||
pout += sizeof(MMVector);
|
||||
|
||||
for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
|
||||
int shamt;
|
||||
uint16_t half0;
|
||||
uint16_t half1;
|
||||
|
||||
shamt = buffer1[i].uh[2 * j + 0] & 0xf;
|
||||
half0 = fVSATUH(buffer0[2 * i + 0].w[j] >> shamt);
|
||||
shamt = buffer1[i].uh[2 * j + 1] & 0xf;
|
||||
half1 = fVSATUH(buffer0[2 * i + 1].w[j] >> shamt);
|
||||
expect[i].w[j] = (half1 << 16) | (half0 & 0xffff);
|
||||
}
|
||||
}
|
||||
|
||||
check_output_w(__LINE__, BUFSIZE / 2);
|
||||
}
|
||||
|
||||
static void test_vassign_tmp(void)
|
||||
{
|
||||
void *p0 = buffer0;
|
||||
void *pout = output;
|
||||
|
||||
memset(expect, 0xaa, sizeof(expect));
|
||||
memset(output, 0xbb, sizeof(output));
|
||||
|
||||
for (int i = 0; i < BUFSIZE; i++) {
|
||||
/*
|
||||
* Assign into v12 as .tmp, then use it in the next packet
|
||||
* Should get the new value within the same packet and
|
||||
* the old value in the next packet
|
||||
*/
|
||||
asm("v3 = vmem(%0 + #0)\n\t"
|
||||
"r1 = #1\n\t"
|
||||
"v12 = vsplat(r1)\n\t"
|
||||
"r1 = #2\n\t"
|
||||
"v13 = vsplat(r1)\n\t"
|
||||
"{\n\t"
|
||||
" v12.tmp = v13\n\t"
|
||||
" v4.w = vadd(v12.w, v3.w)\n\t"
|
||||
"}\n\t"
|
||||
"v4.w = vadd(v4.w, v12.w)\n\t"
|
||||
"vmem(%1 + #0) = v4\n\t"
|
||||
: : "r"(p0), "r"(pout)
|
||||
: "r1", "v3", "v4", "v12", "v13", "memory");
|
||||
p0 += sizeof(MMVector);
|
||||
pout += sizeof(MMVector);
|
||||
|
||||
for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
|
||||
expect[i].w[j] = buffer0[i].w[j] + 3;
|
||||
}
|
||||
}
|
||||
|
||||
check_output_w(__LINE__, BUFSIZE);
|
||||
}
|
||||
|
||||
static void test_vcombine_tmp(void)
|
||||
{
|
||||
void *p0 = buffer0;
|
||||
void *p1 = buffer1;
|
||||
void *pout = output;
|
||||
|
||||
memset(expect, 0xaa, sizeof(expect));
|
||||
memset(output, 0xbb, sizeof(output));
|
||||
|
||||
for (int i = 0; i < BUFSIZE; i++) {
|
||||
/*
|
||||
* Combine into v13:12 as .tmp, then use it in the next packet
|
||||
* Should get the new value within the same packet and
|
||||
* the old value in the next packet
|
||||
*/
|
||||
asm("v3 = vmem(%0 + #0)\n\t"
|
||||
"r1 = #1\n\t"
|
||||
"v12 = vsplat(r1)\n\t"
|
||||
"r1 = #2\n\t"
|
||||
"v13 = vsplat(r1)\n\t"
|
||||
"r1 = #3\n\t"
|
||||
"v14 = vsplat(r1)\n\t"
|
||||
"r1 = #4\n\t"
|
||||
"v15 = vsplat(r1)\n\t"
|
||||
"{\n\t"
|
||||
" v13:12.tmp = vcombine(v15, v14)\n\t"
|
||||
" v4.w = vadd(v12.w, v3.w)\n\t"
|
||||
" v16 = v13\n\t"
|
||||
"}\n\t"
|
||||
"v4.w = vadd(v4.w, v12.w)\n\t"
|
||||
"v4.w = vadd(v4.w, v13.w)\n\t"
|
||||
"v4.w = vadd(v4.w, v16.w)\n\t"
|
||||
"vmem(%2 + #0) = v4\n\t"
|
||||
: : "r"(p0), "r"(p1), "r"(pout)
|
||||
: "r1", "v3", "v4", "v12", "v13", "v14", "v15", "v16", "memory");
|
||||
p0 += sizeof(MMVector);
|
||||
p1 += sizeof(MMVector);
|
||||
pout += sizeof(MMVector);
|
||||
|
||||
for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) {
|
||||
expect[i].w[j] = buffer0[i].w[j] + 10;
|
||||
}
|
||||
}
|
||||
|
||||
check_output_w(__LINE__, BUFSIZE);
|
||||
}
|
||||
|
||||
static void test_vmpyuhvs(void)
|
||||
{
|
||||
void *p0 = buffer0;
|
||||
void *p1 = buffer1;
|
||||
void *pout = output;
|
||||
|
||||
memset(expect, 0xaa, sizeof(expect));
|
||||
memset(output, 0xbb, sizeof(output));
|
||||
|
||||
for (int i = 0; i < BUFSIZE; i++) {
|
||||
asm("v4 = vmem(%0 + #0)\n\t"
|
||||
"v5 = vmem(%1 + #0)\n\t"
|
||||
"v4.uh = vmpy(V4.uh, v5.uh):>>16\n\t"
|
||||
"vmem(%2) = v4\n\t"
|
||||
: : "r"(p0), "r"(p1), "r"(pout)
|
||||
: "v4", "v5", "memory");
|
||||
p0 += sizeof(MMVector);
|
||||
p1 += sizeof(MMVector);
|
||||
pout += sizeof(MMVector);
|
||||
|
||||
for (int j = 0; j < MAX_VEC_SIZE_BYTES / 2; j++) {
|
||||
expect[i].uh[j] = (buffer0[i].uh[j] * buffer1[i].uh[j]) >> 16;
|
||||
}
|
||||
}
|
||||
|
||||
check_output_h(__LINE__, BUFSIZE);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
init_buffers();
|
||||
|
||||
test_vasrvuhubrndsat();
|
||||
test_vasrvuhubsat();
|
||||
test_vasrvwuhrndsat();
|
||||
test_vasrvwuhsat();
|
||||
|
||||
test_vassign_tmp();
|
||||
test_vcombine_tmp();
|
||||
|
||||
test_vmpyuhvs();
|
||||
|
||||
puts(err ? "FAIL" : "PASS");
|
||||
return err ? 1 : 0;
|
||||
}
|
161
tests/tcg/hexagon/v6mpy_ref.c.inc
Normal file
161
tests/tcg/hexagon/v6mpy_ref.c.inc
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright(c) 2021-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/>.
|
||||
*/
|
||||
|
||||
{ 0xffffee11, 0xfffffcca, 0xffffc1b3, 0xffffd0cc,
|
||||
0xffffe215, 0xfffff58e, 0xffffaf37, 0xffffc310,
|
||||
0xffffd919, 0xfffff152, 0xffff9fbb, 0xffffb854,
|
||||
0xffffd31d, 0xfffff016, 0xffff933f, 0xffffb098,
|
||||
0xffffd021, 0xfffff1da, 0xffff89c3, 0xffffabdc,
|
||||
0xffffd025, 0xfffff69e, 0xffff8347, 0xffffaa20,
|
||||
0xffffd329, 0xfffffe62, 0xffff7fcb, 0xffffab64,
|
||||
0xffffd92d, 0x00000926, 0xffff7f4f, 0xffffafa8,
|
||||
},
|
||||
{ 0xffffe231, 0x000016ea, 0xffff81d3, 0xffffb6ec,
|
||||
0xffffee35, 0x000027ae, 0xffff8757, 0xffffc130,
|
||||
0xfffffd39, 0x00003b72, 0xffff8fdb, 0xffffce74,
|
||||
0x00000f3d, 0x00005236, 0xffff9b5f, 0xffffdeb8,
|
||||
0x00002441, 0x00006bfa, 0xffffa9e3, 0xfffff1fc,
|
||||
0x00003c45, 0x000088be, 0xffffbb67, 0x00000840,
|
||||
0x00005749, 0x0000a882, 0xffffcfeb, 0xffffe684,
|
||||
0x0000494d, 0x00009a46, 0xffffb16f, 0x000002c8,
|
||||
},
|
||||
{ 0xfffff351, 0x0000440a, 0xffff4af3, 0xffff9c0c,
|
||||
0xffffef55, 0x000044ce, 0xffff4077, 0xffff9650,
|
||||
0xffffee59, 0x00004892, 0xffff38fb, 0xffff9394,
|
||||
0xfffff05d, 0x00004f56, 0xffff347f, 0xffff93d8,
|
||||
0xfffff561, 0x0000591a, 0xffff3303, 0xffff971c,
|
||||
0xfffffd65, 0x000065de, 0xffff3487, 0xffff9d60,
|
||||
0x00000869, 0x000075a2, 0xffff390b, 0xffffa6a4,
|
||||
0x0000166d, 0x00008866, 0xffff408f, 0xffffb2e8,
|
||||
},
|
||||
{ 0x00002771, 0x00009e2a, 0xffff4b13, 0xffffc22c,
|
||||
0x00003b75, 0x0000b6ee, 0xffff5897, 0xffffd470,
|
||||
0x00005279, 0x0000d2b2, 0xffff691b, 0xffffe9b4,
|
||||
0x00006c7d, 0x0000f176, 0xffff7c9f, 0x000001f8,
|
||||
0x00008981, 0x0001133a, 0xffff9323, 0x00001d3c,
|
||||
0x0000a985, 0x000137fe, 0xffffaca7, 0x00003b80,
|
||||
0x0000cc89, 0x00015fc2, 0xffffc92b, 0xffffe1c4,
|
||||
0x0000868d, 0x00011986, 0xffff72af, 0x00000608,
|
||||
},
|
||||
{ 0xfffff891, 0x00008b4a, 0xfffed433, 0xffff674c,
|
||||
0xfffffc95, 0x0000940e, 0xfffed1b7, 0xffff6990,
|
||||
0x00000399, 0x00009fd2, 0xfffed23b, 0xffff6ed4,
|
||||
0x00000d9d, 0x0000ae96, 0xfffed5bf, 0xffff7718,
|
||||
0x00001aa1, 0x0000c05a, 0xfffedc43, 0xffff825c,
|
||||
0x00002aa5, 0x0000d51e, 0xfffee5c7, 0xffff90a0,
|
||||
0x00003da9, 0x0000ece2, 0xfffef24b, 0xffffa1e4,
|
||||
0x000053ad, 0x000107a6, 0xffff01cf, 0xffffb628,
|
||||
},
|
||||
{ 0x00006cb1, 0x0001256a, 0xffff1453, 0xffffcd6c,
|
||||
0x000088b5, 0x0001462e, 0xffff29d7, 0xffffe7b0,
|
||||
0x0000a7b9, 0x000169f2, 0xffff425b, 0x000004f4,
|
||||
0x0000c9bd, 0x000190b6, 0xffff5ddf, 0x00002538,
|
||||
0x0000eec1, 0x0001ba7a, 0xffff7c63, 0x0000487c,
|
||||
0x000116c5, 0x0001e73e, 0xffff9de7, 0x00006ec0,
|
||||
0x000141c9, 0x00021702, 0xffffc26b, 0xffffdd04,
|
||||
0x0000c3cd, 0x000198c6, 0xffff33ef, 0x00000948,
|
||||
},
|
||||
{ 0xfffffdd1, 0x0000d28a, 0xfffe5d73, 0xffff328c,
|
||||
0x000009d5, 0x0000e34e, 0xfffe62f7, 0xffff3cd0,
|
||||
0x000018d9, 0x0000f712, 0xfffe6b7b, 0xffff4a14,
|
||||
0x00002add, 0x00010dd6, 0xfffe76ff, 0xffff5a58,
|
||||
0x00003fe1, 0x0001279a, 0xfffe8583, 0xffff6d9c,
|
||||
0x000057e5, 0x0001445e, 0xfffe9707, 0xffff83e0,
|
||||
0x000072e9, 0x00016422, 0xfffeab8b, 0xffff9d24,
|
||||
0x000090ed, 0x000186e6, 0xfffec30f, 0xffffb968,
|
||||
},
|
||||
{ 0x0000b1f1, 0x0001acaa, 0xfffedd93, 0xffffd8ac,
|
||||
0x0000d5f5, 0x0001d56e, 0xfffefb17, 0xfffffaf0,
|
||||
0x0000fcf9, 0x00020132, 0xffff1b9b, 0x00002034,
|
||||
0x000126fd, 0x00022ff6, 0xffff3f1f, 0x00008b36,
|
||||
0x000093c3, 0x00009d80, 0x00009d6d, 0x0000a78a,
|
||||
0x0000b4d7, 0x0000c354, 0x0000b801, 0x0000c6de,
|
||||
0x0000d4eb, 0x0000e828, 0x0000d195, 0xffffea32,
|
||||
0x00000fff, 0x000022fc, 0xfffffc29, 0x00000f86,
|
||||
},
|
||||
{ 0xffffee13, 0xfffffcd0, 0xffffc1bd, 0xffffd0da,
|
||||
0xffffe327, 0xfffff6a4, 0xffffb051, 0xffffc42e,
|
||||
0xffffd73b, 0xffffef78, 0xffff9de5, 0xffffb682,
|
||||
0xffffd24f, 0xffffef4c, 0xffff9279, 0xffffafd6,
|
||||
0xffffd063, 0xfffff220, 0xffff8a0d, 0xffffac2a,
|
||||
0xffffd177, 0xfffff7f4, 0xffff84a1, 0xffffab7e,
|
||||
0xffffd18b, 0xfffffcc8, 0xffff7e35, 0xffffa9d2,
|
||||
0xffffd89f, 0x0000089c, 0xffff7ec9, 0xffffaf26,
|
||||
},
|
||||
{ 0xffffe2b3, 0x00001770, 0xffff825d, 0xffffb77a,
|
||||
0xffffefc7, 0x00002944, 0xffff88f1, 0xffffc2ce,
|
||||
0xfffffbdb, 0x00003a18, 0xffff8e85, 0xffffcd22,
|
||||
0x00000eef, 0x000051ec, 0xffff9b19, 0xffffde76,
|
||||
0x00002503, 0x00006cc0, 0xffffaaad, 0xfffff2ca,
|
||||
0x00003e17, 0x00008a94, 0xffffbd41, 0x00000a1e,
|
||||
0x0000562b, 0x0000a768, 0xffffced5, 0xffffe572,
|
||||
0x0000493f, 0x00009a3c, 0xffffb169, 0x000002c6,
|
||||
},
|
||||
{ 0xfffff353, 0x00004410, 0xffff4afd, 0xffff9c1a,
|
||||
0xfffff067, 0x000045e4, 0xffff4191, 0xffff976e,
|
||||
0xffffec7b, 0x000046b8, 0xffff3725, 0xffff91c2,
|
||||
0xffffef8f, 0x00004e8c, 0xffff33b9, 0xffff9316,
|
||||
0xfffff5a3, 0x00005960, 0xffff334d, 0xffff976a,
|
||||
0xfffffeb7, 0x00006734, 0xffff35e1, 0xffff9ebe,
|
||||
0x000006cb, 0x00007408, 0xffff3775, 0xffffa512,
|
||||
0x000015df, 0x000087dc, 0xffff4009, 0xffffb266,
|
||||
},
|
||||
{ 0x000027f3, 0x00009eb0, 0xffff4b9d, 0xffffc2ba,
|
||||
0x00003d07, 0x0000b884, 0xffff5a31, 0xffffd60e,
|
||||
0x0000511b, 0x0000d158, 0xffff67c5, 0xffffe862,
|
||||
0x00006c2f, 0x0000f12c, 0xffff7c59, 0x000001b6,
|
||||
0x00008a43, 0x00011400, 0xffff93ed, 0x00001e0a,
|
||||
0x0000ab57, 0x000139d4, 0xffffae81, 0x00003d5e,
|
||||
0x0000cb6b, 0x00015ea8, 0xffffc815, 0xffffe0b2,
|
||||
0x0000867f, 0x0001197c, 0xffff72a9, 0x00000606,
|
||||
},
|
||||
{ 0xfffff893, 0x00008b50, 0xfffed43d, 0xffff675a,
|
||||
0xfffffda7, 0x00009524, 0xfffed2d1, 0xffff6aae,
|
||||
0x000001bb, 0x00009df8, 0xfffed065, 0xffff6d02,
|
||||
0x00000ccf, 0x0000adcc, 0xfffed4f9, 0xffff7656,
|
||||
0x00001ae3, 0x0000c0a0, 0xfffedc8d, 0xffff82aa,
|
||||
0x00002bf7, 0x0000d674, 0xfffee721, 0xffff91fe,
|
||||
0x00003c0b, 0x0000eb48, 0xfffef0b5, 0xffffa052,
|
||||
0x0000531f, 0x0001071c, 0xffff0149, 0xffffb5a6,
|
||||
},
|
||||
{ 0x00006d33, 0x000125f0, 0xffff14dd, 0xffffcdfa,
|
||||
0x00008a47, 0x000147c4, 0xffff2b71, 0xffffe94e,
|
||||
0x0000a65b, 0x00016898, 0xffff4105, 0x000003a2,
|
||||
0x0000c96f, 0x0001906c, 0xffff5d99, 0x000024f6,
|
||||
0x0000ef83, 0x0001bb40, 0xffff7d2d, 0x0000494a,
|
||||
0x00011897, 0x0001e914, 0xffff9fc1, 0x0000709e,
|
||||
0x000140ab, 0x000215e8, 0xffffc155, 0xffffdbf2,
|
||||
0x0000c3bf, 0x000198bc, 0xffff33e9, 0x00000946,
|
||||
},
|
||||
{ 0xfffffdd3, 0x0000d290, 0xfffe5d7d, 0xffff329a,
|
||||
0x00000ae7, 0x0000e464, 0xfffe6411, 0xffff3dee,
|
||||
0x000016fb, 0x0000f538, 0xfffe69a5, 0xffff4842,
|
||||
0x00002a0f, 0x00010d0c, 0xfffe7639, 0xffff5996,
|
||||
0x00004023, 0x000127e0, 0xfffe85cd, 0xffff6dea,
|
||||
0x00005937, 0x000145b4, 0xfffe9861, 0xffff853e,
|
||||
0x0000714b, 0x00016288, 0xfffea9f5, 0xffff9b92,
|
||||
0x0000905f, 0x0001865c, 0xfffec289, 0xffffb8e6,
|
||||
},
|
||||
{ 0x0000b273, 0x0001ad30, 0xfffede1d, 0xffffd93a,
|
||||
0x0000d787, 0x0001d704, 0xfffefcb1, 0xfffffc8e,
|
||||
0x0000fb9b, 0x0001ffd8, 0xffff1a45, 0x00001ee2,
|
||||
0x000126af, 0x00022fac, 0xffff3ed9, 0x00008af4,
|
||||
0x00009485, 0x00009e46, 0x00009e37, 0x0000a858,
|
||||
0x0000b6a9, 0x0000c52a, 0x0000b9db, 0x0000c8bc,
|
||||
0x0000d3cd, 0x0000e70e, 0x0000d07f, 0xffffe920,
|
||||
0x00000ff1, 0x000022f2, 0xfffffc23, 0x00000f84,
|
||||
},
|
96
tests/tcg/hexagon/v73_scalar.c
Normal file
96
tests/tcg/hexagon/v73_scalar.c
Normal file
@ -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 <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
* 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(&my_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;
|
||||
}
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user