1ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#!/usr/bin/env python 2ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 3ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Copyright (C) 2007 The Android Open Source Project 4ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 5ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Licensed under the Apache License, Version 2.0 (the "License"); 6ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# you may not use this file except in compliance with the License. 7ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# You may obtain a copy of the License at 8ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 9ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# http://www.apache.org/licenses/LICENSE-2.0 10ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 11ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Unless required by applicable law or agreed to in writing, software 12ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# distributed under the License is distributed on an "AS IS" BASIS, 13ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# See the License for the specific language governing permissions and 15ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# limitations under the License. 16ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 17ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 18ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Using instructions from an architecture-specific config file, generate C 19ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# and assembly source files for the Dalvik JIT. 20ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 21ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 22ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengimport sys, string, re, time 23ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengfrom string import Template 24ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 25ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chenginterp_defs_file = "TemplateOpList.h" # need opcode list 26ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 27ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chenghandler_size_bits = -1000 28ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chenghandler_size_bytes = -1000 29ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengin_op_start = 0 # 0=not started, 1=started, 2=ended 30ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdefault_op_dir = None 31ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengopcode_locations = {} 32ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengasm_stub_text = [] 33ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chenglabel_prefix = ".L" # use ".L" to hide labels from gdb 34ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 35ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 36ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Exception class. 37ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengclass DataParseError(SyntaxError): 38ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng "Failure when parsing data file" 39ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 40ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 41ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Set any omnipresent substitution values. 42ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 43ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef getGlobalSubDict(): 44ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return { "handler_size_bits":handler_size_bits, 45ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng "handler_size_bytes":handler_size_bytes } 46ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 47ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 48ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Parse arch config file -- 49ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Set handler_size_bytes to the value of tokens[1], and handler_size_bits to 50ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# log2(handler_size_bytes). Throws an exception if "bytes" is not a power 51ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# of two. 52ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 53ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef setHandlerSize(tokens): 54ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng global handler_size_bits, handler_size_bytes 55ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if len(tokens) != 2: 56ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("handler-size requires one argument") 57ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if handler_size_bits != -1000: 58ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("handler-size may only be set once") 59ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 60ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # compute log2(n), and make sure n is a power of 2 61ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng handler_size_bytes = bytes = int(tokens[1]) 62ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng bits = -1 63ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng while bytes > 0: 64ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng bytes //= 2 # halve with truncating division 65ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng bits += 1 66ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 67ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if handler_size_bytes == 0 or handler_size_bytes != (1 << bits): 68ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("handler-size (%d) must be power of 2 and > 0" \ 69ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng % orig_bytes) 70ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng handler_size_bits = bits 71ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 72ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 73ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Parse arch config file -- 74ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Copy a file in to the C or asm output file. 75ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 76ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef importFile(tokens): 77ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if len(tokens) != 2: 78ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("import requires one argument") 79ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng source = tokens[1] 80ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if source.endswith(".S"): 81ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng appendSourceFile(tokens[1], getGlobalSubDict(), asm_fp, None) 82ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng else: 83ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("don't know how to import %s (expecting .c/.S)" 84ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng % source) 85ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 86ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 87ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Parse arch config file -- 88ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Copy a file in to the C or asm output file. 89ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 90ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef setAsmStub(tokens): 91ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng global asm_stub_text 92ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if len(tokens) != 2: 93ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("import requires one argument") 94ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng try: 95ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng stub_fp = open(tokens[1]) 96ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng asm_stub_text = stub_fp.readlines() 97ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng except IOError, err: 98ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng stub_fp.close() 99ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("unable to load asm-stub: %s" % str(err)) 100ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng stub_fp.close() 101ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 102ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 103ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Parse arch config file -- 104ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Start of opcode list. 105ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 106ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef opStart(tokens): 107ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng global in_op_start 108ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng global default_op_dir 109ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if len(tokens) != 2: 110ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("opStart takes a directory name argument") 111ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if in_op_start != 0: 112ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("opStart can only be specified once") 113ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng default_op_dir = tokens[1] 114ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng in_op_start = 1 115ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 116ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 117ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Parse arch config file -- 118ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Set location of a single opcode's source file. 119ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 120ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef opEntry(tokens): 121ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng #global opcode_locations 122ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if len(tokens) != 3: 123ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("op requires exactly two arguments") 124ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if in_op_start != 1: 125ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("op statements must be between opStart/opEnd") 126ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng try: 127ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng index = opcodes.index(tokens[1]) 128ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng except ValueError: 129ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("unknown opcode %s" % tokens[1]) 130ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng opcode_locations[tokens[1]] = tokens[2] 131ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 132ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 133ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Parse arch config file -- 134ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# End of opcode list; emit instruction blocks. 135ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 136ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef opEnd(tokens): 137ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng global in_op_start 138ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if len(tokens) != 1: 139ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("opEnd takes no arguments") 140ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if in_op_start != 1: 141ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("opEnd must follow opStart, and only appear once") 142ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng in_op_start = 2 143ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 144ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng loadAndEmitOpcodes() 145ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 146ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 147ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 148ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Extract an ordered list of instructions from the VM sources. We use the 149ccaab18ae6d203108445fef7682065dfbb007657Dan Bornstein# "goto table" definition macro, which has exactly kNumPackedOpcodes 150675b642510ed79e8a7a3f23126dfac7679fd65b9Dan Bornstein# entries. 151ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 152ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef getOpcodeList(): 153ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng opcodes = [] 154ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng opcode_fp = open("%s/%s" % (target_arch, interp_defs_file)) 155ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng opcode_re = re.compile(r"^JIT_TEMPLATE\((\w+)\)", re.DOTALL) 156ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for line in opcode_fp: 157ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng match = opcode_re.match(line) 158ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if not match: 159ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue 160ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng opcodes.append("TEMPLATE_" + match.group(1)) 161ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng opcode_fp.close() 162ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 163ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng return opcodes 164ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 165ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 166ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 167ccaab18ae6d203108445fef7682065dfbb007657Dan Bornstein# Load and emit opcodes for all kNumPackedOpcodes instructions. 168ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 169ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef loadAndEmitOpcodes(): 170ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng sister_list = [] 171ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 172ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # point dvmAsmInstructionStart at the first handler or stub 173ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng asm_fp.write("\n .global dvmCompilerTemplateStart\n") 174ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng asm_fp.write(" .type dvmCompilerTemplateStart, %function\n") 1755dfcc78af479937ba8dafceefd9b1931a88dfaafArd Biesheuvel asm_fp.write(" .section .data.rel.ro\n\n") 176ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng asm_fp.write("dvmCompilerTemplateStart:\n\n") 177ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 178ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for i in xrange(len(opcodes)): 179ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng op = opcodes[i] 180ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 181ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if opcode_locations.has_key(op): 182ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng location = opcode_locations[op] 183ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng else: 184ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng location = default_op_dir 185ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 186ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng loadAndEmitAsm(location, i, sister_list) 187ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 188ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # Use variable sized handlers now 189ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # asm_fp.write("\n .balign %d\n" % handler_size_bytes) 190ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng asm_fp.write(" .size dvmCompilerTemplateStart, .-dvmCompilerTemplateStart\n") 191ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 192ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 193ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Load an assembly fragment and emit it. 194ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 195ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef loadAndEmitAsm(location, opindex, sister_list): 196ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng op = opcodes[opindex] 197ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng source = "%s/%s.S" % (location, op) 198ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dict = getGlobalSubDict() 199ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dict.update({ "opcode":op, "opnum":opindex }) 200ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng print " emit %s --> asm" % source 201ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 202ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng emitAsmHeader(asm_fp, dict) 203ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng appendSourceFile(source, dict, asm_fp, sister_list) 204ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 205ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 206ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Output the alignment directive and label for an assembly piece. 207ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 208ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef emitAsmHeader(outfp, dict): 209ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng outfp.write("/* ------------------------------ */\n") 210ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # The alignment directive ensures that the handler occupies 211ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # at least the correct amount of space. We don't try to deal 212ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # with overflow here. 213ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng outfp.write(" .balign 4\n") 214ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # Emit a label so that gdb will say the right thing. We prepend an 2159a1f81699cc05b58378ffb9aadb4e97677943791Dan Bornstein # underscore so the symbol name doesn't clash with the Opcode enum. 216ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng template_name = "dvmCompiler_%(opcode)s" % dict 217ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng outfp.write(" .global %s\n" % template_name); 218ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng outfp.write("%s:\n" % template_name); 219ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 220ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 221ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Output a generic instruction stub that updates the "glue" struct and 222ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# calls the C implementation. 223ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 224ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef emitAsmStub(outfp, dict): 225ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng emitAsmHeader(outfp, dict) 226ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for line in asm_stub_text: 227ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng templ = Template(line) 228ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng outfp.write(templ.substitute(dict)) 229ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 230ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 231ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Append the file specified by "source" to the open "outfp". Each line will 232ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# be template-replaced using the substitution dictionary "dict". 233ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 234ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# If the first line of the file starts with "%" it is taken as a directive. 235ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# A "%include" line contains a filename and, optionally, a Python-style 236ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# dictionary declaration with substitution strings. (This is implemented 237ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# with recursion.) 238ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 239ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# If "sister_list" is provided, and we find a line that contains only "&", 240ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# all subsequent lines from the file will be appended to sister_list instead 241ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# of copied to the output. 242ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 243ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# This may modify "dict". 244ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 245ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef appendSourceFile(source, dict, outfp, sister_list): 246ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng outfp.write("/* File: %s */\n" % source) 247ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng infp = open(source, "r") 248ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng in_sister = False 249ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for line in infp: 250ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if line.startswith("%include"): 251ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # Parse the "include" line 252ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng tokens = line.strip().split(' ', 2) 253ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if len(tokens) < 2: 254ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("malformed %%include in %s" % source) 255ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 256ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng alt_source = tokens[1].strip("\"") 257ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if alt_source == source: 258ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("self-referential %%include in %s" 259ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng % source) 260ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 261ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng new_dict = dict.copy() 262ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if len(tokens) == 3: 263ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng new_dict.update(eval(tokens[2])) 264ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng #print " including src=%s dict=%s" % (alt_source, new_dict) 265ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng appendSourceFile(alt_source, new_dict, outfp, sister_list) 266ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue 267ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 268ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng elif line.startswith("%default"): 269ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # copy keywords into dictionary 270ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng tokens = line.strip().split(' ', 1) 271ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if len(tokens) < 2: 272ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("malformed %%default in %s" % source) 273ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng defaultValues = eval(tokens[1]) 274ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for entry in defaultValues: 275ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng dict.setdefault(entry, defaultValues[entry]) 276ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue 277ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 278ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng elif line.startswith("%verify"): 279ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # more to come, someday 280ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue 281ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 282ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng elif line.startswith("%break") and sister_list != None: 283ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # allow more than one %break, ignoring all following the first 284ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if not in_sister: 285ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng in_sister = True 286ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng sister_list.append("\n/* continuation for %(opcode)s */\n"%dict) 287ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng continue 288ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 289ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # perform keyword substitution if a dictionary was provided 290ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if dict != None: 291ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng templ = Template(line) 292ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng try: 293ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng subline = templ.substitute(dict) 294ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng except KeyError, err: 295ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError("keyword substitution failed in %s: %s" 296ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng % (source, str(err))) 297ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng except: 298ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng print "ERROR: substitution failed: " + line 299ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise 300ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng else: 301ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng subline = line 302ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 303ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # write output to appropriate file 304ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if in_sister: 305ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng sister_list.append(subline) 306ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng else: 307ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng outfp.write(subline) 308ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng outfp.write("\n") 309ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng infp.close() 310ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 311ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 312ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Emit a C-style section header comment. 313ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 314ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengdef emitSectionComment(str, fp): 315ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng equals = "========================================" \ 316ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng "===================================" 317ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 318ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng fp.write("\n/*\n * %s\n * %s\n * %s\n */\n" % 319ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng (equals, str, equals)) 320ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 321ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 322ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 323ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# =========================================================================== 324ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# "main" code 325ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 326ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 327ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 328ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Check args. 329ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 330ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengif len(sys.argv) != 3: 331ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng print "Usage: %s target-arch output-dir" % sys.argv[0] 332ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng sys.exit(2) 333ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 334ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengtarget_arch = sys.argv[1] 335ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengoutput_dir = sys.argv[2] 336ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 337ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 338ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Extract opcode list. 339ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 340ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengopcodes = getOpcodeList() 341ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng#for op in opcodes: 342ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# print " %s" % op 343ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 344ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 345ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Open config file. 346ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 347ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengtry: 348ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng config_fp = open("config-%s" % target_arch) 349ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengexcept: 350ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng print "Unable to open config file 'config-%s'" % target_arch 351ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng sys.exit(1) 352ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 353ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 354ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Open and prepare output files. 355ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 356ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengtry: 357ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng asm_fp = open("%s/CompilerTemplateAsm-%s.S" % (output_dir, target_arch), "w") 358ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengexcept: 359ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng print "Unable to open output files" 360ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng print "Make sure directory '%s' exists and existing files are writable" \ 361ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng % output_dir 362ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # Ideally we'd remove the files to avoid confusing "make", but if they 363ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # failed to open we probably won't be able to remove them either. 364ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng sys.exit(1) 365ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 366ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengprint "Generating %s" % (asm_fp.name) 367ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 368ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengfile_header = """/* 369ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * This file was generated automatically by gen-template.py for '%s'. 370ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * 371ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng * --> DO NOT EDIT <-- 372ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng */ 373ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 374ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng""" % (target_arch) 375ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 376ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengasm_fp.write(file_header) 377ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 378ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 379ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Process the config file. 380ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 381ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengfailed = False 382ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengtry: 383ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng for line in config_fp: 384ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng line = line.strip() # remove CRLF, leading spaces 385ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng tokens = line.split(' ') # tokenize 386ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng #print "%d: %s" % (len(tokens), tokens) 387ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if len(tokens[0]) == 0: 388ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng #print " blank" 389ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pass 390ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng elif tokens[0][0] == '#': 391ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng #print " comment" 392ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng pass 393ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng else: 394ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng if tokens[0] == "handler-size": 395ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng setHandlerSize(tokens) 396ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng elif tokens[0] == "import": 397ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng importFile(tokens) 398ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng elif tokens[0] == "asm-stub": 399ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng setAsmStub(tokens) 400ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng elif tokens[0] == "op-start": 401ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng opStart(tokens) 402ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng elif tokens[0] == "op-end": 403ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng opEnd(tokens) 404ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng elif tokens[0] == "op": 405ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng opEntry(tokens) 406ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng else: 407ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng raise DataParseError, "unrecognized command '%s'" % tokens[0] 408ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengexcept DataParseError, err: 409ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng print "Failed: " + str(err) 410ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng # TODO: remove output files so "make" doesn't get confused 411ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng failed = True 412ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng asm_fp.close() 413ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng c_fp = asm_fp = None 414ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 415ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengconfig_fp.close() 416ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 417ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 418ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# Done! 419ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng# 420ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengif asm_fp: 421ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng asm_fp.close() 422ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Cheng 423ba4fc8bfc1bccae048403bd1cea3b869dca61dd7Ben Chengsys.exit(failed) 424