windows-nt/Source/XPSP1/NT/base/ntos/ke/alpha/xxalign.s
2020-09-26 16:20:57 +08:00

406 lines
8.6 KiB
ArmAsm
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// TITLE("Alignment emulation")
//++
//
//
// Copyright (c) 1992 Digital Equipment Corporation
//
// Module Name:
//
// align.s
//
// Abstract:
//
// This module implements the code to complete unaligned access
// emulation.
//
// Author:
//
// Joe Notarangelo 14-May-1992
//
// Environment:
//
// Kernel mode only.
//
// Revision History:
//
//--
#include "ksalpha.h"
//++
//
// UQUAD
// KiEmulateLoadLong(
// IN PULONG UnalignedAddress
// )
//
// Routine Description:
//
// This routine returns the longword value stored at the unaligned
// address passed in UnalignedAddress.
//
// Arguments:
//
// UnalignedAddress(a0) - Supplies a pointer to long data value.
//
// Return Value:
//
// The longword value at the address pointed to by UnalignedAddress.
//
//--
LEAF_ENTRY(KiEmulateLoadLong)
ldq_u t0, 0(a0) // get 1st quadword
ldq_u v0, 3(a0) // get 2nd quadword
extll t0, a0, t0 // extract bytes from low quadword
extlh v0, a0, v0 // extract bytes from high quadword
bis v0, t0, v0 // v0 = longword
addl v0, zero, v0 // insure canonical longword form
ret zero, (ra) // return
.end KiEmulateLoadLong
//++
//
// UQUAD
// KiEmulateLoadQuad(
// IN PUQUAD UnalignedAddress
// )
//
// Routine Description:
//
// This routine returns the quadword value stored at the unaligned
// address passed in UnalignedAddress.
//
// Arguments:
//
// UnalignedAddress(a0) - Supplies a pointer to quad data value.
//
// Return Value:
//
// The quadword value at the address pointed to by UnalignedAddress.
//
//--
LEAF_ENTRY(KiEmulateLoadQuad)
ldq_u t0, 0(a0) // get 1st quadword
ldq_u v0, 7(a0) // get 2nd quadword
extql t0, a0, t0 // extract bytes from low quadword
extqh v0, a0, v0 // extract bytes from high quadword
bis v0, t0, v0 // v0 = longword
ret zero, (ra) // return
.end KiEmulateLoadQuad
//++
//
// VOID
// KiEmulateStoreLong(
// IN PULONG UnalignedAddress
// IN UQUAD Data
// )
//
// Routine Description:
//
// This routine stores the longword in Data to the UnalignedAddress.
//
// Arguments:
//
// UnalignedAddress(a0) - Supplies a pointer to longword destination.
// Data(a1) - Supplies data value to store.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiEmulateStoreLong)
ldq_u t0, 0(a0) // get 1st quadword
ldq_u t1, 3(a0) // get 2nd quadword
inslh a1, a0, t2 // get bytes for high quadword
insll a1, a0, t3 // get bytes for low quadword
msklh t1, a0, t1 // clear corresponding bytes
mskll t0, a0, t0 // clear corresponding bytes
bis t1, t2, t1 // merge in bytes for high qw
bis t0, t3, t0 // merge in bytes for low qw
stq_u t1, 3(a0) // must store high first in case
stq_u t0, 0(a0) // address was actually aligned
ret zero, (ra) // return
.end KiEmulateStoreLong
//++
//
// VOID
// KiEmulateStoreQuad(
// IN PUQUAD UnalignedAddress
// IN UQUAD Data
// )
//
// Routine Description:
//
// This routine stores the quadword in Data to the UnalignedAddress.
//
// Arguments:
//
// UnalignedAddress(a0) - Supplies a pointer to quadword destination.
// Data(a1) - Supplies the data value to store.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiEmulateStoreQuad)
ldq_u t0, 0(a0) // get 1st quadword
ldq_u t1, 7(a0) // get 2nd quadword
insqh a1, a0, t2 // get bytes for high quadword
insql a1, a0, t3 // get bytes for low quadword
mskqh t1, a0, t1 // clear corresponding bytes
mskql t0, a0, t0 // clear corresponding bytes
bis t1, t2, t1 // merge in bytes for high qw
bis t0, t3, t0 // merge in bytes for low qw
stq_u t1, 7(a0) // must store high first in case
stq_u t0, 0(a0) // address was actually aligned
ret zero, (ra) // return
.end KiEmulateStoreQuad
//++
//
// UQUAD
// KiEmulateLoadFloatIEEESingle(
// IN PULONG UnalignedAddress
// )
//
// Routine Description:
//
// This routine returns the IEEE Single value stored at the unaligned
// address passed in UnalignedAddress.
//
// N.B. The value is returned as the memory format T-formatted
// interpretation of the read S-format value.
//
// Arguments:
//
// UnalignedAddress(a0) - Supplies a pointer to float single data.
//
// Return Value:
//
// The single float value at the address pointed to by UnalignedAddress.
//
//--
.struct 0
FlTemp: .space 8 // temporary memory
.space 8 // filler for alignment
FlFrameLength: // length of stack frame
NESTED_ENTRY(KiEmulateLoadFloatIEEESingle, FlFrameLength, zero)
lda sp, -FlFrameLength(sp) // allocate temp space
PROLOGUE_END
//
// get the value into an integer register
//
ldq_u t0, 0(a0) // get 1st quadword
ldq_u v0, 3(a0) // get 2nd quadword
extll t0, a0, t0 // extract bytes from low quadword
extlh v0, a0, v0 // extract bytes from high quadword
bis v0, t0, v0 // v0 = longword
//
// v0 now is S memory format, however return from exception
// sequence will restore floating registers as T memory format
// convert v0 to T memory format
stl v0, FlTemp(sp) // store bytes, S-mem-format
lds f0, FlTemp(sp) // now S-reg-format
stt f0, FlTemp(sp) // write as T-mem-format
ldq v0, FlTemp(sp) // return as T-mem_format
lda sp, FlFrameLength(sp) // deallocate stack frame
ret zero, (ra) // return
.end KiEmulateLoadFloatIEEESingle
//++
//
// UQUAD
// KiEmulateLoadFloatIEEEDouble(
// IN PUQUAD UnalignedAddress
// )
//
// Routine Description:
//
// This routine returns the quadword value stored at the unaligned
// address passed in UnalignedAddress.
//
// Arguments:
//
// UnalignedAddress(a0) - Supplies a pointer to double float data value.
//
// Return Value:
//
// The double float value at the address pointed to by UnalignedAddress.
//
//--
LEAF_ENTRY(KiEmulateLoadFloatIEEEDouble)
ldq_u t0, 0(a0) // get 1st quadword
ldq_u v0, 7(a0) // get 2nd quadword
extql t0, a0, t0 // extract bytes from low quadword
extqh v0, a0, v0 // extract bytes from high quadword
bis v0, t0, v0 // v0 = longword
ret zero, (ra) // return
.end KiEmulateLoadFloatIEEEDouble
//++
//
// VOID
// KiEmulateStoreFloatIEEESingle(
// IN PULONG UnalignedAddress
// IN UQUAD Data
// )
//
// Routine Description:
//
// This routine stores the float value in Data to the UnalignedAddress.
//
// Arguments:
//
// UnalignedAddress(a0) - Supplies a pointer to float destination.
// Data(a1) - Supplies the data value to store.
//
// Return Value:
//
// None.
//
//--
.struct 0
FsTemp: .space 8 // temporary memory
.space 8 // filler for alignment
FsFrameLength: // length of stack frame
NESTED_ENTRY(KiEmulateStoreFloatIEEESingle, FsFrameLength, zero)
lda sp, -FsFrameLength(sp) // allocate stack space
PROLOGUE_END
//
// a1 is an integer version of the T-memory format
// convert it to integer version of S-memory format
//
stq a1, FsTemp(sp) // store bytes, T-mem-format
ldt f10, FsTemp(sp) // load back in now in S-reg-format
sts f10, FsTemp(sp) // now in S-mem-format
ldl a1, FsTemp(sp) // now integer version of S-mem
//
// now problem is just to store an unaligned longword
//
ldq_u t0, 0(a0) // get 1st quadword
ldq_u t1, 3(a0) // get 2nd quadword
inslh a1, a0, t2 // get bytes for high quadword
insll a1, a0, t3 // get bytes for low quadword
msklh t1, a0, t1 // clear corresponding bytes
mskll t0, a0, t0 // clear corresponding bytes
bis t1, t2, t1 // merge in bytes for high qw
bis t0, t3, t0 // merge in bytes for low qw
stq_u t1, 3(a0) // must store high first in case
stq_u t0, 0(a0) // was actually aligned
lda sp, FsFrameLength(sp) // restore stack frame
ret zero, (ra) // return
.end KiEmulateStoreFloatIEEESingle
//++
//
// VOID
// KiEmulateStoreFloatIEEEDouble(
// IN PUQUAD UnalignedAddress
// IN UQUAD Data
// )
//
// Routine Description:
//
// This routine stores the quadword in Data to the UnalignedAddress.
//
// Arguments:
//
// UnalignedAddress(a0) - Supplies a pointer to double float destination.
// Data(a1) - Supplies the data value to store.
//
// Return Value:
//
// None.
//
//--
LEAF_ENTRY(KiEmulateStoreFloatIEEEDouble)
ldq_u t0, 0(a0) // get 1st quadword
ldq_u t1, 7(a0) // get 2nd quadword
insqh a1, a0, t2 // get bytes for high quadword
insql a1, a0, t3 // get bytes for low quadword
mskqh t1, a0, t1 // clear corresponding bytes
mskql t0, a0, t0 // clear corresponding bytes
bis t1, t2, t1 // merge in bytes for high qw
bis t0, t3, t0 // merge in bytes for low qw
stq_u t1, 7(a0) // must store high first in case
stq_u t0, 0(a0) // was actually aligned
ret zero, (ra) // return
.end KiEmulateStoreFloatIEEEDouble