Commit 137e62bd by Karl Schimpf

Handle branch relative to pc in ARM integrated assembler.

Adds an explicit branch instruction (near form only), which allows branching from the current pc up to 2**26 bytes (in either direction). For now, this near restriction (within a function) doesn't appear to be a bad restriction, and only near jumps have been implemented. Also fixes notationally the concepts of the following types: InstValueType : The 32-bit encoding of an instruction value. InstOffsetType : Offset (+/-) used within an instruction. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4334 R=stichnot@chromium.org Review URL: https://codereview.chromium.org/1418313003 .
parent 50a3331c
...@@ -91,8 +91,8 @@ void Assembler::EmitType01(Condition cond, ...@@ -91,8 +91,8 @@ void Assembler::EmitType01(Condition cond,
o.encoding(); o.encoding();
Emit(encoding); Emit(encoding);
} }
#endif
// Moved to ARM32::AssemblerARM32::emitType05.
void Assembler::EmitType5(Condition cond, int32_t offset, bool link) { void Assembler::EmitType5(Condition cond, int32_t offset, bool link) {
ASSERT(cond != kNoCondition); ASSERT(cond != kNoCondition);
int32_t encoding = static_cast<int32_t>(cond) << kConditionShift | int32_t encoding = static_cast<int32_t>(cond) << kConditionShift |
...@@ -101,8 +101,6 @@ void Assembler::EmitType5(Condition cond, int32_t offset, bool link) { ...@@ -101,8 +101,6 @@ void Assembler::EmitType5(Condition cond, int32_t offset, bool link) {
Emit(Assembler::EncodeBranchOffset(offset, encoding)); Emit(Assembler::EncodeBranchOffset(offset, encoding));
} }
#if 0
// Moved to ARM32::AssemblerARM32::emitMemOp() // Moved to ARM32::AssemblerARM32::emitMemOp()
void Assembler::EmitMemOp(Condition cond, void Assembler::EmitMemOp(Condition cond,
bool load, bool load,
...@@ -222,9 +220,7 @@ void Assembler::add(Register rd, Register rn, Operand o, Condition cond) { ...@@ -222,9 +220,7 @@ void Assembler::add(Register rd, Register rn, Operand o, Condition cond) {
void Assembler::adds(Register rd, Register rn, Operand o, Condition cond) { void Assembler::adds(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), ADD, 1, rn, rd, o); EmitType01(cond, o.type(), ADD, 1, rn, rd, o);
} }
#endif
#if 0
// Moved to ARM32::AssemberARM32::sub() // Moved to ARM32::AssemberARM32::sub()
void Assembler::subs(Register rd, Register rn, Operand o, Condition cond) { void Assembler::subs(Register rd, Register rn, Operand o, Condition cond) {
EmitType01(cond, o.type(), SUB, 1, rn, rd, o); EmitType01(cond, o.type(), SUB, 1, rn, rd, o);
...@@ -2083,13 +2079,16 @@ void Assembler::UpdateRangeFeedback(Register value, ...@@ -2083,13 +2079,16 @@ void Assembler::UpdateRangeFeedback(Register value,
str(scratch2, FieldAddress(ic_data, ICData::state_bits_offset())); str(scratch2, FieldAddress(ic_data, ICData::state_bits_offset()));
} }
#if 0
// Moved to ::canEncodeBranchoffset in IceAssemblerARM32.cpp.
static bool CanEncodeBranchOffset(int32_t offset) { static bool CanEncodeBranchOffset(int32_t offset) {
ASSERT(Utils::IsAligned(offset, 4)); ASSERT(Utils::IsAligned(offset, 4));
// Note: This check doesn't take advantage of the fact that offset>>2
// is stored (allowing two more bits in address space).
return Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset); return Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset);
} }
// Moved to AssemblerARM32::encodeBranchOffset.
int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) { int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) {
// The offset is off by 8 due to the way the ARM CPUs read PC. // The offset is off by 8 due to the way the ARM CPUs read PC.
offset -= Instr::kPCReadOffset; offset -= Instr::kPCReadOffset;
...@@ -2106,12 +2105,12 @@ int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) { ...@@ -2106,12 +2105,12 @@ int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) {
return (inst & ~kBranchOffsetMask) | offset; return (inst & ~kBranchOffsetMask) | offset;
} }
// Moved to AssemberARM32::decodeBranchOffset.
int Assembler::DecodeBranchOffset(int32_t inst) { int Assembler::DecodeBranchOffset(int32_t inst) {
// Sign-extend, left-shift by 2, then add 8. // Sign-extend, left-shift by 2, then add 8.
return ((((inst & kBranchOffsetMask) << 8) >> 6) + Instr::kPCReadOffset); return ((((inst & kBranchOffsetMask) << 8) >> 6) + Instr::kPCReadOffset);
} }
#endif
static int32_t DecodeARMv7LoadImmediate(int32_t movt, int32_t movw) { static int32_t DecodeARMv7LoadImmediate(int32_t movt, int32_t movw) {
int32_t offset = 0; int32_t offset = 0;
......
...@@ -147,18 +147,14 @@ class Operand : public ValueObject { ...@@ -147,18 +147,14 @@ class Operand : public ValueObject {
type_ = 1; type_ = 1;
encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift); encoding_ = (rotate << kRotateShift) | (immed8 << kImmed8Shift);
} }
#endif
#if 0
// Moved to decodeOperand() in IceAssemblerARM32.cpp // Moved to decodeOperand() in IceAssemblerARM32.cpp
// Data-processing operands - Register. // Data-processing operands - Register.
explicit Operand(Register rm) { explicit Operand(Register rm) {
type_ = 0; type_ = 0;
encoding_ = static_cast<uint32_t>(rm); encoding_ = static_cast<uint32_t>(rm);
} }
#endif
#if 0
// Moved to encodeShiftRotateImm5() // Moved to encodeShiftRotateImm5()
// Data-processing operands - Logical shift/rotate by immediate. // Data-processing operands - Logical shift/rotate by immediate.
Operand(Register rm, Shift shift, uint32_t shift_imm) { Operand(Register rm, Shift shift, uint32_t shift_imm) {
...@@ -1121,11 +1117,10 @@ class Assembler : public ValueObject { ...@@ -1121,11 +1117,10 @@ class Assembler : public ValueObject {
Register rn, Register rn,
Register rd, Register rd,
Operand o); Operand o);
#endif
// Moved to ARM32::AssemblerARM32::emitType05()
void EmitType5(Condition cond, int32_t offset, bool link); void EmitType5(Condition cond, int32_t offset, bool link);
#if 0
// Moved to ARM32::AssemberARM32::emitMemOp() // Moved to ARM32::AssemberARM32::emitMemOp()
void EmitMemOp(Condition cond, void EmitMemOp(Condition cond,
bool load, bool load,
...@@ -1214,8 +1209,12 @@ class Assembler : public ValueObject { ...@@ -1214,8 +1209,12 @@ class Assembler : public ValueObject {
void EmitFarBranch(Condition cond, int32_t offset, bool link); void EmitFarBranch(Condition cond, int32_t offset, bool link);
void EmitBranch(Condition cond, Label* label, bool link); void EmitBranch(Condition cond, Label* label, bool link);
#if 0
// Moved to ARM32::AssemblerARM32::encodeBranchoffset().
int32_t EncodeBranchOffset(int32_t offset, int32_t inst); int32_t EncodeBranchOffset(int32_t offset, int32_t inst);
// Moved to ARM32::AssemberARM32::decodeBranchOffset().
static int32_t DecodeBranchOffset(int32_t inst); static int32_t DecodeBranchOffset(int32_t inst);
#endif
int32_t EncodeTstOffset(int32_t offset, int32_t inst); int32_t EncodeTstOffset(int32_t offset, int32_t inst);
int32_t DecodeTstOffset(int32_t inst); int32_t DecodeTstOffset(int32_t inst);
......
...@@ -47,6 +47,9 @@ public: ...@@ -47,6 +47,9 @@ public:
assert(!isLinked()); assert(!isLinked());
} }
/// Returns the encoded position stored in the label.
intptr_t getEncodedPosition() const { return Position; }
/// Returns the position for bound labels (branches that come after this are /// Returns the position for bound labels (branches that come after this are
/// considered backward branches). Cannot be used for unused or linked labels. /// considered backward branches). Cannot be used for unused or linked labels.
intptr_t getPosition() const { intptr_t getPosition() const {
...@@ -77,13 +80,13 @@ public: ...@@ -77,13 +80,13 @@ public:
assert(isBound()); assert(isBound());
} }
protected:
void linkTo(intptr_t position) { void linkTo(intptr_t position) {
assert(!isBound()); assert(!isBound());
Position = position + kWordSize; Position = position + kWordSize;
assert(isLinked()); assert(isLinked());
} }
protected:
intptr_t Position = 0; intptr_t Position = 0;
// TODO(jvoung): why are labels offset by this? // TODO(jvoung): why are labels offset by this?
......
...@@ -38,6 +38,12 @@ ...@@ -38,6 +38,12 @@
namespace Ice { namespace Ice {
namespace ARM32 { namespace ARM32 {
/// Encoding of an ARM 32-bit instruction.
using IValueT = uint32_t;
/// An Offset value (+/-) used in an ARM 32-bit instruction.
using IOffsetT = int32_t;
class AssemblerARM32 : public Assembler { class AssemblerARM32 : public Assembler {
AssemblerARM32() = delete; AssemblerARM32() = delete;
AssemblerARM32(const AssemblerARM32 &) = delete; AssemblerARM32(const AssemblerARM32 &) = delete;
...@@ -63,8 +69,8 @@ public: ...@@ -63,8 +69,8 @@ public:
void alignFunction() override { void alignFunction() override {
const SizeT Align = 1 << getBundleAlignLog2Bytes(); const SizeT Align = 1 << getBundleAlignLog2Bytes();
SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align); SizeT BytesNeeded = Utils::OffsetToAlignment(Buffer.getPosition(), Align);
constexpr uint32_t UndefinedInst = 0xe7fedef0; // udf #60896 constexpr IValueT UndefinedInst = 0xe7fedef0; // udf #60896
constexpr SizeT InstSize = sizeof(int32_t); constexpr SizeT InstSize = sizeof(IValueT);
assert(BytesNeeded % InstSize == 0); assert(BytesNeeded % InstSize == 0);
while (BytesNeeded > 0) { while (BytesNeeded > 0) {
AssemblerBuffer::EnsureCapacity ensured(&Buffer); AssemblerBuffer::EnsureCapacity ensured(&Buffer);
...@@ -94,7 +100,13 @@ public: ...@@ -94,7 +100,13 @@ public:
return CfgNodeLabels[NodeNumber]; return CfgNodeLabels[NodeNumber];
} }
void bindCfgNodeLabel(const CfgNode *Node) override; Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
return getOrCreateLabel(NodeNumber, CfgNodeLabels);
}
Label *getOrCreateLocalLabel(SizeT Number) {
return getOrCreateLabel(Number, LocalLabels);
}
void bindLocalLabel(SizeT Number) { void bindLocalLabel(SizeT Number) {
Label *L = getOrCreateLocalLabel(Number); Label *L = getOrCreateLocalLabel(Number);
...@@ -115,6 +127,8 @@ public: ...@@ -115,6 +127,8 @@ public:
void add(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1, void add(const Operand *OpRd, const Operand *OpRn, const Operand *OpSrc1,
bool SetFlags, CondARM32::Cond Cond); bool SetFlags, CondARM32::Cond Cond);
void b(Label *L, CondARM32::Cond Cond);
void bkpt(uint16_t Imm16); void bkpt(uint16_t Imm16);
void ldr(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond); void ldr(const Operand *OpRt, const Operand *OpAddress, CondARM32::Cond Cond);
...@@ -132,7 +146,7 @@ public: ...@@ -132,7 +146,7 @@ public:
return Asm->getKind() == Asm_ARM32; return Asm->getKind() == Asm_ARM32;
} }
void emitTextInst(const std::string &Text, SizeT InstSize = sizeof(uint32_t)); void emitTextInst(const std::string &Text, SizeT InstSize = sizeof(IValueT));
private: private:
// A vector of pool-allocated x86 labels for CFG nodes. // A vector of pool-allocated x86 labels for CFG nodes.
...@@ -142,26 +156,32 @@ private: ...@@ -142,26 +156,32 @@ private:
LabelVector LocalLabels; LabelVector LocalLabels;
Label *getOrCreateLabel(SizeT Number, LabelVector &Labels); Label *getOrCreateLabel(SizeT Number, LabelVector &Labels);
Label *getOrCreateCfgNodeLabel(SizeT NodeNumber) {
return getOrCreateLabel(NodeNumber, CfgNodeLabels);
}
Label *getOrCreateLocalLabel(SizeT Number) {
return getOrCreateLabel(Number, LocalLabels);
}
void emitInst(uint32_t Value) { Buffer.emit<uint32_t>(Value); } void bindCfgNodeLabel(const CfgNode *Node) override;
void emitInst(IValueT Value) { Buffer.emit<IValueT>(Value); }
// Pattern cccctttoooosnnnnddddiiiiiiiiiiii where cccc=Cond, ttt=Type, // Pattern cccctttoooosnnnnddddiiiiiiiiiiii where cccc=Cond, ttt=Type,
// oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM section A5.2.3). // oooo=Opcode, nnnn=Rn, dddd=Rd, iiiiiiiiiiii=imm12 (See ARM section A5.2.3).
void emitType01(CondARM32::Cond Cond, uint32_t Type, uint32_t Opcode, void emitType01(CondARM32::Cond Cond, IValueT Type, IValueT Opcode,
bool SetCc, uint32_t Rn, uint32_t Rd, uint32_t imm12); bool SetCc, IValueT Rn, IValueT Rd, IValueT imm12);
void emitType05(CondARM32::Cond COnd, int32_t Offset, bool Link);
// Pattern ccccoooaabalnnnnttttaaaaaaaaaaaa where cccc=Cond, ooo=InstType, // Pattern ccccoooaabalnnnnttttaaaaaaaaaaaa where cccc=Cond, ooo=InstType,
// l=isLoad, b=isByte, and aaa0a0aaaa0000aaaaaaaaaaaa=Address. Note that // l=isLoad, b=isByte, and aaa0a0aaaa0000aaaaaaaaaaaa=Address. Note that
// Address is assumed to be defined by decodeAddress() in // Address is assumed to be defined by decodeAddress() in
// IceAssemblerARM32.cpp. // IceAssemblerARM32.cpp.
void emitMemOp(CondARM32::Cond Cond, uint32_t InstType, bool IsLoad, void emitMemOp(CondARM32::Cond Cond, IValueT InstType, bool IsLoad,
bool IsByte, uint32_t Rt, uint32_t Address); bool IsByte, uint32_t Rt, uint32_t Address);
void emitBranch(Label *L, CondARM32::Cond, bool Link);
// Encodes the given Offset into the branch instruction Inst.
IValueT encodeBranchOffset(IOffsetT Offset, IValueT Inst);
// Returns the offset encoded in the branch instruction Inst.
static IOffsetT decodeBranchOffset(IValueT Inst);
}; };
} // end of namespace ARM32 } // end of namespace ARM32
......
...@@ -734,6 +734,23 @@ void InstARM32Br::emit(const Cfg *Func) const { ...@@ -734,6 +734,23 @@ void InstARM32Br::emit(const Cfg *Func) const {
} }
} }
void InstARM32Br::emitIAS(const Cfg *Func) const {
ARM32::AssemblerARM32 *Asm = Func->getAssembler<ARM32::AssemblerARM32>();
if (Label) {
Asm->b(Asm->getOrCreateLocalLabel(Label->getNumber()), getPredicate());
} else if (isUnconditionalBranch()) {
Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()),
getPredicate());
} else {
Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex()),
getPredicate());
Asm->b(Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()),
CondARM32::AL);
}
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
}
void InstARM32Br::dump(const Cfg *Func) const { void InstARM32Br::dump(const Cfg *Func) const {
if (!BuildDefs::dump()) if (!BuildDefs::dump())
return; return;
......
...@@ -861,6 +861,7 @@ public: ...@@ -861,6 +861,7 @@ public:
} }
bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override; bool repointEdges(CfgNode *OldNode, CfgNode *NewNode) override;
void emit(const Cfg *Func) const override; void emit(const Cfg *Func) const override;
void emitIAS(const Cfg *Func) const override;
void dump(const Cfg *Func) const override; void dump(const Cfg *Func) const override;
static bool classof(const Inst *Inst) { return isClassof(Inst, Br); } static bool classof(const Inst *Inst) { return isClassof(Inst, Br); }
......
; Test that we correctly fix multiple forward branches.
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: | FileCheck %s --check-prefix=IASM
; Show bytes in assembled integrated code.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 | FileCheck %s --check-prefix=DIS
; REQUIRES: allow_dump
define internal void @mult_fwd_branches(i32 %a, i32 %b) {
; ASM-LABEL:mult_fwd_branches:
; ASM-LABEL:.Lmult_fwd_branches$__0:
; ASM-NEXT: sub sp, sp, #12
; ASM-NEXT: str r0, [sp, #8]
; ASM-NEXT: str r1, [sp, #4]
; DIS-LABEL:00000000 <mult_fwd_branches>:
; DIS-NEXT: 0: e24dd00c
; DIS-NEXT: 4: e58d0008
; DIS-NEXT: 8: e58d1004
; IASM-LABEL:mult_fwd_branches:
; IASM-LABEL:.Lmult_fwd_branches$__0:
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x4d
; IASM-NEXT: .byte 0xe2
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
%cmp = icmp slt i32 %a, %b
; ASM-NEXT: ldr r0, [sp, #8]
; ASM-NEXT: mov r1, #0
; ASM-NEXT: ldr r2, [sp, #4]
; ASM-NEXT: cmp r0, r2
; ASM-NEXT: movlt r1, #1
; ASM-NEXT: str r1, [sp]
; DIS-NEXT: c: e59d0008
; DIS-NEXT: 10: e3a01000
; DIS-NEXT: 14: e59d2004
; DIS-NEXT: 18: e1500002
; DIS-NEXT: 1c: b3a01001
; DIS-NEXT: 20: e58d1000
; IASM-NEXT: .byte 0x8
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; IASM-NEXT: mov r1, #0
; IASM-NEXT: .byte 0x4
; IASM-NEXT: .byte 0x20
; IASM-NEXT: .byte 0x9d
; IASM-NEXT: .byte 0xe5
; IASM-NEXT: cmp r0, r2
; IASM-NEXT: movlt r1, #1
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x10
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe5
br i1 %cmp, label %then, label %else
; ASM-NEXT: ldr r0, [sp]
; ASM-NEXT: uxtb r0, r0
; ASM-NEXT: cmp r0, #0
; ASM-NEXT: bne .Lmult_fwd_branches$then
; ASM-NEXT: b .Lmult_fwd_branches$else
; DIS-NEXT: 24: e59d0000
; DIS-NEXT: 28: e6ef0070
; DIS-NEXT: 2c: e3500000
; DIS-NEXT: 30: 1a000000
; DIS-NEXT: 34: ea000000
; IASM-NEXT: ldr r0, [sp]
; IASM-NEXT: uxtb r0, r0
; IASM-NEXT: cmp r0, #0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x1a
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xea
then:
; ASM-LABEL:.Lmult_fwd_branches$then:
; IASM-LABEL:.Lmult_fwd_branches$then:
br label %end
; ASM-NEXT: b .Lmult_fwd_branches$end
; DIS-NEXT: 38: ea000000
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xea
else:
; ASM-LABEL:.Lmult_fwd_branches$else:
; IASM-LABEL:.Lmult_fwd_branches$else:
br label %end
; ASM-NEXT: b .Lmult_fwd_branches$end
; DIS-NEXT: 3c: eaffffff
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0xea
end:
; ASM-LABEL:.Lmult_fwd_branches$end:
; IASM-LABEL: .Lmult_fwd_branches$end:
ret void
; ASM-NEXT: add sp, sp, #12
; ASM-NEXT: bx lr
; DIS-NEXT: 40: e28dd00c
; DIS-NEXT: 44: e12fff1e
; IASM-NEXT: .byte 0xc
; IASM-NEXT: .byte 0xd0
; IASM-NEXT: .byte 0x8d
; IASM-NEXT: .byte 0xe2
; IASM-NEXT: .byte 0x1e
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1
}
; Test branching instructions. ; Test branching instructions.
; TODO(kschimpf): Get this working. ; TODO(kschimpf): Get this working.
; REQUIRES: allow_dump
; Compile using standalone assembler. ; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \ ; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: | FileCheck %s --check-prefix=ASM ; RUN: | FileCheck %s --check-prefix=ASM
...@@ -17,8 +19,6 @@ ...@@ -17,8 +19,6 @@
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \ ; RUN: %p2i --filetype=iasm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 | FileCheck %s --check-prefix=DIS ; RUN: --args -Om1 | FileCheck %s --check-prefix=DIS
; REQUIRES: allow_dump
define internal void @simple_uncond_branch() { define internal void @simple_uncond_branch() {
; DIS-LABEL: 00000000 <simple_uncond_branch>: ; DIS-LABEL: 00000000 <simple_uncond_branch>:
; ASM-LABEL: simple_uncond_branch: ; ASM-LABEL: simple_uncond_branch:
...@@ -29,7 +29,10 @@ define internal void @simple_uncond_branch() { ...@@ -29,7 +29,10 @@ define internal void @simple_uncond_branch() {
br label %l2 br label %l2
; ASM-NEXT: b .Lsimple_uncond_branch$l2 ; ASM-NEXT: b .Lsimple_uncond_branch$l2
; IASM-NEXT: b .Lsimple_uncond_branch$l2 ; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xea
; DIS-NEXT: 0: ea000000 ; DIS-NEXT: 0: ea000000
l1: l1:
...@@ -38,7 +41,10 @@ l1: ...@@ -38,7 +41,10 @@ l1:
br label %l3 br label %l3
; ASM-NEXT: b .Lsimple_uncond_branch$l3 ; ASM-NEXT: b .Lsimple_uncond_branch$l3
; IASM-NEXT: b .Lsimple_uncond_branch$l3 ; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0x0
; IASM-NEXT: .byte 0xea
; DIS-NEXT: 4: ea000000 ; DIS-NEXT: 4: ea000000
l2: l2:
...@@ -47,7 +53,10 @@ l2: ...@@ -47,7 +53,10 @@ l2:
br label %l1 br label %l1
; ASM-NEXT: b .Lsimple_uncond_branch$l1 ; ASM-NEXT: b .Lsimple_uncond_branch$l1
; IASM-NEXT: b .Lsimple_uncond_branch$l1 ; IASM-NEXT: .byte 0xfd
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0xea
; DIS-NEXT: 8: eafffffd ; DIS-NEXT: 8: eafffffd
l3: l3:
...@@ -60,5 +69,6 @@ l3: ...@@ -60,5 +69,6 @@ l3:
; IASM-NEXT: .byte 0xff ; IASM-NEXT: .byte 0xff
; IASM-NEXT: .byte 0x2f ; IASM-NEXT: .byte 0x2f
; IASM-NEXT: .byte 0xe1 ; IASM-NEXT: .byte 0xe1
; DIS-NEXT: c: e12fff1e
} }
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