mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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:
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user