1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2018 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21bf215546Sopenharmony_ci * SOFTWARE. 22bf215546Sopenharmony_ci * 23bf215546Sopenharmony_ci */ 24bf215546Sopenharmony_ci 25bf215546Sopenharmony_ci#include <stdio.h> 26bf215546Sopenharmony_ci#include <getopt.h> 27bf215546Sopenharmony_ci#include "i965_asm.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_cienum opt_output_type { 30bf215546Sopenharmony_ci OPT_OUTPUT_HEX, 31bf215546Sopenharmony_ci OPT_OUTPUT_C_LITERAL, 32bf215546Sopenharmony_ci OPT_OUTPUT_BIN, 33bf215546Sopenharmony_ci}; 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ciextern FILE *yyin; 36bf215546Sopenharmony_cistruct brw_codegen *p; 37bf215546Sopenharmony_cistatic enum opt_output_type output_type = OPT_OUTPUT_BIN; 38bf215546Sopenharmony_cichar *input_filename = NULL; 39bf215546Sopenharmony_ciint errors; 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_cistruct list_head instr_labels; 42bf215546Sopenharmony_cistruct list_head target_labels; 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_cistatic void 45bf215546Sopenharmony_ciprint_help(const char *progname, FILE *file) 46bf215546Sopenharmony_ci{ 47bf215546Sopenharmony_ci fprintf(file, 48bf215546Sopenharmony_ci "Usage: %s [OPTION] inputfile\n" 49bf215546Sopenharmony_ci "Assemble i965 instructions from input file.\n\n" 50bf215546Sopenharmony_ci " -h, --help display this help and exit\n" 51bf215546Sopenharmony_ci " -t, --type=OUTPUT_TYPE OUTPUT_TYPE can be 'bin' (default if omitted),\n" 52bf215546Sopenharmony_ci " 'c_literal', or 'hex'\n" 53bf215546Sopenharmony_ci " -o, --output specify output file\n" 54bf215546Sopenharmony_ci " --compact print compacted instructions\n" 55bf215546Sopenharmony_ci " -g, --gen=platform assemble instructions for given \n" 56bf215546Sopenharmony_ci " platform (3 letter platform name)\n" 57bf215546Sopenharmony_ci "Example:\n" 58bf215546Sopenharmony_ci " i965_asm -g kbl input.asm -t hex -o output\n", 59bf215546Sopenharmony_ci progname); 60bf215546Sopenharmony_ci} 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_cistatic uint32_t 63bf215546Sopenharmony_ciget_dword(const brw_inst *inst, int idx) 64bf215546Sopenharmony_ci{ 65bf215546Sopenharmony_ci uint32_t dword; 66bf215546Sopenharmony_ci memcpy(&dword, (char *)inst + 4 * idx, sizeof(dword)); 67bf215546Sopenharmony_ci return dword; 68bf215546Sopenharmony_ci} 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_cistatic void 71bf215546Sopenharmony_ciprint_instruction(FILE *output, bool compact, const brw_inst *instruction) 72bf215546Sopenharmony_ci{ 73bf215546Sopenharmony_ci int byte_limit; 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci byte_limit = (compact == true) ? 8 : 16; 76bf215546Sopenharmony_ci 77bf215546Sopenharmony_ci switch (output_type) { 78bf215546Sopenharmony_ci case OPT_OUTPUT_HEX: { 79bf215546Sopenharmony_ci fprintf(output, "%02x", ((unsigned char *)instruction)[0]); 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci for (unsigned i = 1; i < byte_limit; i++) { 82bf215546Sopenharmony_ci fprintf(output, " %02x", ((unsigned char *)instruction)[i]); 83bf215546Sopenharmony_ci } 84bf215546Sopenharmony_ci break; 85bf215546Sopenharmony_ci } 86bf215546Sopenharmony_ci case OPT_OUTPUT_C_LITERAL: { 87bf215546Sopenharmony_ci fprintf(output, "\t0x%08x,", get_dword(instruction, 0)); 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci for (unsigned i = 1; i < byte_limit / 4; i++) 90bf215546Sopenharmony_ci fprintf(output, " 0x%08x,", get_dword(instruction, i)); 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci break; 93bf215546Sopenharmony_ci } 94bf215546Sopenharmony_ci case OPT_OUTPUT_BIN: 95bf215546Sopenharmony_ci fwrite(instruction, 1, byte_limit, output); 96bf215546Sopenharmony_ci break; 97bf215546Sopenharmony_ci } 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci if (output_type != OPT_OUTPUT_BIN) { 100bf215546Sopenharmony_ci fprintf(output, "\n"); 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci} 103bf215546Sopenharmony_ci 104bf215546Sopenharmony_cistatic struct intel_device_info * 105bf215546Sopenharmony_cii965_disasm_init(uint16_t pci_id) 106bf215546Sopenharmony_ci{ 107bf215546Sopenharmony_ci struct intel_device_info *devinfo; 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_ci devinfo = malloc(sizeof *devinfo); 110bf215546Sopenharmony_ci if (devinfo == NULL) 111bf215546Sopenharmony_ci return NULL; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci if (!intel_get_device_info_from_pci_id(pci_id, devinfo)) { 114bf215546Sopenharmony_ci fprintf(stderr, "can't find device information: pci_id=0x%x\n", 115bf215546Sopenharmony_ci pci_id); 116bf215546Sopenharmony_ci free(devinfo); 117bf215546Sopenharmony_ci return NULL; 118bf215546Sopenharmony_ci } 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci return devinfo; 121bf215546Sopenharmony_ci} 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_cistatic bool 124bf215546Sopenharmony_cii965_postprocess_labels() 125bf215546Sopenharmony_ci{ 126bf215546Sopenharmony_ci if (p->devinfo->ver < 6) { 127bf215546Sopenharmony_ci return true; 128bf215546Sopenharmony_ci } 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci void *store = p->store; 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci struct target_label *tlabel; 133bf215546Sopenharmony_ci struct instr_label *ilabel, *s; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci const unsigned to_bytes_scale = brw_jump_scale(p->devinfo); 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY(tlabel, &target_labels, link) { 138bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY_SAFE(ilabel, s, &instr_labels, link) { 139bf215546Sopenharmony_ci if (!strcmp(tlabel->name, ilabel->name)) { 140bf215546Sopenharmony_ci brw_inst *inst = store + ilabel->offset; 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci int relative_offset = (tlabel->offset - ilabel->offset) / sizeof(brw_inst); 143bf215546Sopenharmony_ci relative_offset *= to_bytes_scale; 144bf215546Sopenharmony_ci 145bf215546Sopenharmony_ci unsigned opcode = brw_inst_opcode(p->isa, inst); 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci if (ilabel->type == INSTR_LABEL_JIP) { 148bf215546Sopenharmony_ci switch (opcode) { 149bf215546Sopenharmony_ci case BRW_OPCODE_IF: 150bf215546Sopenharmony_ci case BRW_OPCODE_ELSE: 151bf215546Sopenharmony_ci case BRW_OPCODE_ENDIF: 152bf215546Sopenharmony_ci case BRW_OPCODE_WHILE: 153bf215546Sopenharmony_ci if (p->devinfo->ver >= 7) { 154bf215546Sopenharmony_ci brw_inst_set_jip(p->devinfo, inst, relative_offset); 155bf215546Sopenharmony_ci } else if (p->devinfo->ver == 6) { 156bf215546Sopenharmony_ci brw_inst_set_gfx6_jump_count(p->devinfo, inst, relative_offset); 157bf215546Sopenharmony_ci } 158bf215546Sopenharmony_ci break; 159bf215546Sopenharmony_ci case BRW_OPCODE_BREAK: 160bf215546Sopenharmony_ci case BRW_OPCODE_HALT: 161bf215546Sopenharmony_ci case BRW_OPCODE_CONTINUE: 162bf215546Sopenharmony_ci brw_inst_set_jip(p->devinfo, inst, relative_offset); 163bf215546Sopenharmony_ci break; 164bf215546Sopenharmony_ci default: 165bf215546Sopenharmony_ci fprintf(stderr, "Unknown opcode %d with JIP label\n", opcode); 166bf215546Sopenharmony_ci return false; 167bf215546Sopenharmony_ci } 168bf215546Sopenharmony_ci } else { 169bf215546Sopenharmony_ci switch (opcode) { 170bf215546Sopenharmony_ci case BRW_OPCODE_IF: 171bf215546Sopenharmony_ci case BRW_OPCODE_ELSE: 172bf215546Sopenharmony_ci if (p->devinfo->ver > 7) { 173bf215546Sopenharmony_ci brw_inst_set_uip(p->devinfo, inst, relative_offset); 174bf215546Sopenharmony_ci } else if (p->devinfo->ver == 7) { 175bf215546Sopenharmony_ci brw_inst_set_uip(p->devinfo, inst, relative_offset); 176bf215546Sopenharmony_ci } else if (p->devinfo->ver == 6) { 177bf215546Sopenharmony_ci // Nothing 178bf215546Sopenharmony_ci } 179bf215546Sopenharmony_ci break; 180bf215546Sopenharmony_ci case BRW_OPCODE_WHILE: 181bf215546Sopenharmony_ci case BRW_OPCODE_ENDIF: 182bf215546Sopenharmony_ci fprintf(stderr, "WHILE/ENDIF cannot have UIP offset\n"); 183bf215546Sopenharmony_ci return false; 184bf215546Sopenharmony_ci case BRW_OPCODE_BREAK: 185bf215546Sopenharmony_ci case BRW_OPCODE_CONTINUE: 186bf215546Sopenharmony_ci case BRW_OPCODE_HALT: 187bf215546Sopenharmony_ci brw_inst_set_uip(p->devinfo, inst, relative_offset); 188bf215546Sopenharmony_ci break; 189bf215546Sopenharmony_ci default: 190bf215546Sopenharmony_ci fprintf(stderr, "Unknown opcode %d with UIP label\n", opcode); 191bf215546Sopenharmony_ci return false; 192bf215546Sopenharmony_ci } 193bf215546Sopenharmony_ci } 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci list_del(&ilabel->link); 196bf215546Sopenharmony_ci } 197bf215546Sopenharmony_ci } 198bf215546Sopenharmony_ci } 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci LIST_FOR_EACH_ENTRY(ilabel, &instr_labels, link) { 201bf215546Sopenharmony_ci fprintf(stderr, "Unknown label '%s'\n", ilabel->name); 202bf215546Sopenharmony_ci } 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci return list_is_empty(&instr_labels); 205bf215546Sopenharmony_ci} 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ciint main(int argc, char **argv) 208bf215546Sopenharmony_ci{ 209bf215546Sopenharmony_ci char *output_file = NULL; 210bf215546Sopenharmony_ci char c; 211bf215546Sopenharmony_ci FILE *output = stdout; 212bf215546Sopenharmony_ci bool help = false, compact = false; 213bf215546Sopenharmony_ci void *store; 214bf215546Sopenharmony_ci uint64_t pci_id = 0; 215bf215546Sopenharmony_ci int offset = 0, err; 216bf215546Sopenharmony_ci int start_offset = 0; 217bf215546Sopenharmony_ci struct disasm_info *disasm_info; 218bf215546Sopenharmony_ci struct intel_device_info *devinfo = NULL; 219bf215546Sopenharmony_ci int result = EXIT_FAILURE; 220bf215546Sopenharmony_ci list_inithead(&instr_labels); 221bf215546Sopenharmony_ci list_inithead(&target_labels); 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci const struct option i965_asm_opts[] = { 224bf215546Sopenharmony_ci { "help", no_argument, (int *) &help, true }, 225bf215546Sopenharmony_ci { "type", required_argument, NULL, 't' }, 226bf215546Sopenharmony_ci { "gen", required_argument, NULL, 'g' }, 227bf215546Sopenharmony_ci { "output", required_argument, NULL, 'o' }, 228bf215546Sopenharmony_ci { "compact", no_argument, (int *) &compact, true }, 229bf215546Sopenharmony_ci { NULL, 0, NULL, 0 } 230bf215546Sopenharmony_ci }; 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci while ((c = getopt_long(argc, argv, ":t:g:o:h", i965_asm_opts, NULL)) != -1) { 233bf215546Sopenharmony_ci switch (c) { 234bf215546Sopenharmony_ci case 'g': { 235bf215546Sopenharmony_ci const int id = intel_device_name_to_pci_device_id(optarg); 236bf215546Sopenharmony_ci if (id < 0) { 237bf215546Sopenharmony_ci fprintf(stderr, "can't parse gen: '%s', expected 3 letter " 238bf215546Sopenharmony_ci "platform name\n", optarg); 239bf215546Sopenharmony_ci goto end; 240bf215546Sopenharmony_ci } else { 241bf215546Sopenharmony_ci pci_id = id; 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci break; 244bf215546Sopenharmony_ci } 245bf215546Sopenharmony_ci case 'h': 246bf215546Sopenharmony_ci help = true; 247bf215546Sopenharmony_ci print_help(argv[0], stderr); 248bf215546Sopenharmony_ci goto end; 249bf215546Sopenharmony_ci case 't': { 250bf215546Sopenharmony_ci if (strcmp(optarg, "hex") == 0) { 251bf215546Sopenharmony_ci output_type = OPT_OUTPUT_HEX; 252bf215546Sopenharmony_ci } else if (strcmp(optarg, "c_literal") == 0) { 253bf215546Sopenharmony_ci output_type = OPT_OUTPUT_C_LITERAL; 254bf215546Sopenharmony_ci } else if (strcmp(optarg, "bin") == 0) { 255bf215546Sopenharmony_ci output_type = OPT_OUTPUT_BIN; 256bf215546Sopenharmony_ci } else { 257bf215546Sopenharmony_ci fprintf(stderr, "invalid value for --type: %s\n", optarg); 258bf215546Sopenharmony_ci goto end; 259bf215546Sopenharmony_ci } 260bf215546Sopenharmony_ci break; 261bf215546Sopenharmony_ci } 262bf215546Sopenharmony_ci case 'o': 263bf215546Sopenharmony_ci output_file = strdup(optarg); 264bf215546Sopenharmony_ci break; 265bf215546Sopenharmony_ci case 0: 266bf215546Sopenharmony_ci break; 267bf215546Sopenharmony_ci case ':': 268bf215546Sopenharmony_ci fprintf(stderr, "%s: option `-%c' requires an argument\n", 269bf215546Sopenharmony_ci argv[0], optopt); 270bf215546Sopenharmony_ci goto end; 271bf215546Sopenharmony_ci case '?': 272bf215546Sopenharmony_ci default: 273bf215546Sopenharmony_ci fprintf(stderr, "%s: option `-%c' is invalid: ignored\n", 274bf215546Sopenharmony_ci argv[0], optopt); 275bf215546Sopenharmony_ci goto end; 276bf215546Sopenharmony_ci } 277bf215546Sopenharmony_ci } 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci if (help || !pci_id) { 280bf215546Sopenharmony_ci print_help(argv[0], stderr); 281bf215546Sopenharmony_ci goto end; 282bf215546Sopenharmony_ci } 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci if (!argv[optind]) { 285bf215546Sopenharmony_ci fprintf(stderr, "Please specify input file\n"); 286bf215546Sopenharmony_ci goto end; 287bf215546Sopenharmony_ci } 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_ci input_filename = strdup(argv[optind]); 290bf215546Sopenharmony_ci yyin = fopen(input_filename, "r"); 291bf215546Sopenharmony_ci if (!yyin) { 292bf215546Sopenharmony_ci fprintf(stderr, "Unable to read input file : %s\n", 293bf215546Sopenharmony_ci input_filename); 294bf215546Sopenharmony_ci goto end; 295bf215546Sopenharmony_ci } 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci if (output_file) { 298bf215546Sopenharmony_ci output = fopen(output_file, "w"); 299bf215546Sopenharmony_ci if (!output) { 300bf215546Sopenharmony_ci fprintf(stderr, "Couldn't open output file\n"); 301bf215546Sopenharmony_ci goto end; 302bf215546Sopenharmony_ci } 303bf215546Sopenharmony_ci } 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci devinfo = i965_disasm_init(pci_id); 306bf215546Sopenharmony_ci if (!devinfo) { 307bf215546Sopenharmony_ci fprintf(stderr, "Unable to allocate memory for " 308bf215546Sopenharmony_ci "intel_device_info struct instance.\n"); 309bf215546Sopenharmony_ci goto end; 310bf215546Sopenharmony_ci } 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci struct brw_isa_info isa; 313bf215546Sopenharmony_ci brw_init_isa_info(&isa, devinfo); 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci p = rzalloc(NULL, struct brw_codegen); 316bf215546Sopenharmony_ci brw_init_codegen(&isa, p, p); 317bf215546Sopenharmony_ci p->automatic_exec_sizes = false; 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci err = yyparse(); 320bf215546Sopenharmony_ci if (err || errors) 321bf215546Sopenharmony_ci goto end; 322bf215546Sopenharmony_ci 323bf215546Sopenharmony_ci if (!i965_postprocess_labels()) 324bf215546Sopenharmony_ci goto end; 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci store = p->store; 327bf215546Sopenharmony_ci 328bf215546Sopenharmony_ci disasm_info = disasm_initialize(p->isa, NULL); 329bf215546Sopenharmony_ci if (!disasm_info) { 330bf215546Sopenharmony_ci fprintf(stderr, "Unable to initialize disasm_info struct instance\n"); 331bf215546Sopenharmony_ci goto end; 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci if (output_type == OPT_OUTPUT_C_LITERAL) 335bf215546Sopenharmony_ci fprintf(output, "{\n"); 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci brw_validate_instructions(p->isa, p->store, 0, 338bf215546Sopenharmony_ci p->next_insn_offset, disasm_info); 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_ci const int nr_insn = (p->next_insn_offset - start_offset) / 16; 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci if (compact) 343bf215546Sopenharmony_ci brw_compact_instructions(p, start_offset, disasm_info); 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci for (int i = 0; i < nr_insn; i++) { 346bf215546Sopenharmony_ci const brw_inst *insn = store + offset; 347bf215546Sopenharmony_ci bool compacted = false; 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci if (compact && brw_inst_cmpt_control(p->devinfo, insn)) { 350bf215546Sopenharmony_ci offset += 8; 351bf215546Sopenharmony_ci compacted = true; 352bf215546Sopenharmony_ci } else { 353bf215546Sopenharmony_ci offset += 16; 354bf215546Sopenharmony_ci } 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci print_instruction(output, compacted, insn); 357bf215546Sopenharmony_ci } 358bf215546Sopenharmony_ci 359bf215546Sopenharmony_ci ralloc_free(disasm_info); 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci if (output_type == OPT_OUTPUT_C_LITERAL) 362bf215546Sopenharmony_ci fprintf(output, "}"); 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci result = EXIT_SUCCESS; 365bf215546Sopenharmony_ci goto end; 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ciend: 368bf215546Sopenharmony_ci free(input_filename); 369bf215546Sopenharmony_ci free(output_file); 370bf215546Sopenharmony_ci 371bf215546Sopenharmony_ci if (yyin) 372bf215546Sopenharmony_ci fclose(yyin); 373bf215546Sopenharmony_ci 374bf215546Sopenharmony_ci if (output) 375bf215546Sopenharmony_ci fclose(output); 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci if (p) 378bf215546Sopenharmony_ci ralloc_free(p); 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci if (devinfo) 381bf215546Sopenharmony_ci free(devinfo); 382bf215546Sopenharmony_ci 383bf215546Sopenharmony_ci exit(result); 384bf215546Sopenharmony_ci} 385