windows-nt/Source/XPSP1/NT/base/ntos/lpc/alpha/lpcmove.s

191 lines
5.9 KiB
ArmAsm
Raw Normal View History

2020-09-26 03:20:57 -05:00
// TITLE("LPC Move Message Support")
//++
//
// Copyright (c) 1990 Microsoft Corporation
// Copyright (c) 1992 Digital Equipment Corporation
//
// Module Name:
//
// lpcmove.s
//
// Abstract:
//
// This module implements functions to support the efficient movement of
// LPC Message blocks.
//
// Author:
//
// David N. Cutler (davec) 11-Apr-1990
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
//
// Thomas Van Baak (tvb) 19-May-1992
//
// Adapted for Alpha AXP.
//
//--
#include "ksalpha.h"
SBTTL("Move Message")
//++
//
// VOID
// LpcpMoveMessage (
// OUT PPORT_MESSAGE DstMsg
// IN PPORT_MESSAGE SrcMsg
// IN PUCHAR SrcMsgData
// IN ULONG MsgType OPTIONAL,
// IN PCLIENT_ID ClientId OPTIONAL
// )
//
// Routine Description:
//
// This function moves an LPC message block and optionally sets the message
// type and client id to the specified values.
//
// Arguments:
//
// DstMsg (a0) - Supplies a pointer to the destination message.
//
// SrcMsg (a1) - Supplies a pointer to the source message.
//
// SrcMsgData (a2) - Supplies a pointer to the source message data to
// copy to destination.
//
// MsgType (a3) - If non-zero, then store in type field of the destination
// message.
//
// ClientId (a4) - If non-NULL, then points to a ClientId to copy to
// the destination message.
//
// N.B. The messages are assumed to be quadword aligned.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(LpcpMoveMessage)
ldq t0, PmLength(a1) // load first quadword of source
//
// The message length is in the low word of the first quadword.
//
addq t0, 3, t1 // round length to
bic t1, 3, t0 // nearest 4-byte multiple
//
// The message type is in the low half of the high longword. If a message
// type was specified, use it instead of the message type in the source
// message.
//
sll a3, 32, t2 // shift message type into position
zap t0, 0x30, t3 // clear message type field
or t3, t2, t1 // merge into new field
cmovne a3, t1, t0 // if a3!=0 use new message field
stq t0, PmLength(a0) // store first quadword of destination
//
// The client id is the third and fourth items. If a client id was
// specified, use it instead of the client id in the source message.
//
lda t3, PmClientId(a1) // get address of source client id
cmovne a4, a4, t3 // if a4!=0, use client id address in a4
//
// Move the process and thread ids into place. Note that for axp32, (t3) isn't
// necessarily quadword aligned.
//
LDP t2, CidUniqueProcess(t3)// load low part of client id
LDP t1, CidUniqueThread(t3) // load high part of client id
STP t2, PmProcess(a0) // store third longword of destination
STP t1, PmThread(a0) // store fourth longword of destination
#if defined(_AXP64_)
//
// Copy MessageId and ClientViewSize.
//
ldl t2,PmMessageId(a1)
stl t2,PmMessageId(a0)
ldq t2,PmClientViewSize(a1)
stq t2,PmClientViewSize(a0)
#else
//
// PmClientViewSize is adjacent to PmMessageId, both can be moved at once
// with a single quadword move.
//
ldq t2,PmMessageId(a1) // get next quadword of source
stq t2,PmMessageId(a0) // set next quadword of destination
#endif
and t0, 0xfff8, t3 // isolate quadword move count
beq t3,20f // if eq, no quadwords to move
and a2, 7, t1 // check if source is quadword aligned
bne t1, UnalignedSource // if ne, not quadword aligned
//
// Source and destination are both quadword aligned, use ldq/stq. Use of
// the constant "PortMessageLength-8" is used in lieu of an additional
// instruction to increment a0 by that amount before entering the copy
// loop.
//
5: ldq t1, 0(a2) // get source qword
ADDP a0, 8, a0 // advance destination address
ADDP a2, 8, a2 // advance source address
subq t3, 8, t3 // decrement number of bytes remaining
stq t1, PortMessageLength-8(a0) // store destination qword
bne t3, 5b // if ne, more quadwords to store
br zero, 20f // move remaining longword
//
// We know that the destination is quadword aligned, but the source is
// not. Use ldq_u to load the low and high parts of the source quadword,
// merge them with EXTQx and store them as one quadword.
//
// By reusing the result of the second ldq_u as the source for the
// next quadword's EXTQL we end up doing one ldq_u/stq for each quadword,
// regardless of the source's alignment.
//
UnalignedSource: //
ldq_u t1, 0(a2) // prime t1 with low half of qword
10: extql t1, a2, t2 // t2 is aligned low part
ADDP a0, 8, a0 // advance destination address
subq t3, 8, t3 // reduce number of bytes remaining
ldq_u t1, 7(a2) // t1 has high part
extqh t1, a2, t4 // t4 is aligned high part
ADDP a2, 8, a2 // advance source address
bis t2, t4, t5 // merge high and low parts
stq t5, PortMessageLength-8(a0) // store result
bne t3, 10b // if ne, more quadwords to move
//
// Move remaining longword (if any)
//
20: and t0, 4, t0 // check if longword to move
beq t0, 50f // if eq, no longword to move
ldl t1, 0(a2) // move last longword to move
stl t1, PortMessageLength(a0) //
50: ret zero, (ra) // return
.end LpcpMoveMessage