diff --git a/ppc64/pp64.csv b/ppc64/pp64.csv index 3150cad..b2aa6b3 100644 --- a/ppc64/pp64.csv +++ b/ppc64/pp64.csv @@ -1,4 +1,4 @@ -# POWER ISA 3.1 instruction description. +# POWER ISA 3.1B instruction description. # # This file contains comment lines, each beginning with #, # followed by entries in CSV format. @@ -13,8 +13,12 @@ # a list of sequences of the form (,sequence)+. A leading comma is used to signify an # instruction encoding requiring multiple instruction words. # The fourth field represents the ISA version where the instruction was introduced as -# stated in Appendix F. of ISA 3.1 +# stated in Appendix F. of ISA 3.1B # +"Hash Check X-form","hashchk RB,offset(RA)","31@0|D@6|RA@11|RB@16|754@21|DX@31|","v3.1B" +"Hash Check Privileged X-form","hashchkp RB,offset(RA)","31@0|D@6|RA@11|RB@16|690@21|DX@31|","v3.1B" +"Hash Store X-form","hashst RB,offset(RA)","31@0|D@6|RA@11|RB@16|722@21|DX@31|","v3.1B" +"Hash Store Privileged X-form","hashstp RB,offset(RA)","31@0|D@6|RA@11|RB@16|658@21|DX@31|","v3.1B" "Byte-Reverse Doubleword X-form","brd RA,RS","31@0|RS@6|RA@11|///@16|187@21|/@31|","v3.1" "Byte-Reverse Halfword X-form","brh RA,RS","31@0|RS@6|RA@11|///@16|219@21|/@31|","v3.1" "Byte-Reverse Word X-form","brw RA,RS","31@0|RS@6|RA@11|///@16|155@21|/@31|","v3.1" @@ -209,7 +213,7 @@ "VSX Vector bfloat16 GER (Rank-2 Update) Negative multiply, Positive accumulate XX3-form","xvbf16ger2np AT,XA,XB","59@0|AT@6|//@9|A@11|B@16|114@21|AX@29|BX@30|/@31|","v3.1" "VSX Vector bfloat16 GER (Rank-2 Update) Positive multiply, Negative accumulate XX3-form","xvbf16ger2pn AT,XA,XB","59@0|AT@6|//@9|A@11|B@16|178@21|AX@29|BX@30|/@31|","v3.1" "VSX Vector bfloat16 GER (Rank-2 Update) Positive multiply, Positive accumulate XX3-form","xvbf16ger2pp AT,XA,XB","59@0|AT@6|//@9|A@11|B@16|50@21|AX@29|BX@30|/@31|","v3.1" -"VSX Vector Convert bfloat16 to Single-Precision format XX2-form","xvcvbf16spn XT,XB","60@0|T@6|16@11|B@16|475@21|BX@30|TX@31|","v3.1" +"VSX Vector Convert bfloat16 to Single-Precision format Non-signaling XX2-form","xvcvbf16spn XT,XB","60@0|T@6|16@11|B@16|475@21|BX@30|TX@31|","v3.1" "VSX Vector Convert with round Single-Precision to bfloat16 format XX2-form","xvcvspbf16 XT,XB","60@0|T@6|17@11|B@16|475@21|BX@30|TX@31|","v3.1" "VSX Vector 16-bit Floating-Point GER (rank-2 update) XX3-form","xvf16ger2 AT,XA,XB","59@0|AT@6|//@9|A@11|B@16|19@21|AX@29|BX@30|/@31|","v3.1" "VSX Vector 16-bit Floating-Point GER (rank-2 update) Negative multiply, Negative accumulate XX3-form","xvf16ger2nn AT,XA,XB","59@0|AT@6|//@9|A@11|B@16|210@21|AX@29|BX@30|/@31|","v3.1" @@ -1034,7 +1038,7 @@ "Add Carrying XO-form","addc RT,RA,RB (OE=0 Rc=0)|addc. RT,RA,RB (OE=0 Rc=1)|addco RT,RA,RB (OE=1 Rc=0)|addco. RT,RA,RB (OE=1 Rc=1)","31@0|RT@6|RA@11|RB@16|OE@21|10@22|Rc@31|","P1" "Add Extended XO-form","adde RT,RA,RB (OE=0 Rc=0)|adde. RT,RA,RB (OE=0 Rc=1)|addeo RT,RA,RB (OE=1 Rc=0)|addeo. RT,RA,RB (OE=1 Rc=1)","31@0|RT@6|RA@11|RB@16|OE@21|138@22|Rc@31|","P1" "Add Immediate D-form","addi RT,RA,SI|li RT,SI (RA=0)","14@0|RT@6|RA@11|SI@16|","P1" -"Add Immediate Carrying D-formy","addic RT,RA,SI","12@0|RT@6|RA@11|SI@16|","P1" +"Add Immediate Carrying D-form","addic RT,RA,SI","12@0|RT@6|RA@11|SI@16|","P1" "Add Immediate Carrying and Record D-form","addic. RT,RA,SI","13@0|RT@6|RA@11|SI@16|","P1" "Add Immediate Shifted D-form","addis RT,RA,SI|lis RT,SI (RA=0)","15@0|RT@6|RA@11|SI@16|","P1" "Add to Minus One Extended XO-form","addme RT,RA (OE=0 Rc=0)|addme. RT,RA (OE=0 Rc=1)|addmeo RT,RA (OE=1 Rc=0)|addmeo. RT,RA (OE=1 Rc=1)","31@0|RT@6|RA@11|///@16|OE@21|234@22|Rc@31|","P1" diff --git a/ppc64/ppc64asm/decode.go b/ppc64/ppc64asm/decode.go index 59bd325..b8d857c 100644 --- a/ppc64/ppc64asm/decode.go +++ b/ppc64/ppc64asm/decode.go @@ -22,9 +22,12 @@ const prefixOpcode = 1 // The Args are stored in the same order as the instruction manual. // // Prefixed instructions are stored as: -// prefix << 32 | suffix, +// +// prefix << 32 | suffix, +// // Regular instructions are: -// inst << 32 +// +// inst << 32 type instFormat struct { Op Op Mask uint64 @@ -77,6 +80,12 @@ func (a argField) Parse(i [2]uint32) Arg { return Label(a.BitFields.ParseSigned(i) << a.Shift) case TypeOffset: return Offset(a.BitFields.ParseSigned(i) << a.Shift) + case TypeNegOffset: + // An oddball encoding of offset for hashchk and similar. + // e.g hashchk offset is 0b1111111000000000 | DX << 8 | D << 3 + off := a.BitFields.ParseSigned(i) << a.Shift + neg := int64(-1) << (int(a.Shift) + a.BitFields.NumBits()) + return Offset(neg | off) } } @@ -98,6 +107,7 @@ const ( TypeImmSigned // signed immediate TypeImmUnsigned // unsigned immediate/flag/mask, this is the catch-all type TypeOffset // signed offset in load/store + TypeNegOffset // A negative 16 bit value 0b1111111xxxxx000 encoded as 0bxxxxx (e.g in the hashchk instruction) TypeLast // must be the last one ) @@ -135,6 +145,8 @@ func (t ArgType) String() string { return "Label" case TypeOffset: return "Offset" + case TypeNegOffset: + return "NegOffset" } } diff --git a/ppc64/ppc64asm/field.go b/ppc64/ppc64asm/field.go index 13df063..3779446 100644 --- a/ppc64/ppc64asm/field.go +++ b/ppc64/ppc64asm/field.go @@ -86,3 +86,12 @@ func (bs BitFields) ParseSigned(i [2]uint32) int64 { u, l := bs.parse(i) return int64(u) << (64 - l) >> (64 - l) } + +// Count the number of bits in the aggregate BitFields +func (bs BitFields) NumBits() int { + num := 0 + for _, b := range bs { + num += int(b.Bits) + } + return num +} diff --git a/ppc64/ppc64asm/field_test.go b/ppc64/ppc64asm/field_test.go index 01402b5..ce18ad5 100644 --- a/ppc64/ppc64asm/field_test.go +++ b/ppc64/ppc64asm/field_test.go @@ -65,26 +65,29 @@ func TestBitFields(t *testing.T) { i [2]uint32 // input u uint64 // unsigned output s int64 // signed output + nb int // Total number of bits in BitField fail bool // if the check should panic }{ - {BitFields{{0, 0, 1}}, [2]uint32{0, 0}, 0, 0, true}, - {BitFields{{31, 2, 1}}, [2]uint32{0, 0}, 0, 0, true}, - {BitFields{{31, 1, 1}}, [2]uint32{0, 1}, 1, -1, false}, - {BitFields{{29, 2, 1}}, [2]uint32{0, 0 << 1}, 0, 0, false}, - {BitFields{{29, 2, 1}}, [2]uint32{0, 1 << 1}, 1, 1, false}, - {BitFields{{29, 2, 1}}, [2]uint32{0, 2 << 1}, 2, -2, false}, - {BitFields{{29, 2, 1}}, [2]uint32{0, 3 << 1}, 3, -1, false}, - {BitFields{{0, 32, 1}}, [2]uint32{0, 1<<32 - 1}, 1<<32 - 1, -1, false}, - {BitFields{{16, 3, 1}}, [2]uint32{0, 1 << 15}, 4, -4, false}, - {BitFields{{16, 16, 0}, {16, 16, 1}}, [2]uint32{0x8016, 0x32}, 0x80160032, -0x7FE9FFCE, false}, - {BitFields{{14, 18, 0}, {16, 16, 1}}, [2]uint32{0x38016, 0x32}, 0x380160032, -0x07FE9FFCE, false}, + {BitFields{{0, 0, 1}}, [2]uint32{0, 0}, 0, 0, 0, true}, + {BitFields{{31, 2, 1}}, [2]uint32{0, 0}, 0, 0, 2, true}, + {BitFields{{31, 1, 1}}, [2]uint32{0, 1}, 1, -1, 1, false}, + {BitFields{{29, 2, 1}}, [2]uint32{0, 0 << 1}, 0, 0, 2, false}, + {BitFields{{29, 2, 1}}, [2]uint32{0, 1 << 1}, 1, 1, 2, false}, + {BitFields{{29, 2, 1}}, [2]uint32{0, 2 << 1}, 2, -2, 2, false}, + {BitFields{{29, 2, 1}}, [2]uint32{0, 3 << 1}, 3, -1, 2, false}, + {BitFields{{0, 32, 1}}, [2]uint32{0, 1<<32 - 1}, 1<<32 - 1, -1, 32, false}, + {BitFields{{16, 3, 1}}, [2]uint32{0, 1 << 15}, 4, -4, 3, false}, + {BitFields{{16, 16, 0}, {16, 16, 1}}, [2]uint32{0x8016, 0x32}, 0x80160032, -0x7FE9FFCE, 32, false}, + {BitFields{{14, 18, 0}, {16, 16, 1}}, [2]uint32{0x38016, 0x32}, 0x380160032, -0x07FE9FFCE, 34, false}, } for i, tst := range tests { var ( - ou uint64 - os int64 + ou uint64 + os int64 + onb int ) failed := panicOrNot(func() { + onb = tst.b.NumBits() ou = tst.b.Parse(tst.i) os = tst.b.ParseSigned(tst.i) }) @@ -99,5 +102,8 @@ func TestBitFields(t *testing.T) { if os != tst.s { t.Errorf("case %d: %v.ParseSigned(%d) returned %d, expected %d", i, tst.b, tst.i, os, tst.s) } + if onb != tst.nb { + t.Errorf("case %d: %v.NumBits() returned %d, expected %d", i, tst.b, onb, tst.nb) + } } } diff --git a/ppc64/ppc64asm/plan9.go b/ppc64/ppc64asm/plan9.go index 4bd1c7f..fcb2a12 100644 --- a/ppc64/ppc64asm/plan9.go +++ b/ppc64/ppc64asm/plan9.go @@ -83,7 +83,9 @@ func GoSyntax(inst Inst, pc uint64, symname func(uint64) (string, uint64)) strin STH, STHU, STW, STWU, STD, STDU, - STQ, STFD, STFDU, STFS, STFSU: + STFD, STFDU, + STFS, STFSU, + STQ, HASHST, HASHSTP: return op + " " + strings.Join(args, ",") case FCMPU, FCMPO, CMPD, CMPDI, CMPLD, CMPLDI, CMPW, CMPWI, CMPLW, CMPLWI: diff --git a/ppc64/ppc64asm/tables.go b/ppc64/ppc64asm/tables.go index 8d0a243..8705077 100644 --- a/ppc64/ppc64asm/tables.go +++ b/ppc64/ppc64asm/tables.go @@ -1,9 +1,13 @@ -// Code generated by ppc64map -fmt=decoder pp64.csv DO NOT EDIT. +// Code generated by ppc64map -fmt=decoder ../pp64.csv DO NOT EDIT. package ppc64asm const ( _ Op = iota + HASHCHK + HASHCHKP + HASHST + HASHSTP BRD BRH BRW @@ -1420,6 +1424,10 @@ const ( ) var opstr = [...]string{ + HASHCHK: "hashchk", + HASHCHKP: "hashchkp", + HASHST: "hashst", + HASHSTP: "hashstp", BRD: "brd", BRH: "brh", BRW: "brw", @@ -2836,9 +2844,10 @@ var opstr = [...]string{ } var ( + ap_Reg_16_20 = &argField{Type: TypeReg, Shift: 0, BitFields: BitFields{{16, 5, 0}}} + ap_NegOffset_31_31_6_10_shift3 = &argField{Type: TypeNegOffset, Shift: 3, BitFields: BitFields{{31, 1, 0}, {6, 5, 0}}} ap_Reg_11_15 = &argField{Type: TypeReg, Shift: 0, BitFields: BitFields{{11, 5, 0}}} ap_Reg_6_10 = &argField{Type: TypeReg, Shift: 0, BitFields: BitFields{{6, 5, 0}}} - ap_Reg_16_20 = &argField{Type: TypeReg, Shift: 0, BitFields: BitFields{{16, 5, 0}}} ap_FPReg_6_10 = &argField{Type: TypeFPReg, Shift: 0, BitFields: BitFields{{6, 5, 0}}} ap_VecReg_16_20 = &argField{Type: TypeVecReg, Shift: 0, BitFields: BitFields{{16, 5, 0}}} ap_VecReg_6_10 = &argField{Type: TypeVecReg, Shift: 0, BitFields: BitFields{{6, 5, 0}}} @@ -2942,6 +2951,14 @@ var ( ) var instFormats = [...]instFormat{ + {HASHCHK, 0xfc0007fe00000000, 0x7c0005e400000000, 0x0, // Hash Check X-form (hashchk RB,offset(RA)) + [6]*argField{ap_Reg_16_20, ap_NegOffset_31_31_6_10_shift3, ap_Reg_11_15}}, + {HASHCHKP, 0xfc0007fe00000000, 0x7c00056400000000, 0x0, // Hash Check Privileged X-form (hashchkp RB,offset(RA)) + [6]*argField{ap_Reg_16_20, ap_NegOffset_31_31_6_10_shift3, ap_Reg_11_15}}, + {HASHST, 0xfc0007fe00000000, 0x7c0005a400000000, 0x0, // Hash Store X-form (hashst RB,offset(RA)) + [6]*argField{ap_Reg_16_20, ap_NegOffset_31_31_6_10_shift3, ap_Reg_11_15}}, + {HASHSTP, 0xfc0007fe00000000, 0x7c00052400000000, 0x0, // Hash Store Privileged X-form (hashstp RB,offset(RA)) + [6]*argField{ap_Reg_16_20, ap_NegOffset_31_31_6_10_shift3, ap_Reg_11_15}}, {BRD, 0xfc0007fe00000000, 0x7c00017600000000, 0xf80100000000, // Byte-Reverse Doubleword X-form (brd RA,RS) [6]*argField{ap_Reg_11_15, ap_Reg_6_10}}, {BRH, 0xfc0007fe00000000, 0x7c0001b600000000, 0xf80100000000, // Byte-Reverse Halfword X-form (brh RA,RS) @@ -3344,7 +3361,7 @@ var instFormats = [...]instFormat{ [6]*argField{ap_MMAReg_6_8, ap_VecSReg_29_29_11_15, ap_VecSReg_30_30_16_20}}, {XVBF16GER2PP, 0xfc0007f800000000, 0xec00019000000000, 0x60000100000000, // VSX Vector bfloat16 GER (Rank-2 Update) Positive multiply, Positive accumulate XX3-form (xvbf16ger2pp AT,XA,XB) [6]*argField{ap_MMAReg_6_8, ap_VecSReg_29_29_11_15, ap_VecSReg_30_30_16_20}}, - {XVCVBF16SPN, 0xfc1f07fc00000000, 0xf010076c00000000, 0x0, // VSX Vector Convert bfloat16 to Single-Precision format XX2-form (xvcvbf16spn XT,XB) + {XVCVBF16SPN, 0xfc1f07fc00000000, 0xf010076c00000000, 0x0, // VSX Vector Convert bfloat16 to Single-Precision format Non-signaling XX2-form (xvcvbf16spn XT,XB) [6]*argField{ap_VecSReg_31_31_6_10, ap_VecSReg_30_30_16_20}}, {XVCVSPBF16, 0xfc1f07fc00000000, 0xf011076c00000000, 0x0, // VSX Vector Convert with round Single-Precision to bfloat16 format XX2-form (xvcvspbf16 XT,XB) [6]*argField{ap_VecSReg_31_31_6_10, ap_VecSReg_30_30_16_20}}, @@ -5334,7 +5351,7 @@ var instFormats = [...]instFormat{ [6]*argField{ap_Reg_6_10, ap_ImmSigned_16_31}}, {ADDI, 0xfc00000000000000, 0x3800000000000000, 0x0, // Add Immediate D-form (addi RT,RA,SI) [6]*argField{ap_Reg_6_10, ap_Reg_11_15, ap_ImmSigned_16_31}}, - {ADDIC, 0xfc00000000000000, 0x3000000000000000, 0x0, // Add Immediate Carrying D-formy (addic RT,RA,SI) + {ADDIC, 0xfc00000000000000, 0x3000000000000000, 0x0, // Add Immediate Carrying D-form (addic RT,RA,SI) [6]*argField{ap_Reg_6_10, ap_Reg_11_15, ap_ImmSigned_16_31}}, {ADDICCC, 0xfc00000000000000, 0x3400000000000000, 0x0, // Add Immediate Carrying and Record D-form (addic. RT,RA,SI) [6]*argField{ap_Reg_6_10, ap_Reg_11_15, ap_ImmSigned_16_31}}, diff --git a/ppc64/ppc64asm/testdata/decode.txt b/ppc64/ppc64asm/testdata/decode.txt index 7bf4355..ef5c90e 100644 --- a/ppc64/ppc64asm/testdata/decode.txt +++ b/ppc64/ppc64asm/testdata/decode.txt @@ -873,3 +873,13 @@ fc811000| plan9 FCMPU F1,F2,CR1 7c2311b8| plan9 CFUGED R1,R2,R3 04100016e4820032| gnu .quad 0x4100016e4820032 0612000138820007| gnu .quad 0x612000138820007 +7fe20de5| plan9 HASHCHK -8(R2),R1 +7fe20da5| plan9 HASHST R1,-8(R2) +7c020de4| plan9 HASHCHK -512(R2),R1 +7c020da4| plan9 HASHST R1,-512(R2) +7c020de5| plan9 HASHCHK -256(R2),R1 +7c020da5| plan9 HASHST R1,-256(R2) +7fe115a5| plan9 HASHST R2,-8(R1) +7fe11525| plan9 HASHSTP R2,-8(R1) +7fe115e5| plan9 HASHCHK -8(R1),R2 +7fe11565| plan9 HASHCHKP -8(R1),R2 diff --git a/ppc64/ppc64asm/testdata/decode_generated.txt b/ppc64/ppc64asm/testdata/decode_generated.txt index d8619d7..13345e9 100644 --- a/ppc64/ppc64asm/testdata/decode_generated.txt +++ b/ppc64/ppc64asm/testdata/decode_generated.txt @@ -1,3 +1,7 @@ +7e0115e5| gnu hashchk r2,-128(r1) +7e011565| gnu hashchkp r2,-128(r1) +7e0115a5| gnu hashst r2,-128(r1) +7e011525| gnu hashstp r2,-128(r1) 7c610176| gnu brd r1,r3 7c6101b6| gnu brh r1,r3 7c610136| gnu brw r1,r3 @@ -23,9 +27,9 @@ f03f0ad1| gnu lxvkq vs33,1 7c611138| gnu pdepd r1,r3,r2 7c611178| gnu pextd r1,r3,r2 0610001688800032| gnu plbz r4,1441842 +60000000| gnu nop 04100016e4800032| gnu pld r4,1441842 06100016c8600032| gnu plfd f3,1441842 -60000000| gnu nop 06100016c0600032| gnu plfs f3,1441842 06100016a8800032| gnu plha r4,1441842 06100016a0800032| gnu plhz r4,1441842 @@ -240,7 +244,6 @@ f02d1769| gnu xxgenpcvwm vs33,v2,13 7f810162| gnu xxmtacc a7 0500000188232a4f| gnu xxpermx vs33,vs35,vs37,vs41,1 7f830162| gnu xxsetaccz a7 -60000000| gnu nop 0500012380234567| gnu xxsplti32dx vs33,1,19088743 0500012380254567| gnu xxspltidp vs33,19088743 0500012380274567| gnu xxspltiw vs33,19088743 @@ -1214,13 +1217,13 @@ fc60382d| gnu fsqrt. f3,f7 7c611079| gnu andc. r1,r3,r2 70610000| gnu andi. r1,r3,0 74610000| gnu andis. r1,r3,0 -48000690| gnu b 0x1a90 +48000690| gnu b 0x1a9c 48000692| gnu ba 0x690 -48000691| gnu bl 0x1a98 +48000691| gnu bl 0x1aa4 48000693| gnu bla 0x690 -40860690| gnu bne cr1,0x1aa0 +40860690| gnu bne cr1,0x1aac 40860692| gnu bnea cr1,0x690 -40860691| gnu bnel cr1,0x1aa8 +40860691| gnu bnel cr1,0x1ab4 40860693| gnu bnela cr1,0x690 4c860420| gnu bnectr cr1 4c860421| gnu bnectrl cr1 diff --git a/ppc64/ppc64map/map.go b/ppc64/ppc64map/map.go index 31d692d..1e3b1b6 100644 --- a/ppc64/ppc64map/map.go +++ b/ppc64/ppc64map/map.go @@ -60,6 +60,7 @@ const ( ISA_V30B ISA_V30C ISA_V31 + ISA_V31B ) var isaToISA = map[string]isaversion{ @@ -77,6 +78,7 @@ var isaToISA = map[string]isaversion{ "v3.0B": ISA_V30B, "v3.0C": ISA_V30C, "v3.1": ISA_V31, + "v3.1B": ISA_V31B, } func usage() { @@ -482,6 +484,18 @@ func add(p *Prog, text, mnemonics, encoding, isa string) { opr = "BD" } + case "offset": + switch inst.Op { + // These encode a 6 bit displacement in the format of an X-form opcode. + // Allowable displaments are -8 to -8*64 in 8B increments. + case "hashchk", "hashchkp", "hashst", "hashstp": + typ = asm.TypeNegOffset + opr = "DX" + opr2 = "D" + shift = 3 + + } + case "XMSK", "YMSK", "PMSK", "IX", "BHRBE": typ = asm.TypeImmUnsigned @@ -737,7 +751,12 @@ var isNotMemopMap = map[string]bool{ } // Some ISA instructions are memops, but are not described like "Load ..." or "Store ..." -var isMemopMap = map[string]bool{} +var isMemopMap = map[string]bool{ + "hashst": true, + "hashstp": true, + "hashchk": true, + "hashchkp": true, +} // Does this instruction contain a memory argument (e.g x-form load or d-form store) func hasMemoryArg(insn *Inst) bool { @@ -767,7 +786,7 @@ func insnEncFuncStr(insn *Inst, firstName [2]string) string { // Does this field require an obj.Addr.Offset? isImmediate := func(t asm.ArgType) bool { - return t == asm.TypeImmUnsigned || t == asm.TypeSpReg || t == asm.TypeImmSigned || t == asm.TypeOffset + return t == asm.TypeImmUnsigned || t == asm.TypeSpReg || t == asm.TypeImmSigned || t == asm.TypeOffset || t == asm.TypeNegOffset } if insn.memOp { @@ -827,13 +846,26 @@ func insnEncFuncStr(insn *Inst, firstName [2]string) string { // Generate a check to verify shifted inputs satisfy their constraints. // For historical reasons this is not needed for 16 bit values shifted by 16. (i.e SI/UI constants in addis/xoris) - if atype.Shift != 0 && atype.Shift != 16 && bits != 32 { + if atype.Type != asm.TypeNegOffset && atype.Shift != 0 && atype.Shift != 16 && bits != 32 { arg := argOrder[j] + itype mod := (1 << atype.Shift) - 1 errCheck += fmt.Sprintf("if %s & 0x%x != 0 {\n", arg, mod) errCheck += fmt.Sprintf("c.ctxt.Diag(\"Constant 0x%%x (%%d) is not a multiple of %d\\n%%v\",%s,%s,p)\n", mod+1, arg, arg) errCheck += fmt.Sprintf("}\n") } + // NegOffset requires a stronger offset check + if atype.Type == asm.TypeNegOffset { + arg := argOrder[j] + itype + mask := -1 << (atype.BitFields.NumBits() + int(atype.Shift)) + maskl := mask // Sign bits are implied in this type. + mask |= (1 << atype.Shift) - 1 + min := maskl + max := maskl | (^mask) + step := 1 << atype.Shift + errCheck += fmt.Sprintf("if %s & 0x%x != 0x%x {\n", arg, uint32(mask), uint32(maskl)) + errCheck += fmt.Sprintf("c.ctxt.Diag(\"Constant(%%d) must within the range of [%d,%d] in steps of %d\\n%%v\",%s,p)\n", min, max, step, arg) + errCheck += fmt.Sprintf("}\n") + } j++ } buf.WriteString(errCheck) @@ -895,6 +927,8 @@ func insnTypeStr(insn *Inst, uniqueRegTypes bool) string { if atype.Shift != 0 { ret += fmt.Sprintf("%d", atype.Shift) } + case asm.TypeNegOffset: // e.g offset in hashst rb, offset(ra) + ret += "N" default: log.Fatalf("Unhandled type in insnTypeStr: %v\n", atype) } @@ -953,6 +987,14 @@ func genOptabEntry(ta *AggInfo, typeMap map[string]*Inst) string { shift = "" } } + if f.Type == asm.TypeNegOffset { + // This is a hack, but allows hashchk and like to correctly + // merge there argument into a C_SOREG memory location type + // argument a little later. + sign = "S" + bits = 16 + shift = "" + } return fmt.Sprintf("C_%s%d%sCON", sign, bits, shift) } insn := ta.Insns[0] diff --git a/ppc64/ppc64util/hack.h b/ppc64/ppc64util/hack.h index e7dada2..3fd9f31 100644 --- a/ppc64/ppc64util/hack.h +++ b/ppc64/ppc64util/hack.h @@ -129,6 +129,9 @@ #define Rpfx 1 #define SIpfx 0xFFFFFFFE00010007 +// A valid displacement value for the hash check and hash store instructions. +#define offset -128 + // These decode as m.fpr* or m.vr*. This is a matter of preference. We // don't support these mnemonics, and I don't think they improve reading // disassembled code in most cases. so ignore.