s390x: Fix bitwise operations (#4146)

Current codegen had a number of logic errors confusing
NAND with AND WITH COMPLEMENT, and NOR with OR WITH COMPLEMENT.

Add support for the missing z15 instructions and fix logic.
This commit is contained in:
Ulrich Weigand
2022-05-12 19:05:22 +02:00
committed by GitHub
parent 9538336f82
commit 0243a16679
7 changed files with 151 additions and 75 deletions

View File

@@ -996,12 +996,16 @@ impl MachInstEmit for Inst {
ALUOp::Orr64 => (0xb9e6, true), // OGRK
ALUOp::Xor32 => (0xb9f7, true), // XRK
ALUOp::Xor64 => (0xb9e7, true), // XGRK
ALUOp::AndNot32 => (0xb974, false), // NNRK
ALUOp::AndNot64 => (0xb964, false), // NNGRK
ALUOp::OrrNot32 => (0xb976, false), // NORK
ALUOp::OrrNot64 => (0xb966, false), // NOGRK
ALUOp::XorNot32 => (0xb977, false), // NXRK
ALUOp::XorNot64 => (0xb967, false), // NXGRK
ALUOp::NotAnd32 => (0xb974, false), // NNRK
ALUOp::NotAnd64 => (0xb964, false), // NNGRK
ALUOp::NotOrr32 => (0xb976, false), // NORK
ALUOp::NotOrr64 => (0xb966, false), // NOGRK
ALUOp::NotXor32 => (0xb977, false), // NXRK
ALUOp::NotXor64 => (0xb967, false), // NXGRK
ALUOp::AndNot32 => (0xb9f5, false), // NCRK
ALUOp::AndNot64 => (0xb9e5, false), // NCGRK
ALUOp::OrrNot32 => (0xb975, false), // OCRK
ALUOp::OrrNot64 => (0xb965, false), // OCGRK
_ => unreachable!(),
};
if have_rr && rd.to_reg() == rn {

View File

@@ -178,7 +178,7 @@ fn test_s390x_binemit() {
));
insns.push((
Inst::AluRRR {
alu_op: ALUOp::AndNot32,
alu_op: ALUOp::NotAnd32,
rd: writable_gpr(1),
rn: gpr(2),
rm: gpr(3),
@@ -188,7 +188,7 @@ fn test_s390x_binemit() {
));
insns.push((
Inst::AluRRR {
alu_op: ALUOp::AndNot64,
alu_op: ALUOp::NotAnd64,
rd: writable_gpr(4),
rn: gpr(5),
rm: gpr(6),
@@ -198,7 +198,7 @@ fn test_s390x_binemit() {
));
insns.push((
Inst::AluRRR {
alu_op: ALUOp::OrrNot32,
alu_op: ALUOp::NotOrr32,
rd: writable_gpr(1),
rn: gpr(2),
rm: gpr(3),
@@ -208,7 +208,7 @@ fn test_s390x_binemit() {
));
insns.push((
Inst::AluRRR {
alu_op: ALUOp::OrrNot64,
alu_op: ALUOp::NotOrr64,
rd: writable_gpr(4),
rn: gpr(5),
rm: gpr(6),
@@ -218,7 +218,7 @@ fn test_s390x_binemit() {
));
insns.push((
Inst::AluRRR {
alu_op: ALUOp::XorNot32,
alu_op: ALUOp::NotXor32,
rd: writable_gpr(1),
rn: gpr(2),
rm: gpr(3),
@@ -228,7 +228,7 @@ fn test_s390x_binemit() {
));
insns.push((
Inst::AluRRR {
alu_op: ALUOp::XorNot64,
alu_op: ALUOp::NotXor64,
rd: writable_gpr(4),
rn: gpr(5),
rm: gpr(6),
@@ -236,6 +236,46 @@ fn test_s390x_binemit() {
"B9676045",
"nxgrk %r4, %r5, %r6",
));
insns.push((
Inst::AluRRR {
alu_op: ALUOp::AndNot32,
rd: writable_gpr(1),
rn: gpr(2),
rm: gpr(3),
},
"B9F53012",
"ncrk %r1, %r2, %r3",
));
insns.push((
Inst::AluRRR {
alu_op: ALUOp::AndNot64,
rd: writable_gpr(4),
rn: gpr(5),
rm: gpr(6),
},
"B9E56045",
"ncgrk %r4, %r5, %r6",
));
insns.push((
Inst::AluRRR {
alu_op: ALUOp::OrrNot32,
rd: writable_gpr(1),
rn: gpr(2),
rm: gpr(3),
},
"B9753012",
"ocrk %r1, %r2, %r3",
));
insns.push((
Inst::AluRRR {
alu_op: ALUOp::OrrNot64,
rd: writable_gpr(4),
rn: gpr(5),
rm: gpr(6),
},
"B9656045",
"ocgrk %r4, %r5, %r6",
));
insns.push((
Inst::AluRRSImm16 {

View File

@@ -193,9 +193,11 @@ impl Inst {
// These depend on the opcode
Inst::AluRRR { alu_op, .. } => match alu_op {
ALUOp::NotAnd32 | ALUOp::NotAnd64 => InstructionSet::MIE2,
ALUOp::NotOrr32 | ALUOp::NotOrr64 => InstructionSet::MIE2,
ALUOp::NotXor32 | ALUOp::NotXor64 => InstructionSet::MIE2,
ALUOp::AndNot32 | ALUOp::AndNot64 => InstructionSet::MIE2,
ALUOp::OrrNot32 | ALUOp::OrrNot64 => InstructionSet::MIE2,
ALUOp::XorNot32 | ALUOp::XorNot64 => InstructionSet::MIE2,
_ => InstructionSet::Base,
},
Inst::UnaryRR { op, .. } => match op {
@@ -933,12 +935,16 @@ impl Inst {
ALUOp::Orr64 => ("ogrk", true),
ALUOp::Xor32 => ("xrk", true),
ALUOp::Xor64 => ("xgrk", true),
ALUOp::AndNot32 => ("nnrk", false),
ALUOp::AndNot64 => ("nngrk", false),
ALUOp::OrrNot32 => ("nork", false),
ALUOp::OrrNot64 => ("nogrk", false),
ALUOp::XorNot32 => ("nxrk", false),
ALUOp::XorNot64 => ("nxgrk", false),
ALUOp::NotAnd32 => ("nnrk", false),
ALUOp::NotAnd64 => ("nngrk", false),
ALUOp::NotOrr32 => ("nork", false),
ALUOp::NotOrr64 => ("nogrk", false),
ALUOp::NotXor32 => ("nxrk", false),
ALUOp::NotXor64 => ("nxgrk", false),
ALUOp::AndNot32 => ("ncrk", false),
ALUOp::AndNot64 => ("ncgrk", false),
ALUOp::OrrNot32 => ("ocrk", false),
ALUOp::OrrNot64 => ("ocgrk", false),
_ => unreachable!(),
};
if have_rr && rd.to_reg() == rn {