Shouldn't that be: =B('0000','1000','1100','1110','1111') ?
Excluding the zero length handling, I've already come across the
requirement to load 1-8 byte sign or unsigned integers.
I wrote a macro to do it, it does some extra stuff but in it's simplest
form, generates:
* R06 = address of source, R02 = length of source
TM FLAG,SIGNED Q. Signed numeric?
JO @0076GA Y. Use first half of jump table
AGHI R02,8 Unsigned uses second half of table
@0076GA DS 0H
AGHI R02,-1 Make length zero relative
SLL R02,2 Times 4 for jump table offset
LLGT R02,@0076GB(R02) Jump target for field length
BR R02 Branch to appropriate LOAD code
@0076GB DC 0A
DC A(@0076S1) Signed, length 1
DC A(@0076S2) Signed, halfword
DC A(@0076S3) Signed, length 3
DC A(@0076S4) Signed, fullword
DC A(@0076S5) Signed, length 5
DC A(@0076S6) Signed, length 6
DC A(@0076S7) Signed, length 7
DC A(@0076U8) Signed, doubleword (same as unsigned)
DC A(@0076U1) Unsigned, length 1
DC A(@0076U2) Unsigned, halfword
DC A(@0076U3) Unsigned, length 3
DC A(@0076U4) Unsigned, fullword
DC A(@0076U5) Unsigned, length 5
DC A(@0076U6) Unsigned, length 6
DC A(@0076U7) Unsigned, length 7
DC A(@0076U8) Unsigned, doubleword
@0076S1 DS 0H Length 1
LGB R00,0(,R06) Load byte, with sign extension
J @0076GC
@0076S2 DS 0H Length 2 (halfword)
LGH R00,0(,R06) Load halfword, with sign extension
J @0076GC
@0076S3 DS 0H Length 3
ICMH R00,B'1110',0(R06) Insert 3 bytes into top of high word
SRAG R00,R00,40 Shift down to low order 3 bytes
J @0076GC
@0076S4 DS 0H Length 4 (fullword)
LGF R00,0(,R06) Load fullword, with sign extension
J @0076GC
@0076S5 DS 0H Length 5
LBH R00,0(,R06) Load first byte into high word
L R00,1(,R06) Load remaining fullword into low word
J @0076GC
@0076S6 DS 0H Length 6
LHH R00,0(,R06) Load first halfword into high word
L R00,2(,R06) Load remaining fullword into low word
J @0076GC
@0076S7 DS 0H Length 7
ICMH R00,B'1110',0(R06) Insert first 3 bytes into high word
SRAG R00,R00,8 Shift down to bottom of word
L R00,3(,R06) Load remaining fullword into low word
J @0076GC
@0076U1 DS 0H Length 1
LLGC R00,0(,R06) Load byte into low-order byte
J @0076GC
@0076U2 DS 0H Length 2 (halfword)
LLGH R00,0(,R06) Load logical halfword
J @0076GC
@0076U3 DS 0H Length 3
SLGR R00,R00 Zero 8 bytes of LOAD register
ICM R00,B'0111',0(R06) Load 3-bytes
J @0076GC
@0076U4 DS 0H Length 4 (fullword)
LLGF R00,0(,R06) Load fullword
J @0076GC
@0076U5 DS 0H Length 5
LLCH R00,0(,R06) Load 1st byte into high word
L R00,1(,R06) Load remaining fullword into low word
J @0076GC
@0076U6 DS 0H Length 6
LLHH R00,0(,R06) Load first halfword into high word
L R00,2(,R06) Load remaining fullword into low word
J @0076GC
@0076U7 DS 0H Length 7
NIHH R00,X'00FF' Zero top byte of LOAD register
ICMH R00,B'0111',0(R06) Insert first 3 bytes into high word
L R00,3(,R06) Load remaining fullword into low word
J @0076GC
@0076U8 DS 0H Length 8 (doubleword)
LG R00,0(,R06) Load all 8 bytes into register
@0076GC DS 0H
Robert Ngan
CSC financial Services Group
IBM Mainframe Assembler List <[email protected]> wrote on
2015/06/16 17:54:44:
> From: Tony Harminc <[email protected]>
> To: [email protected]
> Date: 2015/06/16 17:56
> Subject: Elegant code to extract length+data fields? A small challenge.
> Sent by: IBM Mainframe Assembler List <[email protected]>
>
> Well, it's rather quiet around here...
>
> A common storage format for elements in database rows and the like is a
> fixed-length length field, followed by the data. Often there is an
overall
> length at the start, followed by repeated length/value pairs, and of
course
> there are other variations, including variable-length length fields. For
> example, RACF returns data with repeated {4-byte unaligned length, data}
> fields. In this case the data type is not encoded inline, but has to be
> known by reference to an external database template.
>
> So in the case of character data, it's very easy to use either MVCL or an
> executed MVC to extract the length, perhaps store it locally, copy the
> data, and increment the pointer in the row to the next length field. I
like
> MVCL for this despite its perhaps worse performance, because it's
elegant;
> everything is updated and ready to go for the next field by the MVCL
> itself.
>
> In the case of integer data, in RACF's case the length can be 0, 1, 2, 3,
> or 4, depending on the actual data value. In most cases one wants to
store
> this locally in a fullword, suitably zero extended on the left, rather
than
> in a variable length field. It seems to me the logical instruction to use
> is ICM, varying the mask based on the length field. But what's a method
> that is the right balance between easy to read and understand at a
glance,
> and efficient in instruction count, required setup, and even execution
> time? I've usually used an executed ICM with a literal table to translate
> length to mask - something like:
>
> L R15,0(,Rn) Get length (Rn -> current
length
> field)
> SR R1,R1 Prepare for ICM/default value
> IC R15,=X'000103070F'(R15) Map length to mask
> Do_ICM ICM R1,*-*,4(R14) This can/should be out of line
> instead
> EX R15,Do_ICM
> ST R1,Local_integer
> LA Rn,4(Rlen,Rn) -> next length field
>
> and of course this can be repeated or looped. Perhaps it looks nicer as
> =AL1(0,1,3,7,15), or even =B('0000','0001','0011','0111','1111).
>
> The challenges:
>
> 1) Improve on this snippet (elegance, efficiency, readability) for the
case
> above where the integers are always unsigned and 0-4 bytes. It doesn't
have
> to use ICM.
>
> 2) Mark a missing (0-length) integer as different from one with a *value
*of
> 0. Possibly set it to -1.
>
> 3) Make it work for signed (2's complement) integers of the above lengths
> so the result is a 2's complement fullword.
>
> 4) Extend it to work for length up to 8 bytes, storing the result in a
> doubleword. (Hmmm... no ICMG instruction.)
>
> Have fun...
>
> Tony H.