# Path: awake/instruction.py
# class BadOpcode(Instruction):
#     def __init__(self, opcodes, addr):
#         super(BadOpcode, self).__init__("BAD-OP", addr)
# 
#     def hasContinue(self):
#         return False
# 
# Path: awake/singledecoder.py
# class SingleOpcodeDecoder(object):
#     def __init__(self, text):
# 
#         bit_format, effect_format = text.split('@', 2)
# 
#         items = bit_format.split(None, 3)
# 
#         self.bitPattern = items[0]
#         self.cycles = int(items[1])
#         self.name = items[2];
# 
#         operandText = "";
#         if len(items) >= 4:
#             operandText = items[3]
# 
#         if not operandText:
#             self.operands = []
#         else:
#             self.operands = [x.strip() for x in operandText.split(", ")]
# 
#         if "v16" in operandText:
#             self.argSize = 2;
#         elif "v8" in operandText:
#             self.argSize = 1;
#         else:
#             self.argSize = 0;
# 
#         assert len(self.bitPattern) == 8
# 
#         self.effect = OpcodeEffect(effect_format)
# 
# 
#     def matchBits(self, opcode):
#         params = defaultdict(int)
#         opcode_bits = bin(opcode)[2:].zfill(8)
# 
#         for (x, y) in zip(self.bitPattern, opcode_bits):
#             if x in ('0', '1'):
#                 if x != y:
#                     return None
#             else:
#                 # update according parameter
#                 params[x] <<= 1
#                 params[x] |= int(y)
# 
#         return params
# 
#     def match(self, opcode):
#         return self.matchBits(opcode) is not None
# 
#     def length(self):
#         return 1 + self.argSize
# 
#     def decode(self, proj, opcodes, addr):
#         assert len(opcodes) == self.length()
# 
#         params = self.matchBits(opcodes[0])
# 
#         argument = 0
#         if self.argSize == 1:
#             argument = opcodes[1]
#         elif self.argSize == 2:
#             argument = (opcodes[2] << 8) | opcodes[1];
# 
#         next_addr = addr.offset(self.length())
# 
#         out_operands = [
#             fillOperand(text, params, argument, next_addr) for text in self.operands
#         ]
# 
#         reads, writes, values, loads = self.effect.filled(params, make_context(params, argument, next_addr))
# 
#         return instruction.make(proj, self.name, out_operands, addr, reads, writes, values, loads), next_addr


from awake.instruction import BadOpcode
from awake.singledecoder import SingleOpcodeDecoder
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


class OpcodeDispatcher(object):

    def __init__(self, opcodeFormats):
        self.dispatchTable = dict()
        for bit_format in opcodeFormats:
            if not bit_format:
                continue

            decoder = SingleOpcodeDecoder(bit_format)
            for i in range(256):
                byte = i & 0xFF
                if decoder.match(byte):
                    self.dispatchTable[byte] = decoder

    def decode(self, proj, addr):
        entry = proj.rom.get(addr)
        if entry not in self.dispatchTable:
            print('WARN: bad opcode', addr)

# Path: awake/instruction.py
# class BadOpcode(Instruction):
#     def __init__(self, opcodes, addr):
#         super(BadOpcode, self).__init__("BAD-OP", addr)
# 
#     def hasContinue(self):
#         return False
# 
# Path: awake/singledecoder.py
# class SingleOpcodeDecoder(object):
#     def __init__(self, text):
# 
#         bit_format, effect_format = text.split('@', 2)
# 
#         items = bit_format.split(None, 3)
# 
#         self.bitPattern = items[0]
#         self.cycles = int(items[1])
#         self.name = items[2];
# 
#         operandText = "";
#         if len(items) >= 4:
#             operandText = items[3]
# 
#         if not operandText:
#             self.operands = []
#         else:
#             self.operands = [x.strip() for x in operandText.split(", ")]
# 
#         if "v16" in operandText:
#             self.argSize = 2;
#         elif "v8" in operandText:
#             self.argSize = 1;
#         else:
#             self.argSize = 0;
# 
#         assert len(self.bitPattern) == 8
# 
#         self.effect = OpcodeEffect(effect_format)
# 
# 
#     def matchBits(self, opcode):
#         params = defaultdict(int)
#         opcode_bits = bin(opcode)[2:].zfill(8)
# 
#         for (x, y) in zip(self.bitPattern, opcode_bits):
#             if x in ('0', '1'):
#                 if x != y:
#                     return None
#             else:
#                 # update according parameter
#                 params[x] <<= 1
#                 params[x] |= int(y)
# 
#         return params
# 
#     def match(self, opcode):
#         return self.matchBits(opcode) is not None
# 
#     def length(self):
#         return 1 + self.argSize
# 
#     def decode(self, proj, opcodes, addr):
#         assert len(opcodes) == self.length()
# 
#         params = self.matchBits(opcodes[0])
# 
#         argument = 0
#         if self.argSize == 1:
#             argument = opcodes[1]
#         elif self.argSize == 2:
#             argument = (opcodes[2] << 8) | opcodes[1];
# 
#         next_addr = addr.offset(self.length())
# 
#         out_operands = [
#             fillOperand(text, params, argument, next_addr) for text in self.operands
#         ]
# 
#         reads, writes, values, loads = self.effect.filled(params, make_context(params, argument, next_addr))
# 
#         return instruction.make(proj, self.name, out_operands, addr, reads, writes, values, loads), next_addr


# Path: awake/opcodedispatcher.py
from awake.instruction import BadOpcode
from awake.singledecoder import SingleOpcodeDecoder

# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


class OpcodeDispatcher(object):

    def __init__(self, opcodeFormats):
        self.dispatchTable = dict()
        for bit_format in opcodeFormats:
            if not bit_format:
                continue

            decoder = SingleOpcodeDecoder(bit_format)
            for i in range(256):
                byte = i & 0xFF
                if decoder.match(byte):
                    self.dispatchTable[byte] = decoder

    def decode(self, proj, addr):
        entry = proj.rom.get(addr)
        if entry not in self.dispatchTable:
            print('WARN: bad opcode', addr)

            return BadOpcode([entry], addr), None