Operands.push_back(SparcOperand::CreateToken("]",
Parser.getTok().getLoc()));
Parser.Lex(); // Eat the ]
+
+ // Parse an optional address-space identifier after the address.
+ if (getLexer().is(AsmToken::Integer)) {
+ std::unique_ptr<SparcOperand> Op;
+ ResTy = parseSparcAsmOperand(Op, false);
+ if (ResTy != MatchOperand_Success || !Op)
+ return MatchOperand_ParseFail;
+ Operands.push_back(std::move(Op));
+ }
return MatchOperand_Success;
}
unsigned rd = fieldFromInstruction(insn, 25, 5);
unsigned rs1 = fieldFromInstruction(insn, 14, 5);
bool isImm = fieldFromInstruction(insn, 13, 1);
+ bool hasAsi = fieldFromInstruction(insn, 23, 1); // (in op3 field)
+ unsigned asi = fieldFromInstruction(insn, 5, 8);
unsigned rs2 = 0;
unsigned simm13 = 0;
if (isImm)
return status;
}
+ if (hasAsi)
+ MI.addOperand(MCOperand::createImm(asi));
+
if (!isLoad) {
status = DecodeRD(MI, rd, Address, Decoder);
if (status != MCDisassembler::Success)
unsigned rd = fieldFromInstruction(insn, 25, 5);
unsigned rs1 = fieldFromInstruction(insn, 14, 5);
unsigned isImm = fieldFromInstruction(insn, 13, 1);
+ bool hasAsi = fieldFromInstruction(insn, 23, 1); // (in op3 field)
+ unsigned asi = fieldFromInstruction(insn, 5, 8);
unsigned rs2 = 0;
unsigned simm13 = 0;
if (isImm)
if (status != MCDisassembler::Success)
return status;
}
+
+ if (hasAsi)
+ MI.addOperand(MCOperand::createImm(asi));
+
return MCDisassembler::Success;
}
}
// ATOMICS.
-let Predicates = [Is64Bit], Constraints = "$swap = $rd" in {
- def CASXrr: F3_1_asi<3, 0b111110, 0b10000000,
+let Predicates = [Is64Bit], Constraints = "$swap = $rd", asi = 0b10000000 in {
+ def CASXrr: F3_1_asi<3, 0b111110,
(outs I64Regs:$rd), (ins I64Regs:$rs1, I64Regs:$rs2,
I64Regs:$swap),
"casx [$rs1], $rs2, $rd",
// Specific F3 classes: SparcV8 manual, page 44
//
-class F3_1_asi<bits<2> opVal, bits<6> op3val, bits<8> asi, dag outs, dag ins,
+class F3_1_asi<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
+ bits<8> asi;
bits<5> rs2;
let op = opVal;
}
class F3_1<bits<2> opVal, bits<6> op3val, dag outs, dag ins, string asmstr,
- list<dag> pattern> : F3_1_asi<opVal, op3val, 0, outs, ins,
- asmstr, pattern>;
+ list<dag> pattern> : F3_1_asi<opVal, op3val, outs, ins,
+ asmstr, pattern> {
+ let asi = 0;
+}
class F3_2<bits<2> opVal, bits<6> op3val, dag outs, dag ins,
string asmstr, list<dag> pattern> : F3<outs, ins, asmstr, pattern> {
[(set Ty:$dst, (OpNode ADDRri:$addr))]>;
}
+// LoadA multiclass - As above, but also define alternate address space variant
+multiclass LoadA<string OpcStr, bits<6> Op3Val, bits<6> LoadAOp3Val,
+ SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> :
+ Load<OpcStr, Op3Val, OpNode, RC, Ty> {
+ // TODO: The LD*Arr instructions are currently asm only; hooking up
+ // CodeGen's address spaces to use these is a future task.
+ def Arr : F3_1_asi<3, LoadAOp3Val, (outs RC:$dst), (ins MEMrr:$addr, i8imm:$asi),
+ !strconcat(OpcStr, "a [$addr] $asi, $dst"),
+ []>;
+}
+
// Store multiclass - Define both Reg+Reg/Reg+Imm patterns in one shot.
multiclass Store<string OpcStr, bits<6> Op3Val, SDPatternOperator OpNode,
RegisterClass RC, ValueType Ty> {
[(OpNode Ty:$rd, ADDRri:$addr)]>;
}
+multiclass StoreA<string OpcStr, bits<6> Op3Val, bits<6> StoreAOp3Val,
+ SDPatternOperator OpNode, RegisterClass RC, ValueType Ty> :
+ Store<OpcStr, Op3Val, OpNode, RC, Ty> {
+ // TODO: The ST*Arr instructions are currently asm only; hooking up
+ // CodeGen's address spaces to use these is a future task.
+ def Arr : F3_1_asi<3, StoreAOp3Val, (outs), (ins MEMrr:$addr, RC:$rd, i8imm:$asi),
+ !strconcat(OpcStr, "a $rd, [$addr] $asi"),
+ []>;
+}
+
//===----------------------------------------------------------------------===//
// Instructions
//===----------------------------------------------------------------------===//
// Section B.1 - Load Integer Instructions, p. 90
let DecoderMethod = "DecodeLoadInt" in {
- defm LDSB : Load<"ldsb", 0b001001, sextloadi8, IntRegs, i32>;
- defm LDSH : Load<"ldsh", 0b001010, sextloadi16, IntRegs, i32>;
- defm LDUB : Load<"ldub", 0b000001, zextloadi8, IntRegs, i32>;
- defm LDUH : Load<"lduh", 0b000010, zextloadi16, IntRegs, i32>;
- defm LD : Load<"ld", 0b000000, load, IntRegs, i32>;
+ defm LDSB : LoadA<"ldsb", 0b001001, 0b011001, sextloadi8, IntRegs, i32>;
+ defm LDSH : LoadA<"ldsh", 0b001010, 0b011010, sextloadi16, IntRegs, i32>;
+ defm LDUB : LoadA<"ldub", 0b000001, 0b010001, zextloadi8, IntRegs, i32>;
+ defm LDUH : LoadA<"lduh", 0b000010, 0b010010, zextloadi16, IntRegs, i32>;
+ defm LD : LoadA<"ld", 0b000000, 0b010000, load, IntRegs, i32>;
}
// Section B.2 - Load Floating-point Instructions, p. 92
// Section B.4 - Store Integer Instructions, p. 95
let DecoderMethod = "DecodeStoreInt" in {
- defm STB : Store<"stb", 0b000101, truncstorei8, IntRegs, i32>;
- defm STH : Store<"sth", 0b000110, truncstorei16, IntRegs, i32>;
- defm ST : Store<"st", 0b000100, store, IntRegs, i32>;
+ defm STB : StoreA<"stb", 0b000101, 0b010101, truncstorei8, IntRegs, i32>;
+ defm STH : StoreA<"sth", 0b000110, 0b010110, truncstorei16, IntRegs, i32>;
+ defm ST : StoreA<"st", 0b000100, 0b010100, store, IntRegs, i32>;
}
// Section B.5 - Store Floating-point Instructions, p. 97
(outs IntRegs:$dst), (ins MEMri:$addr, IntRegs:$val),
"swap [$addr], $dst",
[(set i32:$dst, (atomic_swap_32 ADDRri:$addr, i32:$val))]>;
+ def SWAPArr : F3_1_asi<3, 0b011111,
+ (outs IntRegs:$dst), (ins MEMrr:$addr, i8imm:$asi, IntRegs:$val),
+ "swapa [$addr] $asi, $dst",
+ [/*FIXME: pattern?*/]>;
}
-let Predicates = [HasV9], Constraints = "$swap = $rd" in
- def CASrr: F3_1_asi<3, 0b111100, 0b10000000,
+// TODO: Should add a CASArr variant. In fact, the CAS instruction,
+// unlike other instructions, only comes in a form which requires an
+// ASI be provided. The ASI value hardcoded here is ASI_PRIMARY, the
+// default unprivileged ASI for SparcV9. (Also of note: some modern
+// SparcV8 implementations provide CASA as an extension, but require
+// the use of SparcV8's default ASI, 0xA ("User Data") instead.)
+let Predicates = [HasV9], Constraints = "$swap = $rd", asi = 0b10000000 in
+ def CASrr: F3_1_asi<3, 0b111100,
(outs IntRegs:$rd), (ins IntRegs:$rs1, IntRegs:$rs2,
IntRegs:$swap),
"cas [$rs1], $rs2, $rd",
# CHECK: swap [%g1], %o2
0xd4 0x78 0x40 0x00
+
+# CHECK: swapa [%i0+%l6] 131, %o2
+0xd4 0xfe 0x10 0x76
+
+# CHECK: swapa [%g1] 131, %o2
+0xd4 0xf8 0x50 0x60
! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
-
- ! CHECK: membar 15 ! encoding: [0x81,0x43,0xe0,0x0f]
- membar 15
+! RUN: llvm-mc %s -arch=sparc -show-encoding | FileCheck %s
! CHECK: stbar ! encoding: [0x81,0x43,0xc0,0x00]
stbar
! CHECK: swap [%i0+32], %o2 ! encoding: [0xd4,0x7e,0x20,0x20]
swap [%i0+32], %o2
- ! CHECK: cas [%i0], %l6, %o2 ! encoding: [0xd5,0xe6,0x10,0x16]
- cas [%i0], %l6, %o2
-
- ! CHECK: casx [%i0], %l6, %o2 ! encoding: [0xd5,0xf6,0x10,0x16]
- casx [%i0], %l6, %o2
+ ! CHECK: swapa [%i0+%l6] 131, %o2 ! encoding: [0xd4,0xfe,0x10,0x76]
+ swapa [%i0+%l6] 131, %o2
ldsb [%i0 + 32], %o2
! CHECK: ldsb [%g1], %o4 ! encoding: [0xd8,0x48,0x40,0x00]
ldsb [%g1], %o4
+ ! CHECK: ldsba [%i0+%l6] 131, %o2 ! encoding: [0xd4,0xce,0x10,0x76]
+ ldsba [%i0 + %l6] 131, %o2
! CHECK: ldsh [%i0+%l6], %o2 ! encoding: [0xd4,0x56,0x00,0x16]
ldsh [%i0 + %l6], %o2
ldsh [%i0 + 32], %o2
! CHECK: ldsh [%g1], %o4 ! encoding: [0xd8,0x50,0x40,0x00]
ldsh [%g1], %o4
+ ! CHECK: ldsha [%i0+%l6] 131, %o2 ! encoding: [0xd4,0xd6,0x10,0x76]
+ ldsha [%i0 + %l6] 131, %o2
! CHECK: ldub [%i0+%l6], %o2 ! encoding: [0xd4,0x0e,0x00,0x16]
ldub [%i0 + %l6], %o2
ldub [%i0 + 32], %o2
! CHECK: ldub [%g1], %o2 ! encoding: [0xd4,0x08,0x40,0x00]
ldub [%g1], %o2
+ ! CHECK: lduba [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x8e,0x10,0x76]
+ lduba [%i0 + %l6] 131, %o2
! CHECK: lduh [%i0+%l6], %o2 ! encoding: [0xd4,0x16,0x00,0x16]
lduh [%i0 + %l6], %o2
lduh [%i0 + 32], %o2
! CHECK: lduh [%g1], %o2 ! encoding: [0xd4,0x10,0x40,0x00]
lduh [%g1], %o2
+ ! CHECK: lduha [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x96,0x10,0x76]
+ lduha [%i0 + %l6] 131, %o2
! CHECK: ld [%i0+%l6], %o2 ! encoding: [0xd4,0x06,0x00,0x16]
ld [%i0 + %l6], %o2
ld [%i0 + 32], %o2
! CHECK: ld [%g1], %o2 ! encoding: [0xd4,0x00,0x40,0x00]
ld [%g1], %o2
+ ! CHECK: lda [%i0+%l6] 131, %o2 ! encoding: [0xd4,0x86,0x10,0x76]
+ lda [%i0 + %l6] 131, %o2
! CHECK: stb %o2, [%i0+%l6] ! encoding: [0xd4,0x2e,0x00,0x16]
stb %o2, [%i0 + %l6]
stb %o2, [%i0 + 32]
! CHECK: stb %o2, [%g1] ! encoding: [0xd4,0x28,0x40,0x00]
stb %o2, [%g1]
+ ! CHECK: stba %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xae,0x10,0x76]
+ stba %o2, [%i0 + %l6] 131
! CHECK: sth %o2, [%i0+%l6] ! encoding: [0xd4,0x36,0x00,0x16]
sth %o2, [%i0 + %l6]
sth %o2, [%i0 + 32]
! CHECK: sth %o2, [%g1] ! encoding: [0xd4,0x30,0x40,0x00]
sth %o2, [%g1]
+ ! CHECK: stha %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xb6,0x10,0x76]
+ stha %o2, [%i0 + %l6] 131
! CHECK: st %o2, [%i0+%l6] ! encoding: [0xd4,0x26,0x00,0x16]
st %o2, [%i0 + %l6]
st %o2, [%i0 + 32]
! CHECK: st %o2, [%g1] ! encoding: [0xd4,0x20,0x40,0x00]
st %o2, [%g1]
+ ! CHECK: sta %o2, [%i0+%l6] 131 ! encoding: [0xd4,0xa6,0x10,0x76]
+ sta %o2, [%i0 + %l6] 131
--- /dev/null
+! RUN: llvm-mc %s -arch=sparcv9 -show-encoding | FileCheck %s
+
+ ! CHECK: membar 15 ! encoding: [0x81,0x43,0xe0,0x0f]
+ membar 15
+
+ ! CHECK: cas [%i0], %l6, %o2 ! encoding: [0xd5,0xe6,0x10,0x16]
+ cas [%i0], %l6, %o2
+
+ ! CHECK: casx [%i0], %l6, %o2 ! encoding: [0xd5,0xf6,0x10,0x16]
+ casx [%i0], %l6, %o2