Commit ab389f22 by Karl Schimpf

Add missing vcvt instructions to integrated ARM assembler.

parent 2544d4d2
......@@ -1122,37 +1122,37 @@ void Assembler::vcvtid(SRegister sd, DRegister dm, Condition cond) {
EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6, sd, dm);
}
#if 0
// Moved to ARM32::AssemblerARM32::vcvtsi()
void Assembler::vcvtsi(SRegister sd, SRegister sm, Condition cond) {
EmitVFPsss(cond, B23 | B21 | B20 | B19 | B7 | B6, sd, S0, sm);
}
// Moved to ARM32::AssemblerARM32::vcvtdi()
void Assembler::vcvtdi(DRegister dd, SRegister sm, Condition cond) {
EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B7 | B6, dd, sm);
}
// Moved to ARM32::AssemblerARM32::vcvtus().
void Assembler::vcvtus(SRegister sd, SRegister sm, Condition cond) {
EmitVFPsss(cond, B23 | B21 | B20 | B19 | B18 | B7 | B6, sd, S0, sm);
}
// Moved to ARM32::AssemblerARM32::vcvtud().
void Assembler::vcvtud(SRegister sd, DRegister dm, Condition cond) {
EmitVFPsd(cond, B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6, sd, dm);
}
// Moved to ARM32::AssemblerARM32::vcvtsu()
void Assembler::vcvtsu(SRegister sd, SRegister sm, Condition cond) {
EmitVFPsss(cond, B23 | B21 | B20 | B19 | B6, sd, S0, sm);
}
// Moved to ARM32::AssemblerARM32::vcvtdu()
void Assembler::vcvtdu(DRegister dd, SRegister sm, Condition cond) {
EmitVFPds(cond, B23 | B21 | B20 | B19 | B8 | B6, dd, sm);
}
#if 0
// Moved to ARM23::AssemblerARM32::vcmps().
void Assembler::vcmps(SRegister sd, SRegister sm, Condition cond) {
EmitVFPsss(cond, B23 | B21 | B20 | B18 | B6, sd, S0, sm);
......
......@@ -723,22 +723,27 @@ class Assembler : public ValueObject {
void vsqrtd(DRegister dd, DRegister dm, Condition cond = AL);
#if 0
// Moved to ARM32::AssemblerARM32::vcvtsd
// Moved to ARM32::AssemblerARM32::vcvtsd().
void vcvtsd(SRegister sd, DRegister dm, Condition cond = AL);
// Moved to ARM32::AssemblerARM32:vcvtds
// Moved to ARM32::AssemblerARM32:vcvtds().
void vcvtds(DRegister dd, SRegister sm, Condition cond = AL);
// Moved to ARM32::AssemblerARM32::vcvtis()
void vcvtis(SRegister sd, SRegister sm, Condition cond = AL);
#endif
// Moved to ARM32::AssemblerARM32::vcvtid()
void vcvtid(SRegister sd, DRegister dm, Condition cond = AL);
// Moved to ARM32::AssemblerARM32::vcvtsi()
void vcvtsi(SRegister sd, SRegister sm, Condition cond = AL);
// Moved to ARM32::AssemblerARM32::vcvtdi()
void vcvtdi(DRegister dd, SRegister sm, Condition cond = AL);
// Moved to ARM32::AssemblerARM32::vcvtus().
void vcvtus(SRegister sd, SRegister sm, Condition cond = AL);
// Moved to ARM32::AssemblerARM32::vcvtud().
void vcvtud(SRegister sd, DRegister dm, Condition cond = AL);
// Moved to ARM32::AssemblerARM32::vcvtsu()
void vcvtsu(SRegister sd, SRegister sm, Condition cond = AL);
// Moved to ARM32::AssemblerARM32::vcvtdu()
void vcvtdu(DRegister dd, SRegister sm, Condition cond = AL);
#if 0
// Moved to ARM23::AssemblerARM32::vcmps().
void vcmps(SRegister sd, SRegister sm, Condition cond = AL);
// Moved to ARM23::AssemblerARM32::vcmpd().
......
......@@ -2132,6 +2132,34 @@ void AssemblerARM32::emitVFPsd(CondARM32::Cond Cond, IValueT Opcode, IValueT Sd,
emitInst(Encoding);
}
void AssemblerARM32::vcvtdi(const Operand *OpDd, const Operand *OpSm,
CondARM32::Cond Cond) {
// VCVT (between floating-point and integer, Floating-point)
// - ARM Section A8.8.306, encoding A1:
// vcvt<c>.f64.s32 <Dd>, <Sm>
//
// cccc11101D111000dddd10111M0mmmm where cccc=Cond, Ddddd=Dd, and mmmmM=Sm.
constexpr const char *Vcvtdi = "vcvtdi";
IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtdi);
IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtdi);
constexpr IValueT VcvtdiOpcode = B23 | B21 | B20 | B19 | B8 | B7 | B6;
emitVFPds(Cond, VcvtdiOpcode, Dd, Sm);
}
void AssemblerARM32::vcvtdu(const Operand *OpDd, const Operand *OpSm,
CondARM32::Cond Cond) {
// VCVT (between floating-point and integer, Floating-point)
// - ARM Section A8.8.306, encoding A1:
// vcvt<c>.f64.u32 <Dd>, <Sm>
//
// cccc11101D111000dddd10101M0mmmm where cccc=Cond, Ddddd=Dd, and mmmmM=Sm.
constexpr const char *Vcvtdu = "vcvtdu";
IValueT Dd = encodeDRegister(OpDd, "Dd", Vcvtdu);
IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtdu);
constexpr IValueT VcvtduOpcode = B23 | B21 | B20 | B19 | B8 | B6;
emitVFPds(Cond, VcvtduOpcode, Dd, Sm);
}
void AssemblerARM32::vcvtsd(const Operand *OpSd, const Operand *OpDm,
CondARM32::Cond Cond) {
constexpr const char *Vcvtsd = "vcvtsd";
......@@ -2148,11 +2176,85 @@ void AssemblerARM32::vcvtis(const Operand *OpSd, const Operand *OpSm,
// - ARM Section A8.8.306, encoding A1:
// vcvt<c>.s32.f32 <Sd>, <Sm>
//
// cccc11101D111101dddd10101M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
// cccc11101D111101dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
constexpr const char *Vcvtis = "vcvtis";
IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtis);
IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtis);
constexpr IValueT VcvtsiOpcode = B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6;
constexpr IValueT VcvtisOpcode = B23 | B21 | B20 | B19 | B18 | B16 | B7 | B6;
constexpr IValueT S0 = 0;
emitVFPsss(Cond, VcvtisOpcode, Sd, S0, Sm);
}
void AssemblerARM32::vcvtid(const Operand *OpSd, const Operand *OpDm,
CondARM32::Cond Cond) {
// VCVT (between floating-point and integer, Floating-point)
// - ARM Section A8.8.306, encoding A1:
// vcvt<c>.s32.f64 <Sd>, <Dm>
//
// cccc11101D111101dddd10111M0mmmm where cccc=Cond, ddddD=Sd, and Mmmmm=Dm.
constexpr const char *Vcvtid = "vcvtid";
IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtid);
IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtid);
constexpr IValueT VcvtidOpcode =
B23 | B21 | B20 | B19 | B18 | B16 | B8 | B7 | B6;
emitVFPsd(Cond, VcvtidOpcode, Sd, Dm);
}
void AssemblerARM32::vcvtsi(const Operand *OpSd, const Operand *OpSm,
CondARM32::Cond Cond) {
// VCVT (between floating-point and integer, Floating-point)
// - ARM Section A8.8.306, encoding A1:
// vcvt<c>.f32.s32 <Sd>, <Sm>
//
// cccc11101D111000dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
constexpr const char *Vcvtsi = "vcvtsi";
IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsi);
IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtsi);
constexpr IValueT VcvtsiOpcode = B23 | B21 | B20 | B19 | B7 | B6;
constexpr IValueT S0 = 0;
emitVFPsss(Cond, VcvtsiOpcode, Sd, S0, Sm);
}
void AssemblerARM32::vcvtsu(const Operand *OpSd, const Operand *OpSm,
CondARM32::Cond Cond) {
// VCVT (between floating-point and integer, Floating-point)
// - ARM Section A8.8.306, encoding A1:
// vcvt<c>.f32.u32 <Sd>, <Sm>
//
// cccc11101D111000dddd10001M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
constexpr const char *Vcvtsu = "vcvtsu";
IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtsu);
IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtsu);
constexpr IValueT VcvtsuOpcode = B23 | B21 | B20 | B19 | B6;
constexpr IValueT S0 = 0;
emitVFPsss(Cond, VcvtsuOpcode, Sd, S0, Sm);
}
void AssemblerARM32::vcvtud(const Operand *OpSd, const Operand *OpDm,
CondARM32::Cond Cond) {
// VCVT (between floating-point and integer, Floating-point)
// - ARM Section A8.8.306, encoding A1:
// vcvt<c>.u32.f64 <Sd>, <Dm>
//
// cccc11101D111100dddd10111M0mmmm where cccc=Cond, ddddD=Sd, and Mmmmm=Dm.
constexpr const char *Vcvtud = "vcvtud";
IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtud);
IValueT Dm = encodeDRegister(OpDm, "Dm", Vcvtud);
constexpr IValueT VcvtudOpcode = B23 | B21 | B20 | B19 | B18 | B8 | B7 | B6;
emitVFPsd(Cond, VcvtudOpcode, Sd, Dm);
}
void AssemblerARM32::vcvtus(const Operand *OpSd, const Operand *OpSm,
CondARM32::Cond Cond) {
// VCVT (between floating-point and integer, Floating-point)
// - ARM Section A8.8.306, encoding A1:
// vcvt<c>.u32.f32 <Sd>, <Sm>
//
// cccc11101D111100dddd10011M0mmmm where cccc=Cond, ddddD=Sd, and mmmmM=Sm.
constexpr const char *Vcvtus = "vcvtus";
IValueT Sd = encodeSRegister(OpSd, "Sd", Vcvtus);
IValueT Sm = encodeSRegister(OpSm, "Sm", Vcvtus);
constexpr IValueT VcvtsiOpcode = B23 | B21 | B20 | B19 | B18 | B7 | B6;
constexpr IValueT S0 = 0;
emitVFPsss(Cond, VcvtsiOpcode, Sd, S0, Sm);
}
......
......@@ -333,8 +333,29 @@ public:
// vcvt<c>.S32.F32
void vcvtis(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
// vcvt<c>.S32.F64
void vcvtid(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
// vcvt<c>.F64.S32
void vcvtdi(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
// vcvt<c>.F64.U32
void vcvtdu(const Operand *OpDd, const Operand *OpSm, CondARM32::Cond Cond);
void vcvtsd(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
// vcvt<c>.F32.S32
void vcvtsi(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
// vcvt<c>.F32.U32
void vcvtsu(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
// vcvt<c>.U32.F64
void vcvtud(const Operand *OpSd, const Operand *OpDm, CondARM32::Cond Cond);
// vcvt<c>.u32.f32
void vcvtus(const Operand *OpSd, const Operand *OpSm, CondARM32::Cond Cond);
void vdivd(const Operand *OpDd, const Operand *OpDn, const Operand *OpDm,
CondARM32::Cond Cond);
......
......@@ -1863,19 +1863,35 @@ void InstARM32Vcvt::emitIAS(const Cfg *Func) const {
case S2si:
Asm->vcvtis(getDest(), getSrc(0), getPredicate());
break;
case S2ui:
Asm->vcvtus(getDest(), getSrc(0), getPredicate());
break;
case Si2s:
Asm->vcvtsi(getDest(), getSrc(0), getPredicate());
break;
case Ui2s:
Asm->vcvtsu(getDest(), getSrc(0), getPredicate());
break;
case D2si:
Asm->vcvtid(getDest(), getSrc(0), getPredicate());
break;
case D2ui:
Asm->vcvtud(getDest(), getSrc(0), getPredicate());
break;
case Si2d:
Asm->vcvtdi(getDest(), getSrc(0), getPredicate());
break;
case Ui2d:
Asm->vcvtdu(getDest(), getSrc(0), getPredicate());
break;
case S2d:
Asm->vcvtds(getDest(), getSrc(0), getPredicate());
break;
case D2s:
Asm->vcvtsd(getDest(), getSrc(0), getPredicate());
break;
default:
// TODO(kschimpf): Fill in other variants.
Asm->setNeedsTextFixup();
break;
}
if (Asm->needsTextFixup())
emitUsingTextFixup(Func);
assert(!Asm->needsTextFixup());
}
void InstARM32Vcvt::dump(const Cfg *Func) const {
......
; Show that we know how to translate converting signed integer to floast.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 --reg-use=s20 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 \
; 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 --reg-use=s20 | FileCheck %s --check-prefix=DIS
define internal float @SignedIntToFloat() {
; ASM-LABEL: SignedIntToFloat:
; DIS-LABEL: 00000000 <SignedIntToFloat>:
; IASM-LABEL: SignedIntToFloat:
entry:
; ASM: .LSignedIntToFloat$entry:
; IASM: .LSignedIntToFloat$entry:
%v = sitofp i32 17 to float
; ASM: vcvt.f32.s32 s20, s20
; DIS: 10: eeb8aaca
; IASM-NOT: vcvt
ret float %v
}
; Show that we know how to translate converting unsigned integer to float.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 --reg-use=s20 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 \
; 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 --reg-use=s20 | FileCheck %s --check-prefix=DIS
define internal float @SignedIntToFloat() {
; ASM-LABEL: SignedIntToFloat:
; DIS-LABEL: 00000000 <SignedIntToFloat>:
; IASM-LABEL: SignedIntToFloat:
entry:
; ASM: .LSignedIntToFloat$entry:
; IASM: .LSignedIntToFloat$entry:
%v = uitofp i32 17 to float
; ASM: vcvt.f32.u32 s20, s20
; DIS: 10: eeb8aa4a
; IASM-NOT: vcvt
ret float %v
}
; Show that we know how to translate converting signed integer to double.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 --reg-use=s20 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 \
; 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 --reg-use=s20 | FileCheck %s --check-prefix=DIS
define internal double @SignedIntToDouble() {
; ASM-LABEL: SignedIntToDouble:
; DIS-LABEL: 00000000 <SignedIntToDouble>:
; IASM-LABEL: SignedIntToDouble:
entry:
; ASM: .LSignedIntToDouble$entry:
; IASM: .LSignedIntToDouble$entry:
%v = sitofp i32 17 to double
; ASM: vcvt.f64.s32 d0, s20
; DIS: 10: eeb80bca
; IASM-NOT: vcvt
ret double %v
}
; Show that we know how to translate converting unsigned integer to double.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 --reg-use=s20 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 \
; 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 --reg-use=s20 | FileCheck %s --check-prefix=DIS
define internal double @UnsignedIntToDouble() {
; ASM-LABEL: UnsignedIntToDouble:
; DIS-LABEL: 00000000 <UnsignedIntToDouble>:
; IASM-LABEL: UnsignedIntToDouble:
entry:
; ASM: .LUnsignedIntToDouble$entry:
; IASM: .LUnsignedIntToDouble$entry:
%v = uitofp i32 17 to double
; ASM: vcvt.f64.u32 d0, s20
; DIS: 10: eeb80b4a
; IASM-NOT: vcvt
ret double %v
}
; Show that we know how to translate converting double to signed integer.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 --reg-use=s20 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 \
; 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 --reg-use=s20 | FileCheck %s --check-prefix=DIS
define internal i32 @DoubleToSignedInt() {
; ASM-LABEL: DoubleToSignedInt:
; DIS-LABEL: 00000000 <DoubleToSignedInt>:
; IASM-LABEL: DoubleToSignedInt:
entry:
; ASM: .LDoubleToSignedInt$entry:
; IASM: .LDoubleToSignedInt$entry:
%v = fptosi double 0.0 to i32
; ASM: vcvt.s32.f64 s20, d0
; DIS: c: eebdabc0
; IASM-NOT: vcvt
ret i32 %v
}
; Show that we know how to translate converting float to unsigned integer.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 --reg-use=s20 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 \
; 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 --reg-use=s20 | FileCheck %s --check-prefix=DIS
define internal i32 @FloatToUnsignedInt() {
; ASM-LABEL: FloatToUnsignedInt:
; DIS-LABEL: 00000000 <FloatToUnsignedInt>:
; IASM-LABEL: FloatToUnsignedInt:
entry:
; ASM-NEXT: .LFloatToUnsignedInt$entry:
; IASM-NEXT: .LFloatToUnsignedInt$entry:
%v = fptoui float 0.0 to i32
; ASM: vcvt.u32.f32 s20, s20
; DIS: 14: eebcaaca
; IASM-NOT: vcvt
ret i32 %v
}
; Show that we know how to translate converting double to unsigned integer.
; REQUIRES: allow_dump
; Compile using standalone assembler.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 | FileCheck %s --check-prefix=ASM
; Show bytes in assembled standalone code.
; RUN: %p2i --filetype=asm -i %s --target=arm32 --assemble --disassemble \
; RUN: --args -Om1 --reg-use=s20 | FileCheck %s --check-prefix=DIS
; Compile using integrated assembler.
; RUN: %p2i --filetype=iasm -i %s --target=arm32 --args -Om1 \
; RUN: --reg-use=s20 \
; 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 --reg-use=s20 | FileCheck %s --check-prefix=DIS
define internal i32 @DoubleToUnsignedInt() {
; ASM-LABEL: DoubleToUnsignedInt:
; DIS-LABEL: 00000000 <DoubleToUnsignedInt>:
entry:
; ASM: .LDoubleToUnsignedInt$entry:
%v = fptoui double 0.0 to i32
; ASM: vcvt.u32.f64 s20, d0
; DIS: c: eebcabc0
; IASM-NOT: vcvt
ret i32 %v
}
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