aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Belliard <vincent.belliard@arm.com>2017-04-21 13:10:07 -0700
committerVincent Belliard <vincent.belliard@arm.com>2017-04-25 11:20:42 -0700
commit07f9e742691f10b7ff8b0107415eb94e157c2b33 (patch)
treedf43b75dde6197bbeb9914e3d746e1de737aec31
parentba8964e06f9f297a9a795a122755e01adb8e0d72 (diff)
downloadvixl-07f9e742691f10b7ff8b0107415eb94e157c2b33.tar.gz
Use SOperand and DOperand for cmp and cmpe.
Change-Id: Ie5419a9f423c9dca7e21308ce3b35909500f2ca2
-rw-r--r--src/aarch32/assembler-aarch32.cc295
-rw-r--r--src/aarch32/assembler-aarch32.h114
-rw-r--r--src/aarch32/disasm-aarch32.cc54
-rw-r--r--src/aarch32/disasm-aarch32.h22
-rw-r--r--src/aarch32/macro-assembler-aarch32.h84
-rw-r--r--src/aarch32/operands-aarch32.h14
-rw-r--r--test/aarch32/test-assembler-aarch32.cc120
-rw-r--r--test/aarch32/test-disasm-a32.cc17
8 files changed, 398 insertions, 322 deletions
diff --git a/src/aarch32/assembler-aarch32.cc b/src/aarch32/assembler-aarch32.cc
index 239c76c9..183b364a 100644
--- a/src/aarch32/assembler-aarch32.cc
+++ b/src/aarch32/assembler-aarch32.cc
@@ -15425,168 +15425,176 @@ void Assembler::vclz(Condition cond, DataType dt, QRegister rd, QRegister rm) {
Delegate(kVclz, &Assembler::vclz, cond, dt, rd, rm);
}
-void Assembler::vcmp(Condition cond, DataType dt, SRegister rd, SRegister rm) {
+void Assembler::vcmp(Condition cond,
+ DataType dt,
+ SRegister rd,
+ const SOperand& operand) {
VIXL_ASSERT(AllowAssembler());
CheckIT(cond);
- if (IsUsingT32()) {
- // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
- if (dt.Is(F32)) {
- EmitT32_32(0xeeb40a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
- AdvanceIT();
- return;
- }
- } else {
- // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
- if (dt.Is(F32) && cond.IsNotNever()) {
- EmitA32(0x0eb40a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
- rm.Encode(5, 0));
- return;
+ if (operand.IsRegister()) {
+ SRegister rm = operand.GetRegister();
+ if (IsUsingT32()) {
+ // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
+ if (dt.Is(F32)) {
+ EmitT32_32(0xeeb40a40U | rd.Encode(22, 12) | rm.Encode(5, 0));
+ AdvanceIT();
+ return;
+ }
+ } else {
+ // VCMP{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
+ if (dt.Is(F32) && cond.IsNotNever()) {
+ EmitA32(0x0eb40a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
+ rm.Encode(5, 0));
+ return;
+ }
}
}
- Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, rm);
-}
-
-void Assembler::vcmp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
- VIXL_ASSERT(AllowAssembler());
- CheckIT(cond);
- if (IsUsingT32()) {
- // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
- if (dt.Is(F64)) {
- EmitT32_32(0xeeb40b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
- AdvanceIT();
- return;
- }
- } else {
- // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
- if (dt.Is(F64) && cond.IsNotNever()) {
- EmitA32(0x0eb40b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
- rm.Encode(5, 0));
- return;
+ if (operand.IsImmediate()) {
+ if (IsUsingT32()) {
+ // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
+ if (dt.Is(F32) && (operand.IsFloatZero())) {
+ EmitT32_32(0xeeb50a40U | rd.Encode(22, 12));
+ AdvanceIT();
+ return;
+ }
+ } else {
+ // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
+ if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
+ EmitA32(0x0eb50a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
+ return;
+ }
}
}
- Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, rm);
+ Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
}
-void Assembler::vcmp(Condition cond, DataType dt, SRegister rd, double imm) {
+void Assembler::vcmp(Condition cond,
+ DataType dt,
+ DRegister rd,
+ const DOperand& operand) {
VIXL_ASSERT(AllowAssembler());
CheckIT(cond);
- if (IsUsingT32()) {
- // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
- if (dt.Is(F32) && (imm == 0.0)) {
- EmitT32_32(0xeeb50a40U | rd.Encode(22, 12));
- AdvanceIT();
- return;
- }
- } else {
- // VCMP{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
- if (dt.Is(F32) && (imm == 0.0) && cond.IsNotNever()) {
- EmitA32(0x0eb50a40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
- return;
+ if (operand.IsRegister()) {
+ DRegister rm = operand.GetRegister();
+ if (IsUsingT32()) {
+ // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
+ if (dt.Is(F64)) {
+ EmitT32_32(0xeeb40b40U | rd.Encode(22, 12) | rm.Encode(5, 0));
+ AdvanceIT();
+ return;
+ }
+ } else {
+ // VCMP{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
+ if (dt.Is(F64) && cond.IsNotNever()) {
+ EmitA32(0x0eb40b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
+ rm.Encode(5, 0));
+ return;
+ }
}
}
- Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, imm);
-}
-
-void Assembler::vcmp(Condition cond, DataType dt, DRegister rd, double imm) {
- VIXL_ASSERT(AllowAssembler());
- CheckIT(cond);
- if (IsUsingT32()) {
- // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
- if (dt.Is(F64) && (imm == 0.0)) {
- EmitT32_32(0xeeb50b40U | rd.Encode(22, 12));
- AdvanceIT();
- return;
- }
- } else {
- // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
- if (dt.Is(F64) && (imm == 0.0) && cond.IsNotNever()) {
- EmitA32(0x0eb50b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
- return;
+ if (operand.IsImmediate()) {
+ if (IsUsingT32()) {
+ // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
+ if (dt.Is(F64) && (operand.IsFloatZero())) {
+ EmitT32_32(0xeeb50b40U | rd.Encode(22, 12));
+ AdvanceIT();
+ return;
+ }
+ } else {
+ // VCMP{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
+ if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
+ EmitA32(0x0eb50b40U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
+ return;
+ }
}
}
- Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, imm);
+ Delegate(kVcmp, &Assembler::vcmp, cond, dt, rd, operand);
}
-void Assembler::vcmpe(Condition cond, DataType dt, SRegister rd, SRegister rm) {
+void Assembler::vcmpe(Condition cond,
+ DataType dt,
+ SRegister rd,
+ const SOperand& operand) {
VIXL_ASSERT(AllowAssembler());
CheckIT(cond);
- if (IsUsingT32()) {
- // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
- if (dt.Is(F32)) {
- EmitT32_32(0xeeb40ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
- AdvanceIT();
- return;
- }
- } else {
- // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
- if (dt.Is(F32) && cond.IsNotNever()) {
- EmitA32(0x0eb40ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
- rm.Encode(5, 0));
- return;
+ if (operand.IsRegister()) {
+ SRegister rm = operand.GetRegister();
+ if (IsUsingT32()) {
+ // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; T1
+ if (dt.Is(F32)) {
+ EmitT32_32(0xeeb40ac0U | rd.Encode(22, 12) | rm.Encode(5, 0));
+ AdvanceIT();
+ return;
+ }
+ } else {
+ // VCMPE{<c>}{<q>}.F32 <Sd>, <Sm> ; A1
+ if (dt.Is(F32) && cond.IsNotNever()) {
+ EmitA32(0x0eb40ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
+ rm.Encode(5, 0));
+ return;
+ }
}
}
- Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, rm);
-}
-
-void Assembler::vcmpe(Condition cond, DataType dt, DRegister rd, DRegister rm) {
- VIXL_ASSERT(AllowAssembler());
- CheckIT(cond);
- if (IsUsingT32()) {
- // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
- if (dt.Is(F64)) {
- EmitT32_32(0xeeb40bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
- AdvanceIT();
- return;
- }
- } else {
- // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
- if (dt.Is(F64) && cond.IsNotNever()) {
- EmitA32(0x0eb40bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
- rm.Encode(5, 0));
- return;
+ if (operand.IsImmediate()) {
+ if (IsUsingT32()) {
+ // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
+ if (dt.Is(F32) && (operand.IsFloatZero())) {
+ EmitT32_32(0xeeb50ac0U | rd.Encode(22, 12));
+ AdvanceIT();
+ return;
+ }
+ } else {
+ // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
+ if (dt.Is(F32) && (operand.IsFloatZero()) && cond.IsNotNever()) {
+ EmitA32(0x0eb50ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
+ return;
+ }
}
}
- Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, rm);
+ Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
}
-void Assembler::vcmpe(Condition cond, DataType dt, SRegister rd, double imm) {
+void Assembler::vcmpe(Condition cond,
+ DataType dt,
+ DRegister rd,
+ const DOperand& operand) {
VIXL_ASSERT(AllowAssembler());
CheckIT(cond);
- if (IsUsingT32()) {
- // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; T2
- if (dt.Is(F32) && (imm == 0.0)) {
- EmitT32_32(0xeeb50ac0U | rd.Encode(22, 12));
- AdvanceIT();
- return;
- }
- } else {
- // VCMPE{<c>}{<q>}.F32 <Sd>, #0.0 ; A2
- if (dt.Is(F32) && (imm == 0.0) && cond.IsNotNever()) {
- EmitA32(0x0eb50ac0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
- return;
+ if (operand.IsRegister()) {
+ DRegister rm = operand.GetRegister();
+ if (IsUsingT32()) {
+ // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; T1
+ if (dt.Is(F64)) {
+ EmitT32_32(0xeeb40bc0U | rd.Encode(22, 12) | rm.Encode(5, 0));
+ AdvanceIT();
+ return;
+ }
+ } else {
+ // VCMPE{<c>}{<q>}.F64 <Dd>, <Dm> ; A1
+ if (dt.Is(F64) && cond.IsNotNever()) {
+ EmitA32(0x0eb40bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
+ rm.Encode(5, 0));
+ return;
+ }
}
}
- Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, imm);
-}
-
-void Assembler::vcmpe(Condition cond, DataType dt, DRegister rd, double imm) {
- VIXL_ASSERT(AllowAssembler());
- CheckIT(cond);
- if (IsUsingT32()) {
- // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
- if (dt.Is(F64) && (imm == 0.0)) {
- EmitT32_32(0xeeb50bc0U | rd.Encode(22, 12));
- AdvanceIT();
- return;
- }
- } else {
- // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
- if (dt.Is(F64) && (imm == 0.0) && cond.IsNotNever()) {
- EmitA32(0x0eb50bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
- return;
+ if (operand.IsImmediate()) {
+ if (IsUsingT32()) {
+ // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; T2
+ if (dt.Is(F64) && (operand.IsFloatZero())) {
+ EmitT32_32(0xeeb50bc0U | rd.Encode(22, 12));
+ AdvanceIT();
+ return;
+ }
+ } else {
+ // VCMPE{<c>}{<q>}.F64 <Dd>, #0.0 ; A2
+ if (dt.Is(F64) && (operand.IsFloatZero()) && cond.IsNotNever()) {
+ EmitA32(0x0eb50bc0U | (cond.GetCondition() << 28) | rd.Encode(22, 12));
+ return;
+ }
}
}
- Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, imm);
+ Delegate(kVcmpe, &Assembler::vcmpe, cond, dt, rd, operand);
}
void Assembler::vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
@@ -20298,7 +20306,6 @@ void Assembler::vmov(Condition cond,
CheckIT(cond);
if (operand.IsImmediate()) {
ImmediateVmov encoded_dt(dt, operand.GetNeonImmediate());
- ImmediateVFP vfp(operand.GetNeonImmediate());
if (IsUsingT32()) {
// VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; T1
if (encoded_dt.IsValid()) {
@@ -20313,14 +20320,6 @@ void Assembler::vmov(Condition cond,
return;
}
}
- // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; T2
- if (dt.Is(F64) && vfp.IsValid()) {
- EmitT32_32(0xeeb00b00U | rd.Encode(22, 12) |
- (vfp.GetEncodingValue() & 0xf) |
- ((vfp.GetEncodingValue() & 0xf0) << 12));
- AdvanceIT();
- return;
- }
} else {
// VMOV{<c>}{<q>}.<dt> <Dd>, #<imm> ; A1
if (encoded_dt.IsValid()) {
@@ -20333,6 +20332,20 @@ void Assembler::vmov(Condition cond,
return;
}
}
+ }
+ }
+ if (operand.IsImmediate()) {
+ ImmediateVFP vfp(operand.GetNeonImmediate());
+ if (IsUsingT32()) {
+ // VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; T2
+ if (dt.Is(F64) && vfp.IsValid()) {
+ EmitT32_32(0xeeb00b00U | rd.Encode(22, 12) |
+ (vfp.GetEncodingValue() & 0xf) |
+ ((vfp.GetEncodingValue() & 0xf0) << 12));
+ AdvanceIT();
+ return;
+ }
+ } else {
// VMOV{<c>}{<q>}.F64 <Dd>, #<imm> ; A2
if (dt.Is(F64) && vfp.IsValid() && cond.IsNotNever()) {
EmitA32(0x0eb00b00U | (cond.GetCondition() << 28) | rd.Encode(22, 12) |
diff --git a/src/aarch32/assembler-aarch32.h b/src/aarch32/assembler-aarch32.h
index 521c806f..8ac0bca7 100644
--- a/src/aarch32/assembler-aarch32.h
+++ b/src/aarch32/assembler-aarch32.h
@@ -381,14 +381,14 @@ class Assembler : public internal::AssemblerBase {
QRegister rd,
QRegister rn,
const QOperand& operand);
- typedef void (Assembler::*InstructionCondDtSFi)(Condition cond,
- DataType dt,
- SRegister rd,
- double imm);
- typedef void (Assembler::*InstructionCondDtDFi)(Condition cond,
- DataType dt,
- DRegister rd,
- double imm);
+ typedef void (Assembler::*InstructionCondDtSSop)(Condition cond,
+ DataType dt,
+ SRegister rd,
+ const SOperand& operand);
+ typedef void (Assembler::*InstructionCondDtDDop)(Condition cond,
+ DataType dt,
+ DRegister rd,
+ const DOperand& operand);
typedef void (Assembler::*InstructionCondDtDtDS)(
Condition cond, DataType dt1, DataType dt2, DRegister rd, SRegister rm);
typedef void (Assembler::*InstructionCondDtDtSD)(
@@ -546,18 +546,10 @@ class Assembler : public internal::AssemblerBase {
DataType dt,
DRegisterLane rd,
Register rt);
- typedef void (Assembler::*InstructionCondDtDDop)(Condition cond,
- DataType dt,
- DRegister rd,
- const DOperand& operand);
typedef void (Assembler::*InstructionCondDtQQop)(Condition cond,
DataType dt,
QRegister rd,
const QOperand& operand);
- typedef void (Assembler::*InstructionCondDtSSop)(Condition cond,
- DataType dt,
- SRegister rd,
- const SOperand& operand);
typedef void (Assembler::*InstructionCondDtRDx)(Condition cond,
DataType dt,
Register rt,
@@ -1120,12 +1112,12 @@ class Assembler : public internal::AssemblerBase {
DRegister /*rm*/) {
USE(type);
VIXL_ASSERT((type == kVabs) || (type == kVcls) || (type == kVclz) ||
- (type == kVcmp) || (type == kVcmpe) || (type == kVcnt) ||
- (type == kVneg) || (type == kVpadal) || (type == kVpaddl) ||
- (type == kVqabs) || (type == kVqneg) || (type == kVrecpe) ||
- (type == kVrev16) || (type == kVrev32) || (type == kVrev64) ||
- (type == kVrsqrte) || (type == kVsqrt) || (type == kVswp) ||
- (type == kVtrn) || (type == kVuzp) || (type == kVzip));
+ (type == kVcnt) || (type == kVneg) || (type == kVpadal) ||
+ (type == kVpaddl) || (type == kVqabs) || (type == kVqneg) ||
+ (type == kVrecpe) || (type == kVrev16) || (type == kVrev32) ||
+ (type == kVrev64) || (type == kVrsqrte) || (type == kVsqrt) ||
+ (type == kVswp) || (type == kVtrn) || (type == kVuzp) ||
+ (type == kVzip));
UnimplementedDelegate(type);
}
virtual void Delegate(InstructionType type,
@@ -1150,8 +1142,7 @@ class Assembler : public internal::AssemblerBase {
SRegister /*rd*/,
SRegister /*rm*/) {
USE(type);
- VIXL_ASSERT((type == kVabs) || (type == kVcmp) || (type == kVcmpe) ||
- (type == kVneg) || (type == kVsqrt));
+ VIXL_ASSERT((type == kVabs) || (type == kVneg) || (type == kVsqrt));
UnimplementedDelegate(type);
}
virtual void Delegate(InstructionType type,
@@ -1225,23 +1216,24 @@ class Assembler : public internal::AssemblerBase {
UnimplementedDelegate(type);
}
virtual void Delegate(InstructionType type,
- InstructionCondDtSFi /*instruction*/,
+ InstructionCondDtSSop /*instruction*/,
Condition /*cond*/,
DataType /*dt*/,
SRegister /*rd*/,
- double /*imm*/) {
+ const SOperand& /*operand*/) {
USE(type);
- VIXL_ASSERT((type == kVcmp) || (type == kVcmpe));
+ VIXL_ASSERT((type == kVcmp) || (type == kVcmpe) || (type == kVmov));
UnimplementedDelegate(type);
}
virtual void Delegate(InstructionType type,
- InstructionCondDtDFi /*instruction*/,
+ InstructionCondDtDDop /*instruction*/,
Condition /*cond*/,
DataType /*dt*/,
DRegister /*rd*/,
- double /*imm*/) {
+ const DOperand& /*operand*/) {
USE(type);
- VIXL_ASSERT((type == kVcmp) || (type == kVcmpe));
+ VIXL_ASSERT((type == kVcmp) || (type == kVcmpe) || (type == kVmov) ||
+ (type == kVmvn));
UnimplementedDelegate(type);
}
virtual void Delegate(InstructionType type,
@@ -1687,16 +1679,6 @@ class Assembler : public internal::AssemblerBase {
UnimplementedDelegate(type);
}
virtual void Delegate(InstructionType type,
- InstructionCondDtDDop /*instruction*/,
- Condition /*cond*/,
- DataType /*dt*/,
- DRegister /*rd*/,
- const DOperand& /*operand*/) {
- USE(type);
- VIXL_ASSERT((type == kVmov) || (type == kVmvn));
- UnimplementedDelegate(type);
- }
- virtual void Delegate(InstructionType type,
InstructionCondDtQQop /*instruction*/,
Condition /*cond*/,
DataType /*dt*/,
@@ -1707,16 +1689,6 @@ class Assembler : public internal::AssemblerBase {
UnimplementedDelegate(type);
}
virtual void Delegate(InstructionType type,
- InstructionCondDtSSop /*instruction*/,
- Condition /*cond*/,
- DataType /*dt*/,
- SRegister /*rd*/,
- const SOperand& /*operand*/) {
- USE(type);
- VIXL_ASSERT((type == kVmov));
- UnimplementedDelegate(type);
- }
- virtual void Delegate(InstructionType type,
InstructionCondDtRDx /*instruction*/,
Condition /*cond*/,
DataType /*dt*/,
@@ -4111,29 +4083,31 @@ class Assembler : public internal::AssemblerBase {
void vclz(Condition cond, DataType dt, QRegister rd, QRegister rm);
void vclz(DataType dt, QRegister rd, QRegister rm) { vclz(al, dt, rd, rm); }
- void vcmp(Condition cond, DataType dt, SRegister rd, SRegister rm);
- void vcmp(DataType dt, SRegister rd, SRegister rm) { vcmp(al, dt, rd, rm); }
-
- void vcmp(Condition cond, DataType dt, DRegister rd, DRegister rm);
- void vcmp(DataType dt, DRegister rd, DRegister rm) { vcmp(al, dt, rd, rm); }
-
- void vcmp(Condition cond, DataType dt, SRegister rd, double imm);
- void vcmp(DataType dt, SRegister rd, double imm) { vcmp(al, dt, rd, imm); }
-
- void vcmp(Condition cond, DataType dt, DRegister rd, double imm);
- void vcmp(DataType dt, DRegister rd, double imm) { vcmp(al, dt, rd, imm); }
-
- void vcmpe(Condition cond, DataType dt, SRegister rd, SRegister rm);
- void vcmpe(DataType dt, SRegister rd, SRegister rm) { vcmpe(al, dt, rd, rm); }
+ void vcmp(Condition cond, DataType dt, SRegister rd, const SOperand& operand);
+ void vcmp(DataType dt, SRegister rd, const SOperand& operand) {
+ vcmp(al, dt, rd, operand);
+ }
- void vcmpe(Condition cond, DataType dt, DRegister rd, DRegister rm);
- void vcmpe(DataType dt, DRegister rd, DRegister rm) { vcmpe(al, dt, rd, rm); }
+ void vcmp(Condition cond, DataType dt, DRegister rd, const DOperand& operand);
+ void vcmp(DataType dt, DRegister rd, const DOperand& operand) {
+ vcmp(al, dt, rd, operand);
+ }
- void vcmpe(Condition cond, DataType dt, SRegister rd, double imm);
- void vcmpe(DataType dt, SRegister rd, double imm) { vcmpe(al, dt, rd, imm); }
+ void vcmpe(Condition cond,
+ DataType dt,
+ SRegister rd,
+ const SOperand& operand);
+ void vcmpe(DataType dt, SRegister rd, const SOperand& operand) {
+ vcmpe(al, dt, rd, operand);
+ }
- void vcmpe(Condition cond, DataType dt, DRegister rd, double imm);
- void vcmpe(DataType dt, DRegister rd, double imm) { vcmpe(al, dt, rd, imm); }
+ void vcmpe(Condition cond,
+ DataType dt,
+ DRegister rd,
+ const DOperand& operand);
+ void vcmpe(DataType dt, DRegister rd, const DOperand& operand) {
+ vcmpe(al, dt, rd, operand);
+ }
void vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm);
void vcnt(DataType dt, DRegister rd, DRegister rm) { vcnt(al, dt, rd, rm); }
diff --git a/src/aarch32/disasm-aarch32.cc b/src/aarch32/disasm-aarch32.cc
index 6249fa72..c06597fa 100644
--- a/src/aarch32/disasm-aarch32.cc
+++ b/src/aarch32/disasm-aarch32.cc
@@ -4346,75 +4346,37 @@ void Disassembler::vclz(Condition cond,
void Disassembler::vcmp(Condition cond,
DataType dt,
SRegister rd,
- SRegister rm) {
+ const SOperand& operand) {
os().SetCurrentInstruction(kVcmp, kFpNeon);
os() << ToCString(kVcmp) << ConditionPrinter(it_block_, cond) << dt << " "
- << rd << ", " << rm;
+ << rd << ", " << operand;
}
void Disassembler::vcmp(Condition cond,
DataType dt,
DRegister rd,
- DRegister rm) {
- os().SetCurrentInstruction(kVcmp, kFpNeon);
- os() << ToCString(kVcmp) << ConditionPrinter(it_block_, cond) << dt << " "
- << rd << ", " << rm;
-}
-
-void Disassembler::vcmp(Condition cond, DataType dt, SRegister rd, double imm) {
- os().SetCurrentInstruction(kVcmp, kFpNeon);
- os() << ToCString(kVcmp) << ConditionPrinter(it_block_, cond) << dt << " "
- << rd << ", "
- << "#" << std::fixed << std::setprecision(1) << imm
- << std::resetiosflags(std::ios_base::floatfield);
-}
-
-void Disassembler::vcmp(Condition cond, DataType dt, DRegister rd, double imm) {
+ const DOperand& operand) {
os().SetCurrentInstruction(kVcmp, kFpNeon);
os() << ToCString(kVcmp) << ConditionPrinter(it_block_, cond) << dt << " "
- << rd << ", "
- << "#" << std::fixed << std::setprecision(1) << imm
- << std::resetiosflags(std::ios_base::floatfield);
-}
-
-void Disassembler::vcmpe(Condition cond,
- DataType dt,
- SRegister rd,
- SRegister rm) {
- os().SetCurrentInstruction(kVcmpe, kFpNeon);
- os() << ToCString(kVcmpe) << ConditionPrinter(it_block_, cond) << dt << " "
- << rd << ", " << rm;
-}
-
-void Disassembler::vcmpe(Condition cond,
- DataType dt,
- DRegister rd,
- DRegister rm) {
- os().SetCurrentInstruction(kVcmpe, kFpNeon);
- os() << ToCString(kVcmpe) << ConditionPrinter(it_block_, cond) << dt << " "
- << rd << ", " << rm;
+ << rd << ", " << operand;
}
void Disassembler::vcmpe(Condition cond,
DataType dt,
SRegister rd,
- double imm) {
+ const SOperand& operand) {
os().SetCurrentInstruction(kVcmpe, kFpNeon);
os() << ToCString(kVcmpe) << ConditionPrinter(it_block_, cond) << dt << " "
- << rd << ", "
- << "#" << std::fixed << std::setprecision(1) << imm
- << std::resetiosflags(std::ios_base::floatfield);
+ << rd << ", " << operand;
}
void Disassembler::vcmpe(Condition cond,
DataType dt,
DRegister rd,
- double imm) {
+ const DOperand& operand) {
os().SetCurrentInstruction(kVcmpe, kFpNeon);
os() << ToCString(kVcmpe) << ConditionPrinter(it_block_, cond) << dt << " "
- << rd << ", "
- << "#" << std::fixed << std::setprecision(1) << imm
- << std::resetiosflags(std::ios_base::floatfield);
+ << rd << ", " << operand;
}
void Disassembler::vcnt(Condition cond,
diff --git a/src/aarch32/disasm-aarch32.h b/src/aarch32/disasm-aarch32.h
index b5948045..5e0ba2bb 100644
--- a/src/aarch32/disasm-aarch32.h
+++ b/src/aarch32/disasm-aarch32.h
@@ -1537,21 +1537,19 @@ class Disassembler {
void vclz(Condition cond, DataType dt, QRegister rd, QRegister rm);
- void vcmp(Condition cond, DataType dt, SRegister rd, SRegister rm);
+ void vcmp(Condition cond, DataType dt, SRegister rd, const SOperand& operand);
- void vcmp(Condition cond, DataType dt, DRegister rd, DRegister rm);
+ void vcmp(Condition cond, DataType dt, DRegister rd, const DOperand& operand);
- void vcmp(Condition cond, DataType dt, SRegister rd, double imm);
-
- void vcmp(Condition cond, DataType dt, DRegister rd, double imm);
-
- void vcmpe(Condition cond, DataType dt, SRegister rd, SRegister rm);
-
- void vcmpe(Condition cond, DataType dt, DRegister rd, DRegister rm);
-
- void vcmpe(Condition cond, DataType dt, SRegister rd, double imm);
+ void vcmpe(Condition cond,
+ DataType dt,
+ SRegister rd,
+ const SOperand& operand);
- void vcmpe(Condition cond, DataType dt, DRegister rd, double imm);
+ void vcmpe(Condition cond,
+ DataType dt,
+ DRegister rd,
+ const DOperand& operand);
void vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm);
diff --git a/src/aarch32/macro-assembler-aarch32.h b/src/aarch32/macro-assembler-aarch32.h
index cf444a77..d018bafb 100644
--- a/src/aarch32/macro-assembler-aarch32.h
+++ b/src/aarch32/macro-assembler-aarch32.h
@@ -6256,89 +6256,69 @@ class MacroAssembler : public Assembler, public MacroAssemblerInterface {
}
void Vclz(DataType dt, QRegister rd, QRegister rm) { Vclz(al, dt, rd, rm); }
- void Vcmp(Condition cond, DataType dt, SRegister rd, SRegister rm) {
+ void Vcmp(Condition cond,
+ DataType dt,
+ SRegister rd,
+ const SOperand& operand) {
VIXL_ASSERT(!AliasesAvailableScratchRegister(rd));
- VIXL_ASSERT(!AliasesAvailableScratchRegister(rm));
+ VIXL_ASSERT(!AliasesAvailableScratchRegister(operand));
VIXL_ASSERT(allow_macro_instructions_);
VIXL_ASSERT(OutsideITBlock());
MacroEmissionCheckScope guard(this);
ITScope it_scope(this, &cond);
- vcmp(cond, dt, rd, rm);
+ vcmp(cond, dt, rd, operand);
}
- void Vcmp(DataType dt, SRegister rd, SRegister rm) { Vcmp(al, dt, rd, rm); }
-
- void Vcmp(Condition cond, DataType dt, DRegister rd, DRegister rm) {
- VIXL_ASSERT(!AliasesAvailableScratchRegister(rd));
- VIXL_ASSERT(!AliasesAvailableScratchRegister(rm));
- VIXL_ASSERT(allow_macro_instructions_);
- VIXL_ASSERT(OutsideITBlock());
- MacroEmissionCheckScope guard(this);
- ITScope it_scope(this, &cond);
- vcmp(cond, dt, rd, rm);
+ void Vcmp(DataType dt, SRegister rd, const SOperand& operand) {
+ Vcmp(al, dt, rd, operand);
}
- void Vcmp(DataType dt, DRegister rd, DRegister rm) { Vcmp(al, dt, rd, rm); }
- void Vcmp(Condition cond, DataType dt, SRegister rd, double imm) {
+ void Vcmp(Condition cond,
+ DataType dt,
+ DRegister rd,
+ const DOperand& operand) {
VIXL_ASSERT(!AliasesAvailableScratchRegister(rd));
+ VIXL_ASSERT(!AliasesAvailableScratchRegister(operand));
VIXL_ASSERT(allow_macro_instructions_);
VIXL_ASSERT(OutsideITBlock());
MacroEmissionCheckScope guard(this);
ITScope it_scope(this, &cond);
- vcmp(cond, dt, rd, imm);
+ vcmp(cond, dt, rd, operand);
}
- void Vcmp(DataType dt, SRegister rd, double imm) { Vcmp(al, dt, rd, imm); }
-
- void Vcmp(Condition cond, DataType dt, DRegister rd, double imm) {
- VIXL_ASSERT(!AliasesAvailableScratchRegister(rd));
- VIXL_ASSERT(allow_macro_instructions_);
- VIXL_ASSERT(OutsideITBlock());
- MacroEmissionCheckScope guard(this);
- ITScope it_scope(this, &cond);
- vcmp(cond, dt, rd, imm);
+ void Vcmp(DataType dt, DRegister rd, const DOperand& operand) {
+ Vcmp(al, dt, rd, operand);
}
- void Vcmp(DataType dt, DRegister rd, double imm) { Vcmp(al, dt, rd, imm); }
- void Vcmpe(Condition cond, DataType dt, SRegister rd, SRegister rm) {
+ void Vcmpe(Condition cond,
+ DataType dt,
+ SRegister rd,
+ const SOperand& operand) {
VIXL_ASSERT(!AliasesAvailableScratchRegister(rd));
- VIXL_ASSERT(!AliasesAvailableScratchRegister(rm));
+ VIXL_ASSERT(!AliasesAvailableScratchRegister(operand));
VIXL_ASSERT(allow_macro_instructions_);
VIXL_ASSERT(OutsideITBlock());
MacroEmissionCheckScope guard(this);
ITScope it_scope(this, &cond);
- vcmpe(cond, dt, rd, rm);
+ vcmpe(cond, dt, rd, operand);
}
- void Vcmpe(DataType dt, SRegister rd, SRegister rm) { Vcmpe(al, dt, rd, rm); }
-
- void Vcmpe(Condition cond, DataType dt, DRegister rd, DRegister rm) {
- VIXL_ASSERT(!AliasesAvailableScratchRegister(rd));
- VIXL_ASSERT(!AliasesAvailableScratchRegister(rm));
- VIXL_ASSERT(allow_macro_instructions_);
- VIXL_ASSERT(OutsideITBlock());
- MacroEmissionCheckScope guard(this);
- ITScope it_scope(this, &cond);
- vcmpe(cond, dt, rd, rm);
+ void Vcmpe(DataType dt, SRegister rd, const SOperand& operand) {
+ Vcmpe(al, dt, rd, operand);
}
- void Vcmpe(DataType dt, DRegister rd, DRegister rm) { Vcmpe(al, dt, rd, rm); }
- void Vcmpe(Condition cond, DataType dt, SRegister rd, double imm) {
+ void Vcmpe(Condition cond,
+ DataType dt,
+ DRegister rd,
+ const DOperand& operand) {
VIXL_ASSERT(!AliasesAvailableScratchRegister(rd));
+ VIXL_ASSERT(!AliasesAvailableScratchRegister(operand));
VIXL_ASSERT(allow_macro_instructions_);
VIXL_ASSERT(OutsideITBlock());
MacroEmissionCheckScope guard(this);
ITScope it_scope(this, &cond);
- vcmpe(cond, dt, rd, imm);
+ vcmpe(cond, dt, rd, operand);
}
- void Vcmpe(DataType dt, SRegister rd, double imm) { Vcmpe(al, dt, rd, imm); }
-
- void Vcmpe(Condition cond, DataType dt, DRegister rd, double imm) {
- VIXL_ASSERT(!AliasesAvailableScratchRegister(rd));
- VIXL_ASSERT(allow_macro_instructions_);
- VIXL_ASSERT(OutsideITBlock());
- MacroEmissionCheckScope guard(this);
- ITScope it_scope(this, &cond);
- vcmpe(cond, dt, rd, imm);
+ void Vcmpe(DataType dt, DRegister rd, const DOperand& operand) {
+ Vcmpe(al, dt, rd, operand);
}
- void Vcmpe(DataType dt, DRegister rd, double imm) { Vcmpe(al, dt, rd, imm); }
void Vcnt(Condition cond, DataType dt, DRegister rd, DRegister rm) {
VIXL_ASSERT(!AliasesAvailableScratchRegister(rd));
diff --git a/src/aarch32/operands-aarch32.h b/src/aarch32/operands-aarch32.h
index 27497968..1d18bfd3 100644
--- a/src/aarch32/operands-aarch32.h
+++ b/src/aarch32/operands-aarch32.h
@@ -314,6 +314,11 @@ class NeonImmediate {
bool IsInteger() const { return IsInteger32() | IsInteger64(); }
bool IsFloat() const { return immediate_type_.Is(F32); }
bool IsDouble() const { return immediate_type_.Is(F64); }
+ bool IsFloatZero() const {
+ if (immediate_type_.Is(F32)) return imm_.f_ == 0.0f;
+ if (immediate_type_.Is(F64)) return imm_.d_ == 0.0;
+ return false;
+ }
template <typename T>
bool CanConvert() const {
@@ -397,6 +402,10 @@ class NeonOperand {
bool IsImmediate() const { return !rm_.IsValid(); }
bool IsRegister() const { return rm_.IsValid(); }
+ bool IsFloatZero() const {
+ VIXL_ASSERT(IsImmediate());
+ return imm_.IsFloatZero();
+ }
const NeonImmediate& GetNeonImmediate() const { return imm_; }
@@ -427,6 +436,9 @@ class SOperand : public NeonOperand {
// where <immediate> is 32bit float
SOperand(float immediate) // NOLINT(runtime/explicit)
: NeonOperand(immediate) {}
+ // where <immediate> is 64bit float
+ SOperand(double immediate) // NOLINT(runtime/explicit)
+ : NeonOperand(immediate) {}
SOperand(const NeonImmediate& imm) // NOLINT(runtime/explicit)
: NeonOperand(imm) {}
@@ -541,7 +553,7 @@ class ImmediateVFP : public EncodingValue {
} else if (neon_imm.IsDouble()) {
const double imm = neon_imm.GetImmediate<double>();
if (VFP::IsImmFP64(imm)) {
- SetEncodingValue(VFP::FP32ToImm8(imm));
+ SetEncodingValue(VFP::FP64ToImm8(imm));
}
}
}
diff --git a/test/aarch32/test-assembler-aarch32.cc b/test/aarch32/test-assembler-aarch32.cc
index 7ebd9022..23881f77 100644
--- a/test/aarch32/test-assembler-aarch32.cc
+++ b/test/aarch32/test-assembler-aarch32.cc
@@ -2835,6 +2835,126 @@ TEST(msr_i) {
}
+TEST(vcmp_s) {
+ SETUP();
+
+ START();
+
+ __ Vmov(s0, 1.0);
+ __ Vmov(s1, 2.0);
+ __ Vmov(s2, 0.0);
+
+ __ Vcmp(F32, s1, s0);
+ __ Vmrs(RegisterOrAPSR_nzcv(r0.GetCode()), FPSCR);
+
+ __ Vcmp(F32, s0, 0.0f);
+ __ Vmrs(RegisterOrAPSR_nzcv(r1.GetCode()), FPSCR);
+
+ __ Vcmp(F32, s2, 0.0f);
+ __ Vmrs(RegisterOrAPSR_nzcv(r2.GetCode()), FPSCR);
+
+ END();
+
+ RUN();
+
+ ASSERT_EQUAL_32(0x20000000, r0);
+ ASSERT_EQUAL_32(0x80000000, r1);
+ ASSERT_EQUAL_32(0x60000000, r2);
+
+ TEARDOWN();
+}
+
+
+TEST(vcmp_d) {
+ SETUP();
+
+ START();
+
+ __ Vmov(d0, 1.0);
+ __ Vmov(d1, 2.0);
+ __ Vmov(d2, 0.0);
+
+ __ Vcmp(F64, d1, d0);
+ __ Vmrs(RegisterOrAPSR_nzcv(r0.GetCode()), FPSCR);
+
+ __ Vcmp(F64, d0, 0.0);
+ __ Vmrs(RegisterOrAPSR_nzcv(r1.GetCode()), FPSCR);
+
+ __ Vcmp(F64, d2, 0.0);
+ __ Vmrs(RegisterOrAPSR_nzcv(r2.GetCode()), FPSCR);
+
+ END();
+
+ RUN();
+
+ ASSERT_EQUAL_32(0x20000000, r0);
+ ASSERT_EQUAL_32(0x80000000, r1);
+ ASSERT_EQUAL_32(0x60000000, r2);
+
+ TEARDOWN();
+}
+
+
+TEST(vcmpe_s) {
+ SETUP();
+
+ START();
+
+ __ Vmov(s0, 1.0);
+ __ Vmov(s1, 2.0);
+ __ Vmov(s2, 0.0);
+
+ __ Vcmpe(F32, s1, s0);
+ __ Vmrs(RegisterOrAPSR_nzcv(r0.GetCode()), FPSCR);
+
+ __ Vcmpe(F32, s0, 0.0f);
+ __ Vmrs(RegisterOrAPSR_nzcv(r1.GetCode()), FPSCR);
+
+ __ Vcmpe(F32, s2, 0.0f);
+ __ Vmrs(RegisterOrAPSR_nzcv(r2.GetCode()), FPSCR);
+
+ END();
+
+ RUN();
+
+ ASSERT_EQUAL_32(0x20000000, r0);
+ ASSERT_EQUAL_32(0x80000000, r1);
+ ASSERT_EQUAL_32(0x60000000, r2);
+
+ TEARDOWN();
+}
+
+
+TEST(vcmpe_d) {
+ SETUP();
+
+ START();
+
+ __ Vmov(d0, 1.0);
+ __ Vmov(d1, 2.0);
+ __ Vmov(d2, 0.0);
+
+ __ Vcmpe(F64, d1, d0);
+ __ Vmrs(RegisterOrAPSR_nzcv(r0.GetCode()), FPSCR);
+
+ __ Vcmpe(F64, d0, 0.0);
+ __ Vmrs(RegisterOrAPSR_nzcv(r1.GetCode()), FPSCR);
+
+ __ Vcmpe(F64, d2, 0.0);
+ __ Vmrs(RegisterOrAPSR_nzcv(r2.GetCode()), FPSCR);
+
+ END();
+
+ RUN();
+
+ ASSERT_EQUAL_32(0x20000000, r0);
+ ASSERT_EQUAL_32(0x80000000, r1);
+ ASSERT_EQUAL_32(0x60000000, r2);
+
+ TEARDOWN();
+}
+
+
TEST(vmrs_vmsr) {
SETUP();
diff --git a/test/aarch32/test-disasm-a32.cc b/test/aarch32/test-disasm-a32.cc
index b5b41ce5..dae911dc 100644
--- a/test/aarch32/test-disasm-a32.cc
+++ b/test/aarch32/test-disasm-a32.cc
@@ -3477,6 +3477,23 @@ TEST(preloads) {
}
+TEST(vcmp_vcmpe) {
+ SETUP();
+
+ COMPARE_BOTH(Vcmp(F32, s0, s1), "vcmp.f32 s0, s1\n");
+ COMPARE_BOTH(Vcmp(F64, d0, d1), "vcmp.f64 d0, d1\n");
+ COMPARE_BOTH(Vcmp(F32, s0, 0.0f), "vcmp.f32 s0, #0.0\n");
+ COMPARE_BOTH(Vcmp(F64, d0, 0.0), "vcmp.f64 d0, #0.0\n");
+
+ COMPARE_BOTH(Vcmpe(F32, s0, s1), "vcmpe.f32 s0, s1\n");
+ COMPARE_BOTH(Vcmpe(F64, d0, d1), "vcmpe.f64 d0, d1\n");
+ COMPARE_BOTH(Vcmpe(F32, s0, 0.0f), "vcmpe.f32 s0, #0.0\n");
+ COMPARE_BOTH(Vcmpe(F64, d0, 0.0), "vcmpe.f64 d0, #0.0\n");
+
+ CLEANUP();
+}
+
+
TEST(vmrs_vmsr) {
SETUP();