Commit 7406379f authored by Alex Brainman's avatar Alex Brainman

runtime: syscall to return both AX and DX for windows/386

Fixes #2181.

R=golang-dev, jp
CC=golang-dev
https://golang.org/cl/5000042
parent 2b3b5cf4
...@@ -307,7 +307,8 @@ struct WinCall ...@@ -307,7 +307,8 @@ struct WinCall
void (*fn)(void*); void (*fn)(void*);
uintptr n; // number of parameters uintptr n; // number of parameters
void* args; // parameters void* args; // parameters
uintptr r; // return value uintptr r1; // return values
uintptr r2;
uintptr err; // error number uintptr err; // error number
}; };
......
...@@ -39,6 +39,77 @@ func TestStdCall(t *testing.T) { ...@@ -39,6 +39,77 @@ func TestStdCall(t *testing.T) {
} }
} }
func Test64BitReturnStdCall(t *testing.T) {
const (
VER_BUILDNUMBER = 0x0000004
VER_MAJORVERSION = 0x0000002
VER_MINORVERSION = 0x0000001
VER_PLATFORMID = 0x0000008
VER_PRODUCT_TYPE = 0x0000080
VER_SERVICEPACKMAJOR = 0x0000020
VER_SERVICEPACKMINOR = 0x0000010
VER_SUITENAME = 0x0000040
VER_EQUAL = 1
VER_GREATER = 2
VER_GREATER_EQUAL = 3
VER_LESS = 4
VER_LESS_EQUAL = 5
ERROR_OLD_WIN_VERSION = 1150
)
type OSVersionInfoEx struct {
OSVersionInfoSize uint32
MajorVersion uint32
MinorVersion uint32
BuildNumber uint32
PlatformId uint32
CSDVersion [128]uint16
ServicePackMajor uint16
ServicePackMinor uint16
SuiteMask uint16
ProductType byte
Reserve byte
}
kernel32, e := syscall.LoadLibrary("kernel32.dll")
if e != 0 {
t.Fatalf("LoadLibrary(kernel32.dll) failed: %s", syscall.Errstr(e))
}
setMask, e := syscall.GetProcAddress(kernel32, "VerSetConditionMask")
if e != 0 {
t.Fatalf("GetProcAddress(kernel32.dll, VerSetConditionMask) failed: %s", syscall.Errstr(e))
}
verifyVersion, e := syscall.GetProcAddress(kernel32, "VerifyVersionInfoW")
if e != 0 {
t.Fatalf("GetProcAddress(kernel32.dll, VerifyVersionInfoW) failed: %s", syscall.Errstr(e))
}
var m1, m2 uintptr
m1, m2, _ = syscall.Syscall6(setMask, 4, m1, m2, VER_MAJORVERSION, VER_GREATER_EQUAL, 0, 0)
m1, m2, _ = syscall.Syscall6(setMask, 4, m1, m2, VER_MINORVERSION, VER_GREATER_EQUAL, 0, 0)
m1, m2, _ = syscall.Syscall6(setMask, 4, m1, m2, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL, 0, 0)
m1, m2, _ = syscall.Syscall6(setMask, 4, m1, m2, VER_SERVICEPACKMINOR, VER_GREATER_EQUAL, 0, 0)
vi := OSVersionInfoEx{
MajorVersion: 5,
MinorVersion: 1,
ServicePackMajor: 2,
ServicePackMinor: 0,
}
vi.OSVersionInfoSize = uint32(unsafe.Sizeof(vi))
r, _, e2 := syscall.Syscall6(verifyVersion,
4,
uintptr(unsafe.Pointer(&vi)),
VER_MAJORVERSION|VER_MINORVERSION|VER_SERVICEPACKMAJOR|VER_SERVICEPACKMINOR,
m1, m2, 0, 0)
if r == 0 && e2 != ERROR_OLD_WIN_VERSION {
t.Errorf("VerifyVersionInfo failed: (%d) %s", e2, syscall.Errstr(int(e2)))
}
}
func TestCDecl(t *testing.T) { func TestCDecl(t *testing.T) {
h, e := syscall.LoadLibrary("user32.dll") h, e := syscall.LoadLibrary("user32.dll")
if e != 0 { if e != 0 {
......
...@@ -6,35 +6,35 @@ ...@@ -6,35 +6,35 @@
// void runtime·asmstdcall(void *c); // void runtime·asmstdcall(void *c);
TEXT runtime·asmstdcall(SB),7,$0 TEXT runtime·asmstdcall(SB),7,$0
MOVL c+0(FP), DX MOVL c+0(FP), BX
// SetLastError(0). // SetLastError(0).
MOVL $0, 0x34(FS) MOVL $0, 0x34(FS)
// Copy args to the stack. // Copy args to the stack.
MOVL SP, BP MOVL SP, BP
MOVL wincall_n(DX), CX // words MOVL wincall_n(BX), CX // words
MOVL CX, BX MOVL CX, AX
SALL $2, BX SALL $2, AX
SUBL BX, SP // room for args SUBL AX, SP // room for args
MOVL SP, DI MOVL SP, DI
MOVL wincall_args(DX), SI MOVL wincall_args(BX), SI
CLD CLD
REP; MOVSL REP; MOVSL
// Call stdcall or cdecl function. // Call stdcall or cdecl function.
// DI SI BP BX are preserved, SP is not // DI SI BP BX are preserved, SP is not
MOVL wincall_fn(DX), AX CALL wincall_fn(BX)
CALL AX
MOVL BP, SP MOVL BP, SP
// Return result. // Return result.
MOVL c+0(FP), DX MOVL c+0(FP), BX
MOVL AX, wincall_r(DX) MOVL AX, wincall_r1(BX)
MOVL DX, wincall_r2(BX)
// GetLastError(). // GetLastError().
MOVL 0x34(FS), BX MOVL 0x34(FS), AX
MOVL BX, wincall_err(DX) MOVL AX, wincall_err(BX)
RET RET
......
...@@ -49,7 +49,7 @@ loadregs: ...@@ -49,7 +49,7 @@ loadregs:
// Return result. // Return result.
POPQ CX POPQ CX
MOVQ AX, wincall_r(CX) MOVQ AX, wincall_r1(CX)
// GetLastError(). // GetLastError().
MOVQ 0x30(GS), DI MOVQ 0x30(GS), DI
......
...@@ -12,7 +12,6 @@ extern void *runtime·GetProcAddress; ...@@ -12,7 +12,6 @@ extern void *runtime·GetProcAddress;
#pragma varargck type runtime·stdcall uintptr #pragma varargck type runtime·stdcall uintptr
void runtime·asmstdcall(void *c); void runtime·asmstdcall(void *c);
void *runtime·stdcall(void *fn, int32 count, ...); void *runtime·stdcall(void *fn, int32 count, ...);
uintptr runtime·syscall(void *fn, uintptr nargs, void *args, uintptr *err);
uintptr runtime·getlasterror(void); uintptr runtime·getlasterror(void);
void runtime·setlasterror(uintptr err); void runtime·setlasterror(uintptr err);
......
...@@ -5,15 +5,28 @@ ...@@ -5,15 +5,28 @@
package syscall package syscall
#include "runtime.h" #include "runtime.h"
#include "os.h" #include "os.h"
#include "cgocall.h"
func loadlibraryex(filename uintptr) (handle uintptr) { func loadlibraryex(filename uintptr) (handle uintptr) {
uintptr args[3] = { filename }; uintptr args[3] = { filename };
handle = runtime·syscall(runtime·LoadLibraryEx, 3, args, nil); WinCall c;
c.fn = runtime·LoadLibraryEx;
c.n = 3;
c.args = &args[0];
runtime·cgocall(runtime·asmstdcall, &c);
handle = c.r1;
} }
func getprocaddress(handle uintptr, procname uintptr) (proc uintptr) { func getprocaddress(handle uintptr, procname uintptr) (proc uintptr) {
WinCall c;
USED(procname); USED(procname);
proc = runtime·syscall(runtime·GetProcAddress, 2, &handle, nil); c.fn = runtime·GetProcAddress;
c.n = 2;
c.args = &handle;
runtime·cgocall(runtime·asmstdcall, &c);
proc = c.r1;
} }
func NewCallback(fn Eface) (code uintptr) { func NewCallback(fn Eface) (code uintptr) {
...@@ -25,23 +38,39 @@ func NewCallbackCDecl(fn Eface) (code uintptr) { ...@@ -25,23 +38,39 @@ func NewCallbackCDecl(fn Eface) (code uintptr) {
} }
func Syscall(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) { func Syscall(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
WinCall c;
USED(a2); USED(a2);
USED(a3); USED(a3);
r1 = runtime·syscall((void*)fn, nargs, &a1, &err); c.fn = (void*)fn;
r2 = 0; c.n = nargs;
c.args = &a1;
runtime·cgocall(runtime·asmstdcall, &c);
err = c.err;
r1 = c.r1;
r2 = c.r2;
} }
func Syscall6(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr) { func Syscall6(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
WinCall c;
USED(a2); USED(a2);
USED(a3); USED(a3);
USED(a4); USED(a4);
USED(a5); USED(a5);
USED(a6); USED(a6);
r1 = runtime·syscall((void*)fn, nargs, &a1, &err); c.fn = (void*)fn;
r2 = 0; c.n = nargs;
c.args = &a1;
runtime·cgocall(runtime·asmstdcall, &c);
err = c.err;
r1 = c.r1;
r2 = c.r2;
} }
func Syscall9(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr) (r1 uintptr, r2 uintptr, err uintptr) { func Syscall9(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
WinCall c;
USED(a2); USED(a2);
USED(a3); USED(a3);
USED(a4); USED(a4);
...@@ -50,11 +79,18 @@ func Syscall9(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 ...@@ -50,11 +79,18 @@ func Syscall9(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4
USED(a7); USED(a7);
USED(a8); USED(a8);
USED(a9); USED(a9);
r1 = runtime·syscall((void*)fn, nargs, &a1, &err); c.fn = (void*)fn;
r2 = 0; c.n = nargs;
c.args = &a1;
runtime·cgocall(runtime·asmstdcall, &c);
err = c.err;
r1 = c.r1;
r2 = c.r2;
} }
func Syscall12(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr, a10 uintptr, a11 uintptr, a12 uintptr) (r1 uintptr, r2 uintptr, err uintptr) { func Syscall12(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 uintptr, a5 uintptr, a6 uintptr, a7 uintptr, a8 uintptr, a9 uintptr, a10 uintptr, a11 uintptr, a12 uintptr) (r1 uintptr, r2 uintptr, err uintptr) {
WinCall c;
USED(a2); USED(a2);
USED(a3); USED(a3);
USED(a4); USED(a4);
...@@ -66,6 +102,11 @@ func Syscall12(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4 ...@@ -66,6 +102,11 @@ func Syscall12(fn uintptr, nargs uintptr, a1 uintptr, a2 uintptr, a3 uintptr, a4
USED(a10); USED(a10);
USED(a11); USED(a11);
USED(a12); USED(a12);
r1 = runtime·syscall((void*)fn, nargs, &a1, &err); c.fn = (void*)fn;
r2 = 0; c.n = nargs;
c.args = &a1;
runtime·cgocall(runtime·asmstdcall, &c);
err = c.err;
r1 = c.r1;
r2 = c.r2;
} }
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
#include "type.h" #include "type.h"
#include "defs.h" #include "defs.h"
#include "os.h" #include "os.h"
#include "cgocall.h"
#pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll" #pragma dynimport runtime·CloseHandle CloseHandle "kernel32.dll"
#pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll" #pragma dynimport runtime·CreateEvent CreateEventA "kernel32.dll"
...@@ -228,21 +227,7 @@ runtime·stdcall(void *fn, int32 count, ...) ...@@ -228,21 +227,7 @@ runtime·stdcall(void *fn, int32 count, ...)
c.n = count; c.n = count;
c.args = (uintptr*)&count + 1; c.args = (uintptr*)&count + 1;
runtime·asmcgocall(runtime·asmstdcall, &c); runtime·asmcgocall(runtime·asmstdcall, &c);
return (void*)c.r; return (void*)c.r1;
}
uintptr
runtime·syscall(void *fn, uintptr nargs, void *args, uintptr *err)
{
WinCall c;
c.fn = fn;
c.n = nargs;
c.args = args;
runtime·cgocall(runtime·asmstdcall, &c);
if(err)
*err = c.err;
return c.r;
} }
uint32 uint32
......
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