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}
18
19func (b BitField) String() string {
20	if b.Bits > 1 {
21		return fmt.Sprintf("[%d:%d]", b.Offs, int(b.Offs+b.Bits)-1)
22	} else if b.Bits == 1 {
23		return fmt.Sprintf("[%d]", b.Offs)
24	} else {
25		return fmt.Sprintf("[%d, len=0]", b.Offs)
26	}
27}
28
29// Parse extracts the bitfield b from i, and return it as an unsigned integer.
30// Parse will panic if b is invalid.
31func (b BitField) Parse(i uint32) uint32 {
32	if b.Bits > 32 || b.Bits == 0 || b.Offs > 31 || b.Offs+b.Bits > 32 {
33		panic(fmt.Sprintf("invalid bitfiled %v", b))
34	}
35	return (i >> (32 - b.Offs - b.Bits)) & ((1 << b.Bits) - 1)
36}
37
38// ParseSigned extracts the bitfield b from i, and return it as a signed integer.
39// ParseSigned will panic if b is invalid.
40func (b BitField) ParseSigned(i uint32) int32 {
41	u := int32(b.Parse(i))
42	return u << (32 - b.Bits) >> (32 - b.Bits)
43}
44
45// BitFields is a series of BitFields representing a single number.
46type BitFields []BitField
47
48func (bs BitFields) String() string {
49	ss := make([]string, len(bs))
50	for i, bf := range bs {
51		ss[i] = bf.String()
52	}
53	return fmt.Sprintf("<%s>", strings.Join(ss, "|"))
54}
55
56func (bs *BitFields) Append(b BitField) {
57	*bs = append(*bs, b)
58}
59
60// parse extracts the bitfields from i, concatenate them and return the result
61// as an unsigned integer and the total length of all the bitfields.
62// parse will panic if any bitfield in b is invalid, but it doesn't check if
63// the sequence of bitfields is reasonable.
64func (bs BitFields) parse(i uint32) (u uint32, Bits uint8) {
65	for _, b := range bs {
66		u = (u << b.Bits) | b.Parse(i)
67		Bits += b.Bits
68	}
69	return u, Bits
70}
71
72// Parse extracts the bitfields from i, concatenate them and return the result
73// as an unsigned integer. Parse will panic if any bitfield in b is invalid.
74func (bs BitFields) Parse(i uint32) uint32 {
75	u, _ := bs.parse(i)
76	return u
77}
78
79// Parse extracts the bitfields from i, concatenate them and return the result
80// as a signed integer. Parse will panic if any bitfield in b is invalid.
81func (bs BitFields) ParseSigned(i uint32) int32 {
82	u, l := bs.parse(i)
83	return int32(u) << (32 - l) >> (32 - l)
84}
85