• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env ruby
2
3# Copyright (c) 2021-2022 Huawei Device Co., Ltd.
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16require_relative 'regmap'
17
18# RegMask class is like bitset
19class RegMask
20  attr_reader :value, :regmap
21
22  def initialize(*args)
23    @value = 0
24    if Options.arch == :arm64
25      @size = 31
26    elsif Options.arch == :arm32
27      @size = 16
28    elsif Options.arch == :x86_64
29      @size = 16
30    end
31    return if args.empty?
32
33    if args[0].is_a?(Regmap)
34      @regmap = args[0]
35      args = args[1..-1]
36    elsif args[0].nil?
37      args = args[1..-1]
38    elsif args[0].is_a?(RegMask)
39      @regmap = args[-0].regmap
40      @value = args[0].value
41      return
42    end
43
44    args.each do |value|
45      if value.is_a?(Symbol)
46        raise "RegMask is initialized with symbol, but Regmap wasn't specified" unless @regmap
47        value = @regmap[value]
48      end
49      raise "RegMask is initialized with wrong type: #{value.class}" unless value.is_a?(Integer)
50      self[value] = true
51    end
52  end
53
54  def self.from_value(regmap, value)
55    mask = RegMask.new(regmap)
56    mask.set_value(value)
57    mask
58  end
59
60  def self.from_regmap(regmap, map)
61    mask = RegMask.new(regmap)
62    map.data.each { |_, v| mask[v] = true }
63    mask
64  end
65
66  def set_value(value)
67    raise "RegMask is initialized with wrong type: #{value.class}" unless value.is_a?(Integer)
68    @value = value
69  end
70
71  def []=(position, value)
72    position = @regmap[position] if position.is_a? Symbol
73    raise "Wrong `position` type" unless position.is_a? Integer
74    if value
75      @value |= (1 << position)
76    else
77      @value &= ~(1 << position)
78    end
79  end
80
81  def [](position)
82    position = @regmap[position] if position.is_a? Symbol
83    raise "Wrong `position` type" unless position.is_a? Integer
84    @value & (1 << position) != 0
85  end
86
87  def +(other)
88    if other.is_a? RegMask
89      self.class.from_value(@regmap, @value | other.value)
90    elsif other.is_a? Regmap
91      other_value = other.data.values.inject(0) { |res, x| res | (1 << x) }
92      self.class.from_value(@regmap, @value | other_value)
93    elsif other.is_a? Integer
94      self.class.from_value(@regmap, @value | (1 << other))
95    elsif other.is_a? Symbol
96      raise "Symbol argument is only allowed if Regmap was specified" unless @regmap
97      value = @regmap[other]
98      raise "Register '#{other}' is not found in regmap" unless value
99      self.class.from_value(@regmap, @value | (1 << value))
100    else
101      raise "Unsupported type: #{other.class}"
102    end
103  end
104
105  def -(other)
106    if other.is_a? RegMask
107      self.class.from_value(@regmap, @value & ~other.value)
108    elsif other.is_a? Regmap
109      other_value = other.data.values.inject(0) { |res, x| res | (1 << x) }
110      self.class.from_value(@regmap, @value & ~other_value)
111    elsif other.is_a? Integer
112      self.class.from_value(@regmap, @value & ~(1 << other))
113    elsif other.is_a? Symbol
114      raise "Symbol argument is only allowed if Regmap was specified" unless @regmap
115      value = @regmap[other]
116      raise "Register '#{other}' is not found in regmap" unless value
117      self.class.from_value(@regmap, @value & ~(1 << value))
118    else
119      raise "Unsupported type: #{other.class}"
120    end
121  end
122
123  def ~
124    value = ~@value & ((1 << @size) - 1)
125    self.class.from_value(@regmap, value)
126  end
127
128  def ==(other)
129    @value == other.value
130  end
131
132  def each
133    (0..@size - 1).select { |x| self[x] }.each { |x| yield x }
134  end
135end
136