1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. 24 */ 25 26 /* 27 * Assembler for Emu10k1 28 */ 29 /* 30 * Copyright (C) 4Front Technologies 1996-2008. 31 */ 32 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <fcntl.h> 37 #include <string.h> 38 #include <stdarg.h> 39 #include <ctype.h> 40 #include <sys/param.h> 41 42 #define MAX_GPR 256 43 #define MAX_GPR_PARMS 60 44 #define MAX_CONST_PARMS 128 45 #define GPR_NAME_SIZE 32 46 47 typedef struct { 48 char name[GPR_NAME_SIZE]; 49 unsigned int num; 50 int type; 51 int def; 52 } gpr_t; 53 54 typedef struct { 55 unsigned int gpr; 56 unsigned int value; 57 } const_t; 58 59 typedef struct { 60 unsigned int ngpr; 61 62 gpr_t gpr[MAX_GPR_PARMS]; 63 } gpr_info; 64 65 typedef struct { 66 unsigned int nconst; 67 68 const_t consts[MAX_CONST_PARMS]; 69 } const_info; 70 71 typedef struct { 72 unsigned int code[1024]; 73 gpr_info parms; 74 const_info consts; 75 int ninit; 76 struct { 77 uint32_t gpr; 78 uint32_t value; 79 char name[GPR_NAME_SIZE]; 80 } init[MAX_GPR]; 81 } emu10k1_file; 82 83 #define MAX_NAME 64 84 #define MAX_SYMBOLS 1024 85 86 static int parms_only = 0; 87 static int is_audigy = 0; 88 static int verbose = 0; 89 90 static int gpr_base = 0x100; 91 static int input_base = 0x10; 92 static int output_base = 0x20; 93 94 static char *progname; 95 96 typedef struct { 97 char name[MAX_NAME]; 98 int type; 99 #define SY_DUMMY 0 100 #define SY_GPR 1 101 #define SY_INPUT 2 102 #define SY_OUTPUT 3 103 #define SY_CONST 4 104 #define SY_FX 5 105 #define SY_ACCUM 6 106 #define SY_PARM 7 107 int arg; 108 } sym_t; 109 110 typedef struct { 111 char *name; 112 int opcode; 113 } instruction_t; 114 115 static char remarks[2048] = ""; 116 static char *banner = 117 "/*\n" 118 " * Note: This file was automatically generated by %s\n" 119 " * on %s.\n" 120 " */\n"; 121 122 /* 123 * Instructions. Each instruction takes 4 arguments, R, A, X, and Y. 124 */ 125 static instruction_t instructions[] = { 126 { "MACS", 0x0}, /* R = A + (X * Y >> 31); saturation */ 127 { "MACS1", 0x1}, /* R = A + (-X * Y >> 31); saturation */ 128 { "MACW", 0x2}, /* R = A + (X * Y >> 31); wraparound */ 129 { "MACW1", 0x3}, /* R = A + (-X * Y >> 31); wraparound */ 130 { "MACINTS", 0x4}, /* R = A + (X * Y); saturation */ 131 { "MACINTW", 0x5}, /* R = A + (X * Y); wraparound */ 132 { "SUM", 0x6}, /* R = A + X + Y; saturation */ 133 { "ACC3", 0x6}, /* R = A + X + Y; saturation */ 134 { "MACMV", 0x7}, /* R = A, acc += X * Y >> 31 */ 135 { "ANDXOR", 0x8}, /* R = (A & X) ^ Y */ 136 { "TSTNEG", 0x9}, /* R = (A >= Y) ? X : ~X */ 137 { "LIMIT", 0xa}, /* R = (A >= Y) ? X : Y */ 138 { "LIMIT1", 0xb}, /* R = (A < Y) ? X : Y */ 139 { "LOG", 0xc}, /* R = ... (log?) */ 140 { "EXP", 0xd}, /* R = ... (exp?) */ 141 { "INTERP", 0xe}, /* R = A + (X * (Y - A) >> 31) */ 142 { "SKIP", 0xf}, /* R, CCR, CC_TEST, COUNT */ 143 { NULL, 0} 144 }; 145 146 #define CHECK_COUNT(tokens, cnt, mincnt, maxcnt) \ 147 if (cnt < mincnt) { \ 148 error("Too few parameters for '%s' (have %d, min %d)", \ 149 tokens[0], cnt - 1, mincnt - 1); \ 150 return; \ 151 } \ 152 if (cnt > maxcnt) { \ 153 error("Too many parameters for '%s' (have %d, max %d)", \ 154 tokens[0], cnt - 1, maxcnt - 1); \ 155 return; \ 156 } 157 158 static sym_t symtab[MAX_SYMBOLS]; 159 static int nsyms = 0; 160 161 static int lineno = 0, errors = 0; 162 static emu10k1_file fle; 163 static int pc; 164 165 static int ngpr = 0; 166 static char *infile; 167 168 static int 169 getaline(FILE *input, char **tokens) 170 { 171 char *s, *ls; 172 static char *stmt = NULL, *lasts = NULL; 173 static char line[4096]; 174 int cnt, tokcnt; 175 176 for (;;) { 177 178 if (stmt == NULL) { 179 if (fgets(line, sizeof (line), input) == NULL) 180 return (-1); 181 lineno++; 182 183 /* 184 * Special handling for .' comments. We use 185 * .' as a keyword to ensure that entire 186 * comment makes it through the C preprocessor 187 * unmolested. We also need to make sure *we* 188 * don't molest it either. The comment will 189 * be exported to any resulting header, 190 * allowing us to pass through copyright and 191 * other information from the source file to 192 * the resulting header. 193 */ 194 s = line; 195 s += strspn(s, " \t"); 196 if ((strncmp(s, ".'", 2) == 0) && 197 (strchr(" \t\n", s[2]) != NULL)) { 198 /* chop off trailing new line */ 199 (void) strtok(line, "\n"); 200 tokens[0] = s; 201 s += 2; 202 s += strspn(s, " \t"); 203 if ((s[0] == '\'') && 204 (s[strlen(s) - 1] == '\'')) { 205 s[strlen(s) - 1] = 0; 206 s++; 207 } 208 tokens[1] = s; 209 tokens[0][2] = 0; 210 tokens[2] = NULL; 211 stmt = NULL; 212 return (strlen(tokens[1]) ? 2 : 1); 213 } 214 215 /* strip off any C++ style comments that CPP missed */ 216 if ((s = strstr(line, "//")) != NULL) { 217 *s = '\0'; 218 } 219 stmt = strtok_r(line, ";\n", &lasts); 220 } else { 221 stmt = strtok_r(NULL, ";\n", &lasts); 222 } 223 224 if (stmt != NULL) { 225 break; 226 } 227 } 228 229 /* 230 * Ok, we have a statement, lets tokenize it. For 231 * simplicities sake we convert "OPCODE(arg1, arg2)" into 232 * "OPCODE arg1 arg2". This means that commas and parens are 233 * treated as whitespace. This can lead to some really messed 234 * up syntaxes that get assembled properly (such as nested 235 * calls, empty arguments, etc.) Hopefully people don't abuse 236 * this. 237 */ 238 ls = NULL; 239 s = strtok_r(stmt, " \t\n(),", &ls); 240 cnt = 0; 241 tokcnt = 0; 242 while (cnt < 10) { 243 tokens[cnt++] = s; 244 if (s != NULL) { 245 tokcnt++; 246 s = strtok_r(NULL, " \t\n(),", &ls); 247 } 248 } 249 return (tokcnt); 250 } 251 252 static void 253 error(char *msg, ...) 254 { 255 va_list va; 256 char msgbuf[1024]; 257 258 va_start(va, msg); 259 (void) vsnprintf(msgbuf, sizeof (msgbuf), msg, va); 260 va_end(va); 261 262 (void) fprintf(stderr, "Error: %s on line %d of %s\n", msgbuf, lineno, 263 infile); 264 errors++; 265 } 266 267 static sym_t * 268 find_symbol(char *name) 269 { 270 int i; 271 272 for (i = 0; i < nsyms; i++) 273 if (strcmp(symtab[i].name, name) == 0) { 274 return (&symtab[i]); 275 } 276 277 return (NULL); 278 } 279 280 static void 281 add_symbol(char *name, int type, int arg) 282 { 283 sym_t *sym; 284 285 if (nsyms >= MAX_SYMBOLS) { 286 error("Symbol table full"); 287 exit(-1); 288 } 289 290 if (find_symbol(name) != NULL) { 291 error("Dublicate symbol '%s'", name); 292 return; 293 } 294 295 if (strlen(name) >= MAX_NAME) { 296 error("Symbol name '%s' too long", name); 297 exit(-1); 298 } 299 300 sym = &symtab[nsyms++]; 301 302 (void) strcpy(sym->name, name); 303 sym->type = type; 304 sym->arg = arg; 305 } 306 307 static void 308 add_init(uint32_t gpr, uint32_t val, const char *name) 309 { 310 int n; 311 312 n = fle.ninit; 313 if (n >= MAX_GPR) { 314 error("Too many GPRs"); 315 return; 316 } 317 fle.init[n].gpr = gpr; 318 fle.init[n].value = val; 319 if (name) 320 (void) strlcpy(fle.init[n].name, name, 321 sizeof (fle.init[n].name)); 322 fle.ninit++; 323 } 324 325 static void 326 compile_gpr(char **tokens, int cnt) 327 { 328 CHECK_COUNT(tokens, cnt, 2, 2); 329 330 if (ngpr >= MAX_GPR) 331 error("Too many GPR variables"); 332 333 add_symbol(tokens[1], SY_GPR, gpr_base + ngpr++); 334 } 335 336 static void 337 compile_rem(char **tokens, int cnt) 338 { 339 int i; 340 341 (void) strlcat(remarks, " *", sizeof (remarks)); 342 for (i = 1; i < cnt; i++) { 343 (void) strlcat(remarks, " ", sizeof (remarks)); 344 (void) strlcat(remarks, tokens[i], sizeof (remarks)); 345 } 346 (void) strlcat(remarks, "\n", sizeof (remarks)); 347 } 348 349 static void 350 declare_const(unsigned int gpr, char *value) 351 { 352 int n, intv; 353 float v; 354 355 n = fle.consts.nconst; 356 357 if (n >= MAX_CONST_PARMS) { 358 error("Too many constant parameters"); 359 return; 360 } 361 362 if (*value == 'I') { 363 if (sscanf(&value[1], "%g", &v) != 1) { 364 error("Bad floating point value (%s)", value); 365 return; 366 } 367 intv = (int)v; 368 } else if (*value == '0' && value[1] == 'x') { 369 if (sscanf(&value[2], "%x", (unsigned *)&intv) != 1) { 370 error("Bad hexadecimal value (%s)", value); 371 return; 372 } 373 } else { 374 if (sscanf(value, "%g", &v) != 1) { 375 error("Bad floating point value (%s)", value); 376 return; 377 } 378 intv = (int)(v * 0x7fffffff); 379 } 380 381 fle.consts.consts[n].gpr = gpr; 382 fle.consts.consts[n].value = intv; 383 fle.consts.nconst = n + 1; 384 385 add_init(gpr, intv, NULL); 386 } 387 388 static void 389 compile_const(char **tokens, int cnt) 390 { 391 CHECK_COUNT(tokens, cnt, 2, 3); 392 char *name = tokens[1]; 393 char *value = tokens[2] ? tokens[2] : tokens[1]; 394 395 if (ngpr >= MAX_GPR) 396 error("Too many GPR variables"); 397 398 declare_const(ngpr, value); 399 400 add_symbol(name, SY_GPR, gpr_base + ngpr++); 401 } 402 403 static void 404 compile_bool(char **tokens, int cnt) 405 { 406 char *parm, *def; 407 int n, num; 408 409 CHECK_COUNT(tokens, cnt, 3, 3); 410 411 parm = tokens[1]; 412 def = tokens[2]; 413 414 n = fle.parms.ngpr; 415 if (n >= MAX_GPR_PARMS) { 416 error("Too many GPR parameters"); 417 return; 418 } 419 420 if (sscanf(def, "%d", &num) != 1) { 421 error("Bad integer value near '%s'", def); 422 return; 423 } 424 425 (void) strcpy(fle.parms.gpr[n].name, parm); 426 fle.parms.gpr[n].num = ngpr; 427 fle.parms.gpr[n].def = num; 428 fle.parms.ngpr = n + 1; 429 430 add_init(ngpr, num, parm); 431 432 add_symbol(parm, SY_PARM, gpr_base + ngpr++); 433 } 434 435 static void 436 compile_mono(char **tokens, int cnt) 437 { 438 char *parm, *def; 439 int n, num; 440 441 CHECK_COUNT(tokens, cnt, 3, 3); 442 443 parm = tokens[1]; 444 def = tokens[2]; 445 446 n = fle.parms.ngpr; 447 if (n >= MAX_GPR_PARMS) { 448 error("Too many GPR parameters"); 449 return; 450 } 451 452 if (sscanf(def, "%d", &num) != 1) { 453 error("Bad integer value near '%s'", def); 454 return; 455 } 456 457 (void) strcpy(fle.parms.gpr[n].name, parm); 458 fle.parms.gpr[n].num = ngpr; 459 fle.parms.gpr[n].def = num; 460 fle.parms.ngpr = n + 1; 461 462 add_init(ngpr, num, parm); 463 464 add_symbol(parm, SY_PARM, gpr_base + ngpr++); 465 } 466 467 static void 468 compile_stereo(char **tokens, int cnt) 469 { 470 char *parm, *def; 471 int n, num; 472 char tmp[128]; 473 474 CHECK_COUNT(tokens, cnt, 3, 3); 475 476 parm = tokens[1]; 477 def = tokens[2]; 478 479 n = fle.parms.ngpr; 480 if (n >= MAX_GPR_PARMS) { 481 error("Too many GPR parameters"); 482 return; 483 } 484 485 if (sscanf(def, "%d", &num) != 1) { 486 error("Bad integer value near '%s'", def); 487 return; 488 } 489 490 (void) strcpy(fle.parms.gpr[n].name, parm); 491 fle.parms.gpr[n].num = ngpr; 492 fle.parms.gpr[n].def = num | (num << 8); 493 fle.parms.ngpr = n + 1; 494 495 add_init(ngpr, num, parm); 496 add_init(ngpr + 1, num, NULL); 497 498 (void) sprintf(tmp, "%s_L", parm); 499 add_symbol(tmp, SY_PARM, gpr_base + ngpr++); 500 (void) sprintf(tmp, "%s_R", parm); 501 add_symbol(tmp, SY_PARM, gpr_base + ngpr++); 502 } 503 504 static void 505 compile_input(char **tokens, int cnt) 506 { 507 int num; 508 509 CHECK_COUNT(tokens, cnt, 3, 3); 510 511 if (sscanf(tokens[2], "%d", &num) != 1) { 512 error("Bad integer value near '%s'", tokens[2]); 513 return; 514 } 515 516 add_symbol(tokens[1], SY_INPUT, input_base + num); 517 } 518 519 static void 520 compile_send(char **tokens, int cnt) 521 { 522 int num; 523 524 CHECK_COUNT(tokens, cnt, 3, 3); 525 526 if (sscanf(tokens[2], "%d", &num) != 1) { 527 error("Bad integer near '%s'", tokens[2]); 528 return; 529 } 530 531 add_symbol(tokens[1], SY_FX, num); 532 } 533 534 static void 535 compile_output(char **tokens, int cnt) 536 { 537 int num; 538 539 CHECK_COUNT(tokens, cnt, 3, 3); 540 541 if (sscanf(tokens[2], "%d", &num) != 1) { 542 error("Bad integer value near '%s'", tokens[2]); 543 return; 544 } 545 546 add_symbol(tokens[1], SY_OUTPUT, output_base + num); 547 } 548 549 static void 550 compile_directive(char **tokens, int cnt) 551 { 552 if (strcmp(tokens[0], ".gpr") == 0) { 553 compile_gpr(tokens, cnt); 554 return; 555 } 556 557 if (strcmp(tokens[0], ".const") == 0) { 558 compile_const(tokens, cnt); 559 return; 560 } 561 562 if (strcmp(tokens[0], ".stereo") == 0) { 563 compile_stereo(tokens, cnt); 564 return; 565 } 566 567 if (strcmp(tokens[0], ".mono") == 0) { 568 compile_mono(tokens, cnt); 569 return; 570 } 571 572 if (strcmp(tokens[0], ".bool") == 0) { 573 compile_bool(tokens, cnt); 574 return; 575 } 576 577 if (strcmp(tokens[0], ".input") == 0) { 578 compile_input(tokens, cnt); 579 return; 580 } 581 582 if (strcmp(tokens[0], ".send") == 0) { 583 compile_send(tokens, cnt); 584 return; 585 } 586 587 if (strcmp(tokens[0], ".output") == 0) { 588 compile_output(tokens, cnt); 589 return; 590 } 591 592 if (strcmp(tokens[0], ".rem") == 0) { 593 compile_rem(tokens, cnt); 594 return; 595 } 596 if (strcmp(tokens[0], ".'") == 0) { 597 compile_rem(tokens, cnt); 598 return; 599 } 600 601 error("Unknown directive '%s'", tokens[0]); 602 } 603 604 static void 605 compile_asm(char **tokens, int cnt) 606 { 607 sym_t *symbols[4]; 608 #define EMIT(o, r, a, x, y) \ 609 fle.code[pc*2] = ((x) << 10) | (y); \ 610 fle.code[pc*2+1] = ((o) << 20) | ((r) << 10) | a; pc++ 611 #define EMIT_AUDIGY(o, r, a, x, y) \ 612 fle.code[pc*2] = ((x) << 12) | (y); \ 613 fle.code[pc*2+1] = ((o) << 24) | ((r) << 12) | a; pc++ 614 615 int i, nerr = 0; 616 int ninputs = 0; 617 618 CHECK_COUNT(tokens, cnt, 5, 5); 619 620 for (i = 0; i < 4; i++) { 621 if ((symbols[i] = find_symbol(tokens[i+1])) == NULL) { 622 (void) fprintf(stderr, "%s\n", tokens[i+1]); 623 nerr++; 624 error("Undefined symbol '%s'", tokens[i + 1]); 625 continue; 626 } 627 628 if (symbols[i]->type == SY_INPUT) 629 ninputs++; 630 631 if (symbols[i]->type == SY_ACCUM && i != 1) 632 error("Bad usage of 'accum' operand."); 633 } 634 635 if (nerr > 0) 636 return; 637 638 if (ninputs > 1) { 639 error("Attempt to access more than one input " 640 "GPRs by the same instruction"); 641 } 642 643 for (i = 0; instructions[i].name != NULL; i++) 644 if (strcasecmp(tokens[0], instructions[i].name) == 0) { 645 646 if (is_audigy) { 647 EMIT_AUDIGY(instructions[i].opcode, 648 symbols[0]->arg, 649 symbols[1]->arg, 650 symbols[2]->arg, 651 symbols[3]->arg); 652 } else { 653 EMIT(instructions[i].opcode, 654 symbols[0]->arg, 655 symbols[1]->arg, 656 symbols[2]->arg, 657 symbols[3]->arg); 658 } 659 660 return; 661 } 662 663 error("Unrecognized instruction '%s'", tokens[0]); 664 } 665 666 static void 667 init_compiler(void) 668 { 669 char tmp[100]; 670 int i; 671 672 (void) memset(&fle, 0, sizeof (fle)); 673 /* 674 * Initialize few predefined GPR parameter registers. These 675 * definitions have to be in sync with the GPR_* macros in 676 * <sblive.h>. 677 */ 678 679 /* 680 * Make sure we start at gpr id 2 for now; 0 and 1 may be used 681 * differently. 682 */ 683 add_symbol("NULL", SY_DUMMY, gpr_base + ngpr++); 684 add_symbol("NULL_", SY_DUMMY, gpr_base + ngpr++); 685 686 pc = 0; 687 688 if (is_audigy) { 689 /* Initialize the code array with NOPs (AUDIGY) */ 690 for (i = 0; i < 512; i++) { 691 fle.code[i * 2 + 0] = (0xc0 << 12) | 0xc0; 692 fle.code[i * 2 + 1] = 693 (0x06 << 24) | (0xc0 << 12) | 0xc0; 694 } 695 696 for (i = 0; i < 32; i++) { 697 (void) sprintf(tmp, "fx%d", i); 698 add_symbol(tmp, SY_FX, i); 699 } 700 } else { 701 /* Initialize the code array with NOPs (LIVE) */ 702 for (i = 0; i < 512; i++) { 703 fle.code[i * 2 + 0] = 0x10040; 704 fle.code[i * 2 + 1] = 0x610040; 705 } 706 707 for (i = 0; i < 16; i++) { 708 (void) sprintf(tmp, "fx%d", i); 709 add_symbol(tmp, SY_FX, i); 710 } 711 } 712 713 /* 714 * Constants 715 */ 716 717 if (is_audigy) { 718 /* Audigy symbols */ 719 add_symbol("0", SY_CONST, 0x0c0); 720 add_symbol("1", SY_CONST, 0x0c1); 721 add_symbol("2", SY_CONST, 0x0c2); 722 add_symbol("3", SY_CONST, 0x0c3); 723 add_symbol("4", SY_CONST, 0x0c4); 724 add_symbol("8", SY_CONST, 0x0c5); 725 add_symbol("16", SY_CONST, 0x0c6); 726 add_symbol("32", SY_CONST, 0x0c7); 727 add_symbol("256", SY_CONST, 0x0c8); 728 add_symbol("65536", SY_CONST, 0x0c9); 729 730 add_symbol("2048", SY_CONST, 0x0ca); 731 add_symbol("0x800", SY_CONST, 0x0ca); 732 733 add_symbol("2^28", SY_CONST, 0x0cb); 734 add_symbol("0x10000000", SY_CONST, 0x0cb); 735 736 add_symbol("2^29", SY_CONST, 0x0cc); 737 add_symbol("0x20000000", SY_CONST, 0x0cc); 738 739 add_symbol("2^30", SY_CONST, 0x0cd); 740 add_symbol("0x40000000", SY_CONST, 0x0cd); 741 742 add_symbol("2^31", SY_CONST, 0x0ce); 743 add_symbol("0x80000000", SY_CONST, 0x0ce); 744 745 add_symbol("0x7fffffff", SY_CONST, 0x0cf); 746 747 add_symbol("0xffffffff", SY_CONST, 0x0d0); 748 add_symbol("-1", SY_CONST, 0x0d0); 749 750 add_symbol("0xfffffffe", SY_CONST, 0x0d1); 751 add_symbol("-2", SY_CONST, 0x0d1); 752 753 add_symbol("0xc0000000", SY_CONST, 0x0d2); 754 755 add_symbol("0x4f1bbcdc", SY_CONST, 0x0d3); 756 757 add_symbol("0x5a7ef9db", SY_CONST, 0x0d4); 758 759 add_symbol("0x100000", SY_CONST, 0x0d5); 760 add_symbol("accum", SY_ACCUM, 0x0d6); 761 add_symbol("CCR", SY_CONST, 0x0d7); 762 763 add_symbol("noise_L", SY_CONST, 0x0d8); 764 add_symbol("noise_R", SY_CONST, 0x0d9); 765 add_symbol("IRQREQ", SY_CONST, 0x0da); 766 } else { 767 /* SB Live symbols */ 768 add_symbol("0", SY_CONST, 0x040); 769 add_symbol("1", SY_CONST, 0x041); 770 add_symbol("2", SY_CONST, 0x042); 771 add_symbol("3", SY_CONST, 0x043); 772 add_symbol("4", SY_CONST, 0x044); 773 add_symbol("8", SY_CONST, 0x045); 774 add_symbol("16", SY_CONST, 0x046); 775 add_symbol("32", SY_CONST, 0x047); 776 add_symbol("256", SY_CONST, 0x048); 777 add_symbol("65536", SY_CONST, 0x049); 778 779 add_symbol("2^23", SY_CONST, 0x04a); 780 add_symbol("0x80000", SY_CONST, 0x04a); 781 782 add_symbol("2^28", SY_CONST, 0x04b); 783 add_symbol("0x10000000", SY_CONST, 0x04b); 784 785 add_symbol("2^29", SY_CONST, 0x04c); 786 add_symbol("0x20000000", SY_CONST, 0x04c); 787 788 add_symbol("2^30", SY_CONST, 0x04d); 789 add_symbol("0x40000000", SY_CONST, 0x04d); 790 791 add_symbol("2^31", SY_CONST, 0x04e); 792 add_symbol("0x80000000", SY_CONST, 0x04e); 793 794 add_symbol("0x7fffffff", SY_CONST, 0x04f); 795 796 add_symbol("0xffffffff", SY_CONST, 0x050); 797 add_symbol("-1", SY_CONST, 0x050); 798 799 add_symbol("0xfffffffe", SY_CONST, 0x051); 800 add_symbol("-2", SY_CONST, 0x051); 801 802 add_symbol("accum", SY_ACCUM, 0x056); 803 add_symbol("CCR", SY_CONST, 0x057); 804 805 add_symbol("noise_L", SY_CONST, 0x058); 806 add_symbol("noise_R", SY_CONST, 0x059); 807 add_symbol("IRQREQ", SY_CONST, 0x05a); 808 } 809 } 810 811 static void 812 produce_map(char *name) 813 { 814 int i; 815 FILE *f; 816 817 if ((f = fopen(name, "w")) == NULL) { 818 perror(name); 819 return; 820 } 821 822 (void) fprintf(f, "%d\n", pc); 823 824 for (i = 0; i < nsyms; i++) { 825 (void) fprintf(f, "%04x %x %s\n", 826 symtab[i].arg, symtab[i].type, symtab[i].name); 827 } 828 829 (void) fclose(f); 830 if (verbose) { 831 (void) fprintf(stderr, 832 "No errors detected - Map written to %s\n", name); 833 } 834 } 835 836 static void 837 produce_output(char *fname) 838 { 839 int fd; 840 841 if ((fd = creat(fname, 0644)) == -1) { 842 perror(fname); 843 exit(-1); 844 } 845 846 if (write(fd, &fle, sizeof (fle)) != sizeof (fle)) { 847 perror(fname); 848 exit(-1); 849 } 850 851 if (verbose) { 852 (void) fprintf(stderr, 853 "No errors detected - Binary written to %s\n", 854 fname); 855 } 856 857 (void) close(fd); 858 } 859 860 static void 861 produce_header(char *fname, char *prefix) 862 { 863 FILE *f; 864 char *s; 865 char sname[MAXPATHLEN + 1]; 866 char dname[MAXPATHLEN + 1]; 867 int i; 868 clock_t now; 869 char when[128]; 870 871 /* get basename */ 872 if (prefix == NULL) { 873 s = strrchr(fname, '/'); 874 s = (s == NULL) ? fname : s + 1; 875 } else { 876 s = prefix; 877 } 878 (void) strlcpy(sname, s, sizeof (sname)); 879 880 /* strip off any extension */ 881 s = strchr(sname, '.'); 882 if (s != NULL) { 883 *s = 0; 884 } 885 if ((f = fopen(fname, "w")) == NULL) { 886 perror(fname); 887 return; 888 } 889 890 if (remarks[0] != 0) { 891 (void) fprintf(f, "/*\n%s */\n", remarks); 892 } 893 now = time(NULL); 894 strftime(when, sizeof (when), "%c", localtime(&now)); 895 (void) fprintf(f, banner, progname, when); 896 897 (void) strlcpy(dname, prefix ? prefix : sname, sizeof (dname)); 898 for (i = 0; dname[i]; i++) { 899 dname[i] = toupper(dname[i]); 900 if (!isalnum(dname[i])) { 901 dname[i] = '_'; 902 } 903 } 904 905 for (i = 0; i < fle.parms.ngpr; i++) { 906 (void) fprintf(f, "#define\t%s_%s\t\t%d\n", 907 dname, fle.parms.gpr[i].name, fle.parms.gpr[i].num); 908 } 909 910 (void) fprintf(f, "\n"); 911 912 if (parms_only) 913 goto done; 914 915 (void) fprintf(f, "uint32_t %s_code[] = {\n", sname); 916 917 for (i = 0; i < pc * 2; i++) { 918 if (i == 0) { 919 (void) fprintf(f, "\t0x%08xU", fle.code[i]); 920 } else if ((i % 4) == 0) { 921 (void) fprintf(f, ",\n\t0x%08xU", fle.code[i]); 922 } else { 923 (void) fprintf(f, ", 0x%08xU", fle.code[i]); 924 } 925 } 926 (void) fprintf(f, "\n};\n"); 927 928 (void) fprintf(f, "uint32_t %s_ninit = %d;\n", sname, fle.ninit); 929 (void) fprintf(f, "uint32_t %s_init[] = {\n", sname); 930 931 for (i = 0; i < fle.ninit; i++) { 932 if (fle.init[i].name[0]) { 933 (void) fprintf(f, "\t%u, 0x%x%s,\t/* %s */\n", 934 fle.init[i].gpr, fle.init[i].value, 935 fle.init[i].value >= 0x80000000U ? "U" : "", 936 fle.init[i].name); 937 } else { 938 (void) fprintf(f, "\t%u, 0x%x%s,\n", 939 fle.init[i].gpr, fle.init[i].value, 940 fle.init[i].value >= 0x80000000U ? "U" : ""); 941 } 942 } 943 (void) fprintf(f, "};\n"); 944 945 done: 946 (void) fclose(f); 947 if (verbose) { 948 (void) fprintf(stderr, 949 "No errors detected - Header written to %s\n", 950 fname); 951 } 952 } 953 954 int 955 main(int argc, char *argv[]) 956 { 957 char *outfile; 958 int i; 959 FILE *input; 960 char *tokens[10]; 961 int tokcnt; 962 char *mapfile = NULL; 963 char *header = NULL; 964 char *prefix = NULL; 965 966 outfile = NULL; 967 infile = NULL; 968 input = NULL; 969 progname = argv[0]; 970 971 while ((i = getopt(argc, argv, "m:h:o:i:P:021v")) != EOF) { 972 switch (i) { 973 case 'o': 974 outfile = optarg; 975 break; 976 case 'i': 977 infile = strdup(optarg); 978 break; 979 case 'm': 980 mapfile = optarg; 981 break; 982 case 'P': 983 prefix = optarg; 984 break; 985 case 'h': 986 header = optarg; 987 break; 988 case '0': 989 parms_only = 1; 990 break; 991 case '2': 992 is_audigy = 1; 993 break; 994 case '1': 995 is_audigy = 0; 996 break; 997 case 'v': 998 verbose++; 999 break; 1000 default: 1001 (void) fprintf(stderr, 1002 "usage: %s [-m <map>] [-h <header>] " 1003 "[-o <binary>] [-i <source>] [-2|-1]", 1004 progname); 1005 exit(-1); 1006 break; 1007 } 1008 } 1009 1010 if ((outfile == NULL) && (mapfile == NULL) && (header == NULL)) { 1011 outfile = "dsp.bin"; 1012 } 1013 1014 if (infile) { 1015 input = fopen(infile, "r"); 1016 if (input == NULL) { 1017 perror(infile); 1018 exit(-1); 1019 } 1020 } else { 1021 infile = strdup("<stdin>"); 1022 input = stdin; 1023 } 1024 1025 if (is_audigy) { 1026 gpr_base = 0x400; 1027 input_base = 0x40; 1028 output_base = 0x60; 1029 if (verbose) 1030 (void) fprintf(stderr, "Compiling for SB Audigy\n"); 1031 } else { 1032 if (verbose) 1033 (void) fprintf(stderr, "Compiling for SB Live\n"); 1034 } 1035 1036 init_compiler(); 1037 1038 while ((tokcnt = getaline(input, tokens)) != -1) { 1039 /* skip empty lines */ 1040 if (tokcnt == 0) { 1041 continue; 1042 } 1043 1044 if (strcmp(tokens[0], "#") == 0) { 1045 int num; 1046 if ((tokcnt >= 3) && 1047 (sscanf(tokens[1], "%d", &num) == 1)) { 1048 lineno = num; 1049 free(infile); 1050 infile = strdup(tokens[2]); 1051 /* we don't want to count the # directive */ 1052 lineno--; 1053 } 1054 1055 /* unknown # directive? muddle on... */ 1056 continue; 1057 } 1058 if (*tokens[0] == '.') { 1059 compile_directive(tokens, tokcnt); 1060 } else { 1061 compile_asm(tokens, tokcnt); 1062 } 1063 } 1064 1065 if (lineno < 1) { 1066 error("Empty input"); 1067 } 1068 1069 if (errors == 0) { 1070 if (verbose) { 1071 (void) fprintf(stderr, 1072 "%d instructions out of 512 assembled\n", pc); 1073 } 1074 1075 if (outfile) 1076 produce_output(outfile); 1077 if (mapfile) 1078 produce_map(mapfile); 1079 if (header) 1080 produce_header(header, prefix); 1081 } 1082 1083 if (errors > 0) { 1084 (void) fprintf(stderr, "%d errors - compile failed\n", errors); 1085 exit(-1); 1086 } 1087 1088 return (0); 1089 } 1090