odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

tablegen-a64.js (9948B)


      1 // This file is part of AsmJit project <https://asmjit.com>
      2 //
      3 // See <asmjit/core.h> or LICENSE.md for license and copyright information
      4 // SPDX-License-Identifier: Zlib
      5 
      6 "use strict";
      7 
      8 const core = require("./tablegen.js");
      9 const commons = require("./generator-commons.js");
     10 
     11 const asmdb = core.asmdb;
     12 const kIndent = commons.kIndent;
     13 const IndexedArray = commons.IndexedArray;
     14 const StringUtils = commons.StringUtils;
     15 
     16 const FATAL = commons.FATAL;
     17 
     18 // ============================================================================
     19 // [ArmDB]
     20 // ============================================================================
     21 
     22 // Create AArch64 ISA.
     23 const isa = new asmdb.aarch64.ISA();
     24 
     25 /*
     26 class GenUtils {
     27   // Get a list of instructions based on `name` and optional `mode`.
     28   static query(name, mode) {
     29     const insts = isa.query(name);
     30     return !mode ? insts : insts.filter(function(inst) { return inst.arch === mode; });
     31   }
     32 
     33   static archOf(records) {
     34     var t16Arch = false;
     35     var t32Arch = false;
     36     var a32Arch = false;
     37     var a64Arch = false;
     38 
     39     for (var i = 0; i < records.length; i++) {
     40       const record = records[i];
     41       if (record.encoding === "T16") t16Arch = true;
     42       if (record.encoding === "T32") t32Arch = true;
     43       if (record.encoding === "A32") a32Arch = true;
     44       if (record.encoding === "A64") a64Arch = true;
     45     }
     46 
     47     var s = (t16Arch && !t32Arch) ? "T16" :
     48             (t32Arch && !t16Arch) ? "T32" :
     49             (t16Arch &&  t32Arch) ? "Txx" : "---";
     50     s += " ";
     51     s += (a32Arch) ? "A32" : "---";
     52     s += " ";
     53     s += (a64Arch) ? "A64" : "---";
     54 
     55     return `[${s}]`;
     56   }
     57 
     58   static featuresOf(records) {
     59     const exts = Object.create(null);
     60     for (var i = 0; i < records.length; i++) {
     61       const record = records[i];
     62       for (var k in record.extensions)
     63         exts[k] = true;
     64     }
     65     const arr =  Object.keys(exts);
     66     arr.sort();
     67     return arr;
     68   }
     69 }
     70 */
     71 
     72 // ============================================================================
     73 // [tablegen.arm.ArmTableGen]
     74 // ============================================================================
     75 
     76 class ArmTableGen extends core.TableGen {
     77   constructor() {
     78     super("A64");
     79   }
     80 
     81   // --------------------------------------------------------------------------
     82   // [Parse / Merge]
     83   // --------------------------------------------------------------------------
     84 
     85   parse() {
     86     const rawData = this.dataOfFile("src/asmjit/arm/a64instdb.cpp");
     87     const stringData = StringUtils.extract(rawData, "// ${InstInfo:Begin}", "// ${InstInfo:End");
     88 
     89     const re = new RegExp(
     90       "INST\\(\\s*" +
     91         // [01] Instruction.
     92         "(" +
     93           "[A-Za-z0-9_]+" +
     94         ")\\s*,\\s*" +
     95 
     96         // [02] Encoding.
     97         "(" +
     98           "[^,]+" +
     99         ")\\s*,\\s*" +
    100 
    101         // [03] OpcodeData.
    102         "(" +
    103           "\\([^\\)]+\\)" +
    104         ")\\s*,\\s*" +
    105 
    106         // [04] RWInfo.
    107         "(" +
    108           "[^,]+" +
    109         ")\\s*,\\s*" +
    110 
    111         // [05] InstructionFlags.
    112         "(\\s*" +
    113           "(?:" +
    114             "(?:" +
    115               "[\\d]+" +
    116               "|" +
    117               "F\\([^\\)]*\\)" +
    118             ")" +
    119             "\\s*" +
    120             "[|]?\\s*" +
    121           ")+" +
    122         ")\\s*,\\s*" +
    123 
    124         // --- autogenerated fields ---
    125 
    126         // [06] OpcodeDataIndex.
    127         "([^\\)]+)" +
    128         "\\s*\\)"
    129 
    130       , "g");
    131 
    132     var m;
    133     while ((m = re.exec(stringData)) !== null) {
    134       var enumName = m[1];
    135       var name = enumName === "None" ? "" : enumName.toLowerCase();
    136       var encoding = m[2].trim();
    137       var opcodeData = m[3].trim();
    138       var rwInfo = m[4].trim();
    139       var instFlags = m[5].trim();
    140 
    141       var displayName = name;
    142       if (name.endsWith("_v"))
    143         displayName = name.substring(0, name.length - 2);
    144 
    145       // We have just matched #define INST()
    146       if (name == "id" &&
    147           encoding === "encoding" &&
    148           encodingDataIndex === "encodingDataIndex")
    149         continue;
    150 
    151       this.addInstruction({
    152         id                : 0,               // Instruction id (numeric value).
    153         name              : name,            // Instruction name.
    154         displayName       : displayName,     // Instruction name to display.
    155         enum              : enumName,        // Instruction enum without `kId` prefix.
    156         encoding          : encoding,        // Opcode encoding.
    157         opcodeData        : opcodeData,      // Opcode data.
    158         opcodeDataIndex   : -1,              // Opcode data index.
    159         rwInfo            : rwInfo,          // RW info.
    160         flags             : instFlags        // Instruction flags.
    161       });
    162     }
    163 
    164     if (this.insts.length === 0 || this.insts.length !== StringUtils.countOf(stringData, "INST("))
    165       FATAL("ARMTableGen.parse(): Invalid parsing regexp (no data parsed)");
    166 
    167     console.log("Number of Instructions: " + this.insts.length);
    168   }
    169 
    170   merge() {
    171     var s = StringUtils.format(this.insts, "", true, function(inst) {
    172       return "INST(" +
    173         String(inst.enum            ).padEnd(17) + ", " +
    174         String(inst.encoding        ).padEnd(19) + ", " +
    175         String(inst.opcodeData      ).padEnd(86) + ", " +
    176         String(inst.rwInfo          ).padEnd(10) + ", " +
    177         String(inst.flags           ).padEnd(26) + ", " +
    178         String(inst.opcodeDataIndex ).padEnd( 3) + ")" ;
    179     }) + "\n";
    180     return this.inject("InstInfo", s, this.insts.length * 4);
    181   }
    182 
    183   // --------------------------------------------------------------------------
    184   // [Hooks]
    185   // --------------------------------------------------------------------------
    186 
    187   onBeforeRun() {
    188     this.load([
    189       "src/asmjit/arm/a64emitter.h",
    190       "src/asmjit/arm/a64globals.h",
    191       "src/asmjit/arm/a64instdb.cpp",
    192       "src/asmjit/arm/a64instdb.h",
    193       "src/asmjit/arm/a64instdb_p.h"
    194     ]);
    195     this.parse();
    196   }
    197 
    198   onAfterRun() {
    199     this.merge();
    200     this.save();
    201     this.dumpTableSizes();
    202   }
    203 }
    204 
    205 // ============================================================================
    206 // [tablegen.arm.IdEnum]
    207 // ============================================================================
    208 
    209 class IdEnum extends core.IdEnum {
    210   constructor() {
    211     super("IdEnum");
    212   }
    213 
    214   comment(inst) {
    215     let name = inst.name;
    216     let ext = [];
    217 
    218     if (name.endsWith("_v")) {
    219       name = name.substr(0, name.length - 2);
    220       ext.push("ASIMD");
    221     }
    222 
    223     let exts = "";
    224     if (ext.length)
    225       exts = " {" + ext.join("&") + "}";
    226 
    227     return `Instruction '${name}'${exts}.`;
    228   }
    229 }
    230 
    231 // ============================================================================
    232 // [tablegen.arm.NameTable]
    233 // ============================================================================
    234 
    235 class NameTable extends core.NameTable {
    236   constructor() {
    237     super("NameTable");
    238   }
    239 }
    240 
    241 // ============================================================================
    242 // [tablegen.arm.EncodingTable]
    243 // ============================================================================
    244 
    245 class EncodingTable extends core.Task {
    246   constructor() {
    247     super("EncodingTable");
    248   }
    249 
    250   run() {
    251     const insts = this.ctx.insts;
    252     const map = {};
    253 
    254     for (var i = 0; i < insts.length; i++) {
    255       const inst = insts[i];
    256 
    257       const encoding = inst.encoding;
    258       const opcodeData = inst.opcodeData.replace(/\(/g, "{ ").replace(/\)/g, " }");
    259 
    260       if (!Object.hasOwn(map, encoding))
    261         map[encoding] = [];
    262 
    263       if (inst.opcodeData === "(_)") {
    264         inst.opcodeDataIndex = 0;
    265         continue;
    266       }
    267 
    268       const opcodeTable = map[encoding];
    269       const opcodeDataIndex = opcodeTable.length;
    270 
    271       opcodeTable.push({ name: inst.name, data: opcodeData });
    272       inst.opcodeDataIndex = opcodeDataIndex;
    273     }
    274 
    275     const keys = Object.keys(map);
    276     keys.sort();
    277 
    278     var tableSource = "";
    279     var tableHeader = "";
    280     var encodingIds = "";
    281 
    282     encodingIds += "enum EncodingId : uint32_t {\n"
    283     encodingIds += "  kEncodingNone = 0";
    284 
    285     keys.forEach((dataClass) => {
    286       const dataName = dataClass[0].toLowerCase() + dataClass.substr(1);
    287       const opcodeTable = map[dataClass];
    288       const count = opcodeTable.length;
    289 
    290       if (dataClass !== "None") {
    291         encodingIds += ",\n"
    292         encodingIds += "  kEncoding" + dataClass;
    293       }
    294 
    295       if (count) {
    296         tableHeader += `extern const ${dataClass} ${dataName}[${count}];\n`;
    297 
    298         if (tableSource)
    299           tableSource += "\n";
    300 
    301         tableSource += `const ${dataClass} ${dataName}[${count}] = {\n`;
    302         for (var i = 0; i < count; i++) {
    303           tableSource += `  ${opcodeTable[i].data}` + (i == count - 1 ? " " : ",") + " // " + opcodeTable[i].name + "\n";
    304         }
    305         tableSource += `};\n`;
    306       }
    307     });
    308 
    309     encodingIds += "\n};\n";
    310 
    311     return this.ctx.inject("EncodingId"         , StringUtils.disclaimer(encodingIds), 0) +
    312            this.ctx.inject("EncodingDataForward", StringUtils.disclaimer(tableHeader), 0) +
    313            this.ctx.inject("EncodingData"       , StringUtils.disclaimer(tableSource), 0);
    314   }
    315 }
    316 // ============================================================================
    317 // [tablegen.arm.CommonTable]
    318 // ============================================================================
    319 
    320 class CommonTable extends core.Task {
    321   constructor() {
    322     super("CommonTable", [
    323       "IdEnum",
    324       "NameTable"
    325     ]);
    326   }
    327 
    328   run() {
    329     //const table = new IndexedArray();
    330 
    331     //for (var i = 0; i < insts.length; i++) {
    332     //  const inst = insts[i];
    333     //  const item = "{ " + "0" + "}";
    334     //  inst.commonIndex = table.addIndexed(item);
    335     //}
    336 
    337     // return this.ctx.inject("InstInfo", StringUtils.disclaimer(s), 0);
    338     return 0;
    339   }
    340 }
    341 
    342 // ============================================================================
    343 // [Main]
    344 // ============================================================================
    345 
    346 new ArmTableGen()
    347   .addTask(new IdEnum())
    348   .addTask(new NameTable())
    349   .addTask(new EncodingTable())
    350   .addTask(new CommonTable())
    351   .run();