1// Copyright 2014 The Go Authors.  All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package ppc64asm
6
7import (
8	"fmt"
9	"strings"
10)
11
12// A BitField is a bit-field in a 32-bit word.
13// Bits are counted from 0 from the MSB to 31 as the LSB.
14type BitField struct {
15	Offs uint8 // the offset of the left-most bit.
16	Bits uint8 // length in bits.
17	// This instruction word holding this field.
18	// It is always 0 for ISA < 3.1 instructions. It is
19	// in decoding order. (0 == prefix, 1 == suffix on ISA 3.1)
20	Word uint8
21}
22
23func (b BitField) String() string {
24	if b.Bits > 1 {
25		return fmt.Sprintf("[%d:%d]", b.Offs, int(b.Offs+b.Bits)-1)
26	} else if b.Bits == 1 {
27		return fmt.Sprintf("[%d]", b.Offs)
28	} else {
29		return fmt.Sprintf("[%d, len=0]", b.Offs)
30	}
31}
32
33// Parse extracts the bitfield b from i, and return it as an unsigned integer.
34// Parse will panic if b is invalid.
35func (b BitField) Parse(i [2]uint32) uint32 {
36	if b.Bits > 32 || b.Bits == 0 || b.Offs > 31 || b.Offs+b.Bits > 32 {
37		panic(fmt.Sprintf("invalid bitfiled %v", b))
38	}
39	return (i[b.Word] >> (32 - b.Offs - b.Bits)) & ((1 << b.Bits) - 1)
40}
41
42// ParseSigned extracts the bitfield b from i, and return it as a signed integer.
43// ParseSigned will panic if b is invalid.
44func (b BitField) ParseSigned(i [2]uint32) int32 {
45	u := int32(b.Parse(i))
46	return u << (32 - b.Bits) >> (32 - b.Bits)
47}
48
49// BitFields is a series of BitFields representing a single number.
50type BitFields []BitField
51
52func (bs BitFields) String() string {
53	ss := make([]string, len(bs))
54	for i, bf := range bs {
55		ss[i] = bf.String()
56	}
57	return fmt.Sprintf("<%s>", strings.Join(ss, "|"))
58}
59
60func (bs *BitFields) Append(b BitField) {
61	*bs = append(*bs, b)
62}
63
64// parse extracts the bitfields from i, concatenate them and return the result
65// as an unsigned integer and the total length of all the bitfields.
66// parse will panic if any bitfield in b is invalid, but it doesn't check if
67// the sequence of bitfields is reasonable.
68func (bs BitFields) parse(i [2]uint32) (u uint64, Bits uint8) {
69	for _, b := range bs {
70		u = (u << b.Bits) | uint64(b.Parse(i))
71		Bits += b.Bits
72	}
73	return u, Bits
74}
75
76// Parse extracts the bitfields from i, concatenate them and return the result
77// as an unsigned integer. Parse will panic if any bitfield in b is invalid.
78func (bs BitFields) Parse(i [2]uint32) uint64 {
79	u, _ := bs.parse(i)
80	return u
81}
82
83// ParseSigned extracts the bitfields from i, concatenate them and return the result
84// as a signed integer. Parse will panic if any bitfield in b is invalid.
85func (bs BitFields) ParseSigned(i [2]uint32) int64 {
86	u, l := bs.parse(i)
87	return int64(u) << (64 - l) >> (64 - l)
88}
89
90// Count the number of bits in the aggregate BitFields
91func (bs BitFields) NumBits() int {
92	num := 0
93	for _, b := range bs {
94		num += int(b.Bits)
95	}
96	return num
97}
98