1#!/usr/bin/env python3 2# 3# Copyright © 2020 Google, Inc. 4# 5# Permission is hereby granted, free of charge, to any person obtaining a 6# copy of this software and associated documentation files (the "Software"), 7# to deal in the Software without restriction, including without limitation 8# the rights to use, copy, modify, merge, publish, distribute, sublicense, 9# and/or sell copies of the Software, and to permit persons to whom the 10# Software is furnished to do so, subject to the following conditions: 11# 12# The above copyright notice and this permission notice (including the next 13# paragraph) shall be included in all copies or substantial portions of the 14# Software. 15# 16# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22# IN THE SOFTWARE. 23 24from mako.template import Template 25from isa import ISA 26import os 27import sys 28 29template = """\ 30/* Copyright (C) 2020 Google, Inc. 31 * 32 * Permission is hereby granted, free of charge, to any person obtaining a 33 * copy of this software and associated documentation files (the "Software"), 34 * to deal in the Software without restriction, including without limitation 35 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 36 * and/or sell copies of the Software, and to permit persons to whom the 37 * Software is furnished to do so, subject to the following conditions: 38 * 39 * The above copyright notice and this permission notice (including the next 40 * paragraph) shall be included in all copies or substantial portions of the 41 * Software. 42 * 43 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 44 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 45 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 46 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 47 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 48 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 49 * IN THE SOFTWARE. 50 */ 51 52#include "decode.h" 53 54/* 55 * enum tables, these don't have any link back to other tables so just 56 * dump them up front before the bitset tables 57 */ 58 59%for name, enum in isa.enums.items(): 60static const struct isa_enum ${enum.get_c_name()} = { 61 .num_values = ${len(enum.values)}, 62 .values = { 63% for val, display in enum.values.items(): 64 { .val = ${val}, .display = "${display}" }, 65% endfor 66 }, 67}; 68%endfor 69 70/* 71 * generated expression functions, can be linked from bitset tables, so 72 * also dump them up front 73 */ 74 75%for name, expr in isa.expressions.items(): 76static uint64_t 77${expr.get_c_name()}(struct decode_scope *scope) 78{ 79% for fieldname in expr.fieldnames: 80 int64_t ${fieldname} = isa_decode_field(scope, "${fieldname}"); 81% endfor 82 return ${expr.expr}; 83} 84%endfor 85 86/* 87 * Forward-declarations (so we don't have to figure out which order to 88 * emit various tables when they have pointers to each other) 89 */ 90 91%for name, bitset in isa.bitsets.items(): 92static const struct isa_bitset bitset_${bitset.get_c_name()}; 93%endfor 94 95%for root_name, root in isa.roots.items(): 96const struct isa_bitset *${root.get_c_name()}[]; 97%endfor 98 99/* 100 * bitset tables: 101 */ 102 103%for name, bitset in isa.bitsets.items(): 104% for case in bitset.cases: 105% for field_name, field in case.fields.items(): 106% if field.get_c_typename() == 'TYPE_BITSET': 107% if len(field.params) > 0: 108static const struct isa_field_params ${case.get_c_name()}_${field.get_c_name()} = { 109 .num_params = ${len(field.params)}, 110 .params = { 111% for param in field.params: 112 { .name= "${param[0]}", .as = "${param[1]}" }, 113% endfor 114 115 }, 116}; 117% endif 118% endif 119% endfor 120static const struct isa_case ${case.get_c_name()} = { 121% if case.expr is not None: 122 .expr = &${isa.expressions[case.expr].get_c_name()}, 123% endif 124% if case.display is not None: 125 .display = "${case.display}", 126% endif 127 .num_fields = ${len(case.fields)}, 128 .fields = { 129% for field_name, field in case.fields.items(): 130 { .name = "${field_name}", .low = ${field.low}, .high = ${field.high}, 131% if field.expr is not None: 132 .expr = &${isa.expressions[field.expr].get_c_name()}, 133% endif 134% if field.display is not None: 135 .display = "${field.display}", 136% endif 137 .type = ${field.get_c_typename()}, 138% if field.get_c_typename() == 'TYPE_BITSET': 139 .bitsets = ${isa.roots[field.type].get_c_name()}, 140% if len(field.params) > 0: 141 .params = &${case.get_c_name()}_${field.get_c_name()}, 142% endif 143% endif 144% if field.get_c_typename() == 'TYPE_ENUM': 145 .enums = &${isa.enums[field.type].get_c_name()}, 146% endif 147% if field.get_c_typename() == 'TYPE_ASSERT': 148 .val.bitset = { ${', '.join(isa.split_bits(field.val))} }, 149% endif 150 }, 151% endfor 152 }, 153}; 154% endfor 155static const struct isa_bitset bitset_${bitset.get_c_name()} = { 156<% pattern = bitset.get_pattern() %> 157% if bitset.extends is not None: 158 .parent = &bitset_${isa.bitsets[bitset.extends].get_c_name()}, 159% endif 160 .name = "${name}", 161 .gen = { 162 .min = ${bitset.gen_min}, 163 .max = ${bitset.gen_max}, 164 }, 165 .match.bitset = { ${', '.join(isa.split_bits(pattern.match))} }, 166 .dontcare.bitset = { ${', '.join(isa.split_bits(pattern.dontcare))} }, 167 .mask.bitset = { ${', '.join(isa.split_bits(pattern.mask))} }, 168 .num_cases = ${len(bitset.cases)}, 169 .cases = { 170% for case in bitset.cases: 171 &${case.get_c_name()}, 172% endfor 173 }, 174}; 175%endfor 176 177/* 178 * bitset hierarchy root tables (where decoding starts from): 179 */ 180 181%for root_name, root in isa.roots.items(): 182const struct isa_bitset *${root.get_c_name()}[] = { 183% for leaf_name, leaf in isa.leafs.items(): 184% if leaf.get_root() == root: 185 &bitset_${leaf.get_c_name()}, 186% endif 187% endfor 188 (void *)0 189}; 190%endfor 191 192""" 193 194header = """\ 195/* Copyright (C) 2020 Google, Inc. 196 * 197 * Permission is hereby granted, free of charge, to any person obtaining a 198 * copy of this software and associated documentation files (the "Software"), 199 * to deal in the Software without restriction, including without limitation 200 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 201 * and/or sell copies of the Software, and to permit persons to whom the 202 * Software is furnished to do so, subject to the following conditions: 203 * 204 * The above copyright notice and this permission notice (including the next 205 * paragraph) shall be included in all copies or substantial portions of the 206 * Software. 207 * 208 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 209 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 210 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 211 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 212 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 213 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 214 * IN THE SOFTWARE. 215 */ 216 217#ifndef _${guard}_ 218#define _${guard}_ 219 220#include <stdint.h> 221#include <util/bitset.h> 222 223#define BITMASK_WORDS BITSET_WORDS(${isa.bitsize}) 224 225typedef struct { 226 BITSET_WORD bitset[BITMASK_WORDS]; 227} bitmask_t; 228 229 230#define BITSET_FORMAT ${isa.format()} 231#define BITSET_VALUE(v) ${isa.value()} 232 233static inline void 234next_instruction(bitmask_t *instr, BITSET_WORD *start) 235{ 236 %for i in range(0, int(isa.bitsize / 32)): 237 instr->bitset[${i}] = *(start + ${i}); 238 %endfor 239} 240 241static inline uint64_t 242bitmask_to_uint64_t(bitmask_t mask) 243{ 244 return ((uint64_t)mask.bitset[1] << 32) | mask.bitset[0]; 245} 246 247static inline bitmask_t 248uint64_t_to_bitmask(uint64_t val) 249{ 250 bitmask_t mask = { 251 .bitset[0] = val & 0xffffffff, 252 .bitset[1] = (val >> 32) & 0xffffffff, 253 }; 254 255 return mask; 256} 257 258#endif /* _${guard}_ */ 259 260""" 261 262glue = """\ 263/* Copyright (C) 2020 Google, Inc. 264 * 265 * Permission is hereby granted, free of charge, to any person obtaining a 266 * copy of this software and associated documentation files (the "Software"), 267 * to deal in the Software without restriction, including without limitation 268 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 269 * and/or sell copies of the Software, and to permit persons to whom the 270 * Software is furnished to do so, subject to the following conditions: 271 * 272 * The above copyright notice and this permission notice (including the next 273 * paragraph) shall be included in all copies or substantial portions of the 274 * Software. 275 * 276 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 277 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 278 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 279 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 280 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 281 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 282 * IN THE SOFTWARE. 283 */ 284 285#ifndef _${guard}_ 286#define _${guard}_ 287 288#include "${isa}" 289 290#endif /* _${guard}_ */ 291 292""" 293 294xml = sys.argv[1] 295glue_h = sys.argv[2] 296dst_c = sys.argv[3] 297dst_h = sys.argv[4] 298 299isa = ISA(xml) 300 301with open(glue_h, 'w') as f: 302 guard = os.path.basename(glue_h).upper().replace("-", "_").replace(".", "_") 303 f.write(Template(glue).render(guard=guard, isa=os.path.basename(dst_h))) 304 305with open(dst_c, 'w') as f: 306 f.write(Template(template).render(isa=isa)) 307 308with open(dst_h, 'w') as f: 309 guard = os.path.basename(dst_h).upper().replace("-", "_").replace(".", "_") 310 f.write(Template(header).render(isa=isa, guard=guard)) 311