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