.TOC "VFIELD.MIC -- Variable-Length Bit Field Instructions" .TOC "Revision 2.2" ; Bob Supnik .nobin ;**************************************************************************** ;* * ;* COPYRIGHT (c) 1988, 1989, 1990 BY * ;* DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETTS. * ;* ALL RIGHTS RESERVED. * ;* * ;* THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPIED * ;* ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE AND WITH THE * ;* INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTHER * ;* COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY * ;* OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HEREBY * ;* TRANSFERRED. * ;* * ;* THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE * ;* AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT * ;* CORPORATION. * ;* * ;* DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF ITS * ;* SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL. * ;* * ;**************************************************************************** .TOC " Revision History" ; Edit Date Who Description ; ---- --------- --- --------------------- ; 2 16-Jan-90 RMS Editorial changes. ; 1 21-Dec-89 RMS Fixed bug in INSV register. ; (2)0 16-Nov-89 RMS Revised for simplified decoder. ; 5 13-Nov-89 RMS Editorial changes. ; 4 13-Oct-89 RMS Documented ADR forwarding restriction. ; 3 08-Jul-89 RMS Moved SC load out of harms way. ; 2 05-Jul-89 RMS Moved state flag clear out of harms way. ; 1 02-Jul-89 RMS Editorial changes. ; (1)0 12-Jun-89 RMS Revised right shifts and for release to CMS. ; 3 11-Jun-89 RMS Revised register extract algorithm. ; 2 03-Feb-89 RMS Revised for new microbranch latencies. ; 1 10-Jan-89 RMS Revised for new microarchitecture. ; (0)0 12-Oct-88 RMS First edit for Raven. .bin ;= BEGIN VFIELD .nobin ; This module implements the variable-length bit field class instructions. ; The instructions in this class are: ; ; Opcode Instruction N Z V C Exceptions ; ------ ----------- ------- ---------- ; ; EC CMPV pos.rl, size.rb, base.vb, {field.rv}, src.rl * * 0 * rsv ; ED CMPZV pos.rl, size.rb, base.vb, {field.rv}, src.rl * * 0 * rsv ; ; EE EXTV pos.rl, size.rb, base.vb, {field.rv}, dst.wl * * 0 - rsv ; EF EXTZV pos.rl, size.rb, base.vb, {field.rv}, dst.wl * * 0 - rsv ; ; EB FFC startpos.rl, size.rb, base.vb, {field.rv}, findpos.wl 0 * 0 0 rsv ; EA FFS startpos.rl, size.rb, base.vb, {field.rv}, findpos.wl 0 * 0 0 rsv ; ; F0 INSV src.rl, pos.rl, size.rb, base.vb, {field.wv} - - - - rsv ; .TOC " FFS, FFC, CMPV, CMPZV, EXTV, EXTZV" ; These instructions find the first set/clear bit in, compare an operand to, or ; extract, a variable-length bit field. ; ; Mnemonic Opcode Operation Spec AT/DL CC Dispatch BCOND ; -------- ------ --------- ---- ----- -- -------- ----- ; FFS EA dst.wl <-- first one in 4 rrvw/lbbl iiii FFS -- ; field(pos.rl, size.rb, base.vb) ; FFC EB dst.wl <-- first zero in 4 rrvw/lbbl iiii FFC -- ; field(pos.rl, size.rb, base.vb) ; ; CMPV EC sext{field(pos.rl, size.rb, base.vb)} - 4 rrvr/lbbl jizj CMPV -- ; src2.rl ; CMPZV ED zext{field(pos.rl, size.rb, base.vb)} - 4 rrvr/lbbl jizj CMPZV -- ; src2.rl ; ; EXTV EE dst.wl <-- 4 rrvw/lbbl iiip EXTV -- ; sext{field(pos.rl, size.rb, base.vb)} ; EXTZV EF dst.wl <-- 4 rrvw/lbbl iiip EXTZV -- ; zext{field(pos.rl, size.rb, base.vb)} ; ; Entry conditions from specifier flows: ; ; W0 = first (position) operand ; W2 = second (size) operand ; W5'W4 = third (base) operand, if register ; W4 = address of third (base) operand, if memory ; W6 = fourth (src2) operand, if CMPxV memory ; W6 = VA = address of fourth (dst) operand, if EXTxV, FFx memory ; RN = register number of fourth specifier ; DL = data length of fourth operand (longword) ; STATE<2> = 1 if field in register ; = 0 if field in memory ; ; Exit conditions (EXTV, EXTZV, FFS, FFC): ; The PSL condition codes are set. ; The result has been stored in the destination memory location or register. ; (CMPV, CMPZV): ; The PSL condition codes are set. ; ; Condition codes: ; (FFS, FFC) (CMPV, CMPZV) (EXTV, EXTZV) ; N <-- 0 N <-- field LSS src2 N <-- dst LSS 0 ; Z <-- {bit not found} Z <-- field EQL src2 Z <-- dst EQL 0 ; V <-- 0 V <-- 0 V <-- 0 [Integer overflow trap disabled.] ; C <-- 0 C <-- field LSSU src2 C <-- C ; ; Tradeoffs: ; Consolidated entry points save 14 microwords but cost a cycle in EXTxV. ; .bin ; CMPV, CMPZV operation: ; ; sext (zext){field(pos.rl, size.rb, base.vb)} - src2.rl CMPV: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 ;---------------------------------------; [W3] <-- SEXT [W3] LSH (SC 1-32), LONG, ; [10] right justify and sign extend field GOTO [CMPV.EXIT] ; join common code CMPV.R: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 ;---------------------------------------; [W3] <-- SEXT [W3] LSH (SC 1-32), LONG, ; [8] right justify and sign extend field GOTO [CMPV.R.EXIT] ; join common code CMPZV: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 ;---------------------------------------; [W3] <-- ZEXT [W3] LSH (SC 1-32), LONG ; [10] right justify and zero extend field CMPV.EXIT: ;---------------------------------------; [WBUS] <-- (-[W6] + [W3]), LONG, ; [11] compare field to src2 SET PSL CC (JIZJ), ; set psl cc's, psl map is jizj LAST CYCLE ; decode next instruction CMPZV.R: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 ;---------------------------------------; [W3] <-- ZEXT [W3] LSH (SC 1-32), LONG ; [8] right justify and zero extend field CMPV.R.EXIT: ;---------------------------------------; [WBUS] <-- (-[Rrn] + [W3]), LONG, ; [9] compare field to src2 SET PSL CC (JIZJ), ; set psl cc's, psl map is jizj LAST CYCLE ; decode next instruction ; EXTV, EXTZV operation: ; ; dst.wl <-- sext (zext){field(pos.rl, size.rb, base.vb)} EXTV: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 ;---------------------------------------; MEM (VA)&, [WDR] <-- SEXT [W3] LSH (SC 1-32), ; [10] right justify and LONG, ; sign extend field SET PSL CC (IIIP), ; set psl cc's, psl map is iiip SET NORETRY, ; set disable retry flag LAST CYCLE ; decode next instruction EXTV.R: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 ;---------------------------------------; [Rrn] <-- SEXT [W3] LSH (SC 1-32), LONG,; [8] right justify and sign extend field SET PSL CC (IIIP), ; set psl cc's, psl map is iiip SET NORETRY, ; set disable retry flag LAST CYCLE ; decode next instruction EXTZV: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 ;---------------------------------------; MEM (VA)&, [WDR] <-- ZEXT [W3] LSH (SC 1-32), ; [10] right justify and LONG, ; zero extend field SET PSL CC (IIIP), ; set psl cc's, psl map is iiip SET NORETRY, ; set disable retry flag LAST CYCLE ; decode next instruction EXTZV.R: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 ;---------------------------------------; [Rrn] <-- ZEXT [W3] LSH (SC 1-32), LONG,; [8] right justify and zero extend field SET PSL CC (IIIP), ; set psl cc's, psl map is iiip SET NORETRY, ; set disable retry flag LAST CYCLE ; decode next instruction ; FFS, FFC operation: ; ; dst.wl <-- pos of first one (zero) bit in {field(pos.rl, size.rb, base.vb)} FFS: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 FFX: ;---------------------------------------; [W3] <-- [K1]!![W3] LSH (SC 1-32), ; [10] right justify field, guard with '1' LONG, ; load field<3:0> into Wbus<3:0> STATE.0 <-- 1, ; flag memory destination SELECT [STATE.3-0], ; prepare to case on state flags GOTO [FFX.CONTINUE] ; join common flows FFS.R: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 FFX.R: ;---------------------------------------; [W3] <-- [K1]!![W3] LSH (SC 1-32), ; [8] right justify field, guard with '1' LONG, ; load field<3:0> into Wbus<3:0> SELECT [STATE.3-0], ; prepare to case on state flags GOTO [FFX.CONTINUE] ; join common flows FFC: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 ;---------------------------------------; [W3] <-- [K0] + NOT [W3], LONG, ; [10] complement 1's and 0's GOTO [FFX] ; join FFS code FFC.R: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W2], BYTE, ; [1] calc 32 - size, test size > 32 SELECT [STATE.3-0], ; prepare to case on state flags CALL [FIELD.EXTRACT] ; extract left justified field to W3 ;---------------------------------------; [W3] <-- [K0] + NOT [W3], LONG, ; [8] complement 1's and 0's GOTO [FFX.R] ; join FFS code ; FFx, continued. ; Prepare to case through bits. ; At this point, ; W0 = position ; W2 = size ; W3 = right justified field, guarded with leading '1' ; W6 = address of fourth (dst) operand, if memory ; RN = register number of fourth specifier ; WBUS = field<3:0> in cycle [10] ; STATE<1:0> = ; The upcoming bit search can only fail if (FFS) field = 00..00 (FFC) field = 11..11. ; In FFC, the field was complemented BEFORE right shifting. Garbage to the right of ; the field was shifted off, and a guard bit was shifted in. FFX.CONTINUE: ;---------------------------------------; [W3] <-- [K1]!![W3] RSH [4], LONG, ; [11] load field<7:4> into Wbus<3:0> ; bring in guard '1' in case size = 32 SELECT [WBUS.3-0], ; prepare to case on Wbus<3:0> CASE AT [FFX.CONTINUE.1] ; case on field size flag ;= ALIGNLIST **01* (FFX.CONTINUE.1, FFX.ZERO) ; STATE<3:2> = 00 --> STATE<3:0> = 00?? FFX.CONTINUE.1: ;---------------------------------------; state<1> = 0: VA <-- [K0], ; [12] VA will count position [W3] <-- [K0]!![W3] RSH [4], LONG, ; load field<11:8> into Wbus<3:0> SELECT [WBUS.3-0], ; prepare to case on Wbus<3:0> CASE AT [FF.3.0.0000] ; case on Wbus<3:0> from cycle [10] FFX.ZERO: ;---------------------------------------; state<1> = 1: VA <-- [K0], LONG, ; [12] VA is final position SELECT [STATE.3-0], ; prepare to case on state flags GOTO [FFX.TEST] ; abort search ; FFx, continued. ; Search field four bits at a time to find set bit. ; At this point, ; W0 = position ; W2 = size ; W3 = field to search, right shifted 12, known to contain a 1 ; W6 = address of fourth (dst) operand, if memory ; RN = register number of fourth specifier ; VA = relative position ; WBUS = field shifted right 4, 8 in pipeline ; STATE<1:0> = ;= ALIGNLIST 0000* (FF.3.0.0000, FF.3.0.0001, FF.3.0.0010, FF.3.0.0011, ;= FF.3.0.0100, FF.3.0.0101, FF.3.0.0110, FF.3.0.0111, ;= FF.3.0.1000, FF.3.0.1001, FF.3.0.1010, FF.3.0.1011, ;= FF.3.0.1100, FF.3.0.1101, FF.3.0.1110, FF.3.0.1111) FF.3.0.0000: ;---------------------------------------; wbus<3:0> = 0000: VA <-- [VA] + 4, ; [13,14,15,...] increment pos by 4 bits [W3] <-- [VA]!![W3] RSH [4], LONG, ; load next 4b of field into Wbus<3:0> SELECT [WBUS.3-0], ; prepare to case on Wbus<3:0> CASE AT [FF.3.0.0000] ; case on Wbus<3:0> from cycle [11,12,13...] FFX.SET.POS: FF.3.0.0001: ;---------------------------------------; wbus<3:0> = 0001: [W0] <-- [VA] + [W0], LONG, ; VA is right, set final bit position SELECT [STATE.3-0], ; prepare to case on state flags GOTO [FFX.TEST] ; go set condition codes FF.3.0.0010: ;---------------------------------------; wbus<3:0> = 0010: VA <-- [VA] + 000000[01], LONG, ; set final relative bit position GOTO [FFX.SET.POS] ; go set final absolute position FF.3.0.0011: ;---------------------------------------; wbus<3:0> = 0011: [W0] <-- [VA] + [W0], LONG, ; VA is right, set final bit position SELECT [STATE.3-0], ; prepare to case on state flags GOTO [FFX.TEST] ; go set condition codes FF.3.0.0100: ;---------------------------------------; wbus<3:0> = 0100: VA <-- [VA] + 000000[02], LONG, ; set final relative bit position GOTO [FFX.SET.POS] ; go set final absolute position FF.3.0.0101: ;---------------------------------------; wbus<3:0> = 0101: [W0] <-- [VA] + [W0], LONG, ; VA is right, set final bit position SELECT [STATE.3-0], ; prepare to case on state flags GOTO [FFX.TEST] ; go set condition codes FF.3.0.0110: ;---------------------------------------; wbus<3:0> = 0110: VA <-- [VA] + 000000[01], LONG, ; set final relative bit position GOTO [FFX.SET.POS] ; go set final absolute position FF.3.0.0111: ;---------------------------------------; wbus<3:0> = 0111: [W0] <-- [VA] + [W0], LONG, ; VA is right, set final bit position SELECT [STATE.3-0], ; prepare to case on state flags GOTO [FFX.TEST] ; go set condition codes FF.3.0.1000: ;---------------------------------------; wbus<3:0> = 1000: VA <-- [VA] + 000000[03], LONG, ; set final relative bit position GOTO [FFX.SET.POS] ; go set final absolute position FF.3.0.1001: ;---------------------------------------; wbus<3:0> = 1001: [W0] <-- [VA] + [W0], LONG, ; VA is right, set final bit position SELECT [STATE.3-0], ; prepare to case on state flags GOTO [FFX.TEST] ; go set condition codes FF.3.0.1010: ;---------------------------------------; wbus<3:0> = 1010: VA <-- [VA] + 000000[01], LONG, ; set final relative bit position GOTO [FFX.SET.POS] ; go set final absolute position FF.3.0.1011: ;---------------------------------------; wbus<3:0> = 1011: [W0] <-- [VA] + [W0], LONG, ; VA is right, set final bit position SELECT [STATE.3-0], ; prepare to case on state flags GOTO [FFX.TEST] ; go set condition codes FF.3.0.1100: ;---------------------------------------; wbus<3:0> = 1100: VA <-- [VA] + 000000[02], LONG, ; set final relative bit position GOTO [FFX.SET.POS] ; go set final absolute position FF.3.0.1101: ;---------------------------------------; wbus<3:0> = 1101: [W0] <-- [VA] + [W0], LONG, ; VA is right, set final bit position SELECT [STATE.3-0], ; prepare to case on state flags GOTO [FFX.TEST] ; go set condition codes FF.3.0.1110: ;---------------------------------------; wbus<3:0> = 1110: VA <-- [VA] + 000000[01], LONG, ; set final relative bit position GOTO [FFX.SET.POS] ; go set final absolute position FF.3.0.1111: ;---------------------------------------; wbus<3:0> = 1111: [W0] <-- [VA] + [W0], LONG, ; VA is right, set final bit position SELECT [STATE.3-0], ; prepare to case on state flags GOTO [FFX.TEST] ; go set condition codes ; FFx, continued. ; Set PSL condition codes, write result. ; At this point, ; W0 = final bit position ; W2 = size ; W6 = address of fourth (dst) operand, if memory ; VA = relative bit position ; RN = register number of fourth specifier ; The relative bit position must be 0 <= rel pos <= size, because of the ; guard bit inserted into the field before searching. If rel pos = size, ; then the search reached the guard bit and thus failed. Subtracting ; rel pos from size produces the correct condition codes: ; ; psl.n = 0 because rel pos <= size ; psl.z = 0 if rel pos < size (bit found) ; = 1 if rel pos = size (search failed) ; psl.v = 0 because rel pos and size are unsigned integer bytes ; psl.c = 0 because alu.c is always 1 and then inverted FFX.TEST: ;---------------------------------------; [WBUS] <-- (-[VA] + [W2]), BYTE, ; test rel position vs size SET PSL CC (IIIJ), ; set psl cc's, psl map is iiij CASE AT [FFX.WRITE.REG] ; case on register vs memory ;= ALIGNLIST **10* (FFX.WRITE.REG, FFX.WRITE.MEM) ; STATE<3:2> = 00 --> STATE<3:0> = 00?? FFX.WRITE.REG: ;---------------------------------------; state<0> = 0: [Rrn] <-- [W0], LONG, ; store result SET NORETRY, ; set disable retry flag LAST CYCLE ; decode next instruction FFX.WRITE.MEM: ;---------------------------------------; state<0> = 1: VA <-- [W6], ; get address of destination ; >> W6 not written in prev cycle MEM (VA)&, [WDR] <-- B [W0], LONG, ; write result SET NORETRY, ; set disable retry flag LAST CYCLE ; decode next instruction ; Common subroutine to extract a field. ; ; Entry conditions: ; W0 = position ; W1 = SC = 32 - size ; W2 = size ; W5'W4 = field surround if register ; W4 = field address if memory ; W6 = fourth operand ; WBUS CC's = set from 32 - size, testable in [3] ; STATE<2> = 1 if field in register ; ; A case on STATE<3:0> is selected. ; ; Exit conditions: ; W0 = position ; W2 = SC = size ; W3 = left justified field ; W6 = VA = fourth operand ; STATE<3:0> = 000 ; ; If the field size was zero, W3 is zero, and SC is unpredictable. ; The final shift ; ; [W3] <-- {ZEXT/SEXT} [W3] LSH (SC 1-32), LONG, ; ; will produce the correct result (zero), except for FFx, which ; must be special cased. FIELD.EXTRACT: ;---------------------------------------; [W3] <-- [W4] LSH [3], LONG, ; [2] for memory flows, calc base * 8 SELECT [WBUS.NZVC], ; prepare to case on Wbus cc's CASE AT [FIELD.EXTRACT.MEM] ; case on field in memory or register ; Field in memory. ; At this point, ; W0 = position ; W1 = SC = 32 - size ; W2 = size ; W3 = base * 8 ; W4 = field address ; W6 = fourth operand ; WBUS CC's = set from 32 - size, testable in [3] ;= ALIGNLIST *0*** (FIELD.EXTRACT.MEM, FIELD.EXTRACT.REG) ; STATE<3,1:0> = 000 --> STATE<3:0> = 0?00 FIELD.EXTRACT.MEM: ;---------------------------------------; state<2> = 0: [W3] <-- [W0] + [W3], LONG, ; [3] calc base * 8 + position SELECT [SC.7-4], ; prepare to case on SC<7:4> CASE AT [FIELD.MEM.RSRV.OPER] ; case on size > 32 test from [1] ;= ALIGNLIST 1110* (FIELD.MEM.RSRV.OPER, FIELD.MEM.CONTINUE) FIELD.MEM.RSRV.OPER: ;---------------------------------------; wbus.c = 0: RESERVED OPERAND FAULT ; [4] size > 32, fault FIELD.MEM.CONTINUE: ;---------------------------------------; wbus.c = 1: [W3] <-- [W3] AND 000000[1F], LONG, ; [4] mask position to five bits STATE.3-0 <-- 0, ; clear state flags CASE AT [FIELD.MEM.1.255] ; case on size = 0 test from [1] ;= ALIGNLIST **01* (FIELD.MEM.1.255, FIELD.MEM.0) ; 32 - size is known to be >= 0, ie, 0..32. ; If size = 0, then 32 - size = 32 = 00100000, SC<5> = 1. ; If size = 1..32, then 32 - size = 31..0 = 000xxxxx, SC<5> = 0. FIELD.MEM.0: ;---------------------------------------; sc<5> = 1: VA <-- [W6], ; [5] reload VA in case clobbered ; >> W6 not written in prev cycle [W3] <-- 000000[00], LONG, ; field = 0 STATE.1 <-- 1, ; flag special case RETURN ; return to caller ; Field in memory, continued. ; Size verified, longword aligned position calculated. ; Calculate longword aligned base address. ; At this point, ; W0 = position ; W1 = 32 - size ; W2 = size (1..32) ; W3 = position (mod 32) relative to base LONGWORD ; W4 = base address ; W6 = fourth operand ; RN = register number of fourth specifier FIELD.MEM.1.255: ;---------------------------------------; sc<5> = 0: [W5] <-- SEXT [W0] RSH [3], LONG ; [5] convert position to signed byte offset ;---------------------------------------; SC&, [WBUS] <-- [W1] - [W3], BYTE ; [6] calc 32 - size - pos = ; 32 - (pos + size) ;---------------------------------------; VA <-- [W4] + [W5], ; [7] calc base + sext(position) ; >> W4, W5 not written in prev cycle [W4] <-- MEM (VA), BYTE, ; read aligned longword containing field SELECT [WBUS.NZVC] ; prepare to case on Wbus cc's ;---------------------------------------; [W3] <-- [W4] LSH (SC), LONG, ; [8] shift field to left aligned position CASE AT [FIELD.MEM.2] ; case on number of longwords from [6] ;= ALIGNLIST 11*0* (FIELD.MEM.2, FIELD.MEM.1) ; WBUS.NZVC set by subtract of positive integers --> V = 0 FIELD.MEM.1: ;---------------------------------------; wbus.c = 1: VA <-- [W6], ; [9] restore VA in case clobbered ; >> W6 not written in prev cycle SC&, [WBUS] <-- B [W2], LONG, ; load size into SC RETURN ; return to caller FIELD.MEM.2: ;---------------------------------------; wbus.c = 0: VA <-- [VA] + 4, ; [9] point at second longword [W5] <-- MEM (VA), BYTE ; read second aligned longword ;---------------------------------------; [W3] <-- [W5]!![W4] LSH (SC), LONG, ; [10] left align field GOTO [FIELD.MEM.1] ; [11] load size into SC, return to caller ; Field in register(s). ; Verify position and size parameters. ; At this point, ; W0 = position ; W1 = SC = 32 - size ; W2 = size ; W5'W4 = field surround ; W6 = fourth operand ; WBUS CC's = set from 32 - size, testable in [3] FIELD.EXTRACT.REG: ;---------------------------------------; state<2> = 1: [WBUS] <-- [W1] - [W0], BYTE, ; [3] test 32 : (pos + size) SELECT [SC.7-4], ; prepare to case on SC<7:4> CASE AT [FIELD.REG.RSRV.OPER.1] ; case on size > 32 test from [1] ;= ALIGNLIST 1110* (FIELD.REG.RSRV.OPER.1, FIELD.REG.CONTINUE.1) FIELD.REG.RSRV.OPER.1: ;---------------------------------------; wbus.c = 0: RESERVED OPERAND FAULT ; [4] size > 32, fault FIELD.REG.CONTINUE.1: ;---------------------------------------; wbus.c = 1: [WBUS] <-- ZEXT [W0] RSH [5.], LONG, ; [4] test for position < 32 STATE.3-0 <-- 0, ; clear state flags SELECT [WBUS.NZVC], ; prepare to case on Wbus cc's CASE AT [FIELD.REG.1.255] ; case on size = 0 test from [1] ;= ALIGNLIST **01* (FIELD.REG.1.255, FIELD.REG.0) ; 32 - size is known to be >= 0, ie, 0..32. ; If size = 0, then 32 - size = 32 = 00100000, SC<5> = 1. ; If size = 1..32, then 32 - size = 31..0 = 000xxxxx, SC<5> = 0. FIELD.REG.0: ;---------------------------------------; sc<5> = 1: VA <-- [W6], ; [5] reload VA in case clobbered ; >> W6 not written in prev cycle [W3] <-- 000000[00], LONG, ; field = 0 STATE.1 <-- 1, ; flag special case RETURN ; return to caller ; Field in registers, continued. ; Finish field extraction. ; At this point, ; W0 = position ; W1 = 32 - size ; W2 = size ; W5'W4 = field surround ; W6 = fourth operand ; RN = register number of fourth specifier FIELD.REG.1.255: ;---------------------------------------; sc<5> = 0: SC&, [WBUS] <-- [W1] - [W0], BYTE, ; [5] load 32 - (pos + size) into SC SELECT [WBUS.NZVC], ; prepare to case on Wbus cc's CASE AT [FIELD.REG.2] ; case on number of longwords from [3] ;= ALIGNLIST 1110* (FIELD.REG.2, FIELD.REG.1) FIELD.REG.1: ;---------------------------------------; wbus.c = 1: [W3] <-- [W4] LSH (SC), LONG, ; [6] left align field CASE AT [FIELD.REG.RSRV.OPER.2] ; case on position > 31 from [4] FIELD.REG.2: ;---------------------------------------; wbus.c = 0: [W3] <-- [W5]!![W4] LSH (SC), LONG, ; [6] left align field CASE AT [FIELD.REG.RSRV.OPER.2] ; case on position > 31 from [4] ;= ALIGNLIST *0*** (FIELD.REG.RSRV.OPER.2, FIELD.REG.CONTINUE.2) ; WBUS.NZVC set by ZEXT right shift --> N = V = C = 0 FIELD.REG.RSRV.OPER.2: ;---------------------------------------; wbus.z = 0: RESERVED OPERAND FAULT ; [7] position > 31, fault FIELD.REG.CONTINUE.2: ;---------------------------------------; wbus.z = 1: VA <-- [W6], ; [7] restore VA in case clobbered ; >> W6 not written in prev cycle SC&, [WBUS] <-- B [W2], LONG, ; load size into SC RETURN ; return to caller .nobin .TOC " INSV" ; This instruction inserts a source operand into a variable-length bit field. ; ; Mnemonic Opcode Operation Spec AT/DL CC Dispatch BCOND ; -------- ------ --------- ---- ----- -- -------- ----- ; INSV F0 field(pos.rl, size.rb, base.vb) 4 rrrw/llbb -- INSV -- ; <-- src.rl ; ; Entry conditions from specifier flows: ; W0 = first (source) operand ; W2 = second (position) operand ; W4 = third (size) operand ; W6 = address of fourth (base) operand, if memory ; RN = register number of fourth specifier ; DL = data length of fourth operand (byte) ; ; Exit conditions: ; The source has been inserted into the specified bit field. ; ; Condition codes: ; N <-- N ; Z <-- Z ; V <-- V [Integer overflow trap disabled.] ; C <-- C ; ; Tradeoffs: ; None. ; .bin ; INSV operation: ; ; field(pos.rl, size.rb, base.vb) <-- src.rl INSV: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W4], BYTE ; [1] calc 32 - size, test size > 32 ;---------------------------------------; [W3] <-- [W6] LSH [3], LONG, ; [2] calc base * 8 SELECT [WBUS.NZVC] ; prepare to case on Wbus cc's ;---------------------------------------; [W3] <-- [W2] + [W3], LONG, ; [3] calc base * 8 + pos SELECT [SC.7-4], ; prepare to case on SC<7:4> CASE AT [INSV.MEM.RSRV.OPER] ; case on size > 32 test from [1] ;= ALIGNLIST 1110* (INSV.MEM.RSRV.OPER, INSV.MEM.CONTINUE) INSV.MEM.RSRV.OPER: ;---------------------------------------; wbus.c = 0: RESERVED OPERAND FAULT ; [4] size > 32, fault INSV.MEM.CONTINUE: ;---------------------------------------; wbus.c = 1: [W5] <-- SEXT [W2] RSH [3], LONG, ; [4] convert position to signed byte offset CASE AT [INSV.MEM.1.255] ; case on size = 0 test from [1] ;= ALIGNLIST **01* (INSV.MEM.1.255, INSV.MEM.0) ; 32 - size is known to be >= 0, ie, 0..32. ; If size = 0, then 32 - size = 32 = 00100000, SC<5> = 1. ; If size = 1..32, then 32 - size = 31..0 = 000xxxxx, SC<5> = 0. INSV.MEM.0: ;---------------------------------------; sc<5> = 0: NOP, ; [5] nothing to do... LAST CYCLE ; decode next instruction ; INSV, continued. ; Size verified, longword aligned position calculated. ; Calculate longword aligned base address. ; At this point, ; W0 = source ; W1 = 32 - size ; W3 = base*8 + position ; W4 = size (1..32) ; W5 = sext(position) rsh 3 ; W6 = base address INSV.MEM.1.255: ;---------------------------------------; sc<5> = 1: [W2] <-- [W3] AND 000000[1F], LONG ; [5] mask position to five bits ;---------------------------------------; VA <-- [W6] + [W5], ; [6] calc base + sext(position) ; >> W6, W5 not written in prev cycle [W3] <-- MEM.WCHK (VA), BYTE ; read, write check aligned field surround ;---------------------------------------; [W1] <-- [W1] - [W2], BYTE ; [7] calc 32 - size - pos = ; 32 - (pos + size) ;---------------------------------------; SC&, [WBUS] <-- 000000[32.] - [W2], ; [8] load 32 - position into SC LONG, ; SELECT [WBUS.NZVC] ; prepare to case on Wbus cc's ;---------------------------------------; [W3] <-- [W3] LROT (SC), LONG, ; [9] rotate low field left by 32-position CASE AT [INSV.MEM.2] ; case on number of longwords from [7] ; INSV, continued. ; Field in one longword. ; Longword aligned address/position calculated. ; Insert field. ; At this point, ; W0 = source ; W1 = 32 - (pos + size) ; W2 = position (mod 32) relative to base LONGWORD ; W3 = field surround, rotated right by pos (aabbcc --> ccaabb) ; W4 = size ; VA = base LONGWORD address ;= ALIGNLIST 11*0* (INSV.MEM.2, INSV.MEM.1) ; WBUS.NZVC set by subtract of positive integers --> V = 0 INSV.MEM.1: ;---------------------------------------; wbus.c = 1 (pos + size <= 32): SC&, [WBUS] <-- 000000[32.] - [W4], ; [10] set SC = 32 - size for shift LONG ; ;---------------------------------------; --W0-- --W3-- [W0] <-- [W0]!![W3] LSH (SC), LONG, ; [11] nnccaa <-- xxxxnn!!ccaabb CALL [INSV.POS.PLUS.SIZE] ; [12] use pos + size as shift value ;---------------------------------------; --W0-- MEM (VA)&, [WDR] <-- [W0] LROT (SC), ; [13] aanncc <-- nnccaa BYTE, ; write aligned longword SET NORETRY, ; set disable retry flag LAST CYCLE ; decode next instruction ; INSV, continued. ; Field in two longwords. ; Longword aligned address/position calculated. ; Insert field. ; At this point, ; W0 = source ; W1 = 32 - (pos + size) ; W2 = position (mod 32) relative to base LONGWORD ; W3 = low field surround, rot right by pos (yyaaaa --> aaaayy) ; W4 = size ; VA = base LONGWORD address INSV.MEM.2: ;---------------------------------------; wbus.c = 0 (pos + size > 32): VA <-- [VA] + 4, ; [10] point at second lw of field [W5] <-- MEM.WCHK (VA), BYTE ; read second aligned lw of field surround ;---------------------------------------; VA <-- [VA] - 4, ; [11] point back at first lw of field SC&, [WBUS] <-- B [W2], LONG ; load position into SC ;---------------------------------------; [W6] <-- ZEXT [W0] LSH (SC), LONG ; [12] isolate source insert for high lw ;---------------------------------------; --W0-- --W3-- MEM (VA)&, [WDR] <-- [W0]!![W3] LSH (SC), ; [13] mmbbbb <-- xxnnmm!!bbbbzz BYTE, ; SET NORETRY, ; set disable retry flag CALL [INSV.2.INSERT] ; [14] load 32 - (pos + size) into SC, incr VA ; --W1-- --W6-- --W5-- ; [15] nnaaaa <-- ....nn!!aaaayy ; [16] load pos + size into SC ;---------------------------------------; --W1-- MEM (VA)&, [WDR] <-- [W1] LROT (SC), ; [17] aaaann <-- nnaaaa BYTE, ; write high result aligned LAST CYCLE ; decode next instruction ; INSV, register mode. INSV.R: ;********** Hardware dispatch **********; SC&, [W1] <-- 000000[32.] - [W4], BYTE ; [1] calc 32 - size, test size > 32 ;---------------------------------------; [W3] <-- [Rrn], LONG, ; [2] get first lw containing field SELECT [WBUS.NZVC] ; prepare to case on Wbus cc's ;---------------------------------------; [W1] <-- [W1] - [W2], BYTE, ; [3] calc 32 - size - pos = ; 32 - (pos + size) SELECT [SC.7-4], ; prepare to case on SC<7:4> CASE AT [INSV.REG.RSRV.OPER.1] ; case on size > 32 test from [1] ;= ALIGNLIST 1110* (INSV.REG.RSRV.OPER.1, INSV.REG.CONTINUE.1) INSV.REG.RSRV.OPER.1: ;---------------------------------------; wbus.c = 0: RESERVED OPERAND FAULT ; [4] size > 32, fault INSV.REG.CONTINUE.1: ;---------------------------------------; wbus.c = 1: SC&, [WBUS] <-- 000000[32.] - [W2], ; [4] load 32 - pos, test pos > 31 LONG, ; SELECT [WBUS.NZVC], ; prepare to case on Wbus cc's CASE AT [INSV.REG.1.255] ; case on size = 0 test from [1] ;= ALIGNLIST **01* (INSV.REG.1.255, INSV.REG.0) ; 32 - size is known to be >= 0, ie, 0..32. ; If size = 0, then 32 - size = 32 = 00100000, SC<5> = 1. ; If size = 1..32, then 32 - size = 31..0 = 000xxxxx, SC<5> = 0. INSV.REG.0: ;---------------------------------------; sc<5> = 1: NOP, ; [5] nothing to do... LAST CYCLE ; decode next instruction INSV.REG.1.255: ;---------------------------------------; [W3] <-- [W3] LROT (SC), LONG, ; [5] rotate low field left by 32-position SELECT [WBUS.NZVC], ; prepare to case on Wbus cc's CASE AT [INSV.REG.2] ; case on 32 - (pos + size) test from [3] ; INSV register mode, continued. ; Field in one longword. ; At this point, ; W0 = source ; W1 = 32 - (pos + size) ; W2 = position ; W3 = field surround rotated right by position (aabbcc --> ccaabb) ; W4 = size (1..32) ; RN = register number of fourth specifier ; WBUS CC's = 32 - position, testable in [6] ;= ALIGNLIST 1110* (INSV.REG.2, INSV.REG.1) INSV.REG.1: ;---------------------------------------; wbus.c = 1 (pos + size <= 32): SC&, [WBUS] <-- 000000[32.] - [W4], ; [6] set 32 - size for shift BYTE, ; CASE AT [INSV.REG.RSRV.OPER.2] ; case on position > 31 test from [4] ;= ALIGNLIST 1010* (INSV.REG.RSRV.OPER.2, INSV.REG.1.EXIT, ;= , INSV.REG.RSRV.OPER.3) INSV.REG.RSRV.OPER.2: ;---------------------------------------; wbus.zc = 00: RESERVED OPERAND FAULT ; [7] position > 32, fault INSV.REG.RSRV.OPER.3: ;---------------------------------------; wbus.zc = 11: RESERVED OPERAND FAULT ; [7] position = 32, fault INSV.REG.1.EXIT: ;---------------------------------------; wbus.zc = 01: --W0-- --W3-- [W0] <-- [W0]!![W3] LSH (SC), LONG, ; [7] nnccaa <-- xxxxnn!!ccaabb CALL [INSV.POS.PLUS.SIZE] ; [8] use pos + size as shift value ;---------------------------------------; --W0-- [Rrn] <-- [W0] LROT (SC), LONG, ; [9] aanncc <-- nnccaa SET NORETRY, ; set disable retry flag LAST CYCLE ; decode next instruction ; INSV register mode, continued. ; Field in two longwords. ; At this point, ; W0 = source ; W1 = 32 - (pos + size) ; W2 = position ; W3 = low field surround, rot right by pos (yyaaaa --> aaaayy) ; W4 = size (1..32) ; RN = register number of fourth specifier ; WBUS CC's = 32 - position, testable in [7] INSV.REG.2: ;---------------------------------------; wbus.n = 1 (pos + size > 32): [W5] <-- [Rrn+1], LONG, ; [6] get second longword of field surround CASE AT [INSV.REG.2.EXIT] ; case on position > 31 test from [4] ;= ALIGNLIST 1010* (INSV.REG.RSRV.OPER.4, INSV.REG.2.EXIT, ;= , INSV.REG.RSRV.OPER.5) INSV.REG.RSRV.OPER.4: ;---------------------------------------; wbus.zc = 00: RESERVED OPERAND FAULT ; [7] position > 32, fault INSV.REG.RSRV.OPER.5: ;---------------------------------------; wbus.zc = 11: RESERVED OPERAND FAULT ; [7] position = 32, fault INSV.REG.2.EXIT: ;---------------------------------------; wbus.zc = 01: SC&, [WBUS] <-- [W2], LONG ; [7] load position into SC ;---------------------------------------; [W6] <-- ZEXT [W0] LSH (SC), LONG ; [8] isolate source insert for high lw ;---------------------------------------; --W0-- --W3-- [Rrn] <-- [W0]!![W3] LSH (SC), LONG, ; [9] mmbbbb <-- xxnnmm!!bbbbzz SET NORETRY, ; set disable retry flag CALL [INSV.2.INSERT] ; [10] load 32 - size - pos into SC ; --W1-- --W6-- --W5-- ; [11] nnaaaa <-- ....nn!!aaaayy ; [12] load pos + size into SC ;---------------------------------------; --W1-- [Rrn+1] <-- [W1] LROT (SC), LONG, ; [13] aaaann <-- nnaaaa LAST CYCLE ; decode next instruction ; Common subroutine for INSV unaligned field flows. INSV.2.INSERT: ;---------------------------------------; VA <-- [VA] + 4, ; if memory, point at second lw of field SC&, [WBUS] <-- B [W1], BYTE ; load 32 - (pos + size) into SC ;---------------------------------------; [W1] <-- [W6]!![W5] LSH (SC), LONG ; start insert into high longword ; One line subroutine for INSV flows. INSV.POS.PLUS.SIZE: ;---------------------------------------; SC&, [WBUS] <-- [W2] + [W4], BYTE, ; load pos + size into SC RETURN ; return to caller ;= END VFIELD