1#!/usr/bin/env ruby 2 3# Copyright (c) 2021-2024 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 raise "Regmap doesn't contain value for #{value}" unless @regmap.data.keys.include? value 48 value = @regmap[value] 49 end 50 raise "RegMask is initialized with wrong type: #{value.class}" unless value.is_a?(Integer) 51 self[value] = true 52 end 53 end 54 55 def self.from_value(regmap, value) 56 mask = RegMask.new(regmap) 57 mask.set_value(value) 58 mask 59 end 60 61 def self.from_regmap(regmap, map) 62 mask = RegMask.new(regmap) 63 map.data.each { |_, v| mask[v] = true } 64 mask 65 end 66 67 def set_value(value) 68 raise "RegMask is initialized with wrong type: #{value.class}" unless value.is_a?(Integer) 69 @value = value 70 end 71 72 def []=(position, value) 73 position = @regmap[position] if position.is_a? Symbol 74 raise "Wrong `position` type" unless position.is_a? Integer 75 if value 76 @value |= (1 << position) 77 else 78 @value &= ~(1 << position) 79 end 80 end 81 82 def [](position) 83 position = @regmap[position] if position.is_a? Symbol 84 raise "Wrong `position` type" unless position.is_a? Integer 85 @value & (1 << position) != 0 86 end 87 88 def +(other) 89 if other.is_a? RegMask 90 self.class.from_value(@regmap, @value | other.value) 91 elsif other.is_a? Regmap 92 other_value = other.data.values.inject(0) { |res, x| res | (1 << x) } 93 self.class.from_value(@regmap, @value | other_value) 94 elsif other.is_a? Integer 95 self.class.from_value(@regmap, @value | (1 << other)) 96 elsif other.is_a? Symbol 97 raise "Symbol argument is only allowed if Regmap was specified" unless @regmap 98 value = @regmap[other] 99 raise "Register '#{other}' is not found in regmap" unless value 100 self.class.from_value(@regmap, @value | (1 << value)) 101 else 102 raise "Unsupported type: #{other.class}" 103 end 104 end 105 106 def -(other) 107 if other.is_a? RegMask 108 self.class.from_value(@regmap, @value & ~other.value) 109 elsif other.is_a? Regmap 110 other_value = other.data.values.inject(0) { |res, x| res | (1 << x) } 111 self.class.from_value(@regmap, @value & ~other_value) 112 elsif other.is_a? Integer 113 self.class.from_value(@regmap, @value & ~(1 << other)) 114 elsif other.is_a? Symbol 115 raise "Symbol argument is only allowed if Regmap was specified" unless @regmap 116 value = @regmap[other] 117 raise "Register '#{other}' is not found in regmap" unless value 118 self.class.from_value(@regmap, @value & ~(1 << value)) 119 else 120 raise "Unsupported type: #{other.class}" 121 end 122 end 123 124 def ~ 125 value = ~@value & ((1 << @size) - 1) 126 self.class.from_value(@regmap, value) 127 end 128 129 def ==(other) 130 @value == other.value 131 end 132 133 def each(&block) 134 if block 135 (0..@size - 1).select { |x| self[x] }.each { |x| yield x } 136 else 137 (0..@size - 1).select { |x| self[x] } 138 end 139 end 140 141 def to_s 142 "[#{each.join(', ')}]" 143 end 144end 145