summaryrefslogtreecommitdiffstats
path: root/private/ntos/dll/ppc
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/dll/ppc
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/dll/ppc')
-rw-r--r--private/ntos/dll/ppc/critsect.s381
-rw-r--r--private/ntos/dll/ppc/currteb.s35
-rw-r--r--private/ntos/dll/ppc/ldrthunk.s108
-rw-r--r--private/ntos/dll/ppc/sources6
4 files changed, 530 insertions, 0 deletions
diff --git a/private/ntos/dll/ppc/critsect.s b/private/ntos/dll/ppc/critsect.s
new file mode 100644
index 000000000..232b69fb4
--- /dev/null
+++ b/private/ntos/dll/ppc/critsect.s
@@ -0,0 +1,381 @@
+// TITLE("Eenter and Leave Critical Section")
+//++
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Module Name:
+//
+// critsect.s
+//
+// Abstract:
+//
+// This module implements functions to support user mode critical sections.
+//
+// Author:
+//
+// Chuck Bauman 12-Aug-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// Port NT product1 source to PowerPC
+//
+//--
+
+#include "ksppc.h"
+
+// SBTTL("Enter Critical Section")
+//++
+//
+// NTSTATUS
+// RtlEnterCriticalSection(
+// IN PRTL_CRITICAL_SECTION CriticalSection
+// )
+//
+// Routine Description:
+//
+// This function enters a critical section.
+//
+// N.B. This function is duplicated in the runtime library.
+//
+// Arguments:
+//
+// CriticalSection (r.3) - Supplies a pointer to a critical section.
+//
+// Return Value:
+//
+// STATUS_SUCCESS is returned as the function value.
+//
+//--
+.extern ..RtlpWaitForCriticalSection
+.extern ..RtlpNotOwnerCriticalSection
+.extern ..RtlpUnWaitCriticalSection
+.extern ..DbgBreakPoint
+
+ .struct 0
+ .space StackFrameHeaderLength
+EcAddr: .space 4 // saved critical section address
+EcClient: .space 4 // saved ClientId
+ .space 4 // room for LR save
+ .align 3 // ensure 8 byte alignment
+EcFrameLength: // frame length
+
+//
+// RtlEnterCriticalSection has been performance optimized for the fast path
+// making it a leaf entry. When the slow path must be performed to acquire
+// a critical section a branch to a NESTED_ENTRY for unwinding purposes is
+// performed.
+//
+#if DBG
+ NESTED_ENTRY(RtlEnterCriticalSection,EcFrameLength,0,0)
+ PROLOGUE_END(RtlEnterCriticalSection)
+#else
+ LEAF_ENTRY(RtlEnterCriticalSection)
+#endif
+
+//
+// Attempt to enter the critical section.
+//
+ li r.10,CsLockCount // Constant for lwarx/stwcx. pairs
+
+res1failed:
+ lwarx r.8,r.10,r.3 // get addend value
+ addi r.8,r.8,1 // increment addend value
+ // copy updated value
+ stwcx. r.8,r.10,r.3 // store conditionally
+ bne- res1failed // if eq, store failed
+
+//
+// If the critical section is not already owned, then initialize the owner
+// thread id, initialize the recursion count, and return a success status.
+//
+
+ cmpwi cr.5,r.8,0
+ lwz r.4,TeClientId + 4(r.13)// get current thread unique id
+
+#if DBG
+ bne- cr.5,RtlpEnterCriticalSection.body // if ne, lock already owned
+ // NOTE: RtlEnterCriticalSection will
+ // NOT appear in a stack trace
+
+ lwz r.9,CsOwningThread(r.3) // get current owning thread
+ cmpwi cr.5,r.9,0
+ beq cr.5,thdidok // if eq, thread id is correct
+ bl ..DbgBreakPoint // break into debugger
+ // NOTE: RtlEnterCriticalSection will
+ // NOT appear in a stack trace
+thdidok:
+
+#else
+ bne- cr.5,..RtlpEnterCriticalSection // if ne, lock already owned
+ // NOTE: RtlEnterCriticalSection will
+ // NOT appear in a stack trace
+#endif
+
+ stw r.4,CsOwningThread(r.3) // set critical section owner
+ li r.3,STATUS_SUCCESS // set return status
+
+#if DBG
+ NESTED_EXIT(RtlEnterCriticalSection,EcFrameLength,0,0)
+#else
+ LEAF_EXIT(RtlEnterCriticalSection)
+#endif
+
+//
+// r.3 - Pointer to the critical section
+// r.4 - Current thread unique ID
+//
+ NESTED_ENTRY(RtlpEnterCriticalSection,EcFrameLength,0,0)
+ PROLOGUE_END(RtlpEnterCriticalSection)
+//
+// The critical section is owned. If the current thread is the owner, then
+// increment the recursion count, and return a success status. Otherwise,
+// wait for critical section ownership.
+//
+
+ lwz r.5,CsOwningThread(r.3) // get unique id of owner thread
+ cmpw r.5,r.4
+ bne waitforlock // if ne, current thread not owner
+
+ lwz r.5,CsRecursionCount(r.3)// increment the recursion count
+ addi r.5,r.5,1 //
+ stw r.5,CsRecursionCount(r.3)
+ li r.3,STATUS_SUCCESS // set return status
+ addi r.sp, r.sp, EcFrameLength
+ blr
+
+//
+// The critical section is owned by a thread other than the current thread.
+// Wait for ownership of the critical section.
+
+waitforlock:
+ stw r.4, EcClient(r.sp) // Save the client id
+ stw r.3, EcAddr(r.sp) // Save critical section address
+ bl ..RtlpWaitForCriticalSection
+ lwz r.4, EcClient(r.sp) // Restore client id
+ lwz r.5, EcAddr(r.sp) // Restore the critical section address
+ li r.3,STATUS_SUCCESS // set return status
+ stw r.4, CsOwningThread(r.5) // set critical section owner
+
+ NESTED_EXIT(RtlpEnterCriticalSection,EcFrameLength,0,0)
+
+
+// SBTTL("Leave Critical Section")
+//++
+//
+// NTSTATUS
+// RtlLeaveCriticalSection(
+// IN PRTL_CRITICAL_SECTION CriticalSection
+// )
+//
+// Routine Description:
+//
+// This function leaves a critical section.
+//
+// N.B. This function is duplicated in the runtime library.
+//
+// Arguments:
+//
+// CriticalSection (r.3) - Supplies a pointer to a critical section.
+//
+// Return Value:
+//
+// STATUS_SUCCESS is returned as the function value.
+//
+//--
+
+//
+// RtlLeaveCriticalSection has been performance optimized for the fast path
+// making it a leaf entry. When the slow path must be performed to acquire
+// a critical section a branch to a NESTED_ENTRY for unwinding purposes is
+// performed.
+//
+#if DBG
+ NESTED_ENTRY(RtlLeaveCriticalSection,EcFrameLength,0,0)
+ PROLOGUE_END(RtlLeaveCriticalSection)
+#else
+ LEAF_ENTRY(RtlLeaveCriticalSection)
+#endif
+
+ li r.10,CsLockCount // Constant for lwarx/stwcx. pairs
+ li r.9,0
+//
+// If the current thread is not the owner of the critical section, then
+// raise an exception.
+//
+
+#if DBG
+
+ lwz r.6,CsOwningThread(r.3) // get owning thread unique id
+ lwz r.4,TeClientId + 4(r.13) // get current thread unique id
+ cmpw r.4,r.6
+ beq+ owner // if eq, current thread is owner
+
+ bl ..RtlpNotOwnerCriticalSection // call RtlpNotOwnerCriticalSection
+ LWI(r.3,STATUS_INVALID_OWNER) // STATUS_INVALID_OWNER = 0xc000005a
+ b RtlLeaveCriticalSection.epi // return error code
+
+owner:
+
+#endif
+
+//
+// Decrement the recursion count. If the result is zero, then the lock
+// is no longer onwed.
+//
+
+ lwz r.5,CsRecursionCount(r.3) // decrement recursion count
+ subic. r.5,r.5,1 //
+ bge- stillowned // if gez, lock still owned
+ // predict branch not taken
+ stw r.9,CsOwningThread(r.3) // clear owner thread id
+
+//
+// Decrement the lock count and check if a waiter should be continued.
+//
+
+
+res2failed:
+ lwarx r.8,r.10,r.3 // get addend value
+ subi r.8,r.8,1 // decrement addend value
+ stwcx. r.8,r.10,r.3 // store conditionally
+ bne- res2failed // if eq, store failed
+
+ cmpwi cr.0,r.8,0
+
+#if DBG
+ blt+ nowaits // if ltz, no waiter present
+ // predict branch taken
+ bl ..RtlpUnWaitCriticalSection
+ b nowaits
+#else
+ bge- ..RtlpLeaveCriticalSection
+ // predict branch not taken
+ // NOTE: RtlLeaveCriticalSection will
+ // NOT appear in a stack trace
+ li r.3,STATUS_SUCCESS // set completion status
+ blr // return
+#endif
+
+//
+// Decrement the lock count and return a success status since the lock
+// is still owned.
+//
+
+stillowned:
+ stw r.5,CsRecursionCount(r.3)
+
+res3failed:
+ lwarx r.8,r.10,r.3 // get addend value
+ subi r.8,r.8,1 // decrement addend value
+ stwcx. r.8,r.10,r.3 // store conditionally
+ bne- res3failed // if eq, store failed
+
+nowaits:
+ li r.3,STATUS_SUCCESS // set completion status
+
+#if DBG
+ NESTED_EXIT(RtlLeaveCriticalSection,EcFrameLength,0,0)
+#else
+ LEAF_EXIT(RtlLeaveCriticalSection)
+
+//
+// r.3 - Pointer to the critical section
+//
+ NESTED_ENTRY(RtlpLeaveCriticalSection,EcFrameLength,0,0)
+ PROLOGUE_END(RtlpLeaveCriticalSection)
+
+ bl ..RtlpUnWaitCriticalSection
+ li r.3,STATUS_SUCCESS // set completion status
+
+ NESTED_EXIT(RtlpLeaveCriticalSection,EcFrameLength,0,0)
+#endif
+
+
+// SBTTL("Try to Enter Critical Section")
+//++
+//
+// BOOL
+// RtlTryEnterCriticalSection(
+// IN PRTL_CRITICAL_SECTION CriticalSection
+// )
+//
+// Routine Description:
+//
+// This function attempts to enter a critical section without blocking.
+//
+// Arguments:
+//
+// CriticalSection (r3) - Supplies a pointer to a critical section.
+//
+// Return Value:
+//
+// If the critical section was successfully entered, then a value of TRUE
+// is returned as the function value. Otherwise, a value of FALSE is returned.
+//
+//--
+
+ LEAF_ENTRY(RtlTryEnterCriticalSection)
+
+ li r6, CsLockCount // offset into critical section
+ lwz r5, TeClientId+4(r13) // get current thread unique id
+//
+// Attempt to enter the critical section.
+//
+
+tecs10:
+ lwarx r7, r6, r3 // get addend value - locked
+ addic. r8, r7, 1 // increment addend value
+ bne- tecs20 // jump if critical section owned
+ stwcx. r8, r6, r3 // store conditionally
+ bne- tecs10 // loop if store failed
+
+//
+// The critical section is now owned by this thread. Initialize the owner
+// thread id and return a successful status.
+//
+ stw r5, CsOwningThread(r3) // set critical section owner
+ li r3, TRUE // set success status
+ blr // return
+
+tecs20:
+
+//
+// The critical section is already owned. If it is owned by another thread,
+// return FALSE immediately. If it is owned by this thread, we must increment
+// the lock count here.
+//
+ lwz r7, CsOwningThread(r3) // get current owner
+ cmpw r7, r5 // same thread?
+ beq tecs30 // if eq, this thread is already the owner
+
+ li r3, FALSE // set failure status
+ blr // return
+
+tecs30:
+
+ lwz r4, CsRecursionCount(r3)
+
+//
+// This thread is already the owner of the critical section. Perform an atomic
+// increment of the LockCount and a normal increment of the RecursionCount and
+// return success.
+//
+
+tecs40:
+ lwarx r7, r6, r3 // get addend value - locked
+ addi r8, r7, 1 // increment addend value
+ stwcx. r8, r6, r3 // store conditionally
+ bne- tecs40 // loop if store failed
+
+//
+// Increment the recursion count
+//
+ addi r5, r4, 1
+ stw r5, CsRecursionCount(r3)
+
+ li r3, TRUE // set success status
+ LEAF_EXIT(RtlTryEnterCriticalSection) // return
diff --git a/private/ntos/dll/ppc/currteb.s b/private/ntos/dll/ppc/currteb.s
new file mode 100644
index 000000000..96b628039
--- /dev/null
+++ b/private/ntos/dll/ppc/currteb.s
@@ -0,0 +1,35 @@
+// TITLE("LdrInitializeThunk")
+//++
+//
+// Copyright (c) 1993 IBM Corporation
+//
+// Module Name:
+//
+// currteb.s
+//
+// Abstract:
+//
+// This module creates the function descriptor for the fast path
+// service call to get the current TEB address. This is isolated
+// because only positive service numbers go in the service table
+// and NtCurrentTeb uses a negative service number for system
+// call optimization.
+//
+//
+// Author:
+//
+// Chuck Bauman 29-Sep-1993
+//
+// Environment:
+//
+// User mode.
+//
+// Revision History:
+//
+//--
+
+#include "ksppc.h"
+
+ LEAF_ENTRY(NtCurrentTeb)
+ mr r.3, r.13 // Return the TEB which should be in r.13
+ LEAF_EXIT(NtCurrentTeb)
diff --git a/private/ntos/dll/ppc/ldrthunk.s b/private/ntos/dll/ppc/ldrthunk.s
new file mode 100644
index 000000000..0d214620c
--- /dev/null
+++ b/private/ntos/dll/ppc/ldrthunk.s
@@ -0,0 +1,108 @@
+// TITLE("LdrInitializeThunk")
+//++
+//
+// Copyright (c) 1989 Microsoft Corporation
+//
+// Module Name:
+//
+// ldrthunk.s
+//
+// Abstract:
+//
+// This module implements the thunk for the LdrpInitialize APC routine.
+//
+// Author:
+//
+// Chuck Bauman 20-Mar-1993
+//
+// Environment:
+//
+// Any mode.
+//
+// Revision History:
+//
+// Port NT product1 source to PowerPC 12-Aug-1993
+// Changed to nested function and added conversion of function
+// descriptor. Peter Johnston (plj@vnet.ibm.com) 18-Aug-1994
+//
+//--
+
+#include "ksppc.h"
+
+
+//++
+//
+// VOID
+// LdrInitializeThunk(
+// IN PVOID NormalContext,
+// IN PVOID SystemArgument1,
+// IN PVOID SystemArgument2
+// )
+//
+// Routine Description:
+//
+// This routine is called via APC and is the first code executed in
+// user mode for every user mode thread.
+//
+// On entry to this routine, the current stack frame is immediately
+// preceeded by a context record containing the initial state of the
+// new thread.
+//
+// This function computes a pointer to the context record on the stack
+// and calls LdrpInitialize with that pointer as its parameter.
+//
+// On return from LdrpInitialize, we convert the function descriptor
+// whose address is in the Context record Iar field from a pointer to
+// a function descriptor to the actual TOC and entry point values for
+// the thread.
+//
+// Arguments:
+//
+// NormalContext (r.3) - User Mode APC context parameter (ignored).
+//
+// SystemArgument1 (r.4) - User Mode APC system argument 1 (ignored).
+//
+// SystemArgument2 (r.5) - User Mode APC system argument 2 (ignored).
+//
+// Return Value:
+//
+// None.
+//
+//--
+
+ .extern ..LdrpInitialize
+
+ .struct 0
+ .space STK_MIN_FRAME
+LitLr: .space 4
+ .align 3
+LitFr1: .space STK_MIN_FRAME
+LitCx: .space ContextFrameLength
+ .align 3
+LitFrameLen:
+
+ SPECIAL_ENTRY(LdrInitializeThunk)
+ mflr r.0
+ stwu r.sp, -LitFr1(r.sp) // buy stack frame
+ addi r.3, r.sp, LitCx // compute context record addr
+ stw r.0, LitLr(r.sp) // save return address
+ PROLOGUE_END(LdrInitializeThunk)
+
+ bl ..LdrpInitialize // Jump to LdrpInitialize
+ lwz r.11, LitCx + CxGpr2(r.sp) // TOC set
+ cmpwi r.11, 0 // jif true context passed
+ // (e.g: fork)
+ lwz r.11, LitCx + CxIar(r.sp) // read fn descr from Cr Iar
+ lwz r.0, LitLr(r.sp) // get return address
+ bne truectx
+ lwz r.12, 4(r.11) // get toc
+ lwz r.11, 0(r.11) // get fn entry
+ stw r.12, LitCx + CxGpr2(r.sp) // set initial toc
+ stw r.11, LitCx + CxIar(r.sp) // set entry point
+
+truectx:
+ mtlr r.0 // restore return address
+
+ addi r.sp, r.sp, LitFr1 // free out stack frame
+ SPECIAL_EXIT(LdrInitializeThunk)
+
diff --git a/private/ntos/dll/ppc/sources b/private/ntos/dll/ppc/sources
new file mode 100644
index 000000000..2f9b87b04
--- /dev/null
+++ b/private/ntos/dll/ppc/sources
@@ -0,0 +1,6 @@
+PPC_DLLLIBOBJECTS=..\..\rtl\user\obj\ppc\chkstk.obj
+
+PPC_SOURCES=..\ppc\critsect.s \
+ ..\ppc\currteb.s \
+ ppc\usrstubs.s \
+ ..\ppc\ldrthunk.s