mirror of https://github.com/lianthony/NT4.0
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.
137 lines
6.4 KiB
137 lines
6.4 KiB
#+
|
|
# Copyright 1991, Digital Equipment Corporation
|
|
#
|
|
# int ots_insv_vol(char *addr, int position, unsigned size, int value)
|
|
#
|
|
# Arbitrary signed bitfield extraction for volatile cases
|
|
#
|
|
# Special conventions: No stack space, r0-r1, r16-r19 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_ext[z]v
|
|
#
|
|
# 001 5 Sep 1991 KDG Initial version
|
|
#
|
|
# 002 19 May 1992 KDG Changes for common VMS/OSF sources
|
|
#
|
|
# 003 5 Oct 1992 KDG Initial volatile version based on non-volatile
|
|
# version
|
|
#
|
|
# 004 10 Nov 1992 KDG Case-sensitive name
|
|
#
|
|
# 005 26 Jan 1993 KDG Add underscore
|
|
#
|
|
# 006 1 Sep 1994 RBG Fix aligned longword and quadword cases,
|
|
# check for bit 0 within byte GEM_BUGS #3545
|
|
|
|
#include "ots_defs.hs"
|
|
|
|
# Totally general field insertion - arbitrary run-time field of 0-64 bits
|
|
# at an unknown alignment target.
|
|
#
|
|
# Volatile/byte granularity version notes:
|
|
#
|
|
# - Aligned quadword stores must be done using exactly STQ
|
|
#
|
|
# - Aligned longword stores must be done using exactly STL
|
|
#
|
|
# - All other stores must be done using LDx_L/STx_C to avoid
|
|
# corrupting any adjacent data and provide atomic updates
|
|
# for aligned data
|
|
#
|
|
# The first two items are required in case this routine is called for
|
|
# volatile references so that I/O space accesses are handled correctly.
|
|
# (Normally, those references are handled in-line, but if for some
|
|
# reason they wind up coming through here, they must still be correct.)
|
|
#
|
|
# 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
|
|
# r19 - input value
|
|
#
|
|
# This is based on the code GEM generates when not using an out-of-line
|
|
# routine, though it has better by-hand register packing to allow
|
|
# multiple issue.
|
|
#
|
|
.globl _OtsFieldInsertVolatile
|
|
.ent _OtsFieldInsertVolatile
|
|
_OtsFieldInsertVolatile:
|
|
.set noat
|
|
.set noreorder
|
|
sra r17, 3, r27 # get byte part of bit offset (signed!)
|
|
ble r18, noacc # check for zero size - no memory access
|
|
cmpeq r18, 32, r28 # Aligned longword(1) - is the size exactly 32b?
|
|
addq r16, r27, r16 # add to initial base addr.
|
|
and r16, 3, r27 # check for special case of an aligned longword
|
|
cmpult r27, r28, r28 # Aligned longword(2) - byte 0 within longword
|
|
and r17, 7, r17 # get bit-in-byte from bit offset
|
|
cmpult r17, r28, r28 # Aligned longword(3) - bit 0 within byte
|
|
cmpeq r18, 64, r0 # Aligned quadword(1) - is the size exactly 64b?
|
|
and r16, 7, r27 # get byte-in-quadword (must be clean for cmpule)
|
|
bne r28, longwd # if aligned longword, store exactly a longword using stl
|
|
cmpult r27, r0, r0 # Aligned quadword(2) - byte 0 within quadword
|
|
cmpult r17, r0, r0 # Aligned quadword(3) - bit 0 within byte
|
|
s8addq r27, r17, r17 # form the true bit offset in the quadword
|
|
bne r0, quadwd # if aligned quadword, store exactly a quadword using stq
|
|
addq r17, r18, r27 # get bit offset of bit following field
|
|
cmpule r27, 64, r0 # if <=64, field is contained in 1 quadword
|
|
bic r16, 7, r16 # clear unaligned bits in address for locked operations
|
|
not r31, r1 # all ones
|
|
beq r0, double # handle double case if not
|
|
# Common case of field in single QW - fall through
|
|
negq r27, r27 # <5:0> = bits for right shift
|
|
addq r27, r17, r0 # bits for left shift (wordlength-is)
|
|
sll r1, r0, r1 # shift mask to high bits
|
|
sll r19, r0, r19 # shift source to high bits (hand interleaving for better sched)
|
|
srl r1, r27, r1 # and into position
|
|
srl r19, r27, r19 # and into position
|
|
sinrty: ldq_l r28, (r16) # load first or only quadword
|
|
bic r28, r1, r28 # clear the bits...
|
|
bis r28, r19, r28 # insert them
|
|
stq_c r28, (r16) # put the value back...
|
|
blbc r28, sinfl # check for failing interlock/retry
|
|
noacc: ret r31, (r26)
|
|
|
|
double:
|
|
sll r1, r17, r0 # get mask in correct place
|
|
sll r19, r17, r17 # get insert value to top of register
|
|
negq r18, r1 #
|
|
sll r19, r1, r19 # shift to high bits
|
|
negq r27, r1 #
|
|
srl r19, r1, r19 # and into position
|
|
firrty: ldq_l r28, (r16) # load first or only quadword
|
|
bic r28, r0, r28 # clear bits in target
|
|
bis r28, r17, r28 # merge the field in
|
|
stq_c r28, (r16) # store the first word
|
|
blbc r28, firfl # check for failing interlock/retry
|
|
secrty: ldq_l r28, 8(r16) # load the 2nd quadword
|
|
srl r28, r27, r28 # clear bits in target
|
|
sll r28, r27, r28 #
|
|
bis r28, r19, r28 # merge
|
|
stq_c r28, 8(r16) # store back
|
|
blbc r28, secfl # check for failing interlock/retry
|
|
ret r31, (r26)
|
|
longwd: stl r19, (r16) # store aligned longword
|
|
ret r31, (r26)
|
|
quadwd: stq r19, (r16) # store aligned quadword
|
|
ret r31, (r26)
|
|
# out-of-line retry cases
|
|
sinfl: br r31, sinrty # re-try the locked operation for the single case
|
|
firfl: br r31, firrty # re-try the locked operation for the 1st part of the two-part case
|
|
secfl: br r31, secrty # re-try the locked operation for the 2nd part of the two-part case
|
|
|
|
.set at
|
|
.set reorder
|
|
.end _OtsFieldInsertVolatile
|