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 char tmp[128]; 441 442 CHECK_COUNT(tokens, cnt, 3, 3); 443 444 parm = tokens[1]; 445 def = tokens[2]; 446 447 n = fle.parms.ngpr; 448 if (n >= MAX_GPR_PARMS) { 449 error("Too many GPR parameters"); 450 return; 451 } 452 453 if (sscanf(def, "%d", &num) != 1) { 454 error("Bad integer value near '%s'", def); 455 return; 456 } 457 458 (void) strcpy(fle.parms.gpr[n].name, parm); 459 fle.parms.gpr[n].num = ngpr; 460 fle.parms.gpr[n].def = num; 461 fle.parms.ngpr = n + 1; 462 463 add_init(ngpr, num, parm); 464 465 add_symbol(parm, SY_PARM, gpr_base + ngpr++); 466 } 467 468 static void 469 compile_stereo(char **tokens, int cnt) 470 { 471 char *parm, *def; 472 int n, num; 473 char tmp[128]; 474 475 CHECK_COUNT(tokens, cnt, 3, 3); 476 477 parm = tokens[1]; 478 def = tokens[2]; 479 480 n = fle.parms.ngpr; 481 if (n >= MAX_GPR_PARMS) { 482 error("Too many GPR parameters"); 483 return; 484 } 485 486 if (sscanf(def, "%d", &num) != 1) { 487 error("Bad integer value near '%s'", def); 488 return; 489 } 490 491 (void) strcpy(fle.parms.gpr[n].name, parm); 492 fle.parms.gpr[n].num = ngpr; 493 fle.parms.gpr[n].def = num | (num << 8); 494 fle.parms.ngpr = n + 1; 495 496 add_init(ngpr, num, parm); 497 add_init(ngpr + 1, num, NULL); 498 499 (void) sprintf(tmp, "%s_L", parm); 500 add_symbol(tmp, SY_PARM, gpr_base + ngpr++); 501 (void) sprintf(tmp, "%s_R", parm); 502 add_symbol(tmp, SY_PARM, gpr_base + ngpr++); 503 } 504 505 static void 506 compile_input(char **tokens, int cnt) 507 { 508 int num; 509 510 CHECK_COUNT(tokens, cnt, 3, 3); 511 512 if (sscanf(tokens[2], "%d", &num) != 1) { 513 error("Bad integer value near '%s'", tokens[2]); 514 return; 515 } 516 517 add_symbol(tokens[1], SY_INPUT, input_base + num); 518 } 519 520 static void 521 compile_send(char **tokens, int cnt) 522 { 523 int num; 524 525 CHECK_COUNT(tokens, cnt, 3, 3); 526 527 if (sscanf(tokens[2], "%d", &num) != 1) { 528 error("Bad integer near '%s'", tokens[2]); 529 return; 530 } 531 532 add_symbol(tokens[1], SY_FX, num); 533 } 534 535 static void 536 compile_output(char **tokens, int cnt) 537 { 538 int num; 539 540 CHECK_COUNT(tokens, cnt, 3, 3); 541 542 if (sscanf(tokens[2], "%d", &num) != 1) { 543 error("Bad integer value near '%s'", tokens[2]); 544 return; 545 } 546 547 add_symbol(tokens[1], SY_OUTPUT, output_base + num); 548 } 549 550 static void 551 compile_directive(char **tokens, int cnt) 552 { 553 if (strcmp(tokens[0], ".gpr") == 0) { 554 compile_gpr(tokens, cnt); 555 return; 556 } 557 558 if (strcmp(tokens[0], ".const") == 0) { 559 compile_const(tokens, cnt); 560 return; 561 } 562 563 if (strcmp(tokens[0], ".stereo") == 0) { 564 compile_stereo(tokens, cnt); 565 return; 566 } 567 568 if (strcmp(tokens[0], ".mono") == 0) { 569 compile_mono(tokens, cnt); 570 return; 571 } 572 573 if (strcmp(tokens[0], ".bool") == 0) { 574 compile_bool(tokens, cnt); 575 return; 576 } 577 578 if (strcmp(tokens[0], ".input") == 0) { 579 compile_input(tokens, cnt); 580 return; 581 } 582 583 if (strcmp(tokens[0], ".send") == 0) { 584 compile_send(tokens, cnt); 585 return; 586 } 587 588 if (strcmp(tokens[0], ".output") == 0) { 589 compile_output(tokens, cnt); 590 return; 591 } 592 593 if (strcmp(tokens[0], ".rem") == 0) { 594 compile_rem(tokens, cnt); 595 return; 596 } 597 if (strcmp(tokens[0], ".'") == 0) { 598 compile_rem(tokens, cnt); 599 return; 600 } 601 602 error("Unknown directive '%s'", tokens[0]); 603 } 604 605 static void 606 compile_asm(char **tokens, int cnt) 607 { 608 char *parms[4]; 609 sym_t *symbols[4]; 610 #define EMIT(o, r, a, x, y) \ 611 fle.code[pc*2] = ((x) << 10) | (y); \ 612 fle.code[pc*2+1] = ((o) << 20) | ((r) << 10) | a; pc++ 613 #define EMIT_AUDIGY(o, r, a, x, y) \ 614 fle.code[pc*2] = ((x) << 12) | (y); \ 615 fle.code[pc*2+1] = ((o) << 24) | ((r) << 12) | a; pc++ 616 617 int i, n = 0, nerr = 0; 618 int ninputs = 0; 619 620 CHECK_COUNT(tokens, cnt, 5, 5); 621 622 for (i = 0; i < 4; i++) { 623 if ((symbols[i] = find_symbol(tokens[i+1])) == NULL) { 624 (void) fprintf(stderr, "%s\n", tokens[i+1]); 625 nerr++; 626 error("Undefined symbol '%s'", tokens[i + 1]); 627 continue; 628 } 629 630 if (symbols[i]->type == SY_INPUT) 631 ninputs++; 632 633 if (symbols[i]->type == SY_ACCUM && i != 1) 634 error("Bad usage of 'accum' operand."); 635 } 636 637 if (nerr > 0) 638 return; 639 640 if (ninputs > 1) { 641 error("Attempt to access more than one input " 642 "GPRs by the same instruction"); 643 } 644 645 for (i = 0; instructions[i].name != NULL; i++) 646 if (strcasecmp(tokens[0], instructions[i].name) == 0) { 647 648 if (is_audigy) { 649 EMIT_AUDIGY(instructions[i].opcode, 650 symbols[0]->arg, 651 symbols[1]->arg, 652 symbols[2]->arg, 653 symbols[3]->arg); 654 } else { 655 EMIT(instructions[i].opcode, 656 symbols[0]->arg, 657 symbols[1]->arg, 658 symbols[2]->arg, 659 symbols[3]->arg); 660 } 661 662 return; 663 } 664 665 error("Unrecognized instruction '%s'", tokens[0]); 666 } 667 668 static void 669 init_compiler(void) 670 { 671 char tmp[100]; 672 int i; 673 674 (void) memset(&fle, 0, sizeof (fle)); 675 /* 676 * Initialize few predefined GPR parameter registers. These 677 * definitions have to be in sync with the GPR_* macros in 678 * <sblive.h>. 679 */ 680 681 /* 682 * Make sure we start at gpr id 2 for now; 0 and 1 may be used 683 * differently. 684 */ 685 add_symbol("NULL", SY_DUMMY, gpr_base + ngpr++); 686 add_symbol("NULL_", SY_DUMMY, gpr_base + ngpr++); 687 688 pc = 0; 689 690 if (is_audigy) { 691 /* Initialize the code array with NOPs (AUDIGY) */ 692 for (i = 0; i < 512; i++) { 693 fle.code[i * 2 + 0] = (0xc0 << 12) | 0xc0; 694 fle.code[i * 2 + 1] = 695 (0x06 << 24) | (0xc0 << 12) | 0xc0; 696 } 697 698 for (i = 0; i < 32; i++) { 699 (void) sprintf(tmp, "fx%d", i); 700 add_symbol(tmp, SY_FX, i); 701 } 702 } else { 703 /* Initialize the code array with NOPs (LIVE) */ 704 for (i = 0; i < 512; i++) { 705 fle.code[i * 2 + 0] = 0x10040; 706 fle.code[i * 2 + 1] = 0x610040; 707 } 708 709 for (i = 0; i < 16; i++) { 710 (void) sprintf(tmp, "fx%d", i); 711 add_symbol(tmp, SY_FX, i); 712 } 713 } 714 715 /* 716 * Constants 717 */ 718 719 if (is_audigy) { 720 /* Audigy symbols */ 721 add_symbol("0", SY_CONST, 0x0c0); 722 add_symbol("1", SY_CONST, 0x0c1); 723 add_symbol("2", SY_CONST, 0x0c2); 724 add_symbol("3", SY_CONST, 0x0c3); 725 add_symbol("4", SY_CONST, 0x0c4); 726 add_symbol("8", SY_CONST, 0x0c5); 727 add_symbol("16", SY_CONST, 0x0c6); 728 add_symbol("32", SY_CONST, 0x0c7); 729 add_symbol("256", SY_CONST, 0x0c8); 730 add_symbol("65536", SY_CONST, 0x0c9); 731 732 add_symbol("2048", SY_CONST, 0x0ca); 733 add_symbol("0x800", SY_CONST, 0x0ca); 734 735 add_symbol("2^28", SY_CONST, 0x0cb); 736 add_symbol("0x10000000", SY_CONST, 0x0cb); 737 738 add_symbol("2^29", SY_CONST, 0x0cc); 739 add_symbol("0x20000000", SY_CONST, 0x0cc); 740 741 add_symbol("2^30", SY_CONST, 0x0cd); 742 add_symbol("0x40000000", SY_CONST, 0x0cd); 743 744 add_symbol("2^31", SY_CONST, 0x0ce); 745 add_symbol("0x80000000", SY_CONST, 0x0ce); 746 747 add_symbol("0x7fffffff", SY_CONST, 0x0cf); 748 749 add_symbol("0xffffffff", SY_CONST, 0x0d0); 750 add_symbol("-1", SY_CONST, 0x0d0); 751 752 add_symbol("0xfffffffe", SY_CONST, 0x0d1); 753 add_symbol("-2", SY_CONST, 0x0d1); 754 755 add_symbol("0xc0000000", SY_CONST, 0x0d2); 756 757 add_symbol("0x4f1bbcdc", SY_CONST, 0x0d3); 758 759 add_symbol("0x5a7ef9db", SY_CONST, 0x0d4); 760 761 add_symbol("0x100000", SY_CONST, 0x0d5); 762 add_symbol("accum", SY_ACCUM, 0x0d6); 763 add_symbol("CCR", SY_CONST, 0x0d7); 764 765 add_symbol("noise_L", SY_CONST, 0x0d8); 766 add_symbol("noise_R", SY_CONST, 0x0d9); 767 add_symbol("IRQREQ", SY_CONST, 0x0da); 768 } else { 769 /* SB Live symbols */ 770 add_symbol("0", SY_CONST, 0x040); 771 add_symbol("1", SY_CONST, 0x041); 772 add_symbol("2", SY_CONST, 0x042); 773 add_symbol("3", SY_CONST, 0x043); 774 add_symbol("4", SY_CONST, 0x044); 775 add_symbol("8", SY_CONST, 0x045); 776 add_symbol("16", SY_CONST, 0x046); 777 add_symbol("32", SY_CONST, 0x047); 778 add_symbol("256", SY_CONST, 0x048); 779 add_symbol("65536", SY_CONST, 0x049); 780 781 add_symbol("2^23", SY_CONST, 0x04a); 782 add_symbol("0x80000", SY_CONST, 0x04a); 783 784 add_symbol("2^28", SY_CONST, 0x04b); 785 add_symbol("0x10000000", SY_CONST, 0x04b); 786 787 add_symbol("2^29", SY_CONST, 0x04c); 788 add_symbol("0x20000000", SY_CONST, 0x04c); 789 790 add_symbol("2^30", SY_CONST, 0x04d); 791 add_symbol("0x40000000", SY_CONST, 0x04d); 792 793 add_symbol("2^31", SY_CONST, 0x04e); 794 add_symbol("0x80000000", SY_CONST, 0x04e); 795 796 add_symbol("0x7fffffff", SY_CONST, 0x04f); 797 798 add_symbol("0xffffffff", SY_CONST, 0x050); 799 add_symbol("-1", SY_CONST, 0x050); 800 801 add_symbol("0xfffffffe", SY_CONST, 0x051); 802 add_symbol("-2", SY_CONST, 0x051); 803 804 add_symbol("accum", SY_ACCUM, 0x056); 805 add_symbol("CCR", SY_CONST, 0x057); 806 807 add_symbol("noise_L", SY_CONST, 0x058); 808 add_symbol("noise_R", SY_CONST, 0x059); 809 add_symbol("IRQREQ", SY_CONST, 0x05a); 810 } 811 } 812 813 static void 814 produce_map(char *name) 815 { 816 char fname[1024]; 817 int i; 818 FILE *f; 819 820 if ((f = fopen(name, "w")) == NULL) { 821 perror(name); 822 return; 823 } 824 825 (void) fprintf(f, "%d\n", pc); 826 827 for (i = 0; i < nsyms; i++) { 828 (void) fprintf(f, "%04x %x %s\n", 829 symtab[i].arg, symtab[i].type, symtab[i].name); 830 } 831 832 (void) fclose(f); 833 if (verbose) { 834 (void) fprintf(stderr, 835 "No errors detected - Map written to %s\n", name); 836 } 837 } 838 839 static void 840 produce_output(char *fname) 841 { 842 int fd; 843 844 if ((fd = creat(fname, 0644)) == -1) { 845 perror(fname); 846 exit(-1); 847 } 848 849 if (write(fd, &fle, sizeof (fle)) != sizeof (fle)) { 850 perror(fname); 851 exit(-1); 852 } 853 854 if (verbose) { 855 (void) fprintf(stderr, 856 "No errors detected - Binary written to %s\n", 857 fname); 858 } 859 860 (void) close(fd); 861 } 862 863 static void 864 produce_header(char *fname, char *prefix) 865 { 866 FILE *f; 867 char *s; 868 char sname[MAXPATHLEN + 1]; 869 char dname[MAXPATHLEN + 1]; 870 int i; 871 clock_t now; 872 char when[128]; 873 874 /* get basename */ 875 if (prefix == NULL) { 876 s = strrchr(fname, '/'); 877 s = (s == NULL) ? fname : s + 1; 878 } else { 879 s = prefix; 880 } 881 (void) strlcpy(sname, s, sizeof (sname)); 882 883 /* strip off any extension */ 884 s = strchr(sname, '.'); 885 if (s != NULL) { 886 *s = 0; 887 } 888 if ((f = fopen(fname, "w")) == NULL) { 889 perror(fname); 890 return; 891 } 892 893 if (remarks[0] != 0) { 894 (void) fprintf(f, "/*\n%s */\n", remarks); 895 } 896 now = time(NULL); 897 strftime(when, sizeof (when), "%c", localtime(&now)); 898 (void) fprintf(f, banner, progname, when); 899 900 (void) strlcpy(dname, prefix ? prefix : sname, sizeof (dname)); 901 for (i = 0; dname[i]; i++) { 902 dname[i] = toupper(dname[i]); 903 if (!isalnum(dname[i])) { 904 dname[i] = '_'; 905 } 906 } 907 908 for (i = 0; i < fle.parms.ngpr; i++) { 909 (void) fprintf(f, "#define\t%s_%s\t\t%d\n", 910 dname, fle.parms.gpr[i].name, fle.parms.gpr[i].num); 911 } 912 913 (void) fprintf(f, "\n"); 914 915 if (parms_only) 916 goto done; 917 918 (void) fprintf(f, "uint32_t %s_code[] = {\n", sname); 919 920 for (i = 0; i < pc * 2; i++) { 921 if (i == 0) { 922 (void) fprintf(f, "\t0x%08xU", fle.code[i]); 923 } else if ((i % 4) == 0) { 924 (void) fprintf(f, ",\n\t0x%08xU", fle.code[i]); 925 } else { 926 (void) fprintf(f, ", 0x%08xU", fle.code[i]); 927 } 928 } 929 (void) fprintf(f, "\n};\n"); 930 931 (void) fprintf(f, "uint32_t %s_ninit = %d;\n", sname, fle.ninit); 932 (void) fprintf(f, "uint32_t %s_init[] = {\n", sname); 933 934 for (i = 0; i < fle.ninit; i++) { 935 if (fle.init[i].name[0]) { 936 (void) fprintf(f, "\t%u, 0x%x%s,\t/* %s */\n", 937 fle.init[i].gpr, fle.init[i].value, 938 fle.init[i].value >= 0x80000000U ? "U" : "", 939 fle.init[i].name); 940 } else { 941 (void) fprintf(f, "\t%u, 0x%x%s,\n", 942 fle.init[i].gpr, fle.init[i].value, 943 fle.init[i].value >= 0x80000000U ? "U" : ""); 944 } 945 } 946 (void) fprintf(f, "};\n"); 947 948 done: 949 (void) fclose(f); 950 if (verbose) { 951 (void) fprintf(stderr, 952 "No errors detected - Header written to %s\n", 953 fname); 954 } 955 } 956 957 int 958 main(int argc, char *argv[]) 959 { 960 char line[4096], *p, *s, *outfile; 961 char *iline; 962 int i; 963 FILE *input; 964 char *tokens[10]; 965 int tokcnt; 966 char *mapfile = NULL; 967 char *header = NULL; 968 char *prefix = NULL; 969 970 outfile = NULL; 971 infile = NULL; 972 input = NULL; 973 progname = argv[0]; 974 975 while ((i = getopt(argc, argv, "m:h:o:i:P:021v")) != EOF) { 976 switch (i) { 977 case 'o': 978 outfile = optarg; 979 break; 980 case 'i': 981 infile = strdup(optarg); 982 break; 983 case 'm': 984 mapfile = optarg; 985 break; 986 case 'P': 987 prefix = optarg; 988 break; 989 case 'h': 990 header = optarg; 991 break; 992 case '0': 993 parms_only = 1; 994 break; 995 case '2': 996 is_audigy = 1; 997 break; 998 case '1': 999 is_audigy = 0; 1000 break; 1001 case 'v': 1002 verbose++; 1003 break; 1004 default: 1005 (void) fprintf(stderr, 1006 "usage: %s [-m <map>] [-h <header>] " 1007 "[-o <binary>] [-i <source>] [-2|-1]", 1008 progname); 1009 exit(-1); 1010 break; 1011 } 1012 } 1013 1014 if ((outfile == NULL) && (mapfile == NULL) && (header == NULL)) { 1015 outfile = "dsp.bin"; 1016 } 1017 1018 if (infile) { 1019 input = fopen(infile, "r"); 1020 if (input == NULL) { 1021 perror(infile); 1022 exit(-1); 1023 } 1024 } else { 1025 infile = strdup("<stdin>"); 1026 input = stdin; 1027 } 1028 1029 if (is_audigy) { 1030 gpr_base = 0x400; 1031 input_base = 0x40; 1032 output_base = 0x60; 1033 if (verbose) 1034 (void) fprintf(stderr, "Compiling for SB Audigy\n"); 1035 } else { 1036 if (verbose) 1037 (void) fprintf(stderr, "Compiling for SB Live\n"); 1038 } 1039 1040 init_compiler(); 1041 1042 while ((tokcnt = getaline(input, tokens)) != -1) { 1043 /* skip empty lines */ 1044 if (tokcnt == 0) { 1045 continue; 1046 } 1047 1048 if (strcmp(tokens[0], "#") == 0) { 1049 int num; 1050 if ((tokcnt >= 3) && 1051 (sscanf(tokens[1], "%d", &num) == 1)) { 1052 lineno = num; 1053 free(infile); 1054 infile = strdup(tokens[2]); 1055 /* we don't want to count the # directive */ 1056 lineno--; 1057 } 1058 1059 /* unknown # directive? muddle on... */ 1060 continue; 1061 } 1062 if (*tokens[0] == '.') { 1063 compile_directive(tokens, tokcnt); 1064 } else { 1065 compile_asm(tokens, tokcnt); 1066 } 1067 } 1068 1069 if (lineno < 1) { 1070 error("Empty input"); 1071 } 1072 1073 if (errors == 0) { 1074 if (verbose) { 1075 (void) fprintf(stderr, 1076 "%d instructions out of 512 assembled\n", pc); 1077 } 1078 1079 if (outfile) 1080 produce_output(outfile); 1081 if (mapfile) 1082 produce_map(mapfile); 1083 if (header) 1084 produce_header(header, prefix); 1085 } 1086 1087 if (errors > 0) { 1088 (void) fprintf(stderr, "%d errors - compile failed\n", errors); 1089 exit(-1); 1090 } 1091 1092 return (0); 1093 }