11452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee#!/usr/bin/env python 21452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 31452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Copyright (C) 2016 The Android Open Source Project 41452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 51452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Licensed under the Apache License, Version 2.0 (the "License"); 61452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# you may not use this file except in compliance with the License. 71452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# You may obtain a copy of the License at 81452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 91452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# http://www.apache.org/licenses/LICENSE-2.0 101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Unless required by applicable law or agreed to in writing, software 121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# distributed under the License is distributed on an "AS IS" BASIS, 131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# See the License for the specific language governing permissions and 151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# limitations under the License. 161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Using instructions from an architecture-specific config file, generate C 191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# and assembly source files for the Dalvik interpreter. 201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeimport sys, string, re, time 231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeefrom string import Template 241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeinterp_defs_file = "../../dex_instruction_list.h" # need opcode list 261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeekNumPackedOpcodes = 256 271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeesplitops = False 291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeverbose = False 301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeehandler_size_bits = -1000 311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeehandler_size_bytes = -1000 321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeein_op_start = 0 # 0=not started, 1=started, 2=ended 331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeein_alt_op_start = 0 # 0=not started, 1=started, 2=ended 341452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedefault_op_dir = None 351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedefault_alt_stub = None 361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeopcode_locations = {} 371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeealt_opcode_locations = {} 381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeasm_stub_text = [] 391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeefallback_stub_text = [] 401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeelabel_prefix = ".L" # use ".L" to hide labels from gdb 411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeealt_label_prefix = ".L_ALT" # use ".L" to hide labels from gdb 421452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeestyle = None # interpreter style 431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeegenerate_alt_table = False 4405dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkovfunction_type_format = ".type %s, %%function" 4505dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkovfunction_size_format = ".size %s, .-%s" 4605dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkovglobal_name_format = "%s" 471452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 481452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Exception class. 491452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeclass DataParseError(SyntaxError): 501452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee "Failure when parsing data file" 511452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 531452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Set any omnipresent substitution values. 541452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 551452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef getGlobalSubDict(): 561452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee return { "handler_size_bits":handler_size_bits, 571452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee "handler_size_bytes":handler_size_bytes } 581452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 591452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 601452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Parse arch config file -- 611452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Set interpreter style. 621452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 631452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef setHandlerStyle(tokens): 641452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee global style 651452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) != 2: 661452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("handler-style requires one argument") 671452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee style = tokens[1] 681452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if style != "computed-goto": 691452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("handler-style (%s) invalid" % style) 701452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Parse arch config file -- 731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Set handler_size_bytes to the value of tokens[1], and handler_size_bits to 741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# log2(handler_size_bytes). Throws an exception if "bytes" is not 0 or 751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# a power of two. 761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef setHandlerSize(tokens): 781452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee global handler_size_bits, handler_size_bytes 791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if style != "computed-goto": 801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print "Warning: handler-size valid only for computed-goto interpreters" 811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) != 2: 821452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("handler-size requires one argument") 831452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if handler_size_bits != -1000: 841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("handler-size may only be set once") 851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 861452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # compute log2(n), and make sure n is 0 or a power of 2 871452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee handler_size_bytes = bytes = int(tokens[1]) 881452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee bits = -1 891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee while bytes > 0: 901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee bytes //= 2 # halve with truncating division 911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee bits += 1 921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if handler_size_bytes == 0 or handler_size_bytes != (1 << bits): 941452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("handler-size (%d) must be power of 2" \ 951452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee % orig_bytes) 961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee handler_size_bits = bits 971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Parse arch config file -- 1001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Copy a file in to asm output file. 1011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 1021452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef importFile(tokens): 1031452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) != 2: 1041452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("import requires one argument") 1051452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee source = tokens[1] 1061452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if source.endswith(".S"): 1071452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee appendSourceFile(tokens[1], getGlobalSubDict(), asm_fp, None) 1081452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee else: 1091452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("don't know how to import %s (expecting .cpp/.S)" 1101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee % source) 1111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 1121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 1131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Parse arch config file -- 1141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Copy a file in to the C or asm output file. 1151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 1161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef setAsmStub(tokens): 1171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee global asm_stub_text 1181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) != 2: 1191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("import requires one argument") 1201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee try: 1211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee stub_fp = open(tokens[1]) 1221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_stub_text = stub_fp.readlines() 1231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee except IOError, err: 1241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee stub_fp.close() 1251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("unable to load asm-stub: %s" % str(err)) 1261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee stub_fp.close() 1271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 1281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 1291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Parse arch config file -- 1301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Copy a file in to the C or asm output file. 1311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 1321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef setFallbackStub(tokens): 1331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee global fallback_stub_text 1341452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) != 2: 1351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("import requires one argument") 1361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee try: 1371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee stub_fp = open(tokens[1]) 1381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee fallback_stub_text = stub_fp.readlines() 1391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee except IOError, err: 1401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee stub_fp.close() 1411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("unable to load fallback-stub: %s" % str(err)) 1421452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee stub_fp.close() 1431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 1441452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Parse arch config file -- 1451452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Record location of default alt stub 1461452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 1471452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef setAsmAltStub(tokens): 1481452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee global default_alt_stub, generate_alt_table 1491452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) != 2: 1501452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("import requires one argument") 1511452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee default_alt_stub = tokens[1] 1521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee generate_alt_table = True 15305dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov# 15405dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov# Change the default function type format 15505dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov# 15605dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkovdef setFunctionTypeFormat(tokens): 15705dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov global function_type_format 15805dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov function_type_format = tokens[1] 15905dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov# 16005dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov# Change the default function size format 16105dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov# 16205dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkovdef setFunctionSizeFormat(tokens): 16305dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov global function_size_format 16405dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov function_size_format = tokens[1] 16505dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov# 16605dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov# Change the global name format 16705dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov# 16805dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkovdef setGlobalNameFormat(tokens): 16905dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov global global_name_format 17005dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov global_name_format = tokens[1] 1711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 1721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Parse arch config file -- 1731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Start of opcode list. 1741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 1751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef opStart(tokens): 1761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee global in_op_start 1771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee global default_op_dir 1781452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) != 2: 1791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("opStart takes a directory name argument") 1801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if in_op_start != 0: 1811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("opStart can only be specified once") 1821452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee default_op_dir = tokens[1] 1831452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee in_op_start = 1 1841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 1851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 1861452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Parse arch config file -- 1871452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Set location of a single alt opcode's source file. 1881452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 1891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef altEntry(tokens): 1901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee global generate_alt_table 1911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) != 3: 1921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("alt requires exactly two arguments") 1931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if in_op_start != 1: 1941452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("alt statements must be between opStart/opEnd") 1951452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee try: 1961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee index = opcodes.index(tokens[1]) 1971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee except ValueError: 1981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("unknown opcode %s" % tokens[1]) 1991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if alt_opcode_locations.has_key(tokens[1]): 2001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print "Note: alt overrides earlier %s (%s -> %s)" \ 2011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee % (tokens[1], alt_opcode_locations[tokens[1]], tokens[2]) 2021452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee alt_opcode_locations[tokens[1]] = tokens[2] 2031452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee generate_alt_table = True 2041452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2051452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 2061452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Parse arch config file -- 2071452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Set location of a single opcode's source file. 2081452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 2091452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef opEntry(tokens): 2101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee #global opcode_locations 2111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) != 3: 2121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("op requires exactly two arguments") 2131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if in_op_start != 1: 2141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("op statements must be between opStart/opEnd") 2151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee try: 2161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee index = opcodes.index(tokens[1]) 2171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee except ValueError: 2181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("unknown opcode %s" % tokens[1]) 2191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if opcode_locations.has_key(tokens[1]): 2201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print "Note: op overrides earlier %s (%s -> %s)" \ 2211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee % (tokens[1], opcode_locations[tokens[1]], tokens[2]) 2221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee opcode_locations[tokens[1]] = tokens[2] 2231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 2251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Parse arch config file -- 2261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# End of opcode list; emit instruction blocks. 2271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 2281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef opEnd(tokens): 2291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee global in_op_start 2301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) != 1: 2311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("opEnd takes no arguments") 2321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if in_op_start != 1: 2331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("opEnd must follow opStart, and only appear once") 2341452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee in_op_start = 2 2351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee loadAndEmitOpcodes() 2371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if splitops == False: 2381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if generate_alt_table: 2391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee loadAndEmitAltOpcodes() 2401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef genaltop(tokens): 2421452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if in_op_start != 2: 2431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("alt-op can be specified only after op-end") 2441452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) != 1: 2451452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("opEnd takes no arguments") 2461452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if generate_alt_table: 2471452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee loadAndEmitAltOpcodes() 2481452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2491452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 2501452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Extract an ordered list of instructions from the VM sources. We use the 2511452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# "goto table" definition macro, which has exactly kNumPackedOpcodes 2521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# entries. 2531452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 2541452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef getOpcodeList(): 2551452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee opcodes = [] 2561452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee opcode_fp = open(interp_defs_file) 2571452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee opcode_re = re.compile(r"^\s*V\((....), (\w+),.*", re.DOTALL) 2581452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee for line in opcode_fp: 2591452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee match = opcode_re.match(line) 2601452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if not match: 2611452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee continue 2621452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee opcodes.append("op_" + match.group(2).lower()) 2631452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee opcode_fp.close() 2641452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2651452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(opcodes) != kNumPackedOpcodes: 2661452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print "ERROR: found %d opcodes in Interp.h (expected %d)" \ 2671452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee % (len(opcodes), kNumPackedOpcodes) 2681452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise SyntaxError, "bad opcode count" 2691452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee return opcodes 2701452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef emitAlign(): 2721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if style == "computed-goto": 2731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write(" .balign %d\n" % handler_size_bytes) 2741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 2761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Load and emit opcodes for all kNumPackedOpcodes instructions. 2771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 2781452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef loadAndEmitOpcodes(): 2791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee sister_list = [] 2801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee assert len(opcodes) == kNumPackedOpcodes 2811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee need_dummy_start = False 28205dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov start_label = global_name_format % "artMterpAsmInstructionStart" 28305dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov end_label = global_name_format % "artMterpAsmInstructionEnd" 2841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # point MterpAsmInstructionStart at the first handler or stub 2861452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write("\n .global %s\n" % start_label) 28705dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov asm_fp.write(" " + (function_type_format % start_label) + "\n"); 2881452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write("%s = " % start_label + label_prefix + "_op_nop\n") 2891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write(" .text\n\n") 2901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee for i in xrange(kNumPackedOpcodes): 2921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee op = opcodes[i] 2931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2941452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if opcode_locations.has_key(op): 2951452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee location = opcode_locations[op] 2961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee else: 2971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee location = default_op_dir 2981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 2991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if location == "FALLBACK": 3001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee emitFallback(i) 3011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee else: 3021452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee loadAndEmitAsm(location, i, sister_list) 3031452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3041452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # For a 100% C implementation, there are no asm handlers or stubs. We 3051452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # need to have the MterpAsmInstructionStart label point at op_nop, and it's 3061452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # too annoying to try to slide it in after the alignment psuedo-op, so 3071452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # we take the low road and just emit a dummy op_nop here. 3081452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if need_dummy_start: 3091452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee emitAlign() 3101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write(label_prefix + "_op_nop: /* dummy */\n"); 3111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee emitAlign() 31305dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov asm_fp.write(" " + (function_size_format % (start_label, start_label)) + "\n") 3141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write(" .global %s\n" % end_label) 3151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write("%s:\n" % end_label) 3161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if style == "computed-goto": 31805dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov start_sister_label = global_name_format % "artMterpAsmSisterStart" 31905dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov end_sister_label = global_name_format % "artMterpAsmSisterEnd" 3201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee emitSectionComment("Sister implementations", asm_fp) 32105dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov asm_fp.write(" .global %s\n" % start_sister_label) 32205dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov asm_fp.write(" " + (function_type_format % start_sister_label) + "\n"); 3231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write(" .text\n") 3241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write(" .balign 4\n") 32505dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov asm_fp.write("%s:\n" % start_sister_label) 3261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.writelines(sister_list) 32705dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov asm_fp.write("\n " + (function_size_format % (start_sister_label, start_sister_label)) + "\n") 32805dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov asm_fp.write(" .global %s\n" % end_sister_label) 32905dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov asm_fp.write("%s:\n\n" % end_sister_label) 3301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 3321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Load an alternate entry stub 3331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 3341452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef loadAndEmitAltStub(source, opindex): 3351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee op = opcodes[opindex] 3361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if verbose: 3371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print " alt emit %s --> stub" % source 3381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee dict = getGlobalSubDict() 3391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee dict.update({ "opcode":op, "opnum":opindex }) 3401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee emitAsmHeader(asm_fp, dict, alt_label_prefix) 3421452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee appendSourceFile(source, dict, asm_fp, None) 3431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3441452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 3451452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Load and emit alternate opcodes for all kNumPackedOpcodes instructions. 3461452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 3471452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef loadAndEmitAltOpcodes(): 3481452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee assert len(opcodes) == kNumPackedOpcodes 34905dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov start_label = global_name_format % "artMterpAsmAltInstructionStart" 35005dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov end_label = global_name_format % "artMterpAsmAltInstructionEnd" 3511452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # point MterpAsmInstructionStart at the first handler or stub 3531452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write("\n .global %s\n" % start_label) 35405dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov asm_fp.write(" " + (function_type_format % start_label) + "\n"); 3551452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write(" .text\n\n") 3561452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write("%s = " % start_label + label_prefix + "_ALT_op_nop\n") 3571452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3581452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee for i in xrange(kNumPackedOpcodes): 3591452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee op = opcodes[i] 3601452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if alt_opcode_locations.has_key(op): 3611452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee source = "%s/alt_%s.S" % (alt_opcode_locations[op], op) 3621452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee else: 3631452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee source = default_alt_stub 3641452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee loadAndEmitAltStub(source, i) 3651452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3661452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee emitAlign() 36705dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov asm_fp.write(" " + (function_size_format % (start_label, start_label)) + "\n") 3681452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write(" .global %s\n" % end_label) 3691452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write("%s:\n" % end_label) 3701452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 3721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Load an assembly fragment and emit it. 3731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 3741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef loadAndEmitAsm(location, opindex, sister_list): 3751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee op = opcodes[opindex] 3761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee source = "%s/%s.S" % (location, op) 3771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee dict = getGlobalSubDict() 3781452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee dict.update({ "opcode":op, "opnum":opindex }) 3791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if verbose: 3801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print " emit %s --> asm" % source 3811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3821452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee emitAsmHeader(asm_fp, dict, label_prefix) 3831452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee appendSourceFile(source, dict, asm_fp, sister_list) 3841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 3861452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Emit fallback fragment 3871452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 3881452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef emitFallback(opindex): 3891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee op = opcodes[opindex] 3901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee dict = getGlobalSubDict() 3911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee dict.update({ "opcode":op, "opnum":opindex }) 3921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee emitAsmHeader(asm_fp, dict, label_prefix) 3931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee for line in fallback_stub_text: 3941452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write(line) 3951452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.write("\n") 3961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 3971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 3981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Output the alignment directive and label for an assembly piece. 3991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 4001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef emitAsmHeader(outfp, dict, prefix): 4011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee outfp.write("/* ------------------------------ */\n") 4021452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # The alignment directive ensures that the handler occupies 4031452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # at least the correct amount of space. We don't try to deal 4041452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # with overflow here. 4051452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee emitAlign() 4061452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # Emit a label so that gdb will say the right thing. We prepend an 4071452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # underscore so the symbol name doesn't clash with the Opcode enum. 4081452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee outfp.write(prefix + "_%(opcode)s: /* 0x%(opnum)02x */\n" % dict) 4091452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 4101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 4111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Output a generic instruction stub that updates the "glue" struct and 4121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# calls the C implementation. 4131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 4141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef emitAsmStub(outfp, dict): 4151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee emitAsmHeader(outfp, dict, label_prefix) 4161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee for line in asm_stub_text: 4171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee templ = Template(line) 4181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee outfp.write(templ.substitute(dict)) 4191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 4201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 4211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Append the file specified by "source" to the open "outfp". Each line will 4221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# be template-replaced using the substitution dictionary "dict". 4231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 4241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# If the first line of the file starts with "%" it is taken as a directive. 4251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# A "%include" line contains a filename and, optionally, a Python-style 4261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# dictionary declaration with substitution strings. (This is implemented 4271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# with recursion.) 4281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 4291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# If "sister_list" is provided, and we find a line that contains only "&", 4301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# all subsequent lines from the file will be appended to sister_list instead 4311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# of copied to the output. 4321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 4331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# This may modify "dict". 4341452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 4351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef appendSourceFile(source, dict, outfp, sister_list): 4361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee outfp.write("/* File: %s */\n" % source) 4371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee infp = open(source, "r") 4381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee in_sister = False 4391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee for line in infp: 4401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if line.startswith("%include"): 4411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # Parse the "include" line 4421452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee tokens = line.strip().split(' ', 2) 4431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) < 2: 4441452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("malformed %%include in %s" % source) 4451452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 4461452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee alt_source = tokens[1].strip("\"") 4471452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if alt_source == source: 4481452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("self-referential %%include in %s" 4491452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee % source) 4501452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 4511452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee new_dict = dict.copy() 4521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) == 3: 4531452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee new_dict.update(eval(tokens[2])) 4541452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee #print " including src=%s dict=%s" % (alt_source, new_dict) 4551452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee appendSourceFile(alt_source, new_dict, outfp, sister_list) 4561452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee continue 4571452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 4581452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif line.startswith("%default"): 4591452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # copy keywords into dictionary 4601452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee tokens = line.strip().split(' ', 1) 4611452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens) < 2: 4621452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("malformed %%default in %s" % source) 4631452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee defaultValues = eval(tokens[1]) 4641452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee for entry in defaultValues: 4651452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee dict.setdefault(entry, defaultValues[entry]) 4661452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee continue 4671452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 4681452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif line.startswith("%break") and sister_list != None: 4691452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # allow more than one %break, ignoring all following the first 4701452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if style == "computed-goto" and not in_sister: 4711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee in_sister = True 4721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee sister_list.append("\n/* continuation for %(opcode)s */\n"%dict) 4731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee continue 4741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 4751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # perform keyword substitution if a dictionary was provided 4761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if dict != None: 4771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee templ = Template(line) 4781452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee try: 4791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee subline = templ.substitute(dict) 4801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee except KeyError, err: 4811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError("keyword substitution failed in %s: %s" 4821452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee % (source, str(err))) 4831452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee except: 4841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print "ERROR: substitution failed: " + line 4851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise 4861452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee else: 4871452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee subline = line 4881452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 4891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # write output to appropriate file 4901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if in_sister: 4911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee sister_list.append(subline) 4921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee else: 4931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee outfp.write(subline) 4941452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee outfp.write("\n") 4951452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee infp.close() 4961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 4971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 4981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Emit a C-style section header comment. 4991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeedef emitSectionComment(str, fp): 5011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee equals = "========================================" \ 5021452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee "===================================" 5031452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5041452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee fp.write("\n/*\n * %s\n * %s\n * %s\n */\n" % 5051452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee (equals, str, equals)) 5061452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5071452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5081452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5091452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# =========================================================================== 5101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# "main" code 5111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Check args. 5151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeif len(sys.argv) != 3: 5171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print "Usage: %s target-arch output-dir" % sys.argv[0] 5181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee sys.exit(2) 5191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeetarget_arch = sys.argv[1] 5211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeoutput_dir = sys.argv[2] 5221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Extract opcode list. 5251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeopcodes = getOpcodeList() 5271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee#for op in opcodes: 5281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# print " %s" % op 5291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5311452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Open config file. 5321452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5331452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeetry: 5341452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee config_fp = open("config_%s" % target_arch) 5351452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeexcept: 5361452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print "Unable to open config file 'config_%s'" % target_arch 5371452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee sys.exit(1) 5381452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5391452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5401452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Open and prepare output files. 5411452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5421452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeetry: 5431452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp = open("%s/mterp_%s.S" % (output_dir, target_arch), "w") 5441452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeexcept: 5451452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print "Unable to open output files" 5461452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print "Make sure directory '%s' exists and existing files are writable" \ 5471452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee % output_dir 5481452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # Ideally we'd remove the files to avoid confusing "make", but if they 5491452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # failed to open we probably won't be able to remove them either. 5501452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee sys.exit(1) 5511452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5521452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeprint "Generating %s" % (asm_fp.name) 5531452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5541452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeefile_header = """/* 5551452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * This file was generated automatically by gen-mterp.py for '%s'. 5561452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * 5571452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee * --> DO NOT EDIT <-- 5581452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee */ 5591452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5601452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee""" % (target_arch) 5611452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5621452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeasm_fp.write(file_header) 5631452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 5641452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5651452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Process the config file. 5661452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 5671452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeefailed = False 5681452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeetry: 5691452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee for line in config_fp: 5701452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee line = line.strip() # remove CRLF, leading spaces 5711452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee tokens = line.split(' ') # tokenize 5721452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee #print "%d: %s" % (len(tokens), tokens) 5731452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if len(tokens[0]) == 0: 5741452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee #print " blank" 5751452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee pass 5761452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0][0] == '#': 5771452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee #print " comment" 5781452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee pass 5791452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee else: 5801452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if tokens[0] == "handler-size": 5811452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee setHandlerSize(tokens) 5821452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0] == "import": 5831452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee importFile(tokens) 5841452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0] == "asm-stub": 5851452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee setAsmStub(tokens) 5861452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0] == "asm-alt-stub": 5871452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee setAsmAltStub(tokens) 5881452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0] == "op-start": 5891452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee opStart(tokens) 5901452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0] == "op-end": 5911452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee opEnd(tokens) 5921452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0] == "alt": 5931452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee altEntry(tokens) 5941452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0] == "op": 5951452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee opEntry(tokens) 5961452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0] == "handler-style": 5971452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee setHandlerStyle(tokens) 5981452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0] == "alt-ops": 5991452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee genaltop(tokens) 6001452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0] == "split-ops": 6011452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee splitops = True 6021452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee elif tokens[0] == "fallback-stub": 6031452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee setFallbackStub(tokens) 60405dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov elif tokens[0] == "function-type-format": 60505dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov setFunctionTypeFormat(tokens) 60605dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov elif tokens[0] == "function-size-format": 60705dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov setFunctionSizeFormat(tokens) 60805dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov elif tokens[0] == "global-name-format": 60905dfaaa8d1783bcf8fe603dd8ed260a939e846c0Serguei Katkov setGlobalNameFormat(tokens) 6101452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee else: 6111452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError, "unrecognized command '%s'" % tokens[0] 6121452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee if style == None: 6131452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print "tokens[0] = %s" % tokens[0] 6141452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee raise DataParseError, "handler-style must be first command" 6151452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeexcept DataParseError, err: 6161452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee print "Failed: " + str(err) 6171452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee # TODO: remove output files so "make" doesn't get confused 6181452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee failed = True 6191452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.close() 6201452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp = None 6211452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 6221452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeconfig_fp.close() 6231452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 6241452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 6251452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# Done! 6261452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee# 6271452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeeif asm_fp: 6281452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee asm_fp.close() 6291452bee8f06b9f76a333ddf4760e4beaa82f8099buzbee 6301452bee8f06b9f76a333ddf4760e4beaa82f8099buzbeesys.exit(failed) 631