406 lines
8.6 KiB
ArmAsm
406 lines
8.6 KiB
ArmAsm
// 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
|
||
|