/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
/*
* Assembler for Emu10k1
*/
/*
* Copyright (C) 4Front Technologies 1996-2008.
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
typedef struct {
unsigned int num;
int type;
int def;
} gpr_t;
typedef struct {
unsigned int gpr;
unsigned int value;
} const_t;
typedef struct {
unsigned int ngpr;
} gpr_info;
typedef struct {
unsigned int nconst;
} const_info;
typedef struct {
int ninit;
struct {
} emu10k1_file;
static int parms_only = 0;
static int is_audigy = 0;
static int verbose = 0;
static char *progname;
typedef struct {
int type;
#define SY_DUMMY 0
int arg;
} sym_t;
typedef struct {
char *name;
int opcode;
static char *banner =
"/*\n"
" * Note: This file was automatically generated by %s\n"
" * on %s.\n"
" */\n";
/*
* Instructions. Each instruction takes 4 arguments, R, A, X, and Y.
*/
{ "MACS", 0x0}, /* R = A + (X * Y >> 31); saturation */
{ "MACS1", 0x1}, /* R = A + (-X * Y >> 31); saturation */
{ "MACW", 0x2}, /* R = A + (X * Y >> 31); wraparound */
{ "MACW1", 0x3}, /* R = A + (-X * Y >> 31); wraparound */
{ "MACINTS", 0x4}, /* R = A + (X * Y); saturation */
{ "MACINTW", 0x5}, /* R = A + (X * Y); wraparound */
{ "SUM", 0x6}, /* R = A + X + Y; saturation */
{ "ACC3", 0x6}, /* R = A + X + Y; saturation */
{ "MACMV", 0x7}, /* R = A, acc += X * Y >> 31 */
{ "ANDXOR", 0x8}, /* R = (A & X) ^ Y */
{ "TSTNEG", 0x9}, /* R = (A >= Y) ? X : ~X */
{ "LIMIT", 0xa}, /* R = (A >= Y) ? X : Y */
{ "LIMIT1", 0xb}, /* R = (A < Y) ? X : Y */
{ "LOG", 0xc}, /* R = ... (log?) */
{ "EXP", 0xd}, /* R = ... (exp?) */
{ "INTERP", 0xe}, /* R = A + (X * (Y - A) >> 31) */
{ "SKIP", 0xf}, /* R, CCR, CC_TEST, COUNT */
{ NULL, 0}
};
error("Too few parameters for '%s' (have %d, min %d)", \
return; \
} \
error("Too many parameters for '%s' (have %d, max %d)", \
return; \
}
static int nsyms = 0;
static int pc;
static int ngpr = 0;
static char *infile;
static int
{
char *s, *ls;
for (;;) {
return (-1);
lineno++;
/*
* Special handling for .' comments. We use
* .' as a keyword to ensure that entire
* comment makes it through the C preprocessor
* unmolested. We also need to make sure *we*
* don't molest it either. The comment will
* be exported to any resulting header,
* allowing us to pass through copyright and
* other information from the source file to
* the resulting header.
*/
s = line;
s += strspn(s, " \t");
/* chop off trailing new line */
tokens[0] = s;
s += 2;
s += strspn(s, " \t");
if ((s[0] == '\'') &&
s[strlen(s) - 1] = 0;
s++;
}
tokens[1] = s;
tokens[0][2] = 0;
}
/* strip off any C++ style comments that CPP missed */
*s = '\0';
}
} else {
}
break;
}
}
/*
* Ok, we have a statement, lets tokenize it. For
* simplicities sake we convert "OPCODE(arg1, arg2)" into
* "OPCODE arg1 arg2". This means that commas and parens are
* treated as whitespace. This can lead to some really messed
* up syntaxes that get assembled properly (such as nested
* calls, empty arguments, etc.) Hopefully people don't abuse
* this.
*/
cnt = 0;
tokcnt = 0;
while (cnt < 10) {
if (s != NULL) {
tokcnt++;
}
}
return (tokcnt);
}
static void
{
infile);
errors++;
}
static sym_t *
{
int i;
for (i = 0; i < nsyms; i++)
return (&symtab[i]);
}
return (NULL);
}
static void
{
if (nsyms >= MAX_SYMBOLS) {
error("Symbol table full");
exit(-1);
}
return;
}
exit(-1);
}
}
static void
{
int n;
if (n >= MAX_GPR) {
error("Too many GPRs");
return;
}
if (name)
}
static void
{
error("Too many GPR variables");
}
static void
{
int i;
for (i = 1; i < cnt; i++) {
}
}
static void
{
int n, intv;
float v;
if (n >= MAX_CONST_PARMS) {
error("Too many constant parameters");
return;
}
if (*value == 'I') {
return;
}
intv = (int)v;
return;
}
} else {
return;
}
intv = (int)(v * 0x7fffffff);
}
}
static void
{
error("Too many GPR variables");
}
static void
{
int n, num;
if (n >= MAX_GPR_PARMS) {
error("Too many GPR parameters");
return;
}
return;
}
}
static void
{
int n, num;
if (n >= MAX_GPR_PARMS) {
error("Too many GPR parameters");
return;
}
return;
}
}
static void
{
int n, num;
if (n >= MAX_GPR_PARMS) {
error("Too many GPR parameters");
return;
}
return;
}
}
static void
{
int num;
return;
}
}
static void
{
int num;
return;
}
}
static void
{
int num;
return;
}
}
static void
{
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
}
static void
{
#define EMIT(o, r, a, x, y) \
#define EMIT_AUDIGY(o, r, a, x, y) \
int i, nerr = 0;
int ninputs = 0;
for (i = 0; i < 4; i++) {
nerr++;
continue;
}
ninputs++;
error("Bad usage of 'accum' operand.");
}
if (nerr > 0)
return;
if (ninputs > 1) {
error("Attempt to access more than one input "
"GPRs by the same instruction");
}
if (is_audigy) {
} else {
}
return;
}
}
static void
init_compiler(void)
{
int i;
/*
* Initialize few predefined GPR parameter registers. These
* definitions have to be in sync with the GPR_* macros in
* <sblive.h>.
*/
/*
* Make sure we start at gpr id 2 for now; 0 and 1 may be used
* differently.
*/
pc = 0;
if (is_audigy) {
/* Initialize the code array with NOPs (AUDIGY) */
for (i = 0; i < 512; i++) {
(0x06 << 24) | (0xc0 << 12) | 0xc0;
}
for (i = 0; i < 32; i++) {
}
} else {
/* Initialize the code array with NOPs (LIVE) */
for (i = 0; i < 512; i++) {
}
for (i = 0; i < 16; i++) {
}
}
/*
* Constants
*/
if (is_audigy) {
/* Audigy symbols */
} else {
/* SB Live symbols */
}
}
static void
{
int i;
FILE *f;
return;
}
for (i = 0; i < nsyms; i++) {
(void) fprintf(f, "%04x %x %s\n",
}
(void) fclose(f);
if (verbose) {
"No errors detected - Map written to %s\n", name);
}
}
static void
{
int fd;
exit(-1);
}
exit(-1);
}
if (verbose) {
"No errors detected - Binary written to %s\n",
fname);
}
}
static void
{
FILE *f;
char *s;
int i;
/* get basename */
} else {
s = prefix;
}
/* strip off any extension */
if (s != NULL) {
*s = 0;
}
return;
}
if (remarks[0] != 0) {
}
for (i = 0; dname[i]; i++) {
dname[i] = '_';
}
}
(void) fprintf(f, "#define\t%s_%s\t\t%d\n",
}
(void) fprintf(f, "\n");
if (parms_only)
goto done;
for (i = 0; i < pc * 2; i++) {
if (i == 0) {
} else if ((i % 4) == 0) {
} else {
}
}
(void) fprintf(f, "\n};\n");
(void) fprintf(f, "\t%u, 0x%x%s,\t/* %s */\n",
} else {
(void) fprintf(f, "\t%u, 0x%x%s,\n",
}
}
(void) fprintf(f, "};\n");
done:
(void) fclose(f);
if (verbose) {
"No errors detected - Header written to %s\n",
fname);
}
}
int
{
char *outfile;
int i;
int tokcnt;
switch (i) {
case 'o':
break;
case 'i':
break;
case 'm':
break;
case 'P':
break;
case 'h':
break;
case '0':
parms_only = 1;
break;
case '2':
is_audigy = 1;
break;
case '1':
is_audigy = 0;
break;
case 'v':
verbose++;
break;
default:
"usage: %s [-m <map>] [-h <header>] "
"[-o <binary>] [-i <source>] [-2|-1]",
progname);
exit(-1);
break;
}
}
outfile = "dsp.bin";
}
if (infile) {
exit(-1);
}
} else {
}
if (is_audigy) {
gpr_base = 0x400;
input_base = 0x40;
output_base = 0x60;
if (verbose)
} else {
if (verbose)
}
/* skip empty lines */
if (tokcnt == 0) {
continue;
}
int num;
if ((tokcnt >= 3) &&
/* we don't want to count the # directive */
lineno--;
}
/* unknown # directive? muddle on... */
continue;
}
if (*tokens[0] == '.') {
} else {
}
}
if (lineno < 1) {
error("Empty input");
}
if (errors == 0) {
if (verbose) {
"%d instructions out of 512 assembled\n", pc);
}
if (outfile)
if (mapfile)
if (header)
}
if (errors > 0) {
exit(-1);
}
return (0);
}