Commit b9f27229 by Karl Schimpf

Fixes LDR and STR instructions. Two types of mistakes were being made.

First, the width was not being correctly defined for non-vector instructions. Second, the order of the width/condition was incorrect when the instruction was prefixed with a V. That is, for V prefixed instructions, the order is predicate/width while for non-V prefixed instructions the order is width/predicate. Also fixes bug in target lowering that did not always convert results of a compare to i1. BUG= https://bugs.chromium.org/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1415953007 .
parent c59288b3
...@@ -705,6 +705,7 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, ...@@ -705,6 +705,7 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
// ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 // ldr<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
// ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 // ldr<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
// ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1 // ldr<c> <Rt>, [<Rn>, #+/-<imm12>]! ; p=0, w=1
//
// LDRB (immediate) - ARM section A8.8.68, encoding A1: // LDRB (immediate) - ARM section A8.8.68, encoding A1:
// ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0 // ldrb<c> <Rt>, [<Rn>{, #+/-<imm12>}] ; p=1, w=0
// ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1 // ldrb<c> <Rt>, [<Rn>], #+/-<imm12> ; p=1, w=1
...@@ -716,7 +717,7 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress, ...@@ -716,7 +717,7 @@ void AssemblerARM32::ldr(const Operand *OpRt, const Operand *OpAddress,
const Type Ty = OpRt->getType(); const Type Ty = OpRt->getType();
if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand?
return setNeedsTextFixup(); return setNeedsTextFixup();
const bool IsByte = typeWidthInBytes(Ty) == 1; const bool IsByte = isByteSizedType(Ty);
// Check conditions of rules violated. // Check conditions of rules violated.
if (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc) if (getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc)
return setNeedsTextFixup(); return setNeedsTextFixup();
...@@ -873,7 +874,7 @@ void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress, ...@@ -873,7 +874,7 @@ void AssemblerARM32::str(const Operand *OpRt, const Operand *OpAddress,
const Type Ty = OpRt->getType(); const Type Ty = OpRt->getType();
if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand? if (!(Ty == IceType_i32 || Ty == IceType_i8)) // TODO(kschimpf) Expand?
return setNeedsTextFixup(); return setNeedsTextFixup();
const bool IsByte = typeWidthInBytes(Ty) == 1; const bool IsByte = isByteSizedType(Ty);
// Check for rule violations. // Check for rule violations.
if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc)) if ((getGPRReg(kRnShift, Address) == RegARM32::Encoded_Reg_pc))
return setNeedsTextFixup(); return setNeedsTextFixup();
......
...@@ -700,15 +700,14 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -700,15 +700,14 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
Variable *Dest = getDest(); Variable *Dest = getDest();
if (Dest->hasReg()) { if (Dest->hasReg()) {
Type DestTy = Dest->getType(); Type Ty = Dest->getType();
Operand *Src0 = getSrc(0); Operand *Src0 = getSrc(0);
const bool DestIsVector = isVectorType(DestTy); const bool IsVector = isVectorType(Ty);
const bool DestIsScalarFP = isScalarFloatingType(Dest->getType()); const bool IsScalarFP = isScalarFloatingType(Ty);
const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0); const bool CoreVFPMove = isMoveBetweenCoreAndVFPRegisters(Dest, Src0);
const char *LoadOpcode = const char *LoadOpcode = IsVector ? "vld1" : (IsScalarFP ? "vldr" : "ldr");
DestIsVector ? "vld1" : (DestIsScalarFP ? "vldr" : "ldr"); const bool IsVMove = (IsVector || IsScalarFP || CoreVFPMove);
const char *RegMovOpcode = const char *RegMovOpcode = IsVMove ? "vmov" : "mov";
(DestIsVector || DestIsScalarFP || CoreVFPMove) ? "vmov" : "mov";
const char *ActualOpcode = isMemoryAccess(Src0) ? LoadOpcode : RegMovOpcode; const char *ActualOpcode = isMemoryAccess(Src0) ? LoadOpcode : RegMovOpcode;
// when vmov{c}'ing, we need to emit a width string. Otherwise, the // when vmov{c}'ing, we need to emit a width string. Otherwise, the
// assembler might be tempted to assume we want a vector vmov{c}, and that // assembler might be tempted to assume we want a vector vmov{c}, and that
...@@ -716,24 +715,36 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const { ...@@ -716,24 +715,36 @@ void InstARM32Mov::emitSingleDestSingleSource(const Cfg *Func) const {
const char *NoWidthString = ""; const char *NoWidthString = "";
const char *WidthString = const char *WidthString =
isMemoryAccess(Src0) isMemoryAccess(Src0)
? (DestIsVector ? ".64" : NoWidthString) ? (IsVector ? ".64" : getWidthString(Ty))
: (!CoreVFPMove ? getVecWidthString(DestTy) : NoWidthString); : (!CoreVFPMove ? getVecWidthString(Ty) : NoWidthString);
Str << "\t" << ActualOpcode;
Str << "\t" << ActualOpcode << getPredicate() << WidthString << "\t"; const bool IsVInst = IsVMove || IsVector || IsScalarFP;
if (IsVInst) {
Str << getPredicate() << WidthString;
} else {
Str << WidthString << getPredicate();
}
Str << "\t";
Dest->emit(Func); Dest->emit(Func);
Str << ", "; Str << ", ";
Src0->emit(Func); Src0->emit(Func);
} else { } else {
Variable *Src0 = llvm::cast<Variable>(getSrc(0)); Variable *Src0 = llvm::cast<Variable>(getSrc(0));
assert(Src0->hasReg()); assert(Src0->hasReg());
Type Ty = Src0->getType();
const bool IsVector = isVectorType(Ty);
const bool IsScalarFP = isScalarFloatingType(Ty);
const char *ActualOpcode = const char *ActualOpcode =
isVectorType(Src0->getType()) IsVector ? "vst1" : (IsScalarFP ? "vstr" : "str");
? "vst1" const char *WidthString = IsVector ? ".64" : getWidthString(Ty);
: (isScalarFloatingType(Src0->getType()) ? "vstr" : "str"); Str << "\t" << ActualOpcode;
const char *NoWidthString = ""; const bool IsVInst = IsVector || IsScalarFP;
const char *WidthString = if (IsVInst) {
isVectorType(Src0->getType()) ? ".64" : NoWidthString; Str << getPredicate() << WidthString;
Str << "\t" << ActualOpcode << getPredicate() << WidthString << "\t"; } else {
Str << WidthString << getPredicate();
}
Str << "\t";
Src0->emit(Func); Src0->emit(Func);
Str << ", "; Str << ", ";
Dest->emit(Func); Dest->emit(Func);
...@@ -955,15 +966,21 @@ template <> void InstARM32Ldr::emit(const Cfg *Func) const { ...@@ -955,15 +966,21 @@ template <> void InstARM32Ldr::emit(const Cfg *Func) const {
assert(getSrcSize() == 1); assert(getSrcSize() == 1);
assert(getDest()->hasReg()); assert(getDest()->hasReg());
Variable *Dest = getDest(); Variable *Dest = getDest();
Type DestTy = Dest->getType(); Type Ty = Dest->getType();
const bool DestIsVector = isVectorType(DestTy); const bool IsVector = isVectorType(Ty);
const bool DestIsScalarFloat = isScalarFloatingType(DestTy); const bool IsScalarFloat = isScalarFloatingType(Ty);
const char *ActualOpcode = const char *ActualOpcode =
DestIsVector ? "vld1" : (DestIsScalarFloat ? "vldr" : "ldr"); IsVector ? "vld1" : (IsScalarFloat ? "vldr" : "ldr");
const char *VectorMarker = DestIsVector ? ".64" : ""; const char *VectorMarker = IsVector ? ".64" : "";
const char *WidthString = DestIsVector ? "" : getWidthString(DestTy); const char *WidthString = IsVector ? "" : getWidthString(Ty);
Str << "\t" << ActualOpcode << WidthString << getPredicate() << VectorMarker Str << "\t" << ActualOpcode;
<< "\t"; const bool IsVInst = IsVector || IsScalarFloat;
if (IsVInst) {
Str << getPredicate() << WidthString;
} else {
Str << WidthString << getPredicate();
}
Str << VectorMarker << "\t";
getDest()->emit(Func); getDest()->emit(Func);
Str << ", "; Str << ", ";
getSrc(0)->emit(Func); getSrc(0)->emit(Func);
...@@ -1270,11 +1287,18 @@ void InstARM32Str::emit(const Cfg *Func) const { ...@@ -1270,11 +1287,18 @@ void InstARM32Str::emit(const Cfg *Func) const {
assert(getSrcSize() == 2); assert(getSrcSize() == 2);
Type Ty = getSrc(0)->getType(); Type Ty = getSrc(0)->getType();
const bool IsVectorStore = isVectorType(Ty); const bool IsVectorStore = isVectorType(Ty);
const bool IsScalarFloat = isScalarFloatingType(Ty);
const char *Opcode = const char *Opcode =
IsVectorStore ? "vst1" : (isScalarFloatingType(Ty) ? "vstr" : "str"); IsVectorStore ? "vst1" : (IsScalarFloat ? "vstr" : "str");
const char *VecEltWidthString = IsVectorStore ? ".64" : ""; const char *VecEltWidthString = IsVectorStore ? ".64" : "";
Str << "\t" << Opcode << getWidthString(Ty) << getPredicate() Str << "\t" << Opcode;
<< VecEltWidthString << "\t"; const bool IsVInst = IsVectorStore || IsScalarFloat;
if (IsVInst) {
Str << getPredicate() << getWidthString(Ty);
} else {
Str << getWidthString(Ty) << getPredicate();
}
Str << VecEltWidthString << "\t";
getSrc(0)->emit(Func); getSrc(0)->emit(Func);
Str << ", "; Str << ", ";
getSrc(1)->emit(Func); getSrc(1)->emit(Func);
......
...@@ -2506,7 +2506,7 @@ void TargetARM32::lowerFcmp(const InstFcmp *Instr) { ...@@ -2506,7 +2506,7 @@ void TargetARM32::lowerFcmp(const InstFcmp *Instr) {
return; return;
} }
Variable *T = makeReg(IceType_i32); Variable *T = makeReg(IceType_i1);
Operand *_1 = Ctx->getConstantInt32(1); Operand *_1 = Ctx->getConstantInt32(1);
Operand *_0 = Ctx->getConstantZero(IceType_i32); Operand *_0 = Ctx->getConstantZero(IceType_i32);
...@@ -2672,7 +2672,7 @@ void TargetARM32::lowerIcmp(const InstIcmp *Inst) { ...@@ -2672,7 +2672,7 @@ void TargetARM32::lowerIcmp(const InstIcmp *Inst) {
Constant *_0 = Ctx->getConstantZero(IceType_i32); Constant *_0 = Ctx->getConstantZero(IceType_i32);
Constant *_1 = Ctx->getConstantInt32(1); Constant *_1 = Ctx->getConstantInt32(1);
Variable *T = makeReg(IceType_i32); Variable *T = makeReg(IceType_i1);
CondARM32::Cond CondIfTrue, CondIfFalse; CondARM32::Cond CondIfTrue, CondIfFalse;
lowerIcmpCond(Inst, &CondIfTrue, &CondIfFalse); lowerIcmpCond(Inst, &CondIfTrue, &CondIfFalse);
......
...@@ -57,14 +57,14 @@ define internal void @mult_fwd_branches(i32 %a, i32 %b) { ...@@ -57,14 +57,14 @@ define internal void @mult_fwd_branches(i32 %a, i32 %b) {
; ASM-NEXT: cmp r0, r1 ; ASM-NEXT: cmp r0, r1
; ASM-NEXT: movge r0, #0 ; ASM-NEXT: movge r0, #0
; ASM-NEXT: movlt r0, #1 ; ASM-NEXT: movlt r0, #1
; ASM-NEXT: str r0, [sp] ; ASM-NEXT: strb r0, [sp]
; DIS-NEXT: c: e59d0008 ; DIS-NEXT: c: e59d0008
; DIS-NEXT: 10: e59d1004 ; DIS-NEXT: 10: e59d1004
; DIS-NEXT: 14: e1500001 ; DIS-NEXT: 14: e1500001
; DIS-NEXT: 18: a3a00000 ; DIS-NEXT: 18: a3a00000
; DIS-NEXT: 1c: b3a00001 ; DIS-NEXT: 1c: b3a00001
; DIS-NEXT: 20: e58d0000 ; DIS-NEXT: 20: e5cd0000
; IASM-NEXT: .byte 0x8 ; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0 ; IASM-NEXT: .byte 0x0
...@@ -91,26 +91,23 @@ define internal void @mult_fwd_branches(i32 %a, i32 %b) { ...@@ -91,26 +91,23 @@ define internal void @mult_fwd_branches(i32 %a, i32 %b) {
; IASM-NEXT: .byte 0xa0 ; IASM-NEXT: .byte 0xa0
; IASM-NEXT: .byte 0xb3 ; IASM-NEXT: .byte 0xb3
; IASM-NEXT: .byte 0x0 ; IASM-NEXT: strb r0, [sp]
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
br i1 %cmp, label %then, label %else br i1 %cmp, label %then, label %else
; ASM-NEXT: ldr r0, [sp] ; ASM-NEXT: ldrb r0, [sp]
; ASM-NEXT: uxtb r0, r0 ; ASM-NEXT: uxtb r0, r0
; ASM-NEXT: cmp r0, #0 ; ASM-NEXT: cmp r0, #0
; ASM-NEXT: bne .Lmult_fwd_branches$then ; ASM-NEXT: bne .Lmult_fwd_branches$then
; ASM-NEXT: b .Lmult_fwd_branches$else ; ASM-NEXT: b .Lmult_fwd_branches$else
; DIS-NEXT: 24: e59d0000 ; DIS-NEXT: 24: e5dd0000
; DIS-NEXT: 28: e6ef0070 ; DIS-NEXT: 28: e6ef0070
; DIS-NEXT: 2c: e3500000 ; DIS-NEXT: 2c: e3500000
; DIS-NEXT: 30: 1a000000 ; DIS-NEXT: 30: 1a000000
; DIS-NEXT: 34: ea000000 ; DIS-NEXT: 34: ea000000
; IASM-NEXT: ldr r0, [sp] ; IASM-NEXT: ldrb r0, [sp]
; IASM-NEXT: uxtb r0, r0 ; IASM-NEXT: uxtb r0, r0
; IASM-NEXT: .byte 0x0 ; IASM-NEXT: .byte 0x0
......
...@@ -1068,7 +1068,7 @@ entry: ...@@ -1068,7 +1068,7 @@ entry:
; ARM32: ldrexb ; ARM32: ldrexb
; ARM32: cmp ; ARM32: cmp
; ARM32: strexbeq ; ARM32: strexbeq
; ARM32: {{str|mov}}ne ; ARM32: {{strb|mov}}ne
; ARM32: cmpeq ; ARM32: cmpeq
; ARM32: bne ; ARM32: bne
; ARM32: dmb ; ARM32: dmb
...@@ -1092,7 +1092,7 @@ entry: ...@@ -1092,7 +1092,7 @@ entry:
; ARM32: ldrexh ; ARM32: ldrexh
; ARM32: cmp ; ARM32: cmp
; ARM32: strexheq ; ARM32: strexheq
; ARM32: {{str|mov}}ne ; ARM32: {{strh|mov}}ne
; ARM32: cmpeq ; ARM32: cmpeq
; ARM32: bne ; ARM32: bne
; ARM32: dmb ; ARM32: dmb
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment