Merge tag 'pull-hex-20221216-1' of https://github.com/quic/qemu into staging

1)
Performance improvement
Add pkt and insn to DisasContext
Many functions need information from all 3 structures, so merge
them together.

2)
Bug fix
Fix predicated assignment to .tmp and .cur

3)
Performance improvement
Add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat
These functions will not be handled by idef-parser

4-11)
The final 8 patches improve change-of-flow handling.

Currently, we set the PC to a new address before exiting a TB.  The
ultimate goal is to use direct block chaining.  However, several steps
are needed along the way.

4)
When a packet has more than one change-of-flow (COF) instruction, only
the first one taken is considered.  The runtime bookkeeping is only
needed when there is more than one COF instruction in a packet.

5, 6)
Remove PC and next_PC from the runtime state and always use a
translation-time constant.  Note that next_PC is used by call instructions
to set LR and by conditional COF instructions to set the fall-through
address.

7, 8, 9)
Add helper overrides for COF instructions.  In particular, we must
distinguish those that use a PC-relative address for the destination.
These are candidates for direct block chaining later.

10)
Use direct block chaining for packets that have a single PC-relative
COF instruction.  Instead of generating the code while processing the
instruction, we record the effect in DisasContext and generate the code
during gen_end_tb.

11)
Use direct block chaining for tight loops.  We look for TBs that end
with an endloop0 that will branch back to the TB start address.

12-21)
Instruction definition parser (idef-parser) from rev.ng
Parses the instruction semantics and generates TCG

# gpg: Signature made Fri 16 Dec 2022 20:41:53 GMT
# gpg:                using RSA key 3635C788CE62B91FD4C59AB47B0244FB12DE4422
# gpg: Good signature from "Taylor Simpson (Rock on) <tsimpson@quicinc.com>" [undefined]
# 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-20221216-1' of https://github.com/quic/qemu: (21 commits)
  target/hexagon: import additional tests
  target/hexagon: call idef-parser functions
  target/hexagon: import parser for idef-parser
  target/hexagon: import lexer for idef-parser
  target/hexagon: prepare input for the idef-parser
  target/hexagon: introduce new helper functions
  target/hexagon: make helper functions non-static
  target/hexagon: make slot number an unsigned
  target/hexagon: import README for idef-parser
  target/hexagon: update MAINTAINERS for idef-parser
  Hexagon (target/hexagon) Use direct block chaining for tight loops
  Hexagon (target/hexagon) Use direct block chaining for direct jump/branch
  Hexagon (target/hexagon) Add overrides for various forms of jump
  Hexagon (target/hexagon) Add overrides for compound compare and jump
  Hexagon (target/hexagon) Add overrides for direct call instructions
  Hexagon (target/hexagon) Remove next_PC from runtime state
  Hexagon (target/hexagon) Remove PC from the runtime state
  Hexagon (target/hexagon) Only use branch_taken when packet has multi cof
  Hexagon (target/hexagon) Add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat
  Hexagon (target/hexagon) Fix predicated assignment to .tmp and .cur
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell
2022-12-18 17:02:11 +00:00
59 changed files with 7908 additions and 210 deletions
+9
View File
@@ -197,6 +197,8 @@ Hexagon TCG CPUs
M: Taylor Simpson <tsimpson@quicinc.com>
S: Supported
F: target/hexagon/
X: target/hexagon/idef-parser/
X: target/hexagon/gen_idef_parser_funcs.py
F: linux-user/hexagon/
F: tests/tcg/hexagon/
F: disas/hexagon.c
@@ -204,6 +206,13 @@ F: configs/targets/hexagon-linux-user/default.mak
F: docker/dockerfiles/debian-hexagon-cross.docker
F: docker/dockerfiles/debian-hexagon-cross.docker.d/build-toolchain.sh
Hexagon idef-parser
M: Alessandro Di Federico <ale@rev.ng>
M: Anton Johansson <anjo@rev.ng>
S: Supported
F: target/hexagon/idef-parser/
F: target/hexagon/gen_idef_parser_funcs.py
HPPA (PA-RISC) TCG CPUs
M: Richard Henderson <richard.henderson@linaro.org>
S: Maintained
+3
View File
@@ -321,3 +321,6 @@ option('profiler', type: 'boolean', value: false,
description: 'profiler support')
option('slirp_smbd', type : 'feature', value : 'auto',
description: 'use smbd (at path --smbd=*) in slirp networking')
option('hexagon_idef_parser', type : 'boolean', value : true,
description: 'use idef-parser to automatically generate TCG code for the Hexagon frontend')
+5
View File
@@ -27,6 +27,10 @@ Hexagon-specific code are
encode*.def Encoding patterns for each instruction
iclass.def Instruction class definitions used to determine
legal VLIW slots for each instruction
qemu/target/hexagon/idef-parser
Parser that, given the high-level definitions of an instruction,
produces a C function generating equivalent tiny code instructions.
See README.rst.
qemu/linux-user/hexagon
Helpers for loading the ELF file and making Linux system calls,
signals, etc
@@ -47,6 +51,7 @@ header files in <BUILD_DIR>/target/hexagon
gen_tcg_funcs.py -> tcg_funcs_generated.c.inc
gen_tcg_func_table.py -> tcg_func_table_generated.c.inc
gen_helper_funcs.py -> helper_funcs_generated.c.inc
gen_idef_parser_funcs.py -> idef_parser_input.h
Qemu helper functions have 3 parts
DEF_HELPER declaration indicates the signature of the helper
+8 -6
View File
@@ -25,6 +25,7 @@
#include "mmvec/mmvec.h"
#include "qom/object.h"
#include "hw/core/cpu.h"
#include "hw/registerfields.h"
#define NUM_PREGS 4
#define TOTAL_PER_THREAD_REGS 64
@@ -78,7 +79,6 @@ typedef struct CPUArchState {
target_ulong gpr[TOTAL_PER_THREAD_REGS];
target_ulong pred[NUM_PREGS];
target_ulong branch_taken;
target_ulong next_PC;
/* For comparing with LLDB on target - see adjust_stack_ptrs function */
target_ulong last_pc_dumped;
@@ -153,16 +153,18 @@ struct ArchCPU {
#include "cpu_bits.h"
FIELD(TB_FLAGS, IS_TIGHT_LOOP, 0, 1)
static inline void cpu_get_tb_cpu_state(CPUHexagonState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *flags)
{
uint32_t hex_flags = 0;
*pc = env->gpr[HEX_REG_PC];
*cs_base = 0;
#ifdef CONFIG_USER_ONLY
*flags = 0;
#else
#error System mode not supported on Hexagon yet
#endif
if (*pc == env->gpr[HEX_REG_SA0]) {
hex_flags = FIELD_DP32(hex_flags, TB_FLAGS, IS_TIGHT_LOOP, 1);
}
*flags = hex_flags;
}
static inline int cpu_mmu_index(CPUHexagonState *env, bool ifetch)
+13 -2
View File
@@ -388,6 +388,7 @@ static void decode_set_insn_attr_fields(Packet *pkt)
uint16_t opcode;
pkt->pkt_has_cof = false;
pkt->pkt_has_multi_cof = false;
pkt->pkt_has_endloop = false;
pkt->pkt_has_dczeroa = false;
@@ -412,13 +413,23 @@ static void decode_set_insn_attr_fields(Packet *pkt)
}
}
pkt->pkt_has_cof |= decode_opcode_can_jump(opcode);
if (decode_opcode_can_jump(opcode)) {
if (pkt->pkt_has_cof) {
pkt->pkt_has_multi_cof = true;
}
pkt->pkt_has_cof = true;
}
pkt->insn[i].is_endloop = decode_opcode_ends_loop(opcode);
pkt->pkt_has_endloop |= pkt->insn[i].is_endloop;
pkt->pkt_has_cof |= pkt->pkt_has_endloop;
if (pkt->pkt_has_endloop) {
if (pkt->pkt_has_cof) {
pkt->pkt_has_multi_cof = true;
}
pkt->pkt_has_cof = true;
}
}
}
+28 -2
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
##
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
## Copyright(c) 2019-2022 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
@@ -238,6 +238,17 @@ def gen_helper_function(f, tag, tagregs, tagimms):
gen_helper_arg_imm(f,immlett)
i += 1
if (hex_common.need_pkt_has_multi_cof(tag)):
f.write(", uint32_t pkt_has_multi_cof")
if hex_common.need_PC(tag):
if i > 0: f.write(", ")
f.write("target_ulong PC")
i += 1
if hex_common.helper_needs_next_PC(tag):
if i > 0: f.write(", ")
f.write("target_ulong next_PC")
i += 1
if hex_common.need_slot(tag):
if i > 0: f.write(", ")
f.write("uint32_t slot")
@@ -287,11 +298,24 @@ def main():
hex_common.read_attribs_file(sys.argv[2])
hex_common.read_overrides_file(sys.argv[3])
hex_common.read_overrides_file(sys.argv[4])
## Whether or not idef-parser is enabled is
## determined by the number of arguments to
## this script:
##
## 5 args. -> not enabled,
## 6 args. -> idef-parser enabled.
##
## The 6:th arg. then holds a list of the successfully
## parsed instructions.
is_idef_parser_enabled = len(sys.argv) > 6
if is_idef_parser_enabled:
hex_common.read_idef_parser_enabled_file(sys.argv[5])
hex_common.calculate_attribs()
tagregs = hex_common.get_tagregs()
tagimms = hex_common.get_tagimms()
with open(sys.argv[5], 'w') as f:
output_file = sys.argv[-1]
with open(output_file, 'w') as f:
for tag in hex_common.tags:
## Skip the priv instructions
if ( "A_PRIV" in hex_common.attribdict[tag] ) :
@@ -308,6 +332,8 @@ def main():
continue
if ( hex_common.skip_qemu_helper(tag) ):
continue
if ( hex_common.is_idef_parser_enabled(tag) ):
continue
gen_helper_function(f, tag, tagregs, tagimms)
+28 -3
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
##
## Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
## Copyright(c) 2019-2022 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
@@ -82,15 +82,21 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
## Figure out how many arguments the helper will take
if (numscalarresults == 0):
def_helper_size = len(regs)+len(imms)+numscalarreadwrite+1
if hex_common.need_pkt_has_multi_cof(tag): def_helper_size += 1
if hex_common.need_part1(tag): def_helper_size += 1
if hex_common.need_slot(tag): def_helper_size += 1
if hex_common.need_PC(tag): def_helper_size += 1
if hex_common.helper_needs_next_PC(tag): def_helper_size += 1
f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
## The return type is void
f.write(', void' )
else:
def_helper_size = len(regs)+len(imms)+numscalarreadwrite
if hex_common.need_pkt_has_multi_cof(tag): def_helper_size += 1
if hex_common.need_part1(tag): def_helper_size += 1
if hex_common.need_slot(tag): def_helper_size += 1
if hex_common.need_PC(tag): def_helper_size += 1
if hex_common.helper_needs_next_PC(tag): def_helper_size += 1
f.write('DEF_HELPER_%s(%s' % (def_helper_size, tag))
## Generate the qemu DEF_HELPER type for each result
@@ -126,7 +132,11 @@ def gen_helper_prototype(f, tag, tagregs, tagimms):
for immlett,bits,immshift in imms:
f.write(", s32")
## Add the arguments for the instruction slot and part1 (if needed)
## Add the arguments for the instruction pkt_has_multi_cof, slot and
## part1 (if needed)
if hex_common.need_pkt_has_multi_cof(tag): f.write(', i32')
if hex_common.need_PC(tag): f.write(', i32')
if hex_common.helper_needs_next_PC(tag): f.write(', i32')
if hex_common.need_slot(tag): f.write(', i32' )
if hex_common.need_part1(tag): f.write(' , i32' )
f.write(')\n')
@@ -136,11 +146,24 @@ def main():
hex_common.read_attribs_file(sys.argv[2])
hex_common.read_overrides_file(sys.argv[3])
hex_common.read_overrides_file(sys.argv[4])
## Whether or not idef-parser is enabled is
## determined by the number of arguments to
## this script:
##
## 5 args. -> not enabled,
## 6 args. -> idef-parser enabled.
##
## The 6:th arg. then holds a list of the successfully
## parsed instructions.
is_idef_parser_enabled = len(sys.argv) > 6
if is_idef_parser_enabled:
hex_common.read_idef_parser_enabled_file(sys.argv[5])
hex_common.calculate_attribs()
tagregs = hex_common.get_tagregs()
tagimms = hex_common.get_tagimms()
with open(sys.argv[5], 'w') as f:
output_file = sys.argv[-1]
with open(output_file, 'w') as f:
for tag in hex_common.tags:
## Skip the priv instructions
if ( "A_PRIV" in hex_common.attribdict[tag] ) :
@@ -158,6 +181,8 @@ def main():
if ( hex_common.skip_qemu_helper(tag) ):
continue
if ( hex_common.is_idef_parser_enabled(tag) ):
continue
gen_helper_prototype(f, tag, tagregs, tagimms)
+130
View File
@@ -0,0 +1,130 @@
#!/usr/bin/env python3
##
## Copyright(c) 2019-2022 rev.ng Labs Srl. All Rights Reserved.
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program; if not, see <http://www.gnu.org/licenses/>.
##
import sys
import re
import string
from io import StringIO
import hex_common
##
## Generate code to be fed to the idef_parser
##
## Consider A2_add:
##
## Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
##
## We produce:
##
## A2_add(RdV, in RsV, in RtV) {
## { RdV=RsV+RtV;}
## }
##
## A2_add represents the instruction tag. Then we have a list of TCGv
## that the code generated by the parser can expect in input. Some of
## them are inputs ("in" prefix), while some others are outputs.
##
def main():
hex_common.read_semantics_file(sys.argv[1])
hex_common.read_attribs_file(sys.argv[2])
hex_common.calculate_attribs()
tagregs = hex_common.get_tagregs()
tagimms = hex_common.get_tagimms()
with open(sys.argv[3], 'w') as f:
f.write('#include "macros.inc"\n\n')
for tag in hex_common.tags:
## Skip the priv instructions
if ( "A_PRIV" in hex_common.attribdict[tag] ) :
continue
## Skip the guest instructions
if ( "A_GUEST" in hex_common.attribdict[tag] ) :
continue
## Skip instructions that saturate in a ternary expression
if ( tag in {'S2_asr_r_r_sat', 'S2_asl_r_r_sat'} ) :
continue
## Skip instructions using switch
if ( tag in {'S4_vrcrotate_acc', 'S4_vrcrotate'} ) :
continue
## Skip trap instructions
if ( tag in {'J2_trap0', 'J2_trap1'} ) :
continue
## Skip 128-bit instructions
if ( tag in {'A7_croundd_ri', 'A7_croundd_rr'} ) :
continue
if ( tag in {'M7_wcmpyrw', 'M7_wcmpyrwc',
'M7_wcmpyiw', 'M7_wcmpyiwc',
'M7_wcmpyrw_rnd', 'M7_wcmpyrwc_rnd',
'M7_wcmpyiw_rnd', 'M7_wcmpyiwc_rnd'} ) :
continue
## Skip interleave/deinterleave instructions
if ( tag in {'S2_interleave', 'S2_deinterleave'} ) :
continue
## Skip instructions using bit reverse
if ( tag in {'S2_brev', 'S2_brevp', 'S2_ct0', 'S2_ct1',
'S2_ct0p', 'S2_ct1p', 'A4_tlbmatch'} ) :
continue
## Skip other unsupported instructions
if ( tag == 'S2_cabacdecbin' or tag == 'A5_ACS' ) :
continue
if ( tag.startswith('Y') ) :
continue
if ( tag.startswith('V6_') ) :
continue
if ( tag.startswith('F') ) :
continue
if ( tag.endswith('_locked') ) :
continue
if ( "A_COF" in hex_common.attribdict[tag] ) :
continue
regs = tagregs[tag]
imms = tagimms[tag]
arguments = []
for regtype,regid,toss,numregs in regs:
prefix = "in " if hex_common.is_read(regid) else ""
is_pair = hex_common.is_pair(regid)
is_single_old = (hex_common.is_single(regid)
and hex_common.is_old_val(regtype, regid, tag))
is_single_new = (hex_common.is_single(regid)
and hex_common.is_new_val(regtype, regid, tag))
if is_pair or is_single_old:
arguments.append("%s%s%sV" % (prefix, regtype, regid))
elif is_single_new:
arguments.append("%s%s%sN" % (prefix, regtype, regid))
else:
print("Bad register parse: ",regtype,regid,toss,numregs)
for immlett,bits,immshift in imms:
arguments.append(hex_common.imm_name(immlett))
f.write("%s(%s) {\n" % (tag, ", ".join(arguments)))
f.write(" ");
if hex_common.need_ea(tag):
f.write("size4u_t EA; ");
f.write("%s\n" % hex_common.semdict[tag])
f.write("}\n\n")
if __name__ == "__main__":
main()
+411 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
* Copyright(c) 2019-2022 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
@@ -612,6 +612,409 @@
tcg_temp_free(tmp); \
} while (0)
#define fGEN_TCG_J2_call(SHORTCODE) \
gen_call(ctx, riV)
#define fGEN_TCG_J2_callt(SHORTCODE) \
gen_cond_call(ctx, PuV, TCG_COND_EQ, riV)
#define fGEN_TCG_J2_callf(SHORTCODE) \
gen_cond_call(ctx, PuV, TCG_COND_NE, riV)
#define fGEN_TCG_J2_endloop0(SHORTCODE) \
gen_endloop0(ctx)
/*
* Compound compare and jump instructions
* Here is a primer to understand the tag names
*
* Comparison
* cmpeqi compare equal to an immediate
* cmpgti compare greater than an immediate
* cmpgtiu compare greater than an unsigned immediate
* cmpeqn1 compare equal to negative 1
* cmpgtn1 compare greater than negative 1
* cmpeq compare equal (two registers)
* cmpgtu compare greater than unsigned (two registers)
* tstbit0 test bit zero
*
* Condition
* tp0 p0 is true p0 = cmp.eq(r0,#5); if (p0.new) jump:nt address
* fp0 p0 is false p0 = cmp.eq(r0,#5); if (!p0.new) jump:nt address
* tp1 p1 is true p1 = cmp.eq(r0,#5); if (p1.new) jump:nt address
* fp1 p1 is false p1 = cmp.eq(r0,#5); if (!p1.new) jump:nt address
*
* Prediction (not modelled in qemu)
* _nt not taken
* _t taken
*/
#define fGEN_TCG_J4_cmpeq_tp0_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_EQ, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpeq_tp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_EQ, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpeq_fp0_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_EQ, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpeq_fp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_EQ, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpeq_tp1_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_EQ, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpeq_tp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_EQ, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpeq_fp1_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_EQ, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpeq_fp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_EQ, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgt_tp0_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_GT, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgt_tp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_GT, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgt_fp0_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_GT, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgt_fp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_GT, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgt_tp1_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_GT, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgt_tp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_GT, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgt_fp1_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_GT, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgt_fp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_GT, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgtu_tp0_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_GTU, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgtu_tp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 0, TCG_COND_GTU, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgtu_fp0_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_GTU, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgtu_fp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 0, TCG_COND_GTU, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgtu_tp1_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_GTU, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgtu_tp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_t(ctx, 1, TCG_COND_GTU, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgtu_fp1_jump_t(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_GTU, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpgtu_fp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_jmp_f(ctx, 1, TCG_COND_GTU, RsV, RtV, riV)
#define fGEN_TCG_J4_cmpeqi_tp0_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_EQ, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpeqi_tp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_EQ, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpeqi_fp0_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_EQ, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpeqi_fp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_EQ, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpeqi_tp1_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_EQ, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpeqi_tp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_EQ, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpeqi_fp1_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_EQ, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpeqi_fp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_EQ, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgti_tp0_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_GT, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgti_tp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_GT, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgti_fp0_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_GT, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgti_fp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_GT, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgti_tp1_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_GT, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgti_tp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_GT, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgti_fp1_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_GT, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgti_fp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_GT, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgtui_tp0_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_GTU, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgtui_tp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 0, TCG_COND_GTU, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgtui_fp0_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_GTU, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgtui_fp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 0, TCG_COND_GTU, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgtui_tp1_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_GTU, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgtui_tp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_t(ctx, 1, TCG_COND_GTU, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgtui_fp1_jump_t(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_GTU, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpgtui_fp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmpi_jmp_f(ctx, 1, TCG_COND_GTU, RsV, UiV, riV)
#define fGEN_TCG_J4_cmpeqn1_tp0_jump_t(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_t(ctx, 0, TCG_COND_EQ, RsV, riV)
#define fGEN_TCG_J4_cmpeqn1_tp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_t(ctx, 0, TCG_COND_EQ, RsV, riV)
#define fGEN_TCG_J4_cmpeqn1_fp0_jump_t(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_f(ctx, 0, TCG_COND_EQ, RsV, riV)
#define fGEN_TCG_J4_cmpeqn1_fp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_f(ctx, 0, TCG_COND_EQ, RsV, riV)
#define fGEN_TCG_J4_cmpeqn1_tp1_jump_t(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_t(ctx, 1, TCG_COND_EQ, RsV, riV)
#define fGEN_TCG_J4_cmpeqn1_tp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_t(ctx, 1, TCG_COND_EQ, RsV, riV)
#define fGEN_TCG_J4_cmpeqn1_fp1_jump_t(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_f(ctx, 1, TCG_COND_EQ, RsV, riV)
#define fGEN_TCG_J4_cmpeqn1_fp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_f(ctx, 1, TCG_COND_EQ, RsV, riV)
#define fGEN_TCG_J4_cmpgtn1_tp0_jump_t(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_t(ctx, 0, TCG_COND_GT, RsV, riV)
#define fGEN_TCG_J4_cmpgtn1_tp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_t(ctx, 0, TCG_COND_GT, RsV, riV)
#define fGEN_TCG_J4_cmpgtn1_fp0_jump_t(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_f(ctx, 0, TCG_COND_GT, RsV, riV)
#define fGEN_TCG_J4_cmpgtn1_fp0_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_f(ctx, 0, TCG_COND_GT, RsV, riV)
#define fGEN_TCG_J4_cmpgtn1_tp1_jump_t(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_t(ctx, 1, TCG_COND_GT, RsV, riV)
#define fGEN_TCG_J4_cmpgtn1_tp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_t(ctx, 1, TCG_COND_GT, RsV, riV)
#define fGEN_TCG_J4_cmpgtn1_fp1_jump_t(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_f(ctx, 1, TCG_COND_GT, RsV, riV)
#define fGEN_TCG_J4_cmpgtn1_fp1_jump_nt(SHORTCODE) \
gen_cmpnd_cmp_n1_jmp_f(ctx, 1, TCG_COND_GT, RsV, riV)
#define fGEN_TCG_J4_tstbit0_tp0_jump_nt(SHORTCODE) \
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_EQ, riV)
#define fGEN_TCG_J4_tstbit0_tp0_jump_t(SHORTCODE) \
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_EQ, riV)
#define fGEN_TCG_J4_tstbit0_fp0_jump_nt(SHORTCODE) \
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_NE, riV)
#define fGEN_TCG_J4_tstbit0_fp0_jump_t(SHORTCODE) \
gen_cmpnd_tstbit0_jmp(ctx, 0, RsV, TCG_COND_NE, riV)
#define fGEN_TCG_J4_tstbit0_tp1_jump_nt(SHORTCODE) \
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_EQ, riV)
#define fGEN_TCG_J4_tstbit0_tp1_jump_t(SHORTCODE) \
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_EQ, riV)
#define fGEN_TCG_J4_tstbit0_fp1_jump_nt(SHORTCODE) \
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_NE, riV)
#define fGEN_TCG_J4_tstbit0_fp1_jump_t(SHORTCODE) \
gen_cmpnd_tstbit0_jmp(ctx, 1, RsV, TCG_COND_NE, riV)
#define fGEN_TCG_J2_jump(SHORTCODE) \
gen_jump(ctx, riV)
#define fGEN_TCG_J2_jumpr(SHORTCODE) \
gen_jumpr(ctx, RsV)
#define fGEN_TCG_J4_jumpseti(SHORTCODE) \
do { \
tcg_gen_movi_tl(RdV, UiV); \
gen_jump(ctx, riV); \
} while (0)
#define fGEN_TCG_cond_jumpt(COND) \
do { \
TCGv LSB = tcg_temp_new(); \
COND; \
gen_cond_jump(ctx, TCG_COND_EQ, LSB, riV); \
tcg_temp_free(LSB); \
} while (0)
#define fGEN_TCG_cond_jumpf(COND) \
do { \
TCGv LSB = tcg_temp_new(); \
COND; \
gen_cond_jump(ctx, TCG_COND_NE, LSB, riV); \
tcg_temp_free(LSB); \
} while (0)
#define fGEN_TCG_J2_jumpt(SHORTCODE) \
fGEN_TCG_cond_jumpt(fLSBOLD(PuV))
#define fGEN_TCG_J2_jumptpt(SHORTCODE) \
fGEN_TCG_cond_jumpt(fLSBOLD(PuV))
#define fGEN_TCG_J2_jumpf(SHORTCODE) \
fGEN_TCG_cond_jumpf(fLSBOLD(PuV))
#define fGEN_TCG_J2_jumpfpt(SHORTCODE) \
fGEN_TCG_cond_jumpf(fLSBOLD(PuV))
#define fGEN_TCG_J2_jumptnew(SHORTCODE) \
gen_cond_jump(ctx, TCG_COND_EQ, PuN, riV)
#define fGEN_TCG_J2_jumptnewpt(SHORTCODE) \
gen_cond_jump(ctx, TCG_COND_EQ, PuN, riV)
#define fGEN_TCG_J2_jumpfnewpt(SHORTCODE) \
fGEN_TCG_cond_jumpf(fLSBNEW(PuN))
#define fGEN_TCG_J2_jumpfnew(SHORTCODE) \
fGEN_TCG_cond_jumpf(fLSBNEW(PuN))
#define fGEN_TCG_J2_jumprz(SHORTCODE) \
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_NE, LSB, RsV, 0))
#define fGEN_TCG_J2_jumprzpt(SHORTCODE) \
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_NE, LSB, RsV, 0))
#define fGEN_TCG_J2_jumprnz(SHORTCODE) \
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_EQ, LSB, RsV, 0))
#define fGEN_TCG_J2_jumprnzpt(SHORTCODE) \
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_EQ, LSB, RsV, 0))
#define fGEN_TCG_J2_jumprgtez(SHORTCODE) \
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_GE, LSB, RsV, 0))
#define fGEN_TCG_J2_jumprgtezpt(SHORTCODE) \
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_GE, LSB, RsV, 0))
#define fGEN_TCG_J2_jumprltez(SHORTCODE) \
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_LE, LSB, RsV, 0))
#define fGEN_TCG_J2_jumprltezpt(SHORTCODE) \
fGEN_TCG_cond_jumpt(tcg_gen_setcondi_tl(TCG_COND_LE, LSB, RsV, 0))
#define fGEN_TCG_cond_jumprt(COND) \
do { \
TCGv LSB = tcg_temp_new(); \
COND; \
gen_cond_jumpr(ctx, RsV, TCG_COND_EQ, LSB); \
tcg_temp_free(LSB); \
} while (0)
#define fGEN_TCG_cond_jumprf(COND) \
do { \
TCGv LSB = tcg_temp_new(); \
COND; \
gen_cond_jumpr(ctx, RsV, TCG_COND_NE, LSB); \
tcg_temp_free(LSB); \
} while (0)
#define fGEN_TCG_J2_jumprt(SHORTCODE) \
fGEN_TCG_cond_jumprt(fLSBOLD(PuV))
#define fGEN_TCG_J2_jumprtpt(SHORTCODE) \
fGEN_TCG_cond_jumprt(fLSBOLD(PuV))
#define fGEN_TCG_J2_jumprf(SHORTCODE) \
fGEN_TCG_cond_jumprf(fLSBOLD(PuV))
#define fGEN_TCG_J2_jumprfpt(SHORTCODE) \
fGEN_TCG_cond_jumprf(fLSBOLD(PuV))
#define fGEN_TCG_J2_jumprtnew(SHORTCODE) \
fGEN_TCG_cond_jumprt(fLSBNEW(PuN))
#define fGEN_TCG_J2_jumprtnewpt(SHORTCODE) \
fGEN_TCG_cond_jumprt(fLSBNEW(PuN))
#define fGEN_TCG_J2_jumprfnew(SHORTCODE) \
fGEN_TCG_cond_jumprf(fLSBNEW(PuN))
#define fGEN_TCG_J2_jumprfnewpt(SHORTCODE) \
fGEN_TCG_cond_jumprf(fLSBNEW(PuN))
/*
* New value compare & jump instructions
* if ([!]COND(r0.new, r1) jump:t address
* if ([!]COND(r0.new, #7) jump:t address
*/
#define fGEN_TCG_J4_cmpgt_t_jumpnv_t(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_GT, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpgt_t_jumpnv_nt(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_GT, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpgt_f_jumpnv_t(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_LE, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpgt_f_jumpnv_nt(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_LE, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpeq_t_jumpnv_t(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_EQ, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpeq_t_jumpnv_nt(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_EQ, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpeq_f_jumpnv_t(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_NE, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpeq_f_jumpnv_nt(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_NE, NsN, RtV, riV)
#define fGEN_TCG_J4_cmplt_t_jumpnv_t(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_LT, NsN, RtV, riV)
#define fGEN_TCG_J4_cmplt_t_jumpnv_nt(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_LT, NsN, RtV, riV)
#define fGEN_TCG_J4_cmplt_f_jumpnv_t(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_GE, NsN, RtV, riV)
#define fGEN_TCG_J4_cmplt_f_jumpnv_nt(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_GE, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpeqi_t_jumpnv_t(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_EQ, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpeqi_t_jumpnv_nt(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_EQ, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpeqi_f_jumpnv_t(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_NE, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpeqi_f_jumpnv_nt(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_NE, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpgti_t_jumpnv_t(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_GT, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpgti_t_jumpnv_nt(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_GT, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpgti_f_jumpnv_t(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_LE, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpgti_f_jumpnv_nt(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_LE, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpltu_t_jumpnv_t(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_LTU, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpltu_t_jumpnv_nt(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_LTU, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpltu_f_jumpnv_t(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_GEU, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpltu_f_jumpnv_nt(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_GEU, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpgtui_t_jumpnv_t(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_GTU, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpgtui_t_jumpnv_nt(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_GTU, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpgtui_f_jumpnv_t(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_LEU, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpgtui_f_jumpnv_nt(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_LEU, NsN, UiV, riV)
#define fGEN_TCG_J4_cmpgtu_t_jumpnv_t(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_GTU, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpgtu_t_jumpnv_nt(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_GTU, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpgtu_f_jumpnv_t(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_LEU, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpgtu_f_jumpnv_nt(SHORTCODE) \
gen_cmp_jumpnv(ctx, TCG_COND_LEU, NsN, RtV, riV)
#define fGEN_TCG_J4_cmpeqn1_t_jumpnv_t(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_EQ, NsN, -1, riV)
#define fGEN_TCG_J4_cmpeqn1_t_jumpnv_nt(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_EQ, NsN, -1, riV)
#define fGEN_TCG_J4_cmpeqn1_f_jumpnv_t(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_NE, NsN, -1, riV)
#define fGEN_TCG_J4_cmpeqn1_f_jumpnv_nt(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_NE, NsN, -1, riV)
#define fGEN_TCG_J4_cmpgtn1_t_jumpnv_t(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_GT, NsN, -1, riV)
#define fGEN_TCG_J4_cmpgtn1_t_jumpnv_nt(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_GT, NsN, -1, riV)
#define fGEN_TCG_J4_cmpgtn1_f_jumpnv_t(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_LE, NsN, -1, riV)
#define fGEN_TCG_J4_cmpgtn1_f_jumpnv_nt(SHORTCODE) \
gen_cmpi_jumpnv(ctx, TCG_COND_LE, NsN, -1, riV)
#define fGEN_TCG_J4_tstbit0_t_jumpnv_t(SHORTCODE) \
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_EQ, riV)
#define fGEN_TCG_J4_tstbit0_t_jumpnv_nt(SHORTCODE) \
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_EQ, riV)
#define fGEN_TCG_J4_tstbit0_f_jumpnv_t(SHORTCODE) \
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_NE, riV)
#define fGEN_TCG_J4_tstbit0_f_jumpnv_nt(SHORTCODE) \
gen_testbit0_jumpnv(ctx, NsN, TCG_COND_NE, riV)
/* r0 = r1 ; jump address */
#define fGEN_TCG_J4_jumpsetr(SHORTCODE) \
do { \
tcg_gen_mov_tl(RdV, RsV); \
gen_jump(ctx, riV); \
} while (0)
#define fGEN_TCG_J2_pause(SHORTCODE) \
do { \
uiV = uiV; \
tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->next_PC); \
} while (0)
/* r0 = asr(r1, r2):sat */
#define fGEN_TCG_S2_asr_r_r_sat(SHORTCODE) \
gen_asr_r_r_sat(RdV, RsV, RtV)
/* r0 = asl(r1, r2):sat */
#define fGEN_TCG_S2_asl_r_r_sat(SHORTCODE) \
gen_asl_r_r_sat(RdV, RsV, RtV)
/* Floating point */
#define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
gen_helper_conv_sf2df(RddV, cpu_env, RsV)
@@ -742,4 +1145,11 @@
RsV = RsV; \
} while (0)
#define fGEN_TCG_J2_trap0(SHORTCODE) \
do { \
uiV = uiV; \
tcg_gen_movi_tl(hex_gpr[HEX_REG_PC], ctx->pkt->pc); \
TCGv excp = tcg_constant_tl(HEX_EXCP_TRAP0); \
gen_helper_raise_exception(cpu_env, excp); \
} while (0)
#endif
+67 -12
View File
@@ -173,6 +173,18 @@ def genptr_decl(f, tag, regtype, regid, regno):
f.write(" ctx_future_vreg_off(ctx, %s%sN," % \
(regtype, regid))
f.write(" 1, true);\n");
if 'A_CONDEXEC' in hex_common.attribdict[tag]:
f.write(" if (!is_vreg_preloaded(ctx, %s)) {\n" % (regN))
f.write(" intptr_t src_off =")
f.write(" offsetof(CPUHexagonState, VRegs[%s%sN]);\n"% \
(regtype, regid))
f.write(" tcg_gen_gvec_mov(MO_64, %s%sV_off,\n" % \
(regtype, regid))
f.write(" src_off,\n")
f.write(" sizeof(MMVector),\n")
f.write(" sizeof(MMVector));\n")
f.write(" }\n")
if (not hex_common.skip_qemu_helper(tag)):
f.write(" TCGv_ptr %s%sV = tcg_temp_new_ptr();\n" % \
(regtype, regid))
@@ -561,11 +573,7 @@ def genptr_dst_write_opn(f,regtype, regid, tag):
## Generate the TCG code to call the helper
## For A2_add: Rd32=add(Rs32,Rt32), { RdV=RsV+RtV;}
## We produce:
## static void generate_A2_add()
## CPUHexagonState *env
## DisasContext *ctx,
## Insn *insn,
## Packet *pkt)
## static void generate_A2_add(DisasContext *ctx)
## {
## TCGv RdV = tcg_temp_local_new();
## const int RdN = insn->regno[0];
@@ -584,12 +592,11 @@ def genptr_dst_write_opn(f,regtype, regid, tag):
## <GEN> is gen_helper_A2_add(RdV, cpu_env, RsV, RtV);
##
def gen_tcg_func(f, tag, regs, imms):
f.write("static void generate_%s(\n" %tag)
f.write(" CPUHexagonState *env,\n")
f.write(" DisasContext *ctx,\n")
f.write(" Insn *insn,\n")
f.write(" Packet *pkt)\n")
f.write("static void generate_%s(DisasContext *ctx)\n" %tag)
f.write('{\n')
f.write(" Insn *insn __attribute__((unused)) = ctx->insn;\n")
if hex_common.need_ea(tag): gen_decl_ea_tcg(f, tag)
i=0
## Declare all the operands (regs and immediates)
@@ -609,16 +616,45 @@ def gen_tcg_func(f, tag, regs, imms):
if (hex_common.is_read(regid)):
genptr_src_read_opn(f,regtype,regid,tag)
if ( hex_common.skip_qemu_helper(tag) ):
if hex_common.is_idef_parser_enabled(tag):
declared = []
## Handle registers
for regtype,regid,toss,numregs in regs:
if (hex_common.is_pair(regid)
or (hex_common.is_single(regid)
and hex_common.is_old_val(regtype, regid, tag))):
declared.append("%s%sV" % (regtype, regid))
if regtype == "M":
declared.append("%s%sN" % (regtype, regid))
elif hex_common.is_new_val(regtype, regid, tag):
declared.append("%s%sN" % (regtype,regid))
else:
print("Bad register parse: ",regtype,regid,toss,numregs)
## Handle immediates
for immlett,bits,immshift in imms:
declared.append(hex_common.imm_name(immlett))
arguments = ", ".join(["ctx", "ctx->insn", "ctx->pkt"] + declared)
f.write(" emit_%s(%s);\n" % (tag, arguments))
elif ( hex_common.skip_qemu_helper(tag) ):
f.write(" fGEN_TCG_%s(%s);\n" % (tag, hex_common.semdict[tag]))
else:
## Generate the call to the helper
for immlett,bits,immshift in imms:
gen_helper_decl_imm(f,immlett)
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_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")
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):
f.write(" TCGv next_PC = tcg_constant_tl(ctx->next_PC);\n")
f.write(" gen_helper_%s(" % (tag))
i=0
## If there is a scalar result, it is the return type
@@ -647,6 +683,10 @@ def gen_tcg_func(f, tag, regs, imms):
for immlett,bits,immshift in imms:
gen_helper_call_imm(f,immlett)
if hex_common.need_pkt_has_multi_cof(tag):
f.write(", pkt_has_multi_cof")
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")
if hex_common.need_part1(tag): f.write(", part1" )
f.write(");\n")
@@ -676,12 +716,27 @@ def main():
hex_common.read_overrides_file(sys.argv[3])
hex_common.read_overrides_file(sys.argv[4])
hex_common.calculate_attribs()
## Whether or not idef-parser is enabled is
## determined by the number of arguments to
## this script:
##
## 5 args. -> not enabled,
## 6 args. -> idef-parser enabled.
##
## The 6:th arg. then holds a list of the successfully
## parsed instructions.
is_idef_parser_enabled = len(sys.argv) > 6
if is_idef_parser_enabled:
hex_common.read_idef_parser_enabled_file(sys.argv[5])
tagregs = hex_common.get_tagregs()
tagimms = hex_common.get_tagimms()
with open(sys.argv[5], 'w') as f:
output_file = sys.argv[-1]
with open(output_file, 'w') as f:
f.write("#ifndef HEXAGON_TCG_FUNCS_H\n")
f.write("#define HEXAGON_TCG_FUNCS_H\n\n")
if is_idef_parser_enabled:
f.write("#include \"idef-generated-emitter.h.inc\"\n\n")
for tag in hex_common.tags:
## Skip the priv instructions
+3 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
* Copyright(c) 2019-2022 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
@@ -697,7 +697,7 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
#define fGEN_TCG_NEWVAL_VEC_STORE(GET_EA, INC) \
do { \
GET_EA; \
gen_vreg_store(ctx, insn, pkt, EA, OsN_off, insn->slot, true); \
gen_vreg_store(ctx, EA, OsN_off, insn->slot, true); \
INC; \
} while (0)
@@ -736,7 +736,7 @@ static inline void assert_vhist_tmp(DisasContext *ctx)
PRED; \
tcg_gen_brcondi_tl(TCG_COND_EQ, LSB, 0, false_label); \
tcg_temp_free(LSB); \
gen_vreg_store(ctx, insn, pkt, EA, SRCOFF, insn->slot, ALIGN); \
gen_vreg_store(ctx, EA, SRCOFF, insn->slot, ALIGN); \
INC; \
tcg_gen_br(end_label); \
gen_set_label(false_label); \
+561 -24
View File
File diff suppressed because it is too large Load Diff
+36
View File
@@ -19,7 +19,43 @@
#define HEXAGON_GENPTR_H
#include "insn.h"
#include "tcg/tcg.h"
#include "translate.h"
extern const SemanticInsn opcode_genptr[];
void gen_store32(TCGv vaddr, TCGv src, int width, uint32_t slot);
void gen_store1(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot);
void gen_store2(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot);
void gen_store4(TCGv_env cpu_env, TCGv vaddr, TCGv src, uint32_t slot);
void gen_store8(TCGv_env cpu_env, TCGv vaddr, TCGv_i64 src, uint32_t slot);
void gen_store1i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot);
void gen_store2i(TCGv_env cpu_env, TCGv vaddr, int32_t src, uint32_t slot);
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);
void gen_log_pred_write(DisasContext *ctx, int pnum, TCGv val);
void gen_set_usr_field(int field, TCGv val);
void gen_set_usr_fieldi(int field, int x);
void gen_set_usr_field_if(int field, TCGv val);
void gen_sat_i32(TCGv dest, TCGv source, int width);
void gen_sat_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width);
void gen_satu_i32(TCGv dest, TCGv source, int width);
void gen_satu_i32_ovfl(TCGv ovfl, TCGv dest, TCGv source, int width);
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);
void gen_satu_i64(TCGv_i64 dest, TCGv_i64 source, int width);
void gen_satu_i64_ovfl(TCGv ovfl, TCGv_i64 dest, TCGv_i64 source, int width);
void gen_add_sat_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b);
TCGv gen_8bitsof(TCGv result, TCGv value);
void gen_set_byte_i64(int N, TCGv_i64 result, TCGv src);
TCGv gen_get_byte(TCGv result, int N, TCGv src, bool sign);
TCGv gen_get_byte_i64(TCGv result, int N, TCGv_i64 src, bool sign);
TCGv gen_get_half(TCGv result, int N, TCGv src, bool sign);
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);
#endif
+39 -1
View File
@@ -28,6 +28,7 @@ macros = {} # macro -> macro information...
attribinfo = {} # Register information and misc
tags = [] # list of all tags
overrides = {} # tags with helper overrides
idef_parser_enabled = {} # tags enabled for idef-parser
# We should do this as a hash for performance,
# but to keep order let's keep it as a list.
@@ -66,6 +67,19 @@ def add_qemu_macro_attrib(name, attrib):
macros[name].attribs.add(attrib)
immextre = re.compile(r'f(MUST_)?IMMEXT[(]([UuSsRr])')
def is_cond_jump(tag):
if tag == 'J2_rte':
return False
if ('A_HWLOOP0_END' in attribdict[tag] or
'A_HWLOOP1_END' in attribdict[tag]):
return False
return \
re.compile(r"(if.*fBRANCH)|(if.*fJUMPR)").search(semdict[tag]) != None
def is_cond_call(tag):
return re.compile(r"(if.*fCALL)").search(semdict[tag]) != None
def calculate_attribs():
add_qemu_macro_attrib('fREAD_PC', 'A_IMPLICIT_READS_PC')
add_qemu_macro_attrib('fTRAP', 'A_IMPLICIT_READS_PC')
@@ -96,6 +110,11 @@ def calculate_attribs():
for regtype, regid, toss, numregs in regs:
if regtype == "P" and is_written(regid):
attribdict[tag].add('A_WRITES_PRED_REG')
# Mark conditional jumps and calls
# Not all instructions are properly marked with A_CONDEXEC
for tag in tags:
if is_cond_jump(tag) or is_cond_call(tag):
attribdict[tag].add('A_CONDEXEC')
def SEMANTICS(tag, beh, sem):
#print tag,beh,sem
@@ -194,7 +213,8 @@ def is_new_val(regtype, regid, tag):
return regtype+regid+'N' in semdict[tag]
def need_slot(tag):
if ('A_CONDEXEC' in attribdict[tag] or
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]):
return 1
@@ -207,6 +227,15 @@ def need_part1(tag):
def need_ea(tag):
return re.compile(r"\bEA\b").search(semdict[tag])
def need_PC(tag):
return 'A_IMPLICIT_READS_PC' in attribdict[tag]
def helper_needs_next_PC(tag):
return 'A_CALL' in attribdict[tag]
def need_pkt_has_multi_cof(tag):
return 'A_COF' in attribdict[tag]
def skip_qemu_helper(tag):
return tag in overrides.keys()
@@ -217,6 +246,9 @@ def is_tmp_result(tag):
def is_new_result(tag):
return ('A_CVI_NEW' in attribdict[tag])
def is_idef_parser_enabled(tag):
return tag in idef_parser_enabled
def imm_name(immlett):
return "%siV" % immlett
@@ -248,3 +280,9 @@ def read_overrides_file(name):
continue
tag = overridere.findall(line)[0]
overrides[tag] = True
def read_idef_parser_enabled_file(name):
global idef_parser_enabled
with open(name, "r") as idef_parser_enabled_file:
lines = idef_parser_enabled_file.read().strip().split("\n")
idef_parser_enabled = set(lines)
File diff suppressed because it is too large Load Diff
+253
View File
@@ -0,0 +1,253 @@
/*
* Copyright(c) 2019-2022 rev.ng Labs Srl. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#ifndef IDEF_PARSER_H
#define IDEF_PARSER_H
#include <inttypes.h>
#include <stdio.h>
#include <stdbool.h>
#include <glib.h>
#define TCGV_NAME_SIZE 7
#define MAX_WRITTEN_REGS 32
#define OFFSET_STR_LEN 32
#define ALLOC_LIST_LEN 32
#define ALLOC_NAME_SIZE 32
#define INIT_LIST_LEN 32
#define OUT_BUF_LEN (1024 * 1024)
#define SIGNATURE_BUF_LEN (128 * 1024)
#define HEADER_BUF_LEN (128 * 1024)
/* Variadic macros to wrap the buffer printing functions */
#define EMIT(c, ...) \
do { \
g_string_append_printf((c)->out_str, __VA_ARGS__); \
} while (0)
#define EMIT_SIG(c, ...) \
do { \
g_string_append_printf((c)->signature_str, __VA_ARGS__); \
} while (0)
#define EMIT_HEAD(c, ...) \
do { \
g_string_append_printf((c)->header_str, __VA_ARGS__); \
} while (0)
/**
* Type of register, assigned to the HexReg.type field
*/
typedef enum { GENERAL_PURPOSE, CONTROL, MODIFIER, DOTNEW } HexRegType;
typedef enum { UNKNOWN_SIGNEDNESS, SIGNED, UNSIGNED } HexSignedness;
/**
* Semantic record of the REG tokens, identifying registers
*/
typedef struct HexReg {
uint8_t id; /**< Identifier of the register */
HexRegType type; /**< Type of the register */
unsigned bit_width; /**< Bit width of the reg, 32 or 64 bits */
} HexReg;
/**
* Data structure, identifying a TCGv temporary value
*/
typedef struct HexTmp {
unsigned index; /**< Index of the TCGv temporary value */
} HexTmp;
/**
* Enum of the possible immediated, an immediate is a value which is known
* at tinycode generation time, e.g. an integer value, not a TCGv
*/
enum ImmUnionTag {
I,
VARIABLE,
VALUE,
QEMU_TMP,
IMM_PC,
IMM_NPC,
IMM_CONSTEXT,
};
/**
* Semantic record of the IMM token, identifying an immediate constant
*/
typedef struct HexImm {
union {
char id; /**< Identifier, used when type is VARIABLE */
uint64_t value; /**< Immediate value, used when type is VALUE */
uint64_t index; /**< Index, used when type is QEMU_TMP */
};
enum ImmUnionTag type; /**< Type of the immediate */
} HexImm;
/**
* Semantic record of the PRED token, identifying a predicate
*/
typedef struct HexPred {
char id; /**< Identifier of the predicate */
} HexPred;
/**
* Semantic record of the SAT token, identifying the saturate operator
* Note: All saturates are assumed to implicitly set overflow.
*/
typedef struct HexSat {
HexSignedness signedness; /**< Signedness of the sat. op. */
} HexSat;
/**
* Semantic record of the CAST token, identifying the cast operator
*/
typedef struct HexCast {
unsigned bit_width; /**< Bit width of the cast operator */
HexSignedness signedness; /**< Unsigned flag for the cast operator */
} HexCast;
/**
* Semantic record of the EXTRACT token, identifying the cast operator
*/
typedef struct HexExtract {
unsigned bit_width; /**< Bit width of the extract operator */
unsigned storage_bit_width; /**< Actual bit width of the extract operator */
HexSignedness signedness; /**< Unsigned flag for the extract operator */
} HexExtract;
/**
* Semantic record of the MPY token, identifying the fMPY multiplication
* operator
*/
typedef struct HexMpy {
unsigned first_bit_width; /**< Bit width of 1st operand of fMPY */
unsigned second_bit_width; /**< Bit width of 2nd operand of fMPY */
HexSignedness first_signedness; /**< Signedness of 1st operand of fMPY */
HexSignedness second_signedness; /**< Signedness of 2nd operand of fMPY */
} HexMpy;
/**
* Semantic record of the VARID token, identifying declared variables
* of the input language
*/
typedef struct HexVar {
GString *name; /**< Name of the VARID variable */
} HexVar;
/**
* Data structure uniquely identifying a declared VARID variable, used for
* keeping track of declared variable, so that any variable is declared only
* once, and its properties are propagated through all the subsequent instances
* of that variable
*/
typedef struct Var {
GString *name; /**< Name of the VARID variable */
uint8_t bit_width; /**< Bit width of the VARID variable */
HexSignedness signedness; /**< Unsigned flag for the VARID var */
} Var;
/**
* Enum of the possible rvalue types, used in the HexValue.type field
*/
typedef enum RvalueUnionTag {
REGISTER, REGISTER_ARG, TEMP, IMMEDIATE, PREDICATE, VARID
} RvalueUnionTag;
/**
* Semantic record of the rvalue token, identifying any numeric value,
* immediate or register based. The rvalue tokens are combined together
* through the use of several operators, to encode expressions
*/
typedef struct HexValue {
union {
HexReg reg; /**< rvalue of register type */
HexTmp tmp; /**< rvalue of temporary type */
HexImm imm; /**< rvalue of immediate type */
HexPred pred; /**< rvalue of predicate type */
HexVar var; /**< rvalue of declared variable type */
};
RvalueUnionTag type; /**< Type of the rvalue */
unsigned bit_width; /**< Bit width of the rvalue */
HexSignedness signedness; /**< Unsigned flag for the rvalue */
bool is_dotnew; /**< rvalue of predicate type is dotnew? */
bool is_manual; /**< Opt out of automatic freeing of params */
} HexValue;
/**
* State of ternary operator
*/
typedef enum TernaryState { IN_LEFT, IN_RIGHT } TernaryState;
/**
* Data structure used to handle side effects inside ternary operators
*/
typedef struct Ternary {
TernaryState state;
HexValue cond;
} Ternary;
/**
* Operator type, used for referencing the correct operator when calling the
* gen_bin_op() function, which in turn will generate the correct code to
* execute the operation between the two rvalues
*/
typedef enum OpType {
ADD_OP, SUB_OP, MUL_OP, ASL_OP, ASR_OP, LSR_OP, ANDB_OP, ORB_OP,
XORB_OP, ANDL_OP, MINI_OP, MAXI_OP
} OpType;
/**
* Data structure including instruction specific information, to be cleared
* out after the compilation of each instruction
*/
typedef struct Inst {
GString *name; /**< Name of the compiled instruction */
char *code_begin; /**< Beginning of instruction input code */
char *code_end; /**< End of instruction input code */
unsigned tmp_count; /**< Index of the last declared TCGv temp */
unsigned qemu_tmp_count; /**< Index of the last declared int temp */
unsigned if_count; /**< Index of the last declared if label */
unsigned error_count; /**< Number of generated errors */
GArray *allocated; /**< Allocated declaredVARID vars */
GArray *init_list; /**< List of initialized registers */
GArray *strings; /**< Strings allocated by the instruction */
} Inst;
/**
* Data structure representing the whole translation context, which in a
* reentrant flex/bison parser just like ours is passed between the scanner
* and the parser, holding all the necessary information to perform the
* parsing, this data structure survives between the compilation of different
* instructions
*/
typedef struct Context {
void *scanner; /**< Reentrant parser state pointer */
char *input_buffer; /**< Buffer containing the input code */
GString *out_str; /**< String containing the output code */
GString *signature_str; /**< String containing the signatures code */
GString *header_str; /**< String containing the header code */
FILE *defines_file; /**< FILE * of the generated header */
FILE *output_file; /**< FILE * of the C output file */
FILE *enabled_file; /**< FILE * of the list of enabled inst */
GArray *ternary; /**< Array to track nesting of ternary ops */
unsigned total_insn; /**< Number of instructions in input file */
unsigned implemented_insn; /**< Instruction compiled without errors */
Inst inst; /**< Parsing data of the current inst */
} Context;
#endif /* IDEF_PARSER_H */
+471
View File
@@ -0,0 +1,471 @@
%option noyywrap noinput nounput
%option 8bit reentrant bison-bridge
%option warn nodefault
%option bison-locations
%{
/*
* Copyright(c) 2019-2022 rev.ng Labs Srl. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include <stdbool.h>
#include "hex_regs.h"
#include "idef-parser.h"
#include "idef-parser.tab.h"
/* Keep track of scanner position for error message printout */
#define YY_USER_ACTION yylloc->first_column = yylloc->last_column; \
for (int i = 0; yytext[i] != '\0'; i++) { \
yylloc->last_column++; \
}
/* Global Error Counter */
int error_count;
%}
/* Definitions */
DIGIT [0-9]
LOWER_ID [a-z]
UPPER_ID [A-Z]
ID LOWER_ID|UPPER_ID
INST_NAME [A-Z]+[0-9]_([A-Za-z]|[0-9]|_)+
HEX_DIGIT [0-9a-fA-F]
REG_ID_32 e|s|d|t|u|v|x|y
REG_ID_64 ee|ss|dd|tt|uu|vv|xx|yy
SYS_ID_32 s|d
SYS_ID_64 ss|dd
PRED_ID d|s|t|u|v|e|x|x
IMM_ID r|s|S|u|U
VAR_ID [a-zA-Z_][a-zA-Z0-9_]*
SIGN_ID s|u
STRING_LIT \"(\\.|[^"\\])*\"
/* Tokens */
%%
[ \t\f\v]+ { /* Ignore whitespaces. */ }
[\n\r]+ { /* Ignore newlines. */ }
^#.*$ { /* Ignore linemarkers. */ }
{INST_NAME} { yylval->string = g_string_new(yytext);
return INAME; }
"fFLOAT" |
"fUNFLOAT" |
"fDOUBLE" |
"fUNDOUBLE" |
"0.0" |
"0x1.0p52" |
"0x1.0p-52" { return FAIL; }
"in" { return IN; }
"R"{REG_ID_32}"V" {
yylval->rvalue.type = REGISTER_ARG;
yylval->rvalue.reg.type = GENERAL_PURPOSE;
yylval->rvalue.reg.id = yytext[1];
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.is_dotnew = false;
yylval->rvalue.signedness = SIGNED;
return REG; }
"R"{REG_ID_64}"V" {
yylval->rvalue.type = REGISTER_ARG;
yylval->rvalue.reg.type = GENERAL_PURPOSE;
yylval->rvalue.reg.id = yytext[1];
yylval->rvalue.reg.bit_width = 64;
yylval->rvalue.bit_width = 64;
yylval->rvalue.is_dotnew = false;
yylval->rvalue.signedness = SIGNED;
return REG; }
"MuV" {
yylval->rvalue.type = REGISTER_ARG;
yylval->rvalue.reg.type = MODIFIER;
yylval->rvalue.reg.id = 'u';
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = SIGNED;
return REG; }
"C"{REG_ID_32}"V" {
yylval->rvalue.type = REGISTER_ARG;
yylval->rvalue.reg.type = CONTROL;
yylval->rvalue.reg.id = yytext[1];
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.is_dotnew = false;
yylval->rvalue.signedness = SIGNED;
return REG; }
"C"{REG_ID_64}"V" {
yylval->rvalue.type = REGISTER_ARG;
yylval->rvalue.reg.type = CONTROL;
yylval->rvalue.reg.id = yytext[1];
yylval->rvalue.reg.bit_width = 64;
yylval->rvalue.bit_width = 64;
yylval->rvalue.is_dotnew = false;
yylval->rvalue.signedness = SIGNED;
return REG; }
{IMM_ID}"iV" {
yylval->rvalue.type = IMMEDIATE;
yylval->rvalue.signedness = SIGNED;
yylval->rvalue.imm.type = VARIABLE;
yylval->rvalue.imm.id = yytext[0];
yylval->rvalue.bit_width = 32;
yylval->rvalue.is_dotnew = false;
return IMM; }
"P"{PRED_ID}"V" {
yylval->rvalue.type = PREDICATE;
yylval->rvalue.pred.id = yytext[1];
yylval->rvalue.bit_width = 32;
yylval->rvalue.is_dotnew = false;
yylval->rvalue.signedness = SIGNED;
return PRED; }
"P"{PRED_ID}"N" {
yylval->rvalue.type = PREDICATE;
yylval->rvalue.pred.id = yytext[1];
yylval->rvalue.bit_width = 32;
yylval->rvalue.is_dotnew = true;
yylval->rvalue.signedness = SIGNED;
return PRED; }
"IV1DEAD()" |
"fPAUSE(uiV);" { return ';'; }
"+=" { return INC; }
"-=" { return DEC; }
"++" { return PLUSPLUS; }
"&=" { return ANDA; }
"|=" { return ORA; }
"^=" { return XORA; }
"<<" { return ASL; }
">>" { return ASR; }
">>>" { return LSR; }
"==" { return EQ; }
"!=" { return NEQ; }
"<=" { return LTE; }
">=" { return GTE; }
"&&" { return ANDL; }
"else" { return ELSE; }
"for" { return FOR; }
"fREAD_IREG" { return ICIRC; }
"fPART1" { return PART1; }
"if" { return IF; }
"fFRAME_SCRAMBLE" { return FSCR; }
"fFRAME_UNSCRAMBLE" { return FSCR; }
"fFRAMECHECK" { return FCHK; }
"Constant_extended" { return CONSTEXT; }
"fCL1_"{DIGIT} { return LOCNT; }
"fbrev" { return BREV; }
"fSXTN" { return SXT; }
"fZXTN" { return ZXT; }
"fDF_MAX" |
"fSF_MAX" |
"fMAX" { return MAX; }
"fDF_MIN" |
"fSF_MIN" |
"fMIN" { return MIN; }
"fABS" { return ABS; }
"fRNDN" { return ROUND; }
"fCRND" { return CROUND; }
"fCRNDN" { return CROUND; }
"fPM_CIRI" { return CIRCADD; }
"fPM_CIRR" { return CIRCADD; }
"fCOUNTONES_"{DIGIT} { return COUNTONES; }
"fSATN" { yylval->sat.signedness = SIGNED;
return SAT; }
"fSATUN" { yylval->sat.signedness = UNSIGNED;
return SAT; }
"fCONSTLL" { yylval->cast.bit_width = 64;
yylval->cast.signedness = SIGNED;
return CAST; }
"fSE32_64" { yylval->cast.bit_width = 64;
yylval->cast.signedness = SIGNED;
return CAST; }
"fCAST4_4u" { yylval->cast.bit_width = 32;
yylval->cast.signedness = UNSIGNED;
return CAST; }
"fCAST4_8s" { yylval->cast.bit_width = 64;
yylval->cast.signedness = SIGNED;
return CAST; }
"fCAST4_8u" { return CAST4_8U; }
"fCAST4u" { yylval->cast.bit_width = 32;
yylval->cast.signedness = UNSIGNED;
return CAST; }
"fNEWREG" |
"fCAST4_4s" |
"fCAST4s" { yylval->cast.bit_width = 32;
yylval->cast.signedness = SIGNED;
return CAST; }
"fCAST8_8u" { yylval->cast.bit_width = 64;
yylval->cast.signedness = UNSIGNED;
return CAST; }
"fCAST8u" { yylval->cast.bit_width = 64;
yylval->cast.signedness = UNSIGNED;
return CAST; }
"fCAST8_8s" |
"fCAST8s" { yylval->cast.bit_width = 64;
yylval->cast.signedness = SIGNED;
return CAST; }
"fGETBIT" { yylval->extract.bit_width = 1;
yylval->extract.storage_bit_width = 1;
yylval->extract.signedness = UNSIGNED;
return EXTRACT; }
"fGETBYTE" { yylval->extract.bit_width = 8;
yylval->extract.storage_bit_width = 8;
yylval->extract.signedness = SIGNED;
return EXTRACT; }
"fGETUBYTE" { yylval->extract.bit_width = 8;
yylval->extract.storage_bit_width = 8;
yylval->extract.signedness = UNSIGNED;
return EXTRACT; }
"fGETHALF" { yylval->extract.bit_width = 16;
yylval->extract.storage_bit_width = 16;
yylval->extract.signedness = SIGNED;
return EXTRACT; }
"fGETUHALF" { yylval->extract.bit_width = 16;
yylval->extract.storage_bit_width = 16;
yylval->extract.signedness = UNSIGNED;
return EXTRACT; }
"fGETWORD" { yylval->extract.bit_width = 32;
yylval->extract.storage_bit_width = 64;
yylval->extract.signedness = SIGNED;
return EXTRACT; }
"fGETUWORD" { yylval->extract.bit_width = 32;
yylval->extract.storage_bit_width = 64;
yylval->extract.signedness = UNSIGNED;
return EXTRACT; }
"fEXTRACTU_RANGE" { return EXTRANGE; }
"fSETBIT" { yylval->cast.bit_width = 1;
yylval->cast.signedness = SIGNED;
return DEPOSIT; }
"fSETBYTE" { yylval->cast.bit_width = 8;
yylval->cast.signedness = SIGNED;
return DEPOSIT; }
"fSETHALF" { yylval->cast.bit_width = 16;
yylval->cast.signedness = SIGNED;
return SETHALF; }
"fSETWORD" { yylval->cast.bit_width = 32;
yylval->cast.signedness = SIGNED;
return DEPOSIT; }
"fINSERT_BITS" { return INSBITS; }
"fSETBITS" { return SETBITS; }
"fMPY16UU" { yylval->mpy.first_bit_width = 16;
yylval->mpy.second_bit_width = 16;
yylval->mpy.first_signedness = UNSIGNED;
yylval->mpy.second_signedness = UNSIGNED;
return MPY; }
"fMPY16SU" { yylval->mpy.first_bit_width = 16;
yylval->mpy.second_bit_width = 16;
yylval->mpy.first_signedness = SIGNED;
yylval->mpy.second_signedness = UNSIGNED;
return MPY; }
"fMPY16SS" { yylval->mpy.first_bit_width = 16;
yylval->mpy.second_bit_width = 16;
yylval->mpy.first_signedness = SIGNED;
yylval->mpy.second_signedness = SIGNED;
return MPY; }
"fMPY32UU" { yylval->mpy.first_bit_width = 32;
yylval->mpy.second_bit_width = 32;
yylval->mpy.first_signedness = UNSIGNED;
yylval->mpy.second_signedness = UNSIGNED;
return MPY; }
"fMPY32SU" { yylval->mpy.first_bit_width = 32;
yylval->mpy.second_bit_width = 32;
yylval->mpy.first_signedness = SIGNED;
yylval->mpy.second_signedness = UNSIGNED;
return MPY; }
"fSFMPY" |
"fMPY32SS" { yylval->mpy.first_bit_width = 32;
yylval->mpy.second_bit_width = 32;
yylval->mpy.first_signedness = SIGNED;
yylval->mpy.second_signedness = SIGNED;
return MPY; }
"fMPY3216SS" { yylval->mpy.first_bit_width = 32;
yylval->mpy.second_bit_width = 16;
yylval->mpy.first_signedness = SIGNED;
yylval->mpy.second_signedness = SIGNED;
return MPY; }
"fMPY3216SU" { yylval->mpy.first_bit_width = 32;
yylval->mpy.second_bit_width = 16;
yylval->mpy.first_signedness = SIGNED;
yylval->mpy.second_signedness = UNSIGNED;
return MPY; }
"fNEWREG_ST" |
"fIMMEXT" |
"fMUST_IMMEXT" |
"fPASS" |
"fECHO" { return IDENTITY; }
"(size8u_t)" { yylval->cast.bit_width = 64;
yylval->cast.signedness = UNSIGNED;
return CAST; }
"(unsigned int)" { yylval->cast.bit_width = 32;
yylval->cast.signedness = UNSIGNED;
return CAST; }
"fREAD_PC()" |
"PC" { return PC; }
"fREAD_NPC()" |
"NPC" { return NPC; }
"fGET_LPCFG" |
"USR.LPCFG" { return LPCFG; }
"LOAD_CANCEL(EA)" { return LOAD_CANCEL; }
"STORE_CANCEL(EA)" |
"CANCEL" { return CANCEL; }
"N"{LOWER_ID}"N" { yylval->rvalue.type = REGISTER_ARG;
yylval->rvalue.reg.type = DOTNEW;
yylval->rvalue.reg.id = yytext[1];
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = UNSIGNED;
return REG; }
"fREAD_SP()" |
"SP" { yylval->rvalue.type = REGISTER;
yylval->rvalue.reg.type = GENERAL_PURPOSE;
yylval->rvalue.reg.id = HEX_REG_SP;
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = UNSIGNED;
return REG; }
"fREAD_FP()" |
"FP" { yylval->rvalue.type = REGISTER;
yylval->rvalue.reg.type = GENERAL_PURPOSE;
yylval->rvalue.reg.id = HEX_REG_FP;
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = UNSIGNED;
return REG; }
"fREAD_LR()" |
"LR" { yylval->rvalue.type = REGISTER;
yylval->rvalue.reg.type = GENERAL_PURPOSE;
yylval->rvalue.reg.id = HEX_REG_LR;
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = UNSIGNED;
return REG; }
"fREAD_GP()" |
"GP" { yylval->rvalue.type = REGISTER;
yylval->rvalue.reg.type = CONTROL;
yylval->rvalue.reg.id = HEX_REG_GP;
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = UNSIGNED;
return REG; }
"fREAD_LC"[01] { yylval->rvalue.type = REGISTER;
yylval->rvalue.reg.type = CONTROL;
yylval->rvalue.reg.id = HEX_REG_LC0
+ (yytext[8] - '0') * 2;
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = UNSIGNED;
return REG; }
"LC"[01] { yylval->rvalue.type = REGISTER;
yylval->rvalue.reg.type = CONTROL;
yylval->rvalue.reg.id = HEX_REG_LC0
+ (yytext[2] - '0') * 2;
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = UNSIGNED;
return REG; }
"fREAD_SA"[01] { yylval->rvalue.type = REGISTER;
yylval->rvalue.reg.type = CONTROL;
yylval->rvalue.reg.id = HEX_REG_SA0
+ (yytext[8] - '0') * 2;
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = UNSIGNED;
return REG; }
"SA"[01] { yylval->rvalue.type = REGISTER;
yylval->rvalue.reg.type = CONTROL;
yylval->rvalue.reg.id = HEX_REG_SA0
+ (yytext[2] - '0') * 2;
yylval->rvalue.reg.bit_width = 32;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = UNSIGNED;
return REG; }
"fREAD_P0()" { yylval->rvalue.type = PREDICATE;
yylval->rvalue.pred.id = '0';
yylval->rvalue.bit_width = 32;
return PRED; }
[pP]{DIGIT} { yylval->rvalue.type = PREDICATE;
yylval->rvalue.pred.id = yytext[1];
yylval->rvalue.bit_width = 32;
yylval->rvalue.is_dotnew = false;
return PRED; }
[pP]{DIGIT}[nN] { yylval->rvalue.type = PREDICATE;
yylval->rvalue.pred.id = yytext[1];
yylval->rvalue.bit_width = 32;
yylval->rvalue.is_dotnew = true;
return PRED; }
"fLSBNEW" { return LSBNEW; }
"N" { yylval->rvalue.type = IMMEDIATE;
yylval->rvalue.bit_width = 32;
yylval->rvalue.imm.type = VARIABLE;
yylval->rvalue.imm.id = 'N';
return IMM; }
"i" { yylval->rvalue.type = IMMEDIATE;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = SIGNED;
yylval->rvalue.imm.type = I;
return IMM; }
{SIGN_ID} { if (yytext[0] == 'u') {
yylval->signedness = UNSIGNED;
} else {
yylval->signedness = SIGNED;
}
return SIGN;
}
"0x"{HEX_DIGIT}+ |
{DIGIT}+ { yylval->rvalue.type = IMMEDIATE;
yylval->rvalue.bit_width = 32;
yylval->rvalue.signedness = SIGNED;
yylval->rvalue.imm.type = VALUE;
yylval->rvalue.imm.value = strtoull(yytext, NULL, 0);
return IMM; }
"0x"{HEX_DIGIT}+"ULL" |
{DIGIT}+"ULL" { yylval->rvalue.type = IMMEDIATE;
yylval->rvalue.bit_width = 64;
yylval->rvalue.signedness = UNSIGNED;
yylval->rvalue.imm.type = VALUE;
yylval->rvalue.imm.value = strtoull(yytext, NULL, 0);
return IMM; }
"fLOAD" { return LOAD; }
"fSTORE" { return STORE; }
"fROTL" { return ROTL; }
"fCARRY_FROM_ADD" { return CARRY_FROM_ADD; }
"fADDSAT64" { return ADDSAT64; }
"size"[1248][us]"_t" { /* Handles "size_t" variants of int types */
const unsigned int bits_per_byte = 8;
const unsigned int bytes = yytext[4] - '0';
yylval->rvalue.bit_width = bits_per_byte * bytes;
if (yytext[5] == 'u') {
yylval->rvalue.signedness = UNSIGNED;
} else {
yylval->rvalue.signedness = SIGNED;
}
return TYPE_SIZE_T; }
"unsigned" { return TYPE_UNSIGNED; }
"long" { return TYPE_LONG; }
"int" { return TYPE_INT; }
"const" { /* Emit no token */ }
{VAR_ID} { /* Variable name, we adopt the C names convention */
yylval->rvalue.type = VARID;
yylval->rvalue.var.name = g_string_new(yytext);
/* Default to an unknown signedness and 0 width. */
yylval->rvalue.bit_width = 0;
yylval->rvalue.signedness = UNKNOWN_SIGNEDNESS;
return VAR; }
"fatal("{STRING_LIT}")" { /* Emit no token */ }
"fHINTJR(RsV)" { /* Emit no token */ }
. { return yytext[0]; }
%%
File diff suppressed because it is too large Load Diff
+140
View File
@@ -0,0 +1,140 @@
/*
* Copyright(c) 2019-2022 rev.ng Labs Srl. All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
/* Copy rules */
#define fLSBOLD(VAL) (fGETBIT(0, VAL))
#define fSATH(VAL) fSATN(16, VAL)
#define fSATUH(VAL) fSATUN(16, VAL)
#define fVSATH(VAL) fVSATN(16, VAL)
#define fVSATUH(VAL) fVSATUN(16, VAL)
#define fSATUB(VAL) fSATUN(8, VAL)
#define fSATB(VAL) fSATN(8, VAL)
#define fVSATUB(VAL) fVSATUN(8, VAL)
#define fVSATB(VAL) fVSATN(8, VAL)
#define fCALL(A) fWRITE_LR(fREAD_NPC()); fWRITE_NPC(A);
#define fCALLR(A) fWRITE_LR(fREAD_NPC()); fWRITE_NPC(A);
#define fCAST2_8s(A) fSXTN(16, 64, A)
#define fCAST2_8u(A) fZXTN(16, 64, A)
#define fVSATW(A) fVSATN(32, fCAST8_8s(A))
#define fSATW(A) fSATN(32, fCAST8_8s(A))
#define fVSAT(A) fVSATN(32, A)
#define fSAT(A) fSATN(32, A)
/* Ease parsing */
#define f8BITSOF(VAL) ((VAL) ? 0xff : 0x00)
#define fREAD_GP() (Constant_extended ? (0) : GP)
#define fCLIP(DST, SRC, U) (DST = fMIN((1 << U) - 1, fMAX(SRC, -(1 << U))))
#define fBIDIR_ASHIFTL(SRC, SHAMT, REGSTYPE) \
((SHAMT > 0) ? \
(fCAST##REGSTYPE##s(SRC) << SHAMT) : \
(fCAST##REGSTYPE##s(SRC) >> -SHAMT))
#define fBIDIR_LSHIFTL(SRC, SHAMT, REGSTYPE) \
((SHAMT > 0) ? \
(fCAST##REGSTYPE##u(SRC) << SHAMT) : \
(fCAST##REGSTYPE##u(SRC) >>> -SHAMT))
#define fBIDIR_ASHIFTR(SRC, SHAMT, REGSTYPE) \
((SHAMT > 0) ? \
(fCAST##REGSTYPE##s(SRC) >> SHAMT) : \
(fCAST##REGSTYPE##s(SRC) << -SHAMT))
#define fBIDIR_SHIFTR(SRC, SHAMT, REGSTYPE) \
(((SHAMT) < 0) ? ((fCAST##REGSTYPE(SRC) << ((-(SHAMT)) - 1)) << 1) \
: (fCAST##REGSTYPE(SRC) >> (SHAMT)))
#define fBIDIR_LSHIFTR(SRC, SHAMT, REGSTYPE) \
fBIDIR_SHIFTR(SRC, SHAMT, REGSTYPE##u)
#define fSATVALN(N, VAL) \
fSET_OVERFLOW( \
((VAL) < 0) ? (-(1LL << ((N) - 1))) : ((1LL << ((N) - 1)) - 1) \
)
#define fSAT_ORIG_SHL(A, ORIG_REG) \
(((fCAST4s((fSAT(A)) ^ (fCAST4s(ORIG_REG)))) < 0) \
? fSATVALN(32, (fCAST4s(ORIG_REG))) \
: ((((ORIG_REG) > 0) && ((A) == 0)) ? fSATVALN(32, (ORIG_REG)) \
: fSAT(A)))
#define fBIDIR_ASHIFTR_SAT(SRC, SHAMT, REGSTYPE) \
(((SHAMT) < 0) ? fSAT_ORIG_SHL((fCAST##REGSTYPE##s(SRC) \
<< ((-(SHAMT)) - 1)) << 1, (SRC)) \
: (fCAST##REGSTYPE##s(SRC) >> (SHAMT)))
#define fBIDIR_ASHIFTL_SAT(SRC, SHAMT, REGSTYPE) \
(((SHAMT) < 0) \
? ((fCAST##REGSTYPE##s(SRC) >> ((-(SHAMT)) - 1)) >> 1) \
: fSAT_ORIG_SHL(fCAST##REGSTYPE##s(SRC) << (SHAMT), (SRC)))
#define fEXTRACTU_BIDIR(INREG, WIDTH, OFFSET) \
(fZXTN(WIDTH, 32, fBIDIR_LSHIFTR((INREG), (OFFSET), 4_8)))
/* Least significant bit operations */
#define fLSBNEW0 fLSBNEW(P0N)
#define fLSBNEW1 fLSBNEW(P1N)
#define fLSBOLDNOT(VAL) fGETBIT(0, ~VAL)
#define fLSBNEWNOT(PRED) (fLSBNEW(~PRED))
#define fLSBNEW0NOT fLSBNEW(~P0N)
#define fLSBNEW1NOT fLSBNEW(~P1N)
/* Assignments */
#define fPCALIGN(IMM) (IMM = IMM & ~3)
#define fWRITE_LR(A) (LR = A)
#define fWRITE_FP(A) (FP = A)
#define fWRITE_SP(A) (SP = A)
/*
* Note: There is a rule in the parser that matches `PC = ...` and emits
* a call to `gen_write_new_pc`. We need to call `gen_write_new_pc` to
* get the correct semantics when there are multiple stores in a packet.
*/
#define fBRANCH(LOC, TYPE) (PC = LOC)
#define fJUMPR(REGNO, TARGET, TYPE) (PC = TARGET)
#define fWRITE_LOOP_REGS0(START, COUNT) SA0 = START; (LC0 = COUNT)
#define fWRITE_LOOP_REGS1(START, COUNT) SA1 = START; (LC1 = COUNT)
#define fWRITE_LC0(VAL) (LC0 = VAL)
#define fWRITE_LC1(VAL) (LC1 = VAL)
#define fSET_LPCFG(VAL) (USR.LPCFG = VAL)
#define fWRITE_P0(VAL) P0 = VAL;
#define fWRITE_P1(VAL) P1 = VAL;
#define fWRITE_P3(VAL) P3 = VAL;
#define fEA_RI(REG, IMM) (EA = REG + IMM)
#define fEA_RRs(REG, REG2, SCALE) (EA = REG + (REG2 << SCALE))
#define fEA_IRs(IMM, REG, SCALE) (EA = IMM + (REG << SCALE))
#define fEA_IMM(IMM) (EA = IMM)
#define fEA_REG(REG) (EA = REG)
#define fEA_BREVR(REG) (EA = fbrev(REG))
#define fEA_GPI(IMM) (EA = fREAD_GP() + IMM)
#define fPM_I(REG, IMM) (REG = REG + IMM)
#define fPM_M(REG, MVAL) (REG = REG + MVAL)
#define fWRITE_NPC(VAL) (PC = VAL)
/* Unary operators */
#define fROUND(A) (A + 0x8000)
/* Binary operators */
#define fSCALE(N, A) (A << N)
#define fASHIFTR(SRC, SHAMT, REGSTYPE) (fCAST##REGSTYPE##s(SRC) >> SHAMT)
#define fLSHIFTR(SRC, SHAMT, REGSTYPE) (SRC >>> SHAMT)
#define fROTL(SRC, SHAMT, REGSTYPE) fROTL(SRC, SHAMT)
#define fASHIFTL(SRC, SHAMT, REGSTYPE) (fCAST##REGSTYPE##s(SRC) << SHAMT)
/* Include fHIDE macros which hide type declarations */
#define fHIDE(A) A
/* Purge non-relavant parts */
#define fBRANCH_SPECULATE_STALL(A, B, C, D, E)
File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More