Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

101 lines
4.3 KiB

#++
# Copyright 1991, Digital Equipment Corporation
#
# int ots_extzv_vol(char *addr, int position, unsigned size)
#
# Arbitrary unsigned bitfield extraction for volatile cases
#
# Special conventions: No stack space, r0, r16-r18 and r26-r28 ONLY,
# no linkage pointer required.
# (Warning: The auto-loader potentially takes some regs across
# the call if this is being used in a shared lib. environment.)
#
# See also: ots_extv_vol (just uses sra in place of srl in some cases...)
#
# 001 16 Aug 1991 KDG Initial version
#
# 002 4 Sep 1991 KDG Bugfix/improvements
#
# 003 19 May 1992 KDG Changes for common VMS/OSF sources
#
# 004 6 Oct 1992 KDG Initial volatile version (just add longword
# test)
#
# 005 10 Oct 1992 KDG Case-sensitive name
#
# 006 26 Jan 1993 KDG Add underscore
#
# 007 1 Sep 1994 RBG Fix aligned longword case
# check for bit 0 within byte GEM_BUGS #3545
#include "ots_defs.hs"
#
# Totally general field extract - arbitrary run-time field of 0-64 bits
# at an unknown alignment target.
#
# This volatile version always uses exactly LDL for aligned 32 bit field
# extracts, and quadword operations for all other.
#
# Conceptually, this operation takes a 67 bit bit-address, which is the sum
# of a byte-aligned memory address and the bit offset (which is signed).
#
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|Q|L|W|B|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
# | | | | | | | | | | | | | | | | | | | | | | | | | | |.|.|.|b|b|b|
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#
# Inputs:
# r16 - input address
# r17 - input bit offset
# r18 - input size
#
# This is based on the code GEM generates when not using an out-of-line
# routine.
#
.globl _OtsFieldExtractUnsignedVolatile
.ent _OtsFieldExtractUnsignedVolatile
_OtsFieldExtractUnsignedVolatile:
.set noat
.set noreorder
.frame sp,0,r26
.prologue 0
sra r17, 3, r27 # get byte part of bit offset (signed!)
ble r18, zero # check for zero size - no memory access
cmpeq r17, 32, r0 # exactly longword size?
addq r16, r27, r16 # add to initial base addr.
and r16, 3, r28 # aligned longword?
cmpult r28, r0, r28 # true if ((addr & 3) == 0) && (size == 32) && ...
and r17, 7, r17 # get bit-in-byte from bit offset
cmpult r17, r28, r28 # ... && (bit_in_byte == 0)
bne r28, longwd # go handle longword case specially
ldq_u r0, (r16) # start load first or only quadword
and r16, 7, r27 # get byte-in-quadword of first bit
s8addq r27, r17, r17 # form the true bit offset in the quadword
addq r17, r18, r27 # get bit offset of bit following field
cmpule r27, 64, r28 # if <=64, field is contained in 1 quadword
beq r28, double # handle double case if not
# common case - fall through, load result hopefully already available
single: negq r27, r27 # <5:0> = bits for right shift
sll r0, r27, r0 # move to high bits
addq r27, r17, r27 # bits for left shift
srl r0, r27, r0 # and shift into final position
ret r31, (r26)
double: ldq_u r28, 8(r16) # load second quadword
srl r0, r27, r0 # move top piece over
negq r27, r27 # get shift bits for piece in 2nd word
sll r28, r27, r28 # move field in 2nd lw to high bits
bis r0, r28, r0 # form final value
negq r18, r27 # <5:0> = bits for right shift
srl r0, r27, r0 # and shift into final position
ret r31, (r26)
zero: mov 0, r0 # zero-sized field extracts return 0
ret r31, (r26)
longwd: ldl r0, (r16) # load sign-extended aligned longword
zapnot r0, 15, r0
ret r31, (r26)
.set at
.set reorder
.end _OtsFieldExtractUnsignedVolatile