https://github.com/MalaySanghi created https://github.com/llvm/llvm-project/pull/93774
Supported: outp, outpw, _outp, _outpw, _outpd These functions were removed from the Windows runtime library, but for kernel mode development it's still supported >From 38359132ea0b3b56900ba48827c86a93c017223a Mon Sep 17 00:00:00 2001 From: Malay Sanghi <malay.san...@intel.com> Date: Wed, 29 May 2024 22:40:47 -0700 Subject: [PATCH] Add support for _outp{|w|d} --- clang/lib/Headers/intrin.h | 20 +++++ clang/test/CodeGen/X86/ms-x86-intrinsics.c | 85 ++++++++++++++++++++++ 2 files changed, 105 insertions(+) diff --git a/clang/lib/Headers/intrin.h b/clang/lib/Headers/intrin.h index 5ceb986a1f652..21a3f030216e6 100644 --- a/clang/lib/Headers/intrin.h +++ b/clang/lib/Headers/intrin.h @@ -329,6 +329,26 @@ static __inline__ void __DEFAULT_FN_ATTRS __stosq(unsigned __int64 *__dst, static __inline__ void __DEFAULT_FN_ATTRS __halt(void) { __asm__ volatile("hlt"); } + +static __inline__ int __DEFAULT_FN_ATTRS _outp(unsigned short port, int data) { + __asm__ volatile("outb %b0, %w1" : : "a"(data), "Nd"(port) : "memory"); + return data; +} + +static __inline__ unsigned short __DEFAULT_FN_ATTRS +_outpw(unsigned short port, unsigned short data) { + __asm__ volatile("outw %w0, %w1" : : "a"(data), "Nd"(port) : "memory"); + return data; +} + +static __inline__ unsigned long __DEFAULT_FN_ATTRS _outpd(unsigned short port, + unsigned long data) { + __asm__ volatile("outl %k0, %w1" : : "a"(data), "Nd"(port) : "memory"); + return data; +} + +#define outp(port, data) _outp(port, data) +#define outpw(R, D) _outpw(port, data) #endif #if defined(__i386__) || defined(__x86_64__) || defined(__aarch64__) diff --git a/clang/test/CodeGen/X86/ms-x86-intrinsics.c b/clang/test/CodeGen/X86/ms-x86-intrinsics.c index aa557c8e19a83..e990ccd3449ac 100644 --- a/clang/test/CodeGen/X86/ms-x86-intrinsics.c +++ b/clang/test/CodeGen/X86/ms-x86-intrinsics.c @@ -63,6 +63,91 @@ unsigned __int64 test__emulu(unsigned int a, unsigned int b) { // CHECK: [[RES:%[0-9]+]] = mul nuw i64 [[Y]], [[X]] // CHECK: ret i64 [[RES]] +// +// CHECK-I386-LABEL: define dso_local noundef i32 @test_outp( +// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR2:[0-9]+]] { +// CHECK-I386-NEXT: [[ENTRY:.*:]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3:[0-9]+]], !srcloc [[META4:![0-9]+]] +// CHECK-I386-NEXT: ret i32 [[DATA]] +// +// CHECK-X64-LABEL: define dso_local noundef i32 @test_outp( +// CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] { +// CHECK-X64-NEXT: [[ENTRY:.*:]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5:[0-9]+]], !srcloc [[META3:![0-9]+]] +// CHECK-X64-NEXT: ret i32 [[DATA]] +// +int test_outp(unsigned short port, int data) { + return _outp(port, data); +} + +// +// CHECK-I386-LABEL: define dso_local noundef zeroext i16 @test_outpw( +// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i16 noundef returned zeroext [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { +// CHECK-I386-NEXT: [[ENTRY:.*:]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META5:![0-9]+]] +// CHECK-I386-NEXT: ret i16 [[DATA]] +// +// CHECK-X64-LABEL: define dso_local noundef i16 @test_outpw( +// CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i16 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { +// CHECK-X64-NEXT: [[ENTRY:.*:]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META4:![0-9]+]] +// CHECK-X64-NEXT: ret i16 [[DATA]] +// +unsigned short test_outpw(unsigned short port, unsigned short data) { + return _outpw(port, data); +} + +// +// CHECK-I386-LABEL: define dso_local noundef i32 @test_outpd( +// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { +// CHECK-I386-NEXT: [[ENTRY:.*:]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outl ${0:k}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META6:![0-9]+]] +// CHECK-I386-NEXT: ret i32 [[DATA]] +// +// CHECK-X64-LABEL: define dso_local noundef i32 @test_outpd( +// CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { +// CHECK-X64-NEXT: [[ENTRY:.*:]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outl ${0:k}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META5:![0-9]+]] +// CHECK-X64-NEXT: ret i32 [[DATA]] +// +unsigned long test_outpd(unsigned short port, unsigned long data) { + return _outpd(port, data); +} + +// +// CHECK-I386-LABEL: define dso_local noundef i32 @test_outp2( +// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { +// CHECK-I386-NEXT: [[ENTRY:.*:]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META4]] +// CHECK-I386-NEXT: ret i32 [[DATA]] +// +// CHECK-X64-LABEL: define dso_local noundef i32 @test_outp2( +// CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i32 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { +// CHECK-X64-NEXT: [[ENTRY:.*:]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outb ${0:b}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i32 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META3]] +// CHECK-X64-NEXT: ret i32 [[DATA]] +// +int test_outp2(unsigned short port, int data) { + return outp(port, data); +} + +// +// CHECK-I386-LABEL: define dso_local noundef zeroext i16 @test_outpw2( +// CHECK-I386-SAME: i16 noundef zeroext [[PORT:%.*]], i16 noundef returned zeroext [[DATA:%.*]]) local_unnamed_addr #[[ATTR2]] { +// CHECK-I386-NEXT: [[ENTRY:.*:]] +// CHECK-I386-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR3]], !srcloc [[META5]] +// CHECK-I386-NEXT: ret i16 [[DATA]] +// +// CHECK-X64-LABEL: define dso_local noundef i16 @test_outpw2( +// CHECK-X64-SAME: i16 noundef [[PORT:%.*]], i16 noundef returned [[DATA:%.*]]) local_unnamed_addr #[[ATTR1]] { +// CHECK-X64-NEXT: [[ENTRY:.*:]] +// CHECK-X64-NEXT: tail call void asm sideeffect "outw ${0:w}, ${1:w}", "{ax},N{dx},~{memory},~{dirflag},~{fpsr},~{flags}"(i16 [[DATA]], i16 [[PORT]]) #[[ATTR5]], !srcloc [[META4]] +// CHECK-X64-NEXT: ret i16 [[DATA]] +// +unsigned short test_outpw2(unsigned short port, unsigned short data) { + return outpw(port, data); +} + #if defined(__x86_64__) char test__readgsbyte(unsigned long Offset) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits