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.
93 lines
3.3 KiB
93 lines
3.3 KiB
#+
|
|
# Copyright 1991, Digital Equipment Corporation
|
|
#
|
|
# int ots_insv(char *addr, int position, unsigned size, int value)
|
|
#
|
|
# Arbitrary signed bitfield extraction
|
|
#
|
|
# 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 22 Sep 1992 KDG Add case-sensitive name
|
|
#
|
|
# 004 26 Jan 1993 KDG Add underscore
|
|
|
|
#include "ots_defs.hs"
|
|
|
|
# Totally general field insertion - arbitrary run-time field of 0-64 bits
|
|
# at an unknown alignment target.
|
|
#
|
|
# 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 _OtsFieldInsert
|
|
.ent _OtsFieldInsert
|
|
_OtsFieldInsert:
|
|
.set noat
|
|
.set noreorder
|
|
ble r18, noacc # check for zero size - no memory access
|
|
sra r17, 3, r27 # get byte part of bit offset (signed!)
|
|
addq r16, r27, r16 # add to initial base addr.
|
|
and r17, 7, r17 # get bit-in-byte from bit offset
|
|
and r16, 7, r27 # get byte-in-quadword (must be clean for cmpule)
|
|
s8addq r27, r17, r17 # form the true bit offset in the quadword
|
|
ldq_u r28, (r16) # load first or only quadword
|
|
addq r17, r18, r27 # get bit offset of bit following field
|
|
cmpule r27, 64, r0 # if <=64, field is contained in 1 quadword
|
|
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)
|
|
not r31, r1 # all ones
|
|
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
|
|
bic r28, r1, r28 # clear the bits...
|
|
bis r28, r19, r28 # insert them
|
|
stq_u r28, (r16) # put the value back...
|
|
noacc: ret r31, (r26)
|
|
double: ldq_u r1, 8(r16) # load the 2nd quadword (early for better sched.)
|
|
not r31, r0 # all ones
|
|
sll r0, r17, r0 # get mask in correct place
|
|
sll r19, r17, r17 # get insert value to top of register
|
|
bic r28, r0, r28 # clear bits in target
|
|
bis r28, r17, r28 # merge the field in
|
|
negq r18, r0 #
|
|
srl r1, r27, r1 # clear bits in target
|
|
sll r19, r0, r19 # shift to high bits
|
|
negq r27, r0 #
|
|
srl r19, r0, r19 # and into position
|
|
sll r1, r27, r1 #
|
|
bis r1, r19, r1 # merge
|
|
stq_u r28, (r16) # store the first word
|
|
stq_u r1, 8(r16) # store back
|
|
ret r31, (r26)
|
|
|
|
.set at
|
|
.set reorder
|
|
.end _OtsFieldInsert
|