mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8351994: Enable Extended EVEX to REX2/REX demotion when src and dst are the same
Reviewed-by: sviswanathan, jbhateja, epeter
This commit is contained in:
parent
a3f9e22263
commit
fc3d3d9b30
File diff suppressed because it is too large
Load Diff
@ -772,25 +772,42 @@ private:
|
||||
void evex_prefix(bool vex_r, bool vex_b, bool vex_x, bool evex_v, bool evex_r, bool evex_b,
|
||||
bool eevex_x, int nds_enc, VexSimdPrefix pre, VexOpcode opc, bool no_flags = false);
|
||||
|
||||
void evex_prefix_ndd(Address adr, int ndd_enc, int xreg_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
InstructionAttr *attributes, bool no_flags = false);
|
||||
void eevex_prefix_ndd(Address adr, int ndd_enc, int xreg_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
InstructionAttr *attributes, bool no_flags = false);
|
||||
|
||||
void evex_prefix_nf(Address adr, int ndd_enc, int xreg_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
InstructionAttr *attributes, bool no_flags = false);
|
||||
void eevex_prefix_nf(Address adr, int ndd_enc, int xreg_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
InstructionAttr *attributes, bool no_flags = false);
|
||||
|
||||
void vex_prefix(Address adr, int nds_enc, int xreg_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
InstructionAttr *attributes, bool nds_is_ndd = false, bool no_flags = false);
|
||||
|
||||
int vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc,
|
||||
int vex_prefix_and_encode(int dst_enc, int nds_enc, int src_enc,
|
||||
VexSimdPrefix pre, VexOpcode opc,
|
||||
InstructionAttr *attributes, bool src_is_gpr = false, bool nds_is_ndd = false, bool no_flags = false);
|
||||
|
||||
int evex_prefix_and_encode_ndd(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
InstructionAttr *attributes, bool no_flags = false);
|
||||
|
||||
int evex_prefix_and_encode_nf(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
int eevex_prefix_and_encode_nf(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
InstructionAttr *attributes, bool no_flags = false);
|
||||
|
||||
int emit_eevex_prefix_ndd(int dst_enc, VexSimdPrefix pre, VexOpcode opc, InstructionAttr *attributes, bool no_flags = false);
|
||||
|
||||
int emit_eevex_prefix_or_demote_ndd(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
InstructionAttr *attributes, bool no_flags = false, bool use_prefixq = false);
|
||||
|
||||
int emit_eevex_prefix_or_demote_ndd(int dst_enc, int nds_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
InstructionAttr *attributes, bool no_flags = false, bool use_prefixq = false);
|
||||
|
||||
void emit_eevex_prefix_or_demote_arith_ndd(Register dst, Register nds, int32_t imm32, VexSimdPrefix pre, VexOpcode opc,
|
||||
int size, int op1, int op2, bool no_flags);
|
||||
|
||||
void emit_eevex_or_demote(Register dst, Register src1, Address src2, VexSimdPrefix pre, VexOpcode opc,
|
||||
int size, int opcode_byte, bool no_flags = false, bool is_map1 = false);
|
||||
|
||||
void emit_eevex_or_demote(int dst_enc, int nds_enc, int src_enc, VexSimdPrefix pre, VexOpcode opc,
|
||||
int size, int opcode_byte, bool no_flags, bool is_map1 = false, bool swap = false);
|
||||
|
||||
void emit_eevex_or_demote(int dst_enc, int nds_enc, int src_enc, int8_t imm8, VexSimdPrefix pre, VexOpcode opc,
|
||||
int size, int opcode_byte, bool no_flags, bool is_map1 = false);
|
||||
|
||||
void simd_prefix(XMMRegister xreg, XMMRegister nds, Address adr, VexSimdPrefix pre,
|
||||
VexOpcode opc, InstructionAttr *attributes);
|
||||
|
||||
@ -798,10 +815,10 @@ private:
|
||||
VexOpcode opc, InstructionAttr *attributes, bool src_is_gpr = false);
|
||||
|
||||
// Helper functions for groups of instructions
|
||||
bool is_demotable(bool no_flags, int dst_enc, int nds_enc);
|
||||
void emit_arith_b(int op1, int op2, Register dst, int imm8);
|
||||
|
||||
void emit_arith(int op1, int op2, Register dst, int32_t imm32);
|
||||
void emit_arith_ndd(int op1, int op2, Register dst, int32_t imm32);
|
||||
void emit_arith(int op1, int op2, Register dst, int32_t imm32, bool optimize_rax_dst = true);
|
||||
// Force generation of a 4 byte immediate value even if it fits into 8bit
|
||||
void emit_arith_imm32(int op1, int op2, Register dst, int32_t imm32);
|
||||
void emit_arith(int op1, int op2, Register dst, Register src);
|
||||
|
||||
@ -909,7 +909,7 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
|
||||
// Check if processor has Intel Ecore
|
||||
if (FLAG_IS_DEFAULT(EnableX86ECoreOpts) && is_intel() && cpu_family() == 6 &&
|
||||
if (FLAG_IS_DEFAULT(EnableX86ECoreOpts) && is_intel() && is_intel_server_family() &&
|
||||
(_model == 0x97 || _model == 0xAA || _model == 0xAC || _model == 0xAF ||
|
||||
_model == 0xCC || _model == 0xDD)) {
|
||||
FLAG_SET_DEFAULT(EnableX86ECoreOpts, true);
|
||||
@ -1594,7 +1594,7 @@ void VM_Version::get_processor_features() {
|
||||
if (FLAG_IS_DEFAULT(UseStoreImmI16)) {
|
||||
UseStoreImmI16 = false; // don't use it on Intel cpus
|
||||
}
|
||||
if (cpu_family() == 6 || cpu_family() == 15) {
|
||||
if (is_intel_server_family() || cpu_family() == 15) {
|
||||
if (FLAG_IS_DEFAULT(UseAddressNop)) {
|
||||
// Use it on all Intel cpus starting from PentiumPro
|
||||
UseAddressNop = true;
|
||||
@ -1610,7 +1610,7 @@ void VM_Version::get_processor_features() {
|
||||
UseXmmRegToRegMoveAll = false;
|
||||
}
|
||||
}
|
||||
if (cpu_family() == 6 && supports_sse3()) { // New Intel cpus
|
||||
if (is_intel_server_family() && supports_sse3()) { // New Intel cpus
|
||||
#ifdef COMPILER2
|
||||
if (FLAG_IS_DEFAULT(MaxLoopPad)) {
|
||||
// For new Intel cpus do the next optimization:
|
||||
@ -1848,7 +1848,7 @@ void VM_Version::get_processor_features() {
|
||||
FLAG_SET_DEFAULT(AllocatePrefetchDistance, allocate_prefetch_distance(use_watermark_prefetch));
|
||||
}
|
||||
|
||||
if (is_intel() && cpu_family() == 6 && supports_sse3()) {
|
||||
if (is_intel() && is_intel_server_family() && supports_sse3()) {
|
||||
if (FLAG_IS_DEFAULT(AllocatePrefetchLines) &&
|
||||
supports_sse4_2() && supports_ht()) { // Nehalem based cpus
|
||||
FLAG_SET_DEFAULT(AllocatePrefetchLines, 4);
|
||||
@ -3262,7 +3262,7 @@ int VM_Version::allocate_prefetch_distance(bool use_watermark_prefetch) {
|
||||
return 128; // Athlon
|
||||
}
|
||||
} else { // Intel
|
||||
if (supports_sse3() && cpu_family() == 6) {
|
||||
if (supports_sse3() && is_intel_server_family()) {
|
||||
if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus
|
||||
return 192;
|
||||
} else if (use_watermark_prefetch) { // watermark prefetching on Core
|
||||
@ -3270,7 +3270,7 @@ int VM_Version::allocate_prefetch_distance(bool use_watermark_prefetch) {
|
||||
}
|
||||
}
|
||||
if (supports_sse2()) {
|
||||
if (cpu_family() == 6) {
|
||||
if (is_intel_server_family()) {
|
||||
return 256; // Pentium M, Core, Core2
|
||||
} else {
|
||||
return 512; // Pentium 4
|
||||
|
||||
@ -791,6 +791,7 @@ public:
|
||||
static uint32_t cpu_stepping() { return _cpuid_info.cpu_stepping(); }
|
||||
static int cpu_family() { return _cpu;}
|
||||
static bool is_P6() { return cpu_family() >= 6; }
|
||||
static bool is_intel_server_family() { return cpu_family() == 6 || cpu_family() == 19; }
|
||||
static bool is_amd() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x68747541; } // 'htuA'
|
||||
static bool is_hygon() { assert_is_initialized(); return _cpuid_info.std_vendor_name_0 == 0x6F677948; } // 'ogyH'
|
||||
static bool is_amd_family() { return is_amd() || is_hygon(); }
|
||||
@ -946,7 +947,7 @@ public:
|
||||
}
|
||||
|
||||
// Intel Core and newer cpus have fast IDIV instruction (excluding Atom).
|
||||
static bool has_fast_idiv() { return is_intel() && cpu_family() == 6 &&
|
||||
static bool has_fast_idiv() { return is_intel() && is_intel_server_family() &&
|
||||
supports_sse3() && _model != 0x1C; }
|
||||
|
||||
static bool supports_compare_and_exchange() { return true; }
|
||||
|
||||
@ -7052,21 +7052,6 @@ instruct addI_rReg_mem(rRegI dst, memory src, rFlagsReg cr)
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
instruct addI_rReg_mem_rReg_ndd(rRegI dst, memory src1, rRegI src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (AddI (LoadI src1) src2));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "eaddl $dst, $src1, $src2\t# int ndd" %}
|
||||
ins_encode %{
|
||||
__ eaddl($dst$$Register, $src1$$Address, $src2$$Register, false);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
instruct addI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
@ -7370,21 +7355,6 @@ instruct addL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
instruct addL_rReg_mem_rReg_ndd(rRegL dst, memory src1, rRegL src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (AddL (LoadL src1) src2));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_overflow_flag, PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_carry_flag, PD::Flag_sets_parity_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "eaddq $dst, $src1, $src2\t# long ndd" %}
|
||||
ins_encode %{
|
||||
__ eaddq($dst$$Register, $src1$$Address, $src2$$Register, false);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
instruct addL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (StoreL dst (AddL (LoadL dst) src)));
|
||||
@ -8596,7 +8566,6 @@ instruct mulI_rReg_ndd(rRegI dst, rRegI src1, rRegI src2, rFlagsReg cr)
|
||||
|
||||
instruct mulI_rReg_imm(rRegI dst, rRegI src, immI imm, rFlagsReg cr)
|
||||
%{
|
||||
predicate(!UseAPX);
|
||||
match(Set dst (MulI src imm));
|
||||
effect(KILL cr);
|
||||
|
||||
@ -8608,20 +8577,6 @@ instruct mulI_rReg_imm(rRegI dst, rRegI src, immI imm, rFlagsReg cr)
|
||||
ins_pipe(ialu_reg_reg_alu0);
|
||||
%}
|
||||
|
||||
instruct mulI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (MulI src1 src2));
|
||||
effect(KILL cr);
|
||||
|
||||
ins_cost(300);
|
||||
format %{ "eimull $dst, $src1, $src2\t# int ndd" %}
|
||||
ins_encode %{
|
||||
__ eimull($dst$$Register, $src1$$Register, $src2$$constant, false);
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_alu0);
|
||||
%}
|
||||
|
||||
instruct mulI_mem(rRegI dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
predicate(!UseAPX);
|
||||
@ -8652,7 +8607,6 @@ instruct mulI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr
|
||||
|
||||
instruct mulI_mem_imm(rRegI dst, memory src, immI imm, rFlagsReg cr)
|
||||
%{
|
||||
predicate(!UseAPX);
|
||||
match(Set dst (MulI (LoadI src) imm));
|
||||
effect(KILL cr);
|
||||
|
||||
@ -8664,20 +8618,6 @@ instruct mulI_mem_imm(rRegI dst, memory src, immI imm, rFlagsReg cr)
|
||||
ins_pipe(ialu_reg_mem_alu0);
|
||||
%}
|
||||
|
||||
instruct mulI_rReg_mem_imm(rRegI dst, memory src1, immI src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (MulI (LoadI src1) src2));
|
||||
effect(KILL cr);
|
||||
|
||||
ins_cost(300);
|
||||
format %{ "eimull $dst, $src1, $src2\t# int ndd" %}
|
||||
ins_encode %{
|
||||
__ eimull($dst$$Register, $src1$$Address, $src2$$constant, false);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem_alu0);
|
||||
%}
|
||||
|
||||
instruct mulAddS2I_rReg(rRegI dst, rRegI src1, rRegI src2, rRegI src3, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (MulAddS2I (Binary dst src1) (Binary src2 src3)));
|
||||
@ -8718,7 +8658,6 @@ instruct mulL_rReg_ndd(rRegL dst, rRegL src1, rRegL src2, rFlagsReg cr)
|
||||
|
||||
instruct mulL_rReg_imm(rRegL dst, rRegL src, immL32 imm, rFlagsReg cr)
|
||||
%{
|
||||
predicate(!UseAPX);
|
||||
match(Set dst (MulL src imm));
|
||||
effect(KILL cr);
|
||||
|
||||
@ -8730,20 +8669,6 @@ instruct mulL_rReg_imm(rRegL dst, rRegL src, immL32 imm, rFlagsReg cr)
|
||||
ins_pipe(ialu_reg_reg_alu0);
|
||||
%}
|
||||
|
||||
instruct mulL_rReg_rReg_imm_ndd(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (MulL src1 src2));
|
||||
effect(KILL cr);
|
||||
|
||||
ins_cost(300);
|
||||
format %{ "eimulq $dst, $src1, $src2\t# long ndd" %}
|
||||
ins_encode %{
|
||||
__ eimulq($dst$$Register, $src1$$Register, $src2$$constant, false);
|
||||
%}
|
||||
ins_pipe(ialu_reg_reg_alu0);
|
||||
%}
|
||||
|
||||
instruct mulL_mem(rRegL dst, memory src, rFlagsReg cr)
|
||||
%{
|
||||
predicate(!UseAPX);
|
||||
@ -8774,7 +8699,6 @@ instruct mulL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr
|
||||
|
||||
instruct mulL_mem_imm(rRegL dst, memory src, immL32 imm, rFlagsReg cr)
|
||||
%{
|
||||
predicate(!UseAPX);
|
||||
match(Set dst (MulL (LoadL src) imm));
|
||||
effect(KILL cr);
|
||||
|
||||
@ -8786,20 +8710,6 @@ instruct mulL_mem_imm(rRegL dst, memory src, immL32 imm, rFlagsReg cr)
|
||||
ins_pipe(ialu_reg_mem_alu0);
|
||||
%}
|
||||
|
||||
instruct mulL_rReg_mem_imm_ndd(rRegL dst, memory src1, immL32 src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (MulL (LoadL src1) src2));
|
||||
effect(KILL cr);
|
||||
|
||||
ins_cost(300);
|
||||
format %{ "eimulq $dst, $src1, $src2\t# long ndd" %}
|
||||
ins_encode %{
|
||||
__ eimulq($dst$$Register, $src1$$Address, $src2$$constant, false);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem_alu0);
|
||||
%}
|
||||
|
||||
instruct mulHiL_rReg(rdx_RegL dst, rRegL src, rax_RegL rax, rFlagsReg cr)
|
||||
%{
|
||||
match(Set dst (MulHiL src rax));
|
||||
@ -10689,21 +10599,6 @@ instruct xorI_rReg_rReg_mem_ndd(rRegI dst, rRegI src1, memory src2, rFlagsReg cr
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
instruct xorI_rReg_mem_rReg_ndd(rRegI dst, memory src1, rRegI src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (XorI (LoadI src1) src2));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "exorl $dst, $src1, $src2\t# int ndd" %}
|
||||
ins_encode %{
|
||||
__ exorl($dst$$Register, $src1$$Address, $src2$$Register, false);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Xor Memory with Register
|
||||
instruct xorB_mem_rReg(memory dst, rRegI src, rFlagsReg cr)
|
||||
%{
|
||||
@ -10883,21 +10778,6 @@ instruct andL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
instruct andL_rReg_mem_rReg_ndd(rRegL dst, memory src1, rRegL src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (AndL (LoadL src1) src2));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "eandq $dst, $src1, $src2\t# long ndd" %}
|
||||
ins_encode %{
|
||||
__ eandq($dst$$Register, $src1$$Address, $src2$$Register, false);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// And Memory with Register
|
||||
instruct andL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
@ -11393,21 +11273,6 @@ instruct xorL_rReg_rReg_mem_ndd(rRegL dst, rRegL src1, memory src2, rFlagsReg cr
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
instruct xorL_rReg_mem_rReg_ndd(rRegL dst, memory src1, rRegL src2, rFlagsReg cr)
|
||||
%{
|
||||
predicate(UseAPX);
|
||||
match(Set dst (XorL (LoadL src1) src2));
|
||||
effect(KILL cr);
|
||||
flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag);
|
||||
|
||||
ins_cost(150);
|
||||
format %{ "exorq $dst, $src1, $src2\t# long ndd" %}
|
||||
ins_encode %{
|
||||
__ exorq($dst$$Register, $src1$$Address, $src2$$Register, false);
|
||||
%}
|
||||
ins_pipe(ialu_reg_mem);
|
||||
%}
|
||||
|
||||
// Xor Memory with Register
|
||||
instruct xorL_mem_rReg(memory dst, rRegL src, rFlagsReg cr)
|
||||
%{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -71,7 +71,7 @@ TEST_VM(AssemblerX86, validate) {
|
||||
VM_Version::set_evex_cpuFeatures();
|
||||
VM_Version::set_avx_cpuFeatures();
|
||||
VM_Version::set_apx_cpuFeatures();
|
||||
BufferBlob* b = BufferBlob::create("x64Test", 500000);
|
||||
BufferBlob* b = BufferBlob::create("x64Test", 5000000);
|
||||
CodeBuffer code(b);
|
||||
MacroAssembler _masm(&code);
|
||||
address entry = __ pc();
|
||||
|
||||
@ -30,6 +30,7 @@ OBJDUMP = "objdump"
|
||||
X86_AS = "as"
|
||||
X86_OBJCOPY = "objcopy"
|
||||
SEED = 1327
|
||||
TEST_DEMOTION = True
|
||||
|
||||
random.seed(SEED)
|
||||
|
||||
@ -301,12 +302,18 @@ class CondRegRegRegInstruction(Instruction):
|
||||
self.reg3 = Register().generate(reg3, width)
|
||||
self.cond = cond
|
||||
self.generate_operands(self.reg1, self.reg2, self.reg3)
|
||||
self.demote = True
|
||||
|
||||
def cstr(self):
|
||||
return f'__ {self._name} (' + 'Assembler::Condition::' + self.cond + ', ' + ', '.join([reg.cstr() for reg in self.operands]) + ');'
|
||||
|
||||
def astr(self):
|
||||
return f'{self._aname}' + cond_to_suffix[self.cond] + ' ' + ', '.join([reg.astr() for reg in self.operands])
|
||||
operands = self.operands
|
||||
if self.demote:
|
||||
ops = [op.cstr() for op in self.operands]
|
||||
if ops[0] == ops[1]:
|
||||
operands = operands[1:]
|
||||
return f'{self._aname}' + cond_to_suffix[self.cond] + ' ' + ', '.join([reg.astr() for reg in operands])
|
||||
|
||||
class CondRegRegMemInstruction(Instruction):
|
||||
def __init__(self, name, aname, width, cond, reg1, reg2, mem_base, mem_idx):
|
||||
@ -316,12 +323,18 @@ class CondRegRegMemInstruction(Instruction):
|
||||
self.mem = Address().generate(mem_base, mem_idx, width)
|
||||
self.cond = cond
|
||||
self.generate_operands(self.reg1, self.reg2, self.mem)
|
||||
self.demote = True
|
||||
|
||||
def cstr(self):
|
||||
return f'__ {self._name} (' + 'Assembler::Condition::' + self.cond + ', ' + ', '.join([reg.cstr() for reg in self.operands]) + ');'
|
||||
|
||||
def astr(self):
|
||||
return f'{self._aname}' + cond_to_suffix[self.cond] + ' ' + ', '.join([reg.astr() for reg in self.operands])
|
||||
operands = self.operands
|
||||
if self.demote:
|
||||
ops = [op.cstr() for op in self.operands]
|
||||
if ops[0] == ops[1]:
|
||||
operands = operands[1:]
|
||||
return f'{self._aname}' + cond_to_suffix[self.cond] + ' ' + ', '.join([reg.astr() for reg in operands])
|
||||
|
||||
class MoveRegMemInstruction(Instruction):
|
||||
def __init__(self, name, aname, width, mem_width, reg, mem_base, mem_idx):
|
||||
@ -355,6 +368,15 @@ class RegRegNddInstruction(NFInstruction):
|
||||
self.reg1 = Register().generate(reg1, width)
|
||||
self.reg2 = Register().generate(reg2, width)
|
||||
self.generate_operands(self.reg1, self.reg2)
|
||||
self.demote = True
|
||||
|
||||
def astr(self):
|
||||
if self.demote and self._aname not in ['popcnt', 'lzcnt', 'tzcnt']:
|
||||
ops = [op.cstr() for op in self.operands]
|
||||
if ops[0] == ops[1] and (not self.no_flag):
|
||||
cl_str = (', cl' if self._name in shift_rot_ops and len(self.operands) == 2 else '')
|
||||
return f'{self._aname} ' + ', '.join([op.astr() for op in self.operands[1:]]) + cl_str
|
||||
return super().astr()
|
||||
|
||||
class RegMemNddInstruction(NFInstruction):
|
||||
def __init__(self, name, aname, width, no_flag, reg, mem_base, mem_idx):
|
||||
@ -386,6 +408,14 @@ class RegRegImmNddInstruction(NFInstruction):
|
||||
self.reg2 = Register().generate(reg2, width)
|
||||
self.imm = Immediate().generate(imm)
|
||||
self.generate_operands(self.reg1, self.reg2, self.imm)
|
||||
self.demote = True
|
||||
|
||||
def astr(self):
|
||||
if self.demote and self._aname not in ['imul']:
|
||||
ops = [op.cstr() for op in self.operands]
|
||||
if ops[0] == ops[1] and (not self.no_flag):
|
||||
return f'{self._aname} ' + ', '.join([op.astr() for op in self.operands[1:]])
|
||||
return super().astr()
|
||||
|
||||
class RegRegMemNddInstruction(NFInstruction):
|
||||
def __init__(self, name, aname, width, no_flag, reg1, reg2, mem_base, mem_idx):
|
||||
@ -394,6 +424,14 @@ class RegRegMemNddInstruction(NFInstruction):
|
||||
self.reg2 = Register().generate(reg2, width)
|
||||
self.mem = Address().generate(mem_base, mem_idx, width)
|
||||
self.generate_operands(self.reg1, self.reg2, self.mem)
|
||||
self.demote = True
|
||||
|
||||
def astr(self):
|
||||
if self.demote:
|
||||
ops = [op.cstr() for op in self.operands]
|
||||
if ops[0] == ops[1] and (not self.no_flag):
|
||||
return f'{self._aname} ' + ', '.join([op.astr() for op in self.operands[1:]])
|
||||
return super().astr()
|
||||
|
||||
class RegRegRegNddInstruction(NFInstruction):
|
||||
def __init__(self, name, aname, width, no_flag, reg1, reg2, reg3):
|
||||
@ -402,9 +440,15 @@ class RegRegRegNddInstruction(NFInstruction):
|
||||
self.reg2 = Register().generate(reg2, width)
|
||||
self.reg3 = Register().generate(reg3, width)
|
||||
self.generate_operands(self.reg1, self.reg2, self.reg3)
|
||||
self.demote = True
|
||||
|
||||
def astr(self):
|
||||
return f'{{load}}' + super().astr()
|
||||
hdr = f'{{load}}'
|
||||
if self.demote:
|
||||
ops = [op.cstr() for op in self.operands]
|
||||
if ops[0] == ops[1] and (not self.no_flag):
|
||||
return hdr + f'{self._aname} ' + ', '.join([op.astr() for op in self.operands[1:]])
|
||||
return hdr + super().astr()
|
||||
|
||||
class RegRegRegImmNddInstruction(NFInstruction):
|
||||
def __init__(self, name, aname, width, no_flag, reg1, reg2, reg3, imm):
|
||||
@ -414,6 +458,15 @@ class RegRegRegImmNddInstruction(NFInstruction):
|
||||
self.reg3 = Register().generate(reg3, width)
|
||||
self.imm = Immediate().generate(imm)
|
||||
self.generate_operands(self.reg1, self.reg2, self.reg3, self.imm)
|
||||
self.demote = True
|
||||
|
||||
def astr(self):
|
||||
if self.demote:
|
||||
ops = [op.cstr() for op in self.operands]
|
||||
if ops[0] == ops[1] and (not self.no_flag):
|
||||
return (f'{self._aname} ' + ', '.join([op.astr() for op in self.operands[1:]]))
|
||||
return super().astr()
|
||||
|
||||
|
||||
test_regs = [key for key in registers_mapping.keys() if key != 'rax']
|
||||
|
||||
@ -499,36 +552,28 @@ def generate(RegOp, ops, print_lp64_flag=True, full_set=False):
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
|
||||
elif RegOp in [TwoRegInstruction, MoveRegRegInstruction, RegRegNddInstruction]:
|
||||
if full_set:
|
||||
for i in range(len(test_regs)):
|
||||
test_reg1 = test_regs[i]
|
||||
test_reg2 = test_regs[(i + 1) % len(test_regs)]
|
||||
demote_options = [False, True] if TEST_DEMOTION and RegOp in [RegRegNddInstruction] else [False]
|
||||
for demote in demote_options:
|
||||
for i in range(len(test_regs) if full_set else 1):
|
||||
test_reg1 = test_regs[i] if full_set else random.choice(test_regs)
|
||||
test_reg2 = test_reg1 if demote \
|
||||
else test_regs[(i + 1) % len(test_regs)] if full_set \
|
||||
else random.choice(test_regs)
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
|
||||
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
else:
|
||||
test_reg1 = random.choice(test_regs)
|
||||
test_reg2 = random.choice(test_regs)
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
|
||||
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
|
||||
elif RegOp in [RegRegRegNddInstruction, CondRegRegRegInstruction]:
|
||||
if full_set:
|
||||
for i in range(len(test_regs)):
|
||||
test_reg1 = test_regs[i]
|
||||
test_reg2 = test_regs[(i + 1) % len(test_regs)]
|
||||
test_reg3 = test_regs[(i + 2) % len(test_regs)]
|
||||
for demote in [False, True] if TEST_DEMOTION else [False]:
|
||||
for i in range(len(test_regs) if full_set else 1):
|
||||
test_reg1 = test_regs[i] if full_set else random.choice(test_regs)
|
||||
test_reg2 = test_reg1 if demote \
|
||||
else test_regs[(i + 1) % len(test_regs)] if full_set \
|
||||
else random.choice(test_regs)
|
||||
test_reg3 = test_regs[(i + 2) % len(test_regs)] if full_set else random.choice(test_regs)
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2, test_reg3)
|
||||
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, reg3=test_reg3)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
else:
|
||||
test_reg1 = random.choice(test_regs)
|
||||
test_reg2 = random.choice(test_regs)
|
||||
test_reg3 = random.choice(test_regs)
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2, test_reg3)
|
||||
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, reg3=test_reg3)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
|
||||
elif RegOp in [MemRegInstruction, RegMemInstruction, MoveRegMemInstruction, CmpxchgInstruction, CondRegMemInstruction, RegMemNddInstruction]:
|
||||
if full_set:
|
||||
@ -607,30 +652,28 @@ def generate(RegOp, ops, print_lp64_flag=True, full_set=False):
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
|
||||
elif RegOp in [RegRegImmInstruction, RegRegImmNddInstruction]:
|
||||
if full_set:
|
||||
demote_options = [False, True] if TEST_DEMOTION and RegOp in [RegRegImmNddInstruction] else [False]
|
||||
for demote in demote_options:
|
||||
imm_list = get_immediate_list(op_name, width)
|
||||
for i in range(len(test_regs)):
|
||||
test_reg1 = test_regs[i]
|
||||
test_reg2 = test_regs[(i + 1) % len(test_regs)]
|
||||
if not full_set:
|
||||
imm_list = [random.choice(imm_list)]
|
||||
for i in range(len(test_regs) if full_set else 1):
|
||||
test_reg1 = test_regs[i] if full_set else random.choice(test_regs)
|
||||
test_reg2 = test_reg1 if demote \
|
||||
else test_regs[(i + 1) % len(test_regs)] if full_set \
|
||||
else random.choice(test_regs)
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
|
||||
for imm in imm_list:
|
||||
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, imm=imm)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
else:
|
||||
imm = random.choice(get_immediate_list(op_name, width))
|
||||
test_reg1 = random.choice(test_regs)
|
||||
test_reg2 = random.choice(test_regs)
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
|
||||
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, imm=imm)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
|
||||
# additional tests with rax as destination
|
||||
if RegOp in [RegRegImmNddInstruction]:
|
||||
test_reg1 = 'rax'
|
||||
test_reg2 = random.choice(test_regs)
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
|
||||
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, imm=imm)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
# additional tests with rax as destination
|
||||
if RegOp in [RegRegImmNddInstruction] and not demote and not full_set:
|
||||
test_reg1 = 'rax'
|
||||
test_reg2 = random.choice(test_regs)
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2)
|
||||
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, imm=imm)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
|
||||
elif RegOp in [RegMemImmInstruction, RegMemImmNddInstruction]:
|
||||
if full_set:
|
||||
@ -656,46 +699,37 @@ def generate(RegOp, ops, print_lp64_flag=True, full_set=False):
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
|
||||
elif RegOp in [RegMemRegNddInstruction, RegRegMemNddInstruction, CondRegRegMemInstruction]:
|
||||
if full_set:
|
||||
for i in range(len(test_regs)):
|
||||
test_reg1 = test_regs[i]
|
||||
test_mem_base = test_regs[(i + 1) % len(test_regs)]
|
||||
test_mem_idx = test_regs[(i + 2) % len(test_regs)]
|
||||
test_reg2 = test_regs[(i + 3) % len(test_regs)]
|
||||
demote_options = [False] if TEST_DEMOTION and RegOp not in [RegMemRegNddInstruction] else [False, True]
|
||||
for demote in demote_options:
|
||||
for i in range(len(test_regs) if full_set else 1):
|
||||
test_reg1 = test_regs[i] if full_set else random.choice(test_regs)
|
||||
test_mem_base = test_regs[(i + 1) % len(test_regs)] if full_set else random.choice(test_regs)
|
||||
test_mem_idx = test_regs[(i + 2) % len(test_regs)] if full_set \
|
||||
else random.choice([reg for reg in test_regs if reg != 'rsp'])
|
||||
test_reg2 = test_reg1 if demote \
|
||||
else test_regs[(i + 3) % len(test_regs)] if full_set \
|
||||
else random.choice(test_regs)
|
||||
if test_mem_idx == 'rsp':
|
||||
continue
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_mem_base, test_mem_idx, test_reg2)
|
||||
instr = RegOp(*op, reg1=test_reg1, mem_base=test_mem_base, mem_idx=test_mem_idx, reg2=test_reg2)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
else:
|
||||
filtered_regs = [reg for reg in test_regs if reg != 'rsp']
|
||||
test_reg1 = random.choice(test_regs)
|
||||
test_mem_base = random.choice(test_regs)
|
||||
test_mem_idx = random.choice(filtered_regs)
|
||||
test_reg2 = random.choice(test_regs)
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_mem_base, test_mem_idx, test_reg2)
|
||||
instr = RegOp(*op, reg1=test_reg1, mem_base=test_mem_base, mem_idx=test_mem_idx, reg2=test_reg2)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
|
||||
|
||||
elif RegOp in [RegRegRegImmNddInstruction]:
|
||||
if full_set:
|
||||
for demote in [False, True] if TEST_DEMOTION else [False]:
|
||||
imm_list = get_immediate_list(op_name, width)
|
||||
for i in range(len(test_regs)):
|
||||
test_reg1 = test_regs[i]
|
||||
test_reg2 = test_regs[(i + 1) % len(test_regs)]
|
||||
test_reg3 = test_regs[(i + 2) % len(test_regs)]
|
||||
if not full_set:
|
||||
imm_list = [random.choice(imm_list)]
|
||||
for i in range(len(test_regs) if full_set else 1):
|
||||
test_reg1 = test_regs[i] if full_set else random.choice(test_regs)
|
||||
test_reg2 = test_reg1 if demote \
|
||||
else test_regs[(i + 1) % len(test_regs)] if full_set \
|
||||
else random.choice(test_regs)
|
||||
test_reg3 = test_regs[(i + 2) % len(test_regs)] if full_set else random.choice(test_regs)
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2, test_reg3)
|
||||
for imm in imm_list:
|
||||
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, reg3=test_reg3, imm=imm)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
else:
|
||||
imm = random.choice(get_immediate_list(op_name, width))
|
||||
test_reg1 = random.choice(test_regs)
|
||||
test_reg2 = random.choice(test_regs)
|
||||
test_reg3 = random.choice(test_regs)
|
||||
lp64_flag = handle_lp64_flag(lp64_flag, print_lp64_flag, test_reg1, test_reg2, test_reg3)
|
||||
instr = RegOp(*op, reg1=test_reg1, reg2=test_reg2, reg3=test_reg3, imm=imm)
|
||||
print_instruction(instr, lp64_flag, print_lp64_flag)
|
||||
|
||||
elif RegOp in [Push2Instruction, Pop2Instruction]:
|
||||
if full_set:
|
||||
@ -936,7 +970,7 @@ instruction_set = {
|
||||
('edecl', 'dec', 32, False),
|
||||
('edecl', 'dec', 32, True),
|
||||
('eincl', 'inc', 32, False),
|
||||
('eincl', 'inc', 32, True),
|
||||
('eincl', 'inc', 32, True),
|
||||
('eshll', 'shl', 32, False),
|
||||
('eshll', 'shl', 32, True),
|
||||
('eshrl', 'shr', 32, False),
|
||||
@ -1357,8 +1391,8 @@ instruction_set64 = {
|
||||
('exorq', 'xor', 64, True),
|
||||
('eorq_imm32', 'or', 64, False),
|
||||
('eorq_imm32', 'or', 64, False),
|
||||
('esubq_imm32', 'sub', 64, False),
|
||||
('esubq_imm32', 'sub', 64, True),
|
||||
('esubq_imm32', 'sub', 64, False),
|
||||
('esubq_imm32', 'sub', 64, True),
|
||||
],
|
||||
RegRegMemNddInstruction: [
|
||||
('eaddq', 'add', 64, False),
|
||||
@ -1422,7 +1456,7 @@ if __name__ == "__main__":
|
||||
|
||||
for RegOp, ops in instruction_set.items():
|
||||
generate(RegOp, ops, True, full_set)
|
||||
|
||||
|
||||
if lp64_flag:
|
||||
lp64_flag = False
|
||||
print("#endif // _LP64")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user