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