OpenCores
URL https://opencores.org/ocsvn/eco32/eco32/trunk

Subversion Repositories eco32

[/] [eco32/] [tags/] [eco32-0.22/] [binutils/] [as/] [as.c] - Diff between revs 7 and 21

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 7 Rev 21
/*
/*
 * as.c -- ECO32 assembler
 * as.c -- ECO32 assembler
 */
 */
 
 
 
 
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
#include <stdarg.h>
#include <stdarg.h>
#include <ctype.h>
#include <ctype.h>
#include <unistd.h>
#include <unistd.h>
 
 
#include "../include/a.out.h"
#include "../include/a.out.h"
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
#define NUM_REGS        32
#define NUM_REGS        32
#define AUX_REG         1
#define AUX_REG         1
 
 
#define LINE_SIZE       200
#define LINE_SIZE       200
 
 
#define TOK_EOL         0
#define TOK_EOL         0
#define TOK_LABEL       1
#define TOK_LABEL       1
#define TOK_IDENT       2
#define TOK_IDENT       2
#define TOK_STRING      3
#define TOK_STRING      3
#define TOK_NUMBER      4
#define TOK_NUMBER      4
#define TOK_REGISTER    5
#define TOK_REGISTER    5
#define TOK_PLUS        6
#define TOK_PLUS        6
#define TOK_MINUS       7
#define TOK_MINUS       7
#define TOK_STAR        8
#define TOK_STAR        8
#define TOK_SLASH       9
#define TOK_SLASH       9
#define TOK_PERCENT     10
#define TOK_PERCENT     10
#define TOK_LSHIFT      11
#define TOK_LSHIFT      11
#define TOK_RSHIFT      12
#define TOK_RSHIFT      12
#define TOK_LPAREN      13
#define TOK_LPAREN      13
#define TOK_RPAREN      14
#define TOK_RPAREN      14
#define TOK_COMMA       15
#define TOK_COMMA       15
#define TOK_TILDE       16
#define TOK_TILDE       16
#define TOK_AMPER       17
#define TOK_AMPER       17
#define TOK_BAR         18
#define TOK_BAR         18
#define TOK_CARET       19
#define TOK_CARET       19
 
 
#define STATUS_UNKNOWN  0        /* symbol is not yet defined */
#define STATUS_UNKNOWN  0        /* symbol is not yet defined */
#define STATUS_DEFINED  1       /* symbol is defined */
#define STATUS_DEFINED  1       /* symbol is defined */
#define STATUS_GLOBREF  2       /* local entry refers to a global one */
#define STATUS_GLOBREF  2       /* local entry refers to a global one */
 
 
#define GLOBAL_TABLE    0        /* global symbol table identifier */
#define GLOBAL_TABLE    0        /* global symbol table identifier */
#define LOCAL_TABLE     1       /* local symbol table identifier */
#define LOCAL_TABLE     1       /* local symbol table identifier */
 
 
#define MSB     ((unsigned int) 1 << (sizeof(unsigned int) * 8 - 1))
#define MSB     ((unsigned int) 1 << (sizeof(unsigned int) * 8 - 1))
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
#define OP_ADD          0x00
#define OP_ADD          0x00
#define OP_ADDI         0x01
#define OP_ADDI         0x01
#define OP_SUB          0x02
#define OP_SUB          0x02
#define OP_SUBI         0x03
#define OP_SUBI         0x03
 
 
#define OP_MUL          0x04
#define OP_MUL          0x04
#define OP_MULI         0x05
#define OP_MULI         0x05
#define OP_MULU         0x06
#define OP_MULU         0x06
#define OP_MULUI        0x07
#define OP_MULUI        0x07
#define OP_DIV          0x08
#define OP_DIV          0x08
#define OP_DIVI         0x09
#define OP_DIVI         0x09
#define OP_DIVU         0x0A
#define OP_DIVU         0x0A
#define OP_DIVUI        0x0B
#define OP_DIVUI        0x0B
#define OP_REM          0x0C
#define OP_REM          0x0C
#define OP_REMI         0x0D
#define OP_REMI         0x0D
#define OP_REMU         0x0E
#define OP_REMU         0x0E
#define OP_REMUI        0x0F
#define OP_REMUI        0x0F
 
 
#define OP_AND          0x10
#define OP_AND          0x10
#define OP_ANDI         0x11
#define OP_ANDI         0x11
#define OP_OR           0x12
#define OP_OR           0x12
#define OP_ORI          0x13
#define OP_ORI          0x13
#define OP_XOR          0x14
#define OP_XOR          0x14
#define OP_XORI         0x15
#define OP_XORI         0x15
#define OP_XNOR         0x16
#define OP_XNOR         0x16
#define OP_XNORI        0x17
#define OP_XNORI        0x17
 
 
#define OP_SLL          0x18
#define OP_SLL          0x18
#define OP_SLLI         0x19
#define OP_SLLI         0x19
#define OP_SLR          0x1A
#define OP_SLR          0x1A
#define OP_SLRI         0x1B
#define OP_SLRI         0x1B
#define OP_SAR          0x1C
#define OP_SAR          0x1C
#define OP_SARI         0x1D
#define OP_SARI         0x1D
 
 
#define OP_LDHI         0x1F
#define OP_LDHI         0x1F
 
 
#define OP_BEQ          0x20
#define OP_BEQ          0x20
#define OP_BNE          0x21
#define OP_BNE          0x21
#define OP_BLE          0x22
#define OP_BLE          0x22
#define OP_BLEU         0x23
#define OP_BLEU         0x23
#define OP_BLT          0x24
#define OP_BLT          0x24
#define OP_BLTU         0x25
#define OP_BLTU         0x25
#define OP_BGE          0x26
#define OP_BGE          0x26
#define OP_BGEU         0x27
#define OP_BGEU         0x27
#define OP_BGT          0x28
#define OP_BGT          0x28
#define OP_BGTU         0x29
#define OP_BGTU         0x29
 
 
#define OP_J            0x2A
#define OP_J            0x2A
#define OP_JR           0x2B
#define OP_JR           0x2B
#define OP_JAL          0x2C
#define OP_JAL          0x2C
#define OP_JALR         0x2D
#define OP_JALR         0x2D
 
 
#define OP_TRAP         0x2E
#define OP_TRAP         0x2E
#define OP_RFX          0x2F
#define OP_RFX          0x2F
 
 
#define OP_LDW          0x30
#define OP_LDW          0x30
#define OP_LDH          0x31
#define OP_LDH          0x31
#define OP_LDHU         0x32
#define OP_LDHU         0x32
#define OP_LDB          0x33
#define OP_LDB          0x33
#define OP_LDBU         0x34
#define OP_LDBU         0x34
 
 
#define OP_STW          0x35
#define OP_STW          0x35
#define OP_STH          0x36
#define OP_STH          0x36
#define OP_STB          0x37
#define OP_STB          0x37
 
 
#define OP_MVFS         0x38
#define OP_MVFS         0x38
#define OP_MVTS         0x39
#define OP_MVTS         0x39
#define OP_TBS          0x3A
#define OP_TBS          0x3A
#define OP_TBWR         0x3B
#define OP_TBWR         0x3B
#define OP_TBRI         0x3C
#define OP_TBRI         0x3C
#define OP_TBWI         0x3D
#define OP_TBWI         0x3D
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
int debugToken = 0;
int debugToken = 0;
int debugCode = 0;
int debugCode = 0;
int debugFixup = 0;
int debugFixup = 0;
 
 
char codeName[L_tmpnam];
char codeName[L_tmpnam];
char dataName[L_tmpnam];
char dataName[L_tmpnam];
char *outName = NULL;
char *outName = NULL;
char *inName = NULL;
char *inName = NULL;
 
 
FILE *codeFile = NULL;
FILE *codeFile = NULL;
FILE *dataFile = NULL;
FILE *dataFile = NULL;
FILE *outFile = NULL;
FILE *outFile = NULL;
FILE *inFile = NULL;
FILE *inFile = NULL;
 
 
char line[LINE_SIZE];
char line[LINE_SIZE];
char *lineptr;
char *lineptr;
int lineno;
int lineno;
 
 
int token;
int token;
int tokenvalNumber;
int tokenvalNumber;
char tokenvalString[LINE_SIZE];
char tokenvalString[LINE_SIZE];
 
 
int allowSyn = 1;
int allowSyn = 1;
int currSeg = SEGMENT_CODE;
int currSeg = SEGMENT_CODE;
unsigned int segPtr[4] = { 0, 0, 0, 0 };
unsigned int segPtr[4] = { 0, 0, 0, 0 };
char *segName[4] = { "ABS", "CODE", "DATA", "BSS" };
char *segName[4] = { "ABS", "CODE", "DATA", "BSS" };
char *methodName[5] = { "H16", "L16", "R16", "R26", "W32" };
char *methodName[5] = { "H16", "L16", "R16", "R26", "W32" };
 
 
 
 
typedef struct fixup {
typedef struct fixup {
  int segment;                  /* in which segment */
  int segment;                  /* in which segment */
  unsigned int offset;          /* at which offset */
  unsigned int offset;          /* at which offset */
  int method;                   /* what kind of coding method is to be used */
  int method;                   /* what kind of coding method is to be used */
  int value;                    /* known part of value */
  int value;                    /* known part of value */
  int base;                     /* segment which this ref is relative to */
  int base;                     /* segment which this ref is relative to */
                                /* valid only when used for relocation */
                                /* valid only when used for relocation */
  struct fixup *next;           /* next fixup */
  struct fixup *next;           /* next fixup */
} Fixup;
} Fixup;
 
 
 
 
typedef struct symbol {
typedef struct symbol {
  char *name;                   /* name of symbol */
  char *name;                   /* name of symbol */
  int status;                   /* status of symbol */
  int status;                   /* status of symbol */
  int segment;                  /* the symbol's segment */
  int segment;                  /* the symbol's segment */
  int value;                    /* the symbol's value */
  int value;                    /* the symbol's value */
  Fixup *fixups;                /* list of locations to fix */
  Fixup *fixups;                /* list of locations to fix */
  struct symbol *globref;       /* set if this local refers to a global */
  struct symbol *globref;       /* set if this local refers to a global */
  struct symbol *left;          /* left son in binary search tree */
  struct symbol *left;          /* left son in binary search tree */
  struct symbol *right;         /* right son in binary search tree */
  struct symbol *right;         /* right son in binary search tree */
  int skip;                     /* this symbol is not defined here nor is */
  int skip;                     /* this symbol is not defined here nor is */
                                /* it used here: don't write to object file */
                                /* it used here: don't write to object file */
} Symbol;
} Symbol;
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
void error(char *fmt, ...) {
void error(char *fmt, ...) {
  va_list ap;
  va_list ap;
 
 
  va_start(ap, fmt);
  va_start(ap, fmt);
  fprintf(stderr, "Error: ");
  fprintf(stderr, "Error: ");
  vfprintf(stderr, fmt, ap);
  vfprintf(stderr, fmt, ap);
  fprintf(stderr, "\n");
  fprintf(stderr, "\n");
  va_end(ap);
  va_end(ap);
  if (codeFile != NULL) {
  if (codeFile != NULL) {
    fclose(codeFile);
    fclose(codeFile);
    codeFile = NULL;
    codeFile = NULL;
  }
  }
  if (dataFile != NULL) {
  if (dataFile != NULL) {
    fclose(dataFile);
    fclose(dataFile);
    dataFile = NULL;
    dataFile = NULL;
  }
  }
  if (outFile != NULL) {
  if (outFile != NULL) {
    fclose(outFile);
    fclose(outFile);
    outFile = NULL;
    outFile = NULL;
  }
  }
  if (inFile != NULL) {
  if (inFile != NULL) {
    fclose(inFile);
    fclose(inFile);
    inFile = NULL;
    inFile = NULL;
  }
  }
  if (codeName != NULL) {
  if (codeName != NULL) {
    unlink(codeName);
    unlink(codeName);
  }
  }
  if (dataName != NULL) {
  if (dataName != NULL) {
    unlink(dataName);
    unlink(dataName);
  }
  }
  if (outName != NULL) {
  if (outName != NULL) {
    unlink(outName);
    unlink(outName);
  }
  }
  exit(1);
  exit(1);
}
}
 
 
 
 
void *allocateMemory(unsigned int size) {
void *allocateMemory(unsigned int size) {
  void *p;
  void *p;
 
 
  p = malloc(size);
  p = malloc(size);
  if (p == NULL) {
  if (p == NULL) {
    error("out of memory");
    error("out of memory");
  }
  }
  return p;
  return p;
}
}
 
 
 
 
void freeMemory(void *p) {
void freeMemory(void *p) {
  free(p);
  free(p);
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
int getNextToken(void) {
int getNextToken(void) {
  char *p;
  char *p;
  int base;
  int base;
  int digit;
  int digit;
 
 
  while (*lineptr == ' ' || *lineptr == '\t') {
  while (*lineptr == ' ' || *lineptr == '\t') {
    lineptr++;
    lineptr++;
  }
  }
  if (*lineptr == '\n' || *lineptr == '\0' || *lineptr == ';') {
  if (*lineptr == '\n' || *lineptr == '\0' || *lineptr == ';') {
    return TOK_EOL;
    return TOK_EOL;
  }
  }
  if (isalpha((int) *lineptr) || *lineptr == '_' || *lineptr == '.') {
  if (isalpha((int) *lineptr) || *lineptr == '_' || *lineptr == '.') {
    p = tokenvalString;
    p = tokenvalString;
    while (isalnum((int) *lineptr) || *lineptr == '_' || *lineptr == '.') {
    while (isalnum((int) *lineptr) || *lineptr == '_' || *lineptr == '.') {
      *p++ = *lineptr++;
      *p++ = *lineptr++;
    }
    }
    *p = '\0';
    *p = '\0';
    if (*lineptr == ':') {
    if (*lineptr == ':') {
      lineptr++;
      lineptr++;
      return TOK_LABEL;
      return TOK_LABEL;
    } else {
    } else {
      return TOK_IDENT;
      return TOK_IDENT;
    }
    }
  }
  }
  if (isdigit((int) *lineptr)) {
  if (isdigit((int) *lineptr)) {
    base = 10;
    base = 10;
    tokenvalNumber = 0;
    tokenvalNumber = 0;
    if (*lineptr == '0') {
    if (*lineptr == '0') {
      lineptr++;
      lineptr++;
      if (*lineptr == 'x' || *lineptr == 'X') {
      if (*lineptr == 'x' || *lineptr == 'X') {
        base = 16;
        base = 16;
        lineptr++;
        lineptr++;
      } else
      } else
      if (isdigit((int) *lineptr)) {
      if (isdigit((int) *lineptr)) {
        base = 8;
        base = 8;
      } else {
      } else {
        return TOK_NUMBER;
        return TOK_NUMBER;
      }
      }
    }
    }
    while (isxdigit((int) *lineptr)) {
    while (isxdigit((int) *lineptr)) {
      digit = *lineptr++ - '0';
      digit = *lineptr++ - '0';
      if (digit >= 'A' - '0') {
      if (digit >= 'A' - '0') {
        if (digit >= 'a' - '0') {
        if (digit >= 'a' - '0') {
          digit += '0' - 'a' + 10;
          digit += '0' - 'a' + 10;
        } else {
        } else {
          digit += '0' - 'A' + 10;
          digit += '0' - 'A' + 10;
        }
        }
      }
      }
      if (digit >= base) {
      if (digit >= base) {
        error("illegal digit value %d in line %d", digit, lineno);
        error("illegal digit value %d in line %d", digit, lineno);
      }
      }
      tokenvalNumber *= base;
      tokenvalNumber *= base;
      tokenvalNumber += digit;
      tokenvalNumber += digit;
    }
    }
    return TOK_NUMBER;
    return TOK_NUMBER;
  }
  }
  if (*lineptr == '\'') {
  if (*lineptr == '\'') {
    lineptr++;
    lineptr++;
    if (!isprint((int) *lineptr)) {
    if (!isprint((int) *lineptr)) {
      error("cannot quote character 0x%02X in line %d", *lineptr, lineno);
      error("cannot quote character 0x%02X in line %d", *lineptr, lineno);
    }
    }
    tokenvalNumber = *lineptr;
    tokenvalNumber = *lineptr;
    lineptr++;
    lineptr++;
    if (*lineptr != '\'') {
    if (*lineptr != '\'') {
      error("unbalanced quote in line %d", lineno);
      error("unbalanced quote in line %d", lineno);
    }
    }
    lineptr++;
    lineptr++;
    return TOK_NUMBER;
    return TOK_NUMBER;
  }
  }
  if (*lineptr == '\"') {
  if (*lineptr == '\"') {
    lineptr++;
    lineptr++;
    p = tokenvalString;
    p = tokenvalString;
    while (1) {
    while (1) {
      if (*lineptr == '\n' || *lineptr == '\0') {
      if (*lineptr == '\n' || *lineptr == '\0') {
        error("unterminated string constant in line %d", lineno);
        error("unterminated string constant in line %d", lineno);
      }
      }
      if (!isprint((int) *lineptr)) {
      if (!isprint((int) *lineptr)) {
        error("string contains illegal character 0x%02X in line %d",
        error("string contains illegal character 0x%02X in line %d",
              *lineptr, lineno);
              *lineptr, lineno);
      }
      }
      if (*lineptr == '\"') {
      if (*lineptr == '\"') {
        break;
        break;
      }
      }
      *p++ = *lineptr++;
      *p++ = *lineptr++;
    }
    }
    lineptr++;
    lineptr++;
    *p = '\0';
    *p = '\0';
    return TOK_STRING;
    return TOK_STRING;
  }
  }
  if (*lineptr == '$') {
  if (*lineptr == '$') {
    lineptr++;
    lineptr++;
    if (!isdigit((int) *lineptr)) {
    if (!isdigit((int) *lineptr)) {
      error("register number expected after '$' in line %d", lineno);
      error("register number expected after '$' in line %d", lineno);
    }
    }
    tokenvalNumber = 0;
    tokenvalNumber = 0;
    while (isdigit((int) *lineptr)) {
    while (isdigit((int) *lineptr)) {
      digit = *lineptr++ - '0';
      digit = *lineptr++ - '0';
      tokenvalNumber *= 10;
      tokenvalNumber *= 10;
      tokenvalNumber += digit;
      tokenvalNumber += digit;
    }
    }
    if (tokenvalNumber < 0 || tokenvalNumber >= NUM_REGS) {
    if (tokenvalNumber < 0 || tokenvalNumber >= NUM_REGS) {
      error("illegal register number %d in line %d", tokenvalNumber, lineno);
      error("illegal register number %d in line %d", tokenvalNumber, lineno);
    }
    }
    return TOK_REGISTER;
    return TOK_REGISTER;
  }
  }
  if (*lineptr == '+') {
  if (*lineptr == '+') {
    lineptr++;
    lineptr++;
    return TOK_PLUS;
    return TOK_PLUS;
  }
  }
  if (*lineptr == '-') {
  if (*lineptr == '-') {
    lineptr++;
    lineptr++;
    return TOK_MINUS;
    return TOK_MINUS;
  }
  }
  if (*lineptr == '*') {
  if (*lineptr == '*') {
    lineptr++;
    lineptr++;
    return TOK_STAR;
    return TOK_STAR;
  }
  }
  if (*lineptr == '/') {
  if (*lineptr == '/') {
    lineptr++;
    lineptr++;
    return TOK_SLASH;
    return TOK_SLASH;
  }
  }
  if (*lineptr == '%') {
  if (*lineptr == '%') {
    lineptr++;
    lineptr++;
    return TOK_PERCENT;
    return TOK_PERCENT;
  }
  }
  if (*lineptr == '<' && *(lineptr + 1) == '<') {
  if (*lineptr == '<' && *(lineptr + 1) == '<') {
    lineptr += 2;
    lineptr += 2;
    return TOK_LSHIFT;
    return TOK_LSHIFT;
  }
  }
  if (*lineptr == '>' && *(lineptr + 1) == '>') {
  if (*lineptr == '>' && *(lineptr + 1) == '>') {
    lineptr += 2;
    lineptr += 2;
    return TOK_RSHIFT;
    return TOK_RSHIFT;
  }
  }
  if (*lineptr == '(') {
  if (*lineptr == '(') {
    lineptr++;
    lineptr++;
    return TOK_LPAREN;
    return TOK_LPAREN;
  }
  }
  if (*lineptr == ')') {
  if (*lineptr == ')') {
    lineptr++;
    lineptr++;
    return TOK_RPAREN;
    return TOK_RPAREN;
  }
  }
  if (*lineptr == ',') {
  if (*lineptr == ',') {
    lineptr++;
    lineptr++;
    return TOK_COMMA;
    return TOK_COMMA;
  }
  }
  if (*lineptr == '~') {
  if (*lineptr == '~') {
    lineptr++;
    lineptr++;
    return TOK_TILDE;
    return TOK_TILDE;
  }
  }
  if (*lineptr == '&') {
  if (*lineptr == '&') {
    lineptr++;
    lineptr++;
    return TOK_AMPER;
    return TOK_AMPER;
  }
  }
  if (*lineptr == '|') {
  if (*lineptr == '|') {
    lineptr++;
    lineptr++;
    return TOK_BAR;
    return TOK_BAR;
  }
  }
  if (*lineptr == '^') {
  if (*lineptr == '^') {
    lineptr++;
    lineptr++;
    return TOK_CARET;
    return TOK_CARET;
  }
  }
  error("illegal character 0x%02X in line %d", *lineptr, lineno);
  error("illegal character 0x%02X in line %d", *lineptr, lineno);
  return 0;
  return 0;
}
}
 
 
 
 
void showToken(void) {
void showToken(void) {
  printf("DEBUG: ");
  printf("DEBUG: ");
  switch (token) {
  switch (token) {
    case TOK_EOL:
    case TOK_EOL:
      printf("token = TOK_EOL\n");
      printf("token = TOK_EOL\n");
      break;
      break;
    case TOK_LABEL:
    case TOK_LABEL:
      printf("token = TOK_LABEL, value = %s\n", tokenvalString);
      printf("token = TOK_LABEL, value = %s\n", tokenvalString);
      break;
      break;
    case TOK_IDENT:
    case TOK_IDENT:
      printf("token = TOK_IDENT, value = %s\n", tokenvalString);
      printf("token = TOK_IDENT, value = %s\n", tokenvalString);
      break;
      break;
    case TOK_STRING:
    case TOK_STRING:
      printf("token = TOK_STRING, value = %s\n", tokenvalString);
      printf("token = TOK_STRING, value = %s\n", tokenvalString);
      break;
      break;
    case TOK_NUMBER:
    case TOK_NUMBER:
      printf("token = TOK_NUMBER, value = 0x%x\n", tokenvalNumber);
      printf("token = TOK_NUMBER, value = 0x%x\n", tokenvalNumber);
      break;
      break;
    case TOK_REGISTER:
    case TOK_REGISTER:
      printf("token = TOK_REGISTER, value = %d\n", tokenvalNumber);
      printf("token = TOK_REGISTER, value = %d\n", tokenvalNumber);
      break;
      break;
    case TOK_PLUS:
    case TOK_PLUS:
      printf("token = TOK_PLUS\n");
      printf("token = TOK_PLUS\n");
      break;
      break;
    case TOK_MINUS:
    case TOK_MINUS:
      printf("token = TOK_MINUS\n");
      printf("token = TOK_MINUS\n");
      break;
      break;
    case TOK_STAR:
    case TOK_STAR:
      printf("token = TOK_STAR\n");
      printf("token = TOK_STAR\n");
      break;
      break;
    case TOK_SLASH:
    case TOK_SLASH:
      printf("token = TOK_SLASH\n");
      printf("token = TOK_SLASH\n");
      break;
      break;
    case TOK_PERCENT:
    case TOK_PERCENT:
      printf("token = TOK_PERCENT\n");
      printf("token = TOK_PERCENT\n");
      break;
      break;
    case TOK_LSHIFT:
    case TOK_LSHIFT:
      printf("token = TOK_LSHIFT\n");
      printf("token = TOK_LSHIFT\n");
      break;
      break;
    case TOK_RSHIFT:
    case TOK_RSHIFT:
      printf("token = TOK_RSHIFT\n");
      printf("token = TOK_RSHIFT\n");
      break;
      break;
    case TOK_LPAREN:
    case TOK_LPAREN:
      printf("token = TOK_LPAREN\n");
      printf("token = TOK_LPAREN\n");
      break;
      break;
    case TOK_RPAREN:
    case TOK_RPAREN:
      printf("token = TOK_RPAREN\n");
      printf("token = TOK_RPAREN\n");
      break;
      break;
    case TOK_COMMA:
    case TOK_COMMA:
      printf("token = TOK_COMMA\n");
      printf("token = TOK_COMMA\n");
      break;
      break;
    case TOK_TILDE:
    case TOK_TILDE:
      printf("token = TOK_TILDE\n");
      printf("token = TOK_TILDE\n");
      break;
      break;
    case TOK_AMPER:
    case TOK_AMPER:
      printf("token = TOK_AMPER\n");
      printf("token = TOK_AMPER\n");
      break;
      break;
    case TOK_BAR:
    case TOK_BAR:
      printf("token = TOK_BAR\n");
      printf("token = TOK_BAR\n");
      break;
      break;
    case TOK_CARET:
    case TOK_CARET:
      printf("token = TOK_CARET\n");
      printf("token = TOK_CARET\n");
      break;
      break;
    default:
    default:
      error("illegal token %d in showToken()", token);
      error("illegal token %d in showToken()", token);
  }
  }
}
}
 
 
 
 
void getToken(void) {
void getToken(void) {
  token = getNextToken();
  token = getNextToken();
  if (debugToken) {
  if (debugToken) {
    showToken();
    showToken();
  }
  }
}
}
 
 
 
 
static char *tok2str[] = {
static char *tok2str[] = {
  "end-of-line",
  "end-of-line",
  "label",
  "label",
  "identifier",
  "identifier",
  "string",
  "string",
  "number",
  "number",
  "register",
  "register",
  "+",
  "+",
  "-",
  "-",
  "*",
  "*",
  "/",
  "/",
  "%",
  "%",
  "<<",
  "<<",
  ">>",
  ">>",
  "(",
  "(",
  ")",
  ")",
  ",",
  ",",
  "~",
  "~",
  "&",
  "&",
  "|",
  "|",
  "^"
  "^"
};
};
 
 
 
 
void expect(int expected) {
void expect(int expected) {
  if (token != expected) {
  if (token != expected) {
    error("'%s' expected, got '%s' in line %d",
    error("'%s' expected, got '%s' in line %d",
          tok2str[expected], tok2str[token], lineno);
          tok2str[expected], tok2str[token], lineno);
  }
  }
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
Fixup *fixupList = NULL;
Fixup *fixupList = NULL;
 
 
 
 
Fixup *newFixup(int segment, unsigned int offset, int method, int value) {
Fixup *newFixup(int segment, unsigned int offset, int method, int value) {
  Fixup *f;
  Fixup *f;
 
 
  f = allocateMemory(sizeof(Fixup));
  f = allocateMemory(sizeof(Fixup));
  f->segment = segment;
  f->segment = segment;
  f->offset = offset;
  f->offset = offset;
  f->method = method;
  f->method = method;
  f->value = value;
  f->value = value;
  f->base = 0;
  f->base = 0;
  f->next = NULL;
  f->next = NULL;
  return f;
  return f;
}
}
 
 
 
 
void addFixup(Symbol *s,
void addFixup(Symbol *s,
              int segment, unsigned int offset, int method, int value) {
              int segment, unsigned int offset, int method, int value) {
  Fixup *f;
  Fixup *f;
 
 
  if (debugFixup) {
  if (debugFixup) {
    printf("DEBUG: fixup (s:%s, o:%08X, m:%s, v:%08X) added to '%s'\n",
    printf("DEBUG: fixup (s:%s, o:%08X, m:%s, v:%08X) added to '%s'\n",
           segName[segment], offset, methodName[method], value, s->name);
           segName[segment], offset, methodName[method], value, s->name);
  }
  }
  f = newFixup(segment, offset, method, value);
  f = newFixup(segment, offset, method, value);
  f->next = s->fixups;
  f->next = s->fixups;
  s->fixups = f;
  s->fixups = f;
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
Symbol *globalTable = NULL;
Symbol *globalTable = NULL;
Symbol *localTable = NULL;
Symbol *localTable = NULL;
 
 
 
 
Symbol *deref(Symbol *s) {
Symbol *deref(Symbol *s) {
  if (s->status == STATUS_GLOBREF) {
  if (s->status == STATUS_GLOBREF) {
    return s->globref;
    return s->globref;
  } else {
  } else {
    return s;
    return s;
  }
  }
}
}
 
 
 
 
Symbol *newSymbol(char *name) {
Symbol *newSymbol(char *name) {
  Symbol *p;
  Symbol *p;
 
 
  p = allocateMemory(sizeof(Symbol));
  p = allocateMemory(sizeof(Symbol));
  p->name = allocateMemory(strlen(name) + 1);
  p->name = allocateMemory(strlen(name) + 1);
  strcpy(p->name, name);
  strcpy(p->name, name);
  p->status = STATUS_UNKNOWN;
  p->status = STATUS_UNKNOWN;
  p->segment = 0;
  p->segment = 0;
  p->value = 0;
  p->value = 0;
  p->fixups = NULL;
  p->fixups = NULL;
  p->globref = NULL;
  p->globref = NULL;
  p->left = NULL;
  p->left = NULL;
  p->right = NULL;
  p->right = NULL;
  return p;
  return p;
}
}
 
 
 
 
Symbol *lookupEnter(char *name, int whichTable) {
Symbol *lookupEnter(char *name, int whichTable) {
  Symbol *p, *q, *r;
  Symbol *p, *q, *r;
  int cmp;
  int cmp;
 
 
  if (whichTable == GLOBAL_TABLE) {
  if (whichTable == GLOBAL_TABLE) {
    p = globalTable;
    p = globalTable;
  } else {
  } else {
    p = localTable;
    p = localTable;
  }
  }
  if (p == NULL) {
  if (p == NULL) {
    r = newSymbol(name);
    r = newSymbol(name);
    if (whichTable == GLOBAL_TABLE) {
    if (whichTable == GLOBAL_TABLE) {
      globalTable = r;
      globalTable = r;
    } else {
    } else {
      localTable = r;
      localTable = r;
    }
    }
    return r;
    return r;
  }
  }
  while (1) {
  while (1) {
    q = p;
    q = p;
    cmp = strcmp(name, q->name);
    cmp = strcmp(name, q->name);
    if (cmp == 0) {
    if (cmp == 0) {
      return q;
      return q;
    }
    }
    if (cmp < 0) {
    if (cmp < 0) {
      p = q->left;
      p = q->left;
    } else {
    } else {
      p = q->right;
      p = q->right;
    }
    }
    if (p == NULL) {
    if (p == NULL) {
      r = newSymbol(name);
      r = newSymbol(name);
      if (cmp < 0) {
      if (cmp < 0) {
        q->left = r;
        q->left = r;
      } else {
      } else {
        q->right = r;
        q->right = r;
      }
      }
      return r;
      return r;
    }
    }
  }
  }
}
}
 
 
 
 
static void linkSymbol(Symbol *s) {
static void linkSymbol(Symbol *s) {
  Fixup *f;
  Fixup *f;
 
 
  if (s->status == STATUS_UNKNOWN) {
  if (s->status == STATUS_UNKNOWN) {
    error("undefined symbol '%s'", s->name);
    error("undefined symbol '%s'", s->name);
  }
  }
  if (s->status == STATUS_GLOBREF) {
  if (s->status == STATUS_GLOBREF) {
    if (s->fixups != NULL) {
    if (s->fixups != NULL) {
      error("local fixups detected with global symbol '%s'", s->name);
      error("local fixups detected with global symbol '%s'", s->name);
    }
    }
  } else {
  } else {
    if (debugFixup) {
    if (debugFixup) {
      printf("DEBUG: link '%s' (s:%s, v:%08X)\n",
      printf("DEBUG: link '%s' (s:%s, v:%08X)\n",
             s->name, segName[s->segment], s->value);
             s->name, segName[s->segment], s->value);
    }
    }
    while (s->fixups != NULL) {
    while (s->fixups != NULL) {
      /* get next fixup record */
      /* get next fixup record */
      f = s->fixups;
      f = s->fixups;
      s->fixups = f->next;
      s->fixups = f->next;
      /* add the symbol's value to the value in the record */
      /* add the symbol's value to the value in the record */
      /* and remember the symbol's segment */
      /* and remember the symbol's segment */
      if (debugFixup) {
      if (debugFixup) {
        printf("       (s:%s, o:%08X, m:%s, v:%08X --> %08X, b:%s)\n",
        printf("       (s:%s, o:%08X, m:%s, v:%08X --> %08X, b:%s)\n",
               segName[f->segment], f->offset, methodName[f->method],
               segName[f->segment], f->offset, methodName[f->method],
               f->value, f->value + s->value, segName[s->segment]);
               f->value, f->value + s->value, segName[s->segment]);
      }
      }
      f->value += s->value;
      f->value += s->value;
      f->base = s->segment;
      f->base = s->segment;
      /* transfer the record to the fixup list */
      /* transfer the record to the fixup list */
      f->next = fixupList;
      f->next = fixupList;
      fixupList = f;
      fixupList = f;
    }
    }
  }
  }
}
}
 
 
 
 
static void linkTree(Symbol *s) {
static void linkTree(Symbol *s) {
  if (s == NULL) {
  if (s == NULL) {
    return;
    return;
  }
  }
  linkTree(s->left);
  linkTree(s->left);
  linkSymbol(s);
  linkSymbol(s);
  linkTree(s->right);
  linkTree(s->right);
  freeMemory(s->name);
  freeMemory(s->name);
  freeMemory(s);
  freeMemory(s);
}
}
 
 
 
 
void linkLocals(void) {
void linkLocals(void) {
  linkTree(localTable);
  linkTree(localTable);
  localTable = NULL;
  localTable = NULL;
  fseek(codeFile, 0, SEEK_END);
  fseek(codeFile, 0, SEEK_END);
  fseek(dataFile, 0, SEEK_END);
  fseek(dataFile, 0, SEEK_END);
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
void emitByte(unsigned int byte) {
void emitByte(unsigned int byte) {
  byte &= 0x000000FF;
  byte &= 0x000000FF;
  if (debugCode) {
  if (debugCode) {
    printf("DEBUG: byte @ segment = %s, offset = %08X",
    printf("DEBUG: byte @ segment = %s, offset = %08X",
           segName[currSeg], segPtr[currSeg]);
           segName[currSeg], segPtr[currSeg]);
    printf(", value = %02X\n", byte);
    printf(", value = %02X\n", byte);
  }
  }
  switch (currSeg) {
  switch (currSeg) {
    case SEGMENT_ABS:
    case SEGMENT_ABS:
      error("illegal segment in emitByte()");
      error("illegal segment in emitByte()");
      break;
      break;
    case SEGMENT_CODE:
    case SEGMENT_CODE:
      fputc(byte, codeFile);
      fputc(byte, codeFile);
      break;
      break;
    case SEGMENT_DATA:
    case SEGMENT_DATA:
      fputc(byte, dataFile);
      fputc(byte, dataFile);
      break;
      break;
    case SEGMENT_BSS:
    case SEGMENT_BSS:
      break;
      break;
  }
  }
  segPtr[currSeg] += 1;
  segPtr[currSeg] += 1;
}
}
 
 
 
 
void emitHalf(unsigned int half) {
void emitHalf(unsigned int half) {
  half &= 0x0000FFFF;
  half &= 0x0000FFFF;
  if (debugCode) {
  if (debugCode) {
    printf("DEBUG: half @ segment = %s, offset = %08X",
    printf("DEBUG: half @ segment = %s, offset = %08X",
           segName[currSeg], segPtr[currSeg]);
           segName[currSeg], segPtr[currSeg]);
    printf(", value = %02X%02X\n",
    printf(", value = %02X%02X\n",
           (half >> 8) & 0xFF, half & 0xFF);
           (half >> 8) & 0xFF, half & 0xFF);
  }
  }
  switch (currSeg) {
  switch (currSeg) {
    case SEGMENT_ABS:
    case SEGMENT_ABS:
      error("illegal segment in emitHalf()");
      error("illegal segment in emitHalf()");
      break;
      break;
    case SEGMENT_CODE:
    case SEGMENT_CODE:
      fputc((half >> 8) & 0xFF, codeFile);
      fputc((half >> 8) & 0xFF, codeFile);
      fputc(half & 0xFF, codeFile);
      fputc(half & 0xFF, codeFile);
      break;
      break;
    case SEGMENT_DATA:
    case SEGMENT_DATA:
      fputc((half >> 8) & 0xFF, dataFile);
      fputc((half >> 8) & 0xFF, dataFile);
      fputc(half & 0xFF, dataFile);
      fputc(half & 0xFF, dataFile);
      break;
      break;
    case SEGMENT_BSS:
    case SEGMENT_BSS:
      break;
      break;
  }
  }
  segPtr[currSeg] += 2;
  segPtr[currSeg] += 2;
}
}
 
 
 
 
void emitWord(unsigned int word) {
void emitWord(unsigned int word) {
  if (debugCode) {
  if (debugCode) {
    printf("DEBUG: word @ segment = %s, offset = %08X",
    printf("DEBUG: word @ segment = %s, offset = %08X",
           segName[currSeg], segPtr[currSeg]);
           segName[currSeg], segPtr[currSeg]);
    printf(", value = %02X%02X%02X%02X\n",
    printf(", value = %02X%02X%02X%02X\n",
           (word >> 24) & 0xFF, (word >> 16) & 0xFF,
           (word >> 24) & 0xFF, (word >> 16) & 0xFF,
           (word >> 8) & 0xFF, word & 0xFF);
           (word >> 8) & 0xFF, word & 0xFF);
  }
  }
  switch (currSeg) {
  switch (currSeg) {
    case SEGMENT_ABS:
    case SEGMENT_ABS:
      error("illegal segment in emitWord()");
      error("illegal segment in emitWord()");
      break;
      break;
    case SEGMENT_CODE:
    case SEGMENT_CODE:
      fputc((word >> 24) & 0xFF, codeFile);
      fputc((word >> 24) & 0xFF, codeFile);
      fputc((word >> 16) & 0xFF, codeFile);
      fputc((word >> 16) & 0xFF, codeFile);
      fputc((word >> 8) & 0xFF, codeFile);
      fputc((word >> 8) & 0xFF, codeFile);
      fputc(word & 0xFF, codeFile);
      fputc(word & 0xFF, codeFile);
      break;
      break;
    case SEGMENT_DATA:
    case SEGMENT_DATA:
      fputc((word >> 24) & 0xFF, dataFile);
      fputc((word >> 24) & 0xFF, dataFile);
      fputc((word >> 16) & 0xFF, dataFile);
      fputc((word >> 16) & 0xFF, dataFile);
      fputc((word >> 8) & 0xFF, dataFile);
      fputc((word >> 8) & 0xFF, dataFile);
      fputc(word & 0xFF, dataFile);
      fputc(word & 0xFF, dataFile);
      break;
      break;
    case SEGMENT_BSS:
    case SEGMENT_BSS:
      break;
      break;
  }
  }
  segPtr[currSeg] += 4;
  segPtr[currSeg] += 4;
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
typedef struct {
typedef struct {
  int con;
  int con;
  Symbol *sym;
  Symbol *sym;
} Value;
} Value;
 
 
 
 
Value parseExpression(void);
Value parseExpression(void);
 
 
 
 
Value parsePrimaryExpression(void) {
Value parsePrimaryExpression(void) {
  Value v;
  Value v;
  Symbol *s;
  Symbol *s;
 
 
  if (token == TOK_NUMBER) {
  if (token == TOK_NUMBER) {
    v.con = tokenvalNumber;
    v.con = tokenvalNumber;
    v.sym = NULL;
    v.sym = NULL;
    getToken();
    getToken();
  } else
  } else
  if (token == TOK_IDENT) {
  if (token == TOK_IDENT) {
    s = deref(lookupEnter(tokenvalString, LOCAL_TABLE));
    s = deref(lookupEnter(tokenvalString, LOCAL_TABLE));
    if (s->status == STATUS_DEFINED && s->segment == SEGMENT_ABS) {
    if (s->status == STATUS_DEFINED && s->segment == SEGMENT_ABS) {
      v.con = s->value;
      v.con = s->value;
      v.sym = NULL;
      v.sym = NULL;
    } else {
    } else {
      v.con = 0;
      v.con = 0;
      v.sym = s;
      v.sym = s;
    }
    }
    getToken();
    getToken();
  } else
  } else
  if (token == TOK_LPAREN) {
  if (token == TOK_LPAREN) {
    getToken();
    getToken();
    v = parseExpression();
    v = parseExpression();
    expect(TOK_RPAREN);
    expect(TOK_RPAREN);
    getToken();
    getToken();
  } else {
  } else {
    error("illegal primary expression, line %d", lineno);
    error("illegal primary expression, line %d", lineno);
  }
  }
  return v;
  return v;
}
}
 
 
 
 
Value parseUnaryExpression(void) {
Value parseUnaryExpression(void) {
  Value v;
  Value v;
 
 
  if (token == TOK_PLUS) {
  if (token == TOK_PLUS) {
    getToken();
    getToken();
    v = parseUnaryExpression();
    v = parseUnaryExpression();
  } else
  } else
  if (token == TOK_MINUS) {
  if (token == TOK_MINUS) {
    getToken();
    getToken();
    v = parseUnaryExpression();
    v = parseUnaryExpression();
    if (v.sym != NULL) {
    if (v.sym != NULL) {
      error("cannot negate symbol '%s' in line %d", v.sym->name, lineno);
      error("cannot negate symbol '%s' in line %d", v.sym->name, lineno);
    }
    }
    v.con = -v.con;
    v.con = -v.con;
  } else
  } else
  if (token == TOK_TILDE) {
  if (token == TOK_TILDE) {
    getToken();
    getToken();
    v = parseUnaryExpression();
    v = parseUnaryExpression();
    if (v.sym != NULL) {
    if (v.sym != NULL) {
      error("cannot complement symbol '%s' in line %d", v.sym->name, lineno);
      error("cannot complement symbol '%s' in line %d", v.sym->name, lineno);
    }
    }
    v.con = ~v.con;
    v.con = ~v.con;
  } else {
  } else {
    v = parsePrimaryExpression();
    v = parsePrimaryExpression();
  }
  }
  return v;
  return v;
}
}
 
 
 
 
Value parseMultiplicativeExpression(void) {
Value parseMultiplicativeExpression(void) {
  Value v1, v2;
  Value v1, v2;
 
 
  v1 = parseUnaryExpression();
  v1 = parseUnaryExpression();
  while (token == TOK_STAR || token == TOK_SLASH || token == TOK_PERCENT) {
  while (token == TOK_STAR || token == TOK_SLASH || token == TOK_PERCENT) {
    if (token == TOK_STAR) {
    if (token == TOK_STAR) {
      getToken();
      getToken();
      v2 = parseUnaryExpression();
      v2 = parseUnaryExpression();
      if (v1.sym != NULL || v2.sym != NULL) {
      if (v1.sym != NULL || v2.sym != NULL) {
        error("multiplication of symbols not supported, line %d", lineno);
        error("multiplication of symbols not supported, line %d", lineno);
      }
      }
      v1.con *= v2.con;
      v1.con *= v2.con;
    } else
    } else
    if (token == TOK_SLASH) {
    if (token == TOK_SLASH) {
      getToken();
      getToken();
      v2 = parseUnaryExpression();
      v2 = parseUnaryExpression();
      if (v1.sym != NULL || v2.sym != NULL) {
      if (v1.sym != NULL || v2.sym != NULL) {
        error("division of symbols not supported, line %d", lineno);
        error("division of symbols not supported, line %d", lineno);
      }
      }
      if (v2.con == 0) {
      if (v2.con == 0) {
        error("division by zero, line %d", lineno);
        error("division by zero, line %d", lineno);
      }
      }
      v1.con /= v2.con;
      v1.con /= v2.con;
    } else
    } else
    if (token == TOK_PERCENT) {
    if (token == TOK_PERCENT) {
      getToken();
      getToken();
      v2 = parseUnaryExpression();
      v2 = parseUnaryExpression();
      if (v1.sym != NULL || v2.sym != NULL) {
      if (v1.sym != NULL || v2.sym != NULL) {
        error("division of symbols not supported, line %d", lineno);
        error("division of symbols not supported, line %d", lineno);
      }
      }
      if (v2.con == 0) {
      if (v2.con == 0) {
        error("division by zero, line %d", lineno);
        error("division by zero, line %d", lineno);
      }
      }
      v1.con %= v2.con;
      v1.con %= v2.con;
    }
    }
  }
  }
  return v1;
  return v1;
}
}
 
 
 
 
Value parseAdditiveExpression(void) {
Value parseAdditiveExpression(void) {
  Value v1, v2;
  Value v1, v2;
 
 
  v1 = parseMultiplicativeExpression();
  v1 = parseMultiplicativeExpression();
  while (token == TOK_PLUS || token == TOK_MINUS) {
  while (token == TOK_PLUS || token == TOK_MINUS) {
    if (token == TOK_PLUS) {
    if (token == TOK_PLUS) {
      getToken();
      getToken();
      v2 = parseMultiplicativeExpression();
      v2 = parseMultiplicativeExpression();
      if (v1.sym != NULL && v2.sym != NULL) {
      if (v1.sym != NULL && v2.sym != NULL) {
        error("addition of symbols not supported, line %d", lineno);
        error("addition of symbols not supported, line %d", lineno);
      }
      }
      if (v2.sym != NULL) {
      if (v2.sym != NULL) {
        v1.sym = v2.sym;
        v1.sym = v2.sym;
      }
      }
      v1.con += v2.con;
      v1.con += v2.con;
    } else
    } else
    if (token == TOK_MINUS) {
    if (token == TOK_MINUS) {
      getToken();
      getToken();
      v2 = parseMultiplicativeExpression();
      v2 = parseMultiplicativeExpression();
      if (v2.sym != NULL) {
      if (v2.sym != NULL) {
        error("subtraction of symbols not supported, line %d", lineno);
        error("subtraction of symbols not supported, line %d", lineno);
      }
      }
      v1.con -= v2.con;
      v1.con -= v2.con;
    }
    }
  }
  }
  return v1;
  return v1;
}
}
 
 
 
 
Value parseShiftExpression(void) {
Value parseShiftExpression(void) {
  Value v1, v2;
  Value v1, v2;
 
 
  v1 = parseAdditiveExpression();
  v1 = parseAdditiveExpression();
  while (token == TOK_LSHIFT || token == TOK_RSHIFT) {
  while (token == TOK_LSHIFT || token == TOK_RSHIFT) {
    if (token == TOK_LSHIFT) {
    if (token == TOK_LSHIFT) {
      getToken();
      getToken();
      v2 = parseAdditiveExpression();
      v2 = parseAdditiveExpression();
      if (v1.sym != NULL || v2.sym != NULL) {
      if (v1.sym != NULL || v2.sym != NULL) {
        error("shifting of symbols not supported, line %d", lineno);
        error("shifting of symbols not supported, line %d", lineno);
      }
      }
      v1.con <<= v2.con;
      v1.con <<= v2.con;
    } else
    } else
    if (token == TOK_RSHIFT) {
    if (token == TOK_RSHIFT) {
      getToken();
      getToken();
      v2 = parseAdditiveExpression();
      v2 = parseAdditiveExpression();
      if (v1.sym != NULL || v2.sym != NULL) {
      if (v1.sym != NULL || v2.sym != NULL) {
        error("shifting of symbols not supported, line %d", lineno);
        error("shifting of symbols not supported, line %d", lineno);
      }
      }
      v1.con >>= v2.con;
      v1.con >>= v2.con;
    }
    }
  }
  }
  return v1;
  return v1;
}
}
 
 
 
 
Value parseAndExpression(void) {
Value parseAndExpression(void) {
  Value v1, v2;
  Value v1, v2;
 
 
  v1 = parseShiftExpression();
  v1 = parseShiftExpression();
  while (token == TOK_AMPER) {
  while (token == TOK_AMPER) {
    getToken();
    getToken();
    v2 = parseShiftExpression();
    v2 = parseShiftExpression();
    if (v2.sym != NULL) {
    if (v2.sym != NULL) {
      error("bitwise 'and' of symbols not supported, line %d", lineno);
      error("bitwise 'and' of symbols not supported, line %d", lineno);
    }
    }
    v1.con &= v2.con;
    v1.con &= v2.con;
  }
  }
  return v1;
  return v1;
}
}
 
 
 
 
Value parseExclusiveOrExpression(void) {
Value parseExclusiveOrExpression(void) {
  Value v1, v2;
  Value v1, v2;
 
 
  v1 = parseAndExpression();
  v1 = parseAndExpression();
  while (token == TOK_CARET) {
  while (token == TOK_CARET) {
    getToken();
    getToken();
    v2 = parseAndExpression();
    v2 = parseAndExpression();
    if (v2.sym != NULL) {
    if (v2.sym != NULL) {
      error("bitwise 'xor' of symbols not supported, line %d", lineno);
      error("bitwise 'xor' of symbols not supported, line %d", lineno);
    }
    }
    v1.con ^= v2.con;
    v1.con ^= v2.con;
  }
  }
  return v1;
  return v1;
}
}
 
 
 
 
Value parseInclusiveOrExpression(void) {
Value parseInclusiveOrExpression(void) {
  Value v1, v2;
  Value v1, v2;
 
 
  v1 = parseExclusiveOrExpression();
  v1 = parseExclusiveOrExpression();
  while (token == TOK_BAR) {
  while (token == TOK_BAR) {
    getToken();
    getToken();
    v2 = parseExclusiveOrExpression();
    v2 = parseExclusiveOrExpression();
    if (v2.sym != NULL) {
    if (v2.sym != NULL) {
      error("bitwise 'or' of symbols not supported, line %d", lineno);
      error("bitwise 'or' of symbols not supported, line %d", lineno);
    }
    }
    v1.con |= v2.con;
    v1.con |= v2.con;
  }
  }
  return v1;
  return v1;
}
}
 
 
 
 
Value parseExpression(void) {
Value parseExpression(void) {
  Value v;
  Value v;
 
 
  v = parseInclusiveOrExpression();
  v = parseInclusiveOrExpression();
  return v;
  return v;
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
void dotSyn(unsigned int code) {
void dotSyn(unsigned int code) {
  allowSyn = 1;
  allowSyn = 1;
}
}
 
 
 
 
void dotNosyn(unsigned int code) {
void dotNosyn(unsigned int code) {
  allowSyn = 0;
  allowSyn = 0;
}
}
 
 
 
 
void dotCode(unsigned int code) {
void dotCode(unsigned int code) {
  currSeg = SEGMENT_CODE;
  currSeg = SEGMENT_CODE;
}
}
 
 
 
 
void dotData(unsigned int code) {
void dotData(unsigned int code) {
  currSeg = SEGMENT_DATA;
  currSeg = SEGMENT_DATA;
}
}
 
 
 
 
void dotBss(unsigned int code) {
void dotBss(unsigned int code) {
  currSeg = SEGMENT_BSS;
  currSeg = SEGMENT_BSS;
}
}
 
 
 
 
void dotExport(unsigned int code) {
void dotExport(unsigned int code) {
  Symbol *global;
  Symbol *global;
  Symbol *local;
  Symbol *local;
  Fixup *f;
  Fixup *f;
 
 
  while (1) {
  while (1) {
    expect(TOK_IDENT);
    expect(TOK_IDENT);
    global = lookupEnter(tokenvalString, GLOBAL_TABLE);
    global = lookupEnter(tokenvalString, GLOBAL_TABLE);
    if (global->status != STATUS_UNKNOWN) {
    if (global->status != STATUS_UNKNOWN) {
      error("exported symbol '%s' multiply defined in line %d",
      error("exported symbol '%s' multiply defined in line %d",
            global->name, lineno);
            global->name, lineno);
    }
    }
    local = lookupEnter(tokenvalString, LOCAL_TABLE);
    local = lookupEnter(tokenvalString, LOCAL_TABLE);
    if (local->status == STATUS_GLOBREF) {
    if (local->status == STATUS_GLOBREF) {
      error("exported symbol '%s' multiply exported in line %d",
      error("exported symbol '%s' multiply exported in line %d",
            local->name, lineno);
            local->name, lineno);
    }
    }
    global->status = local->status;
    global->status = local->status;
    global->segment = local->segment;
    global->segment = local->segment;
    global->value = local->value;
    global->value = local->value;
    while (local->fixups != NULL) {
    while (local->fixups != NULL) {
      f = local->fixups;
      f = local->fixups;
      local->fixups = f->next;
      local->fixups = f->next;
      f->next = global->fixups;
      f->next = global->fixups;
      global->fixups = f;
      global->fixups = f;
    }
    }
    local->status = STATUS_GLOBREF;
    local->status = STATUS_GLOBREF;
    local->globref = global;
    local->globref = global;
    getToken();
    getToken();
    if (token != TOK_COMMA) {
    if (token != TOK_COMMA) {
      break;
      break;
    }
    }
    getToken();
    getToken();
  }
  }
}
}
 
 
 
 
void dotImport(unsigned int code) {
void dotImport(unsigned int code) {
  Symbol *global;
  Symbol *global;
  Symbol *local;
  Symbol *local;
  Fixup *f;
  Fixup *f;
 
 
  while (1) {
  while (1) {
    expect(TOK_IDENT);
    expect(TOK_IDENT);
    global = lookupEnter(tokenvalString, GLOBAL_TABLE);
    global = lookupEnter(tokenvalString, GLOBAL_TABLE);
    local = lookupEnter(tokenvalString, LOCAL_TABLE);
    local = lookupEnter(tokenvalString, LOCAL_TABLE);
    if (local->status != STATUS_UNKNOWN) {
    if (local->status != STATUS_UNKNOWN) {
      error("imported symbol '%s' multiply defined in line %d",
      error("imported symbol '%s' multiply defined in line %d",
            local->name, lineno);
            local->name, lineno);
    }
    }
    while (local->fixups != NULL) {
    while (local->fixups != NULL) {
      f = local->fixups;
      f = local->fixups;
      local->fixups = f->next;
      local->fixups = f->next;
      f->next = global->fixups;
      f->next = global->fixups;
      global->fixups = f;
      global->fixups = f;
    }
    }
    local->status = STATUS_GLOBREF;
    local->status = STATUS_GLOBREF;
    local->globref = global;
    local->globref = global;
    getToken();
    getToken();
    if (token != TOK_COMMA) {
    if (token != TOK_COMMA) {
      break;
      break;
    }
    }
    getToken();
    getToken();
  }
  }
}
}
 
 
 
 
int countBits(unsigned int x) {
int countBits(unsigned int x) {
  int n;
  int n;
 
 
  n = 0;
  n = 0;
  while (x != 0) {
  while (x != 0) {
    x &= x - 1;
    x &= x - 1;
    n++;
    n++;
  }
  }
  return n;
  return n;
}
}
 
 
 
 
void dotAlign(unsigned int code) {
void dotAlign(unsigned int code) {
  Value v;
  Value v;
  unsigned int mask;
  unsigned int mask;
 
 
  v = parseExpression();
  v = parseExpression();
  if (v.sym != NULL) {
  if (v.sym != NULL) {
    error("absolute expression expected in line %d", lineno);
    error("absolute expression expected in line %d", lineno);
  }
  }
  if (countBits(v.con) != 1) {
  if (countBits(v.con) != 1) {
    error("argument must be a power of 2 in line %d", lineno);
    error("argument must be a power of 2 in line %d", lineno);
  }
  }
  mask = v.con - 1;
  mask = v.con - 1;
  while ((segPtr[currSeg] & mask) != 0) {
  while ((segPtr[currSeg] & mask) != 0) {
    emitByte(0);
    emitByte(0);
  }
  }
}
}
 
 
 
 
void dotSpace(unsigned int code) {
void dotSpace(unsigned int code) {
  Value v;
  Value v;
  int i;
  int i;
 
 
  v = parseExpression();
  v = parseExpression();
  if (v.sym != NULL) {
  if (v.sym != NULL) {
    error("absolute expression expected in line %d", lineno);
    error("absolute expression expected in line %d", lineno);
  }
  }
  for (i = 0; i < v.con; i++) {
  for (i = 0; i < v.con; i++) {
    emitByte(0);
    emitByte(0);
  }
  }
}
}
 
 
 
 
void dotLocate(unsigned int code) {
void dotLocate(unsigned int code) {
  Value v;
  Value v;
 
 
  v = parseExpression();
  v = parseExpression();
  if (v.sym != NULL) {
  if (v.sym != NULL) {
    error("absolute expression expected in line %d", lineno);
    error("absolute expression expected in line %d", lineno);
  }
  }
  while (segPtr[currSeg] != v.con) {
  while (segPtr[currSeg] != v.con) {
    emitByte(0);
    emitByte(0);
  }
  }
}
}
 
 
 
 
void dotByte(unsigned int code) {
void dotByte(unsigned int code) {
  Value v;
  Value v;
  char *p;
  char *p;
 
 
  while (1) {
  while (1) {
    if (token == TOK_STRING) {
    if (token == TOK_STRING) {
      p = tokenvalString;
      p = tokenvalString;
      while (*p != '\0') {
      while (*p != '\0') {
        emitByte(*p);
        emitByte(*p);
        p++;
        p++;
      }
      }
      getToken();
      getToken();
    } else {
    } else {
      v = parseExpression();
      v = parseExpression();
      if (v.sym != NULL) {
      if (v.sym != NULL) {
        error("absolute expression expected in line %d", lineno);
        error("absolute expression expected in line %d", lineno);
      }
      }
      emitByte(v.con);
      emitByte(v.con);
    }
    }
    if (token != TOK_COMMA) {
    if (token != TOK_COMMA) {
      break;
      break;
    }
    }
    getToken();
    getToken();
  }
  }
}
}
 
 
 
 
void dotHalf(unsigned int code) {
void dotHalf(unsigned int code) {
  Value v;
  Value v;
 
 
  while (1) {
  while (1) {
    v = parseExpression();
    v = parseExpression();
    if (v.sym != NULL) {
    if (v.sym != NULL) {
      error("absolute expression expected in line %d", lineno);
      error("absolute expression expected in line %d", lineno);
    }
    }
    emitHalf(v.con);
    emitHalf(v.con);
    if (token != TOK_COMMA) {
    if (token != TOK_COMMA) {
      break;
      break;
    }
    }
    getToken();
    getToken();
  }
  }
}
}
 
 
 
 
void dotWord(unsigned int code) {
void dotWord(unsigned int code) {
  Value v;
  Value v;
 
 
  while (1) {
  while (1) {
    v = parseExpression();
    v = parseExpression();
    if (v.sym == NULL) {
    if (v.sym == NULL) {
      emitWord(v.con);
      emitWord(v.con);
    } else {
    } else {
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_W32, v.con);
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_W32, v.con);
      emitWord(0);
      emitWord(0);
    }
    }
    if (token != TOK_COMMA) {
    if (token != TOK_COMMA) {
      break;
      break;
    }
    }
    getToken();
    getToken();
  }
  }
}
}
 
 
 
 
void dotSet(unsigned int code) {
void dotSet(unsigned int code) {
  Value v;
  Value v;
  Symbol *symbol;
  Symbol *symbol;
 
 
  expect(TOK_IDENT);
  expect(TOK_IDENT);
  symbol = deref(lookupEnter(tokenvalString, LOCAL_TABLE));
  symbol = deref(lookupEnter(tokenvalString, LOCAL_TABLE));
  if (symbol->status != STATUS_UNKNOWN) {
  if (symbol->status != STATUS_UNKNOWN) {
    error("symbol '%s' multiply defined in line %d",
    error("symbol '%s' multiply defined in line %d",
          symbol->name, lineno);
          symbol->name, lineno);
  }
  }
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  v = parseExpression();
  v = parseExpression();
  if (v.sym == NULL) {
  if (v.sym == NULL) {
    symbol->status = STATUS_DEFINED;
    symbol->status = STATUS_DEFINED;
    symbol->segment = SEGMENT_ABS;
    symbol->segment = SEGMENT_ABS;
    symbol->value = v.con;
    symbol->value = v.con;
  } else {
  } else {
    error("illegal type of symbol '%s' in expression, line %d",
    error("illegal type of symbol '%s' in expression, line %d",
          v.sym->name, lineno);
          v.sym->name, lineno);
  }
  }
}
}
 
 
 
 
void formatN(unsigned int code) {
void formatN(unsigned int code) {
  Value v;
  Value v;
  unsigned int immed;
  unsigned int immed;
 
 
  /* opcode with no operands */
  /* opcode with no operands */
  if (token != TOK_EOL) {
  if (token != TOK_EOL) {
    /* in exceptional cases (trap) there may be one constant operand */
    /* in exceptional cases (trap) there may be one constant operand */
    v = parseExpression();
    v = parseExpression();
    if (v.sym != NULL) {
    if (v.sym != NULL) {
      error("operand must be a constant, line %d", lineno);
      error("operand must be a constant, line %d", lineno);
    }
    }
    immed = v.con;
    immed = v.con;
  } else {
  } else {
    immed = 0;
    immed = 0;
  }
  }
  emitWord(code << 26 | (immed & 0x03FFFFFF));
  emitWord(code << 26 | (immed & 0x03FFFFFF));
}
}
 
 
 
 
void formatRH(unsigned int code) {
void formatRH(unsigned int code) {
  int reg;
  int reg;
  Value v;
  Value v;
 
 
  /* opcode with one register and a half operand */
  /* opcode with one register and a half operand */
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  reg = tokenvalNumber;
  reg = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  v = parseExpression();
  v = parseExpression();
  if (v.sym == NULL) {
  if (v.sym == NULL) {
    emitHalf(code << 10 | reg);
    emitHalf(code << 10 | reg);
    emitHalf(v.con);
    emitHalf(v.con);
  } else {
  } else {
    addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
    addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
    emitHalf(code << 10 | reg);
    emitHalf(code << 10 | reg);
    emitHalf(0);
    emitHalf(0);
  }
  }
}
}
 
 
 
 
void formatRHH(unsigned int code) {
void formatRHH(unsigned int code) {
  int reg;
  int reg;
  Value v;
  Value v;
 
 
  /* opcode with one register and a half operand */
  /* opcode with one register and a half operand */
  /* ATTENTION: high order 16 bits encoded in instruction */
  /* ATTENTION: high order 16 bits encoded in instruction */
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  reg = tokenvalNumber;
  reg = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  v = parseExpression();
  v = parseExpression();
  if (v.sym == NULL) {
  if (v.sym == NULL) {
    emitHalf(code << 10 | reg);
    emitHalf(code << 10 | reg);
    emitHalf(v.con >> 16);
    emitHalf(v.con >> 16);
  } else {
  } else {
    addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
    addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
    emitHalf(code << 10 | reg);
    emitHalf(code << 10 | reg);
    emitHalf(0);
    emitHalf(0);
  }
  }
}
}
 
 
 
 
void formatRRH(unsigned int code) {
void formatRRH(unsigned int code) {
  int dst, src;
  int dst, src;
  Value v;
  Value v;
 
 
  /* opcode with two registers and a half operand */
  /* opcode with two registers and a half operand */
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  dst = tokenvalNumber;
  dst = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  src = tokenvalNumber;
  src = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  v = parseExpression();
  v = parseExpression();
  if (allowSyn) {
  if (allowSyn) {
    if (v.sym == NULL) {
    if (v.sym == NULL) {
      if ((v.con & 0xFFFF0000) == 0) {
      if ((v.con & 0xFFFF0000) == 0) {
        /* code: op dst,src,con */
        /* code: op dst,src,con */
        emitHalf(code << 10 | src << 5 | dst);
        emitHalf(code << 10 | src << 5 | dst);
        emitHalf(v.con);
        emitHalf(v.con);
      } else {
      } else {
        /* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
        /* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
        emitHalf(OP_LDHI << 10 | AUX_REG);
        emitHalf(OP_LDHI << 10 | AUX_REG);
        emitHalf(v.con >> 16);
        emitHalf(v.con >> 16);
        emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
        emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
        emitHalf(v.con);
        emitHalf(v.con);
        emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
        emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
        emitHalf(AUX_REG << 11);
        emitHalf(AUX_REG << 11);
        emitHalf(code << 10 | AUX_REG << 5 | dst);
        emitHalf(code << 10 | AUX_REG << 5 | dst);
        emitHalf(0);
        emitHalf(0);
      }
      }
    } else {
    } else {
      /* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
      /* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
      emitHalf(OP_LDHI << 10 | AUX_REG);
      emitHalf(OP_LDHI << 10 | AUX_REG);
      emitHalf(0);
      emitHalf(0);
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
      emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
      emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
      emitHalf(0);
      emitHalf(0);
      emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
      emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
      emitHalf(AUX_REG << 11);
      emitHalf(AUX_REG << 11);
      emitHalf(code << 10 | AUX_REG << 5 | dst);
      emitHalf(code << 10 | AUX_REG << 5 | dst);
      emitHalf(0);
      emitHalf(0);
    }
    }
  } else {
  } else {
    if (v.sym == NULL) {
    if (v.sym == NULL) {
      emitHalf(code << 10 | src << 5 | dst);
      emitHalf(code << 10 | src << 5 | dst);
      emitHalf(v.con);
      emitHalf(v.con);
    } else {
    } else {
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
      emitHalf(code << 10 | src << 5 | dst);
      emitHalf(code << 10 | src << 5 | dst);
      emitHalf(0);
      emitHalf(0);
    }
    }
  }
  }
}
}
 
 
 
 
void formatRRS(unsigned int code) {
void formatRRS(unsigned int code) {
  int dst, src;
  int dst, src;
  Value v;
  Value v;
 
 
  /* opcode with two registers and a signed half operand */
  /* opcode with two registers and a signed half operand */
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  dst = tokenvalNumber;
  dst = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  src = tokenvalNumber;
  src = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  v = parseExpression();
  v = parseExpression();
  if (allowSyn) {
  if (allowSyn) {
    if (v.sym == NULL) {
    if (v.sym == NULL) {
      if ((v.con & 0xFFFF8000) == 0x00000000 ||
      if ((v.con & 0xFFFF8000) == 0x00000000 ||
          (v.con & 0xFFFF8000) == 0xFFFF8000) {
          (v.con & 0xFFFF8000) == 0xFFFF8000) {
        /* code: op dst,src,con */
        /* code: op dst,src,con */
        emitHalf(code << 10 | src << 5 | dst);
        emitHalf(code << 10 | src << 5 | dst);
        emitHalf(v.con);
        emitHalf(v.con);
      } else {
      } else {
        /* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
        /* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
        emitHalf(OP_LDHI << 10 | AUX_REG);
        emitHalf(OP_LDHI << 10 | AUX_REG);
        emitHalf(v.con >> 16);
        emitHalf(v.con >> 16);
        emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
        emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
        emitHalf(v.con);
        emitHalf(v.con);
        emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
        emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
        emitHalf(AUX_REG << 11);
        emitHalf(AUX_REG << 11);
        emitHalf(code << 10 | AUX_REG << 5 | dst);
        emitHalf(code << 10 | AUX_REG << 5 | dst);
        emitHalf(0);
        emitHalf(0);
      }
      }
    } else {
    } else {
      /* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
      /* code: ldhi $1,con; or $1,$1,con; add $1,$1,src; op dst,$1,0 */
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
      emitHalf(OP_LDHI << 10 | AUX_REG);
      emitHalf(OP_LDHI << 10 | AUX_REG);
      emitHalf(0);
      emitHalf(0);
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
      emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
      emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
      emitHalf(0);
      emitHalf(0);
      emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
      emitHalf(OP_ADD << 10 | AUX_REG << 5 | src);
      emitHalf(AUX_REG << 11);
      emitHalf(AUX_REG << 11);
      emitHalf(code << 10 | AUX_REG << 5 | dst);
      emitHalf(code << 10 | AUX_REG << 5 | dst);
      emitHalf(0);
      emitHalf(0);
    }
    }
  } else {
  } else {
    if (v.sym == NULL) {
    if (v.sym == NULL) {
      emitHalf(code << 10 | src << 5 | dst);
      emitHalf(code << 10 | src << 5 | dst);
      emitHalf(v.con);
      emitHalf(v.con);
    } else {
    } else {
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
      emitHalf(code << 10 | src << 5 | dst);
      emitHalf(code << 10 | src << 5 | dst);
      emitHalf(0);
      emitHalf(0);
    }
    }
  }
  }
}
}
 
 
 
 
void formatRRR(unsigned int code) {
void formatRRR(unsigned int code) {
  int dst, src1, src2;
  int dst, src1, src2;
 
 
  /* opcode with three register operands */
  /* opcode with three register operands */
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  dst = tokenvalNumber;
  dst = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  src1 = tokenvalNumber;
  src1 = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  src2 = tokenvalNumber;
  src2 = tokenvalNumber;
  getToken();
  getToken();
  emitHalf(code << 10 | src1 << 5 | src2);
  emitHalf(code << 10 | src1 << 5 | src2);
  emitHalf(dst << 11);
  emitHalf(dst << 11);
}
}
 
 
 
 
void formatRRX(unsigned int code) {
void formatRRX(unsigned int code) {
  int dst, src1, src2;
  int dst, src1, src2;
  Value v;
  Value v;
 
 
  /* opcode with three register operands
  /* opcode with three register operands
     or two registers and a half operand */
     or two registers and a half operand */
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  dst = tokenvalNumber;
  dst = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  src1 = tokenvalNumber;
  src1 = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  if (token == TOK_REGISTER) {
  if (token == TOK_REGISTER) {
    src2 = tokenvalNumber;
    src2 = tokenvalNumber;
    getToken();
    getToken();
    emitHalf(code << 10 | src1 << 5 | src2);
    emitHalf(code << 10 | src1 << 5 | src2);
    emitHalf(dst << 11);
    emitHalf(dst << 11);
  } else {
  } else {
    v = parseExpression();
    v = parseExpression();
    if (allowSyn) {
    if (allowSyn) {
      if (v.sym == NULL) {
      if (v.sym == NULL) {
        if ((v.con & 0xFFFF0000) == 0) {
        if ((v.con & 0xFFFF0000) == 0) {
          /* code: op dst,src,con */
          /* code: op dst,src,con */
          emitHalf((code + 1) << 10 | src1 << 5 | dst);
          emitHalf((code + 1) << 10 | src1 << 5 | dst);
          emitHalf(v.con);
          emitHalf(v.con);
        } else {
        } else {
          if ((v.con & 0x0000FFFF) == 0) {
          if ((v.con & 0x0000FFFF) == 0) {
            /* code: ldhi $1,con; op dst,src,$1 */
            /* code: ldhi $1,con; op dst,src,$1 */
            emitHalf(OP_LDHI << 10 | AUX_REG);
            emitHalf(OP_LDHI << 10 | AUX_REG);
            emitHalf(v.con >> 16);
            emitHalf(v.con >> 16);
            emitHalf(code << 10 | src1 << 5 | AUX_REG);
            emitHalf(code << 10 | src1 << 5 | AUX_REG);
            emitHalf(dst << 11);
            emitHalf(dst << 11);
          } else {
          } else {
            /* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
            /* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
            emitHalf(OP_LDHI << 10 | AUX_REG);
            emitHalf(OP_LDHI << 10 | AUX_REG);
            emitHalf(v.con >> 16);
            emitHalf(v.con >> 16);
            emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
            emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
            emitHalf(v.con);
            emitHalf(v.con);
            emitHalf(code << 10 | src1 << 5 | AUX_REG);
            emitHalf(code << 10 | src1 << 5 | AUX_REG);
            emitHalf(dst << 11);
            emitHalf(dst << 11);
          }
          }
        }
        }
      } else {
      } else {
        /* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
        /* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
        emitHalf(OP_LDHI << 10 | AUX_REG);
        emitHalf(OP_LDHI << 10 | AUX_REG);
        emitHalf(0);
        emitHalf(0);
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
        emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
        emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
        emitHalf(0);
        emitHalf(0);
        emitHalf(code << 10 | src1 << 5 | AUX_REG);
        emitHalf(code << 10 | src1 << 5 | AUX_REG);
        emitHalf(dst << 11);
        emitHalf(dst << 11);
      }
      }
    } else {
    } else {
      if (v.sym == NULL) {
      if (v.sym == NULL) {
        emitHalf((code + 1) << 10 | src1 << 5 | dst);
        emitHalf((code + 1) << 10 | src1 << 5 | dst);
        emitHalf(v.con);
        emitHalf(v.con);
      } else {
      } else {
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
        emitHalf((code + 1) << 10 | src1 << 5 | dst);
        emitHalf((code + 1) << 10 | src1 << 5 | dst);
        emitHalf(0);
        emitHalf(0);
      }
      }
    }
    }
  }
  }
}
}
 
 
 
 
void formatRRY(unsigned int code) {
void formatRRY(unsigned int code) {
  int dst, src1, src2;
  int dst, src1, src2;
  Value v;
  Value v;
 
 
  /* opcode with three register operands
  /* opcode with three register operands
     or two registers and a signed half operand */
     or two registers and a signed half operand */
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  dst = tokenvalNumber;
  dst = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  src1 = tokenvalNumber;
  src1 = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  if (token == TOK_REGISTER) {
  if (token == TOK_REGISTER) {
    src2 = tokenvalNumber;
    src2 = tokenvalNumber;
    getToken();
    getToken();
    emitHalf(code << 10 | src1 << 5 | src2);
    emitHalf(code << 10 | src1 << 5 | src2);
    emitHalf(dst << 11);
    emitHalf(dst << 11);
  } else {
  } else {
    v = parseExpression();
    v = parseExpression();
    if (allowSyn) {
    if (allowSyn) {
      if (v.sym == NULL) {
      if (v.sym == NULL) {
        if ((v.con & 0xFFFF8000) == 0x00000000 ||
        if ((v.con & 0xFFFF8000) == 0x00000000 ||
            (v.con & 0xFFFF8000) == 0xFFFF8000) {
            (v.con & 0xFFFF8000) == 0xFFFF8000) {
          /* code: op dst,src,con */
          /* code: op dst,src,con */
          emitHalf((code + 1) << 10 | src1 << 5 | dst);
          emitHalf((code + 1) << 10 | src1 << 5 | dst);
          emitHalf(v.con);
          emitHalf(v.con);
        } else {
        } else {
          if ((v.con & 0x0000FFFF) == 0) {
          if ((v.con & 0x0000FFFF) == 0) {
            /* code: ldhi $1,con; op dst,src,$1 */
            /* code: ldhi $1,con; op dst,src,$1 */
            emitHalf(OP_LDHI << 10 | AUX_REG);
            emitHalf(OP_LDHI << 10 | AUX_REG);
            emitHalf(v.con >> 16);
            emitHalf(v.con >> 16);
            emitHalf(code << 10 | src1 << 5 | AUX_REG);
            emitHalf(code << 10 | src1 << 5 | AUX_REG);
            emitHalf(dst << 11);
            emitHalf(dst << 11);
          } else {
          } else {
            /* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
            /* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
            emitHalf(OP_LDHI << 10 | AUX_REG);
            emitHalf(OP_LDHI << 10 | AUX_REG);
            emitHalf(v.con >> 16);
            emitHalf(v.con >> 16);
            emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
            emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
            emitHalf(v.con);
            emitHalf(v.con);
            emitHalf(code << 10 | src1 << 5 | AUX_REG);
            emitHalf(code << 10 | src1 << 5 | AUX_REG);
            emitHalf(dst << 11);
            emitHalf(dst << 11);
          }
          }
        }
        }
      } else {
      } else {
        /* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
        /* code: ldhi $1,con; or $1,$1,con; op dst,src,$1 */
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_H16, v.con);
        emitHalf(OP_LDHI << 10 | AUX_REG);
        emitHalf(OP_LDHI << 10 | AUX_REG);
        emitHalf(0);
        emitHalf(0);
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
        emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
        emitHalf((OP_OR + 1) << 10 | AUX_REG << 5 | AUX_REG);
        emitHalf(0);
        emitHalf(0);
        emitHalf(code << 10 | src1 << 5 | AUX_REG);
        emitHalf(code << 10 | src1 << 5 | AUX_REG);
        emitHalf(dst << 11);
        emitHalf(dst << 11);
      }
      }
    } else {
    } else {
      if (v.sym == NULL) {
      if (v.sym == NULL) {
        emitHalf((code + 1) << 10 | src1 << 5 | dst);
        emitHalf((code + 1) << 10 | src1 << 5 | dst);
        emitHalf(v.con);
        emitHalf(v.con);
      } else {
      } else {
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
        addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_L16, v.con);
        emitHalf((code + 1) << 10 | src1 << 5 | dst);
        emitHalf((code + 1) << 10 | src1 << 5 | dst);
        emitHalf(0);
        emitHalf(0);
      }
      }
    }
    }
  }
  }
}
}
 
 
 
 
void formatRRB(unsigned int code) {
void formatRRB(unsigned int code) {
  int src1, src2;
  int src1, src2;
  Value v;
  Value v;
  unsigned int immed;
  unsigned int immed;
 
 
  /* opcode with two registers and a 16 bit signed offset operand */
  /* opcode with two registers and a 16 bit signed offset operand */
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  src1 = tokenvalNumber;
  src1 = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  src2 = tokenvalNumber;
  src2 = tokenvalNumber;
  getToken();
  getToken();
  expect(TOK_COMMA);
  expect(TOK_COMMA);
  getToken();
  getToken();
  v = parseExpression();
  v = parseExpression();
  if (v.sym == NULL) {
  if (v.sym == NULL) {
    immed = (v.con - ((signed) segPtr[currSeg] + 4)) / 4;
    immed = (v.con - ((signed) segPtr[currSeg] + 4)) / 4;
  } else {
  } else {
    addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_R16, v.con);
    addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_R16, v.con);
    immed = 0;
    immed = 0;
  }
  }
  emitHalf(code << 10 | src1 << 5 | src2);
  emitHalf(code << 10 | src1 << 5 | src2);
  emitHalf(immed);
  emitHalf(immed);
}
}
 
 
 
 
void formatJ(unsigned int code) {
void formatJ(unsigned int code) {
  Value v;
  Value v;
  unsigned int immed;
  unsigned int immed;
  int target;
  int target;
 
 
  /* opcode with no registers and a 26 bit signed offset operand or
  /* opcode with no registers and a 26 bit signed offset operand or
     opcode with a single register */
     opcode with a single register */
  if (token == TOK_REGISTER) {
  if (token == TOK_REGISTER) {
    target = tokenvalNumber;
    target = tokenvalNumber;
    getToken();
    getToken();
    emitWord((code + 1) << 26 | target << 21);
    emitWord((code + 1) << 26 | target << 21);
  } else {
  } else {
    v = parseExpression();
    v = parseExpression();
    if (v.sym == NULL) {
    if (v.sym == NULL) {
      immed = (v.con - ((signed) segPtr[currSeg] + 4)) / 4;
      immed = (v.con - ((signed) segPtr[currSeg] + 4)) / 4;
    } else {
    } else {
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_R26, v.con);
      addFixup(v.sym, currSeg, segPtr[currSeg], METHOD_R26, v.con);
      immed = 0;
      immed = 0;
    }
    }
    emitWord(code << 26 | (immed & 0x03FFFFFF));
    emitWord(code << 26 | (immed & 0x03FFFFFF));
  }
  }
}
}
 
 
 
 
void formatJR(unsigned int code) {
void formatJR(unsigned int code) {
  int target;
  int target;
 
 
  /* opcode with one register operand */
  /* opcode with one register operand */
  expect(TOK_REGISTER);
  expect(TOK_REGISTER);
  target = tokenvalNumber;
  target = tokenvalNumber;
  getToken();
  getToken();
  emitWord(code << 26 | target << 21);
  emitWord(code << 26 | target << 21);
}
}
 
 
 
 
typedef struct instr {
typedef struct instr {
  char *name;
  char *name;
  void (*func)(unsigned int code);
  void (*func)(unsigned int code);
  unsigned int code;
  unsigned int code;
} Instr;
} Instr;
 
 
 
 
Instr instrTable[] = {
Instr instrTable[] = {
 
 
  /* pseudo instructions */
  /* pseudo instructions */
  { ".syn",    dotSyn,    0 },
  { ".syn",    dotSyn,    0 },
  { ".nosyn",  dotNosyn,  0 },
  { ".nosyn",  dotNosyn,  0 },
  { ".code",   dotCode,   0 },
  { ".code",   dotCode,   0 },
  { ".data",   dotData,   0 },
  { ".data",   dotData,   0 },
  { ".bss",    dotBss,    0 },
  { ".bss",    dotBss,    0 },
  { ".export", dotExport, 0 },
  { ".export", dotExport, 0 },
  { ".import", dotImport, 0 },
  { ".import", dotImport, 0 },
  { ".align",  dotAlign,  0 },
  { ".align",  dotAlign,  0 },
  { ".space",  dotSpace,  0 },
  { ".space",  dotSpace,  0 },
  { ".locate", dotLocate, 0 },
  { ".locate", dotLocate, 0 },
  { ".byte",   dotByte,   0 },
  { ".byte",   dotByte,   0 },
  { ".half",   dotHalf,   0 },
  { ".half",   dotHalf,   0 },
  { ".word",   dotWord,   0 },
  { ".word",   dotWord,   0 },
  { ".set",    dotSet,    0 },
  { ".set",    dotSet,    0 },
 
 
  /* arithmetical instructions */
  /* arithmetical instructions */
  { "add",     formatRRY, OP_ADD  },
  { "add",     formatRRY, OP_ADD  },
  { "sub",     formatRRY, OP_SUB  },
  { "sub",     formatRRY, OP_SUB  },
 
 
  { "mul",     formatRRY, OP_MUL  },
  { "mul",     formatRRY, OP_MUL  },
  { "mulu",    formatRRX, OP_MULU },
  { "mulu",    formatRRX, OP_MULU },
  { "div",     formatRRY, OP_DIV  },
  { "div",     formatRRY, OP_DIV  },
  { "divu",    formatRRX, OP_DIVU },
  { "divu",    formatRRX, OP_DIVU },
  { "rem",     formatRRY, OP_REM  },
  { "rem",     formatRRY, OP_REM  },
  { "remu",    formatRRX, OP_REMU },
  { "remu",    formatRRX, OP_REMU },
 
 
  /* logical instructions */
  /* logical instructions */
  { "and",     formatRRX, OP_AND  },
  { "and",     formatRRX, OP_AND  },
  { "or",      formatRRX, OP_OR   },
  { "or",      formatRRX, OP_OR   },
  { "xor",     formatRRX, OP_XOR  },
  { "xor",     formatRRX, OP_XOR  },
  { "xnor",    formatRRX, OP_XNOR },
  { "xnor",    formatRRX, OP_XNOR },
 
 
  /* shift instructions */
  /* shift instructions */
  { "sll",     formatRRX, OP_SLL  },
  { "sll",     formatRRX, OP_SLL  },
  { "slr",     formatRRX, OP_SLR  },
  { "slr",     formatRRX, OP_SLR  },
  { "sar",     formatRRX, OP_SAR  },
  { "sar",     formatRRX, OP_SAR  },
 
 
  /* load immediate instructions */
  /* load immediate instructions */
  { "ldhi",    formatRHH, OP_LDHI },
  { "ldhi",    formatRHH, OP_LDHI },
 
 
  /* branch instructions */
  /* branch instructions */
  { "beq",     formatRRB, OP_BEQ  },
  { "beq",     formatRRB, OP_BEQ  },
  { "bne",     formatRRB, OP_BNE  },
  { "bne",     formatRRB, OP_BNE  },
  { "ble",     formatRRB, OP_BLE  },
  { "ble",     formatRRB, OP_BLE  },
  { "bleu",    formatRRB, OP_BLEU },
  { "bleu",    formatRRB, OP_BLEU },
  { "blt",     formatRRB, OP_BLT  },
  { "blt",     formatRRB, OP_BLT  },
  { "bltu",    formatRRB, OP_BLTU },
  { "bltu",    formatRRB, OP_BLTU },
  { "bge",     formatRRB, OP_BGE  },
  { "bge",     formatRRB, OP_BGE  },
  { "bgeu",    formatRRB, OP_BGEU },
  { "bgeu",    formatRRB, OP_BGEU },
  { "bgt",     formatRRB, OP_BGT  },
  { "bgt",     formatRRB, OP_BGT  },
  { "bgtu",    formatRRB, OP_BGTU },
  { "bgtu",    formatRRB, OP_BGTU },
 
 
  /* jump, call & return instructions */
  /* jump, call & return instructions */
  { "j",       formatJ,   OP_J    },
  { "j",       formatJ,   OP_J    },
  { "jr",      formatJR,  OP_JR   },
  { "jr",      formatJR,  OP_JR   },
  { "jal",     formatJ,   OP_JAL  },
  { "jal",     formatJ,   OP_JAL  },
  { "jalr",    formatJR,  OP_JALR },
  { "jalr",    formatJR,  OP_JALR },
 
 
  /* interrupt related instructions */
  /* interrupt related instructions */
  { "trap",    formatN,   OP_TRAP },
  { "trap",    formatN,   OP_TRAP },
  { "rfx",     formatN,   OP_RFX  },
  { "rfx",     formatN,   OP_RFX  },
 
 
  /* load instructions */
  /* load instructions */
  { "ldw",     formatRRS, OP_LDW  },
  { "ldw",     formatRRS, OP_LDW  },
  { "ldh",     formatRRS, OP_LDH  },
  { "ldh",     formatRRS, OP_LDH  },
  { "ldhu",    formatRRS, OP_LDHU },
  { "ldhu",    formatRRS, OP_LDHU },
  { "ldb",     formatRRS, OP_LDB  },
  { "ldb",     formatRRS, OP_LDB  },
  { "ldbu",    formatRRS, OP_LDBU },
  { "ldbu",    formatRRS, OP_LDBU },
 
 
  /* store instructions */
  /* store instructions */
  { "stw",     formatRRS, OP_STW  },
  { "stw",     formatRRS, OP_STW  },
  { "sth",     formatRRS, OP_STH  },
  { "sth",     formatRRS, OP_STH  },
  { "stb",     formatRRS, OP_STB  },
  { "stb",     formatRRS, OP_STB  },
 
 
  /* processor control instructions */
  /* processor control instructions */
  { "mvfs",    formatRH,  OP_MVFS },
  { "mvfs",    formatRH,  OP_MVFS },
  { "mvts",    formatRH,  OP_MVTS },
  { "mvts",    formatRH,  OP_MVTS },
  { "tbs",     formatN,   OP_TBS  },
  { "tbs",     formatN,   OP_TBS  },
  { "tbwr",    formatN,   OP_TBWR },
  { "tbwr",    formatN,   OP_TBWR },
  { "tbri",    formatN,   OP_TBRI },
  { "tbri",    formatN,   OP_TBRI },
  { "tbwi",    formatN,   OP_TBWI }
  { "tbwi",    formatN,   OP_TBWI }
 
 
};
};
 
 
 
 
static int cmpInstr(const void *instr1, const void *instr2) {
static int cmpInstr(const void *instr1, const void *instr2) {
  return strcmp(((Instr *) instr1)->name, ((Instr *) instr2)->name);
  return strcmp(((Instr *) instr1)->name, ((Instr *) instr2)->name);
}
}
 
 
 
 
void sortInstrTable(void) {
void sortInstrTable(void) {
  qsort(instrTable, sizeof(instrTable)/sizeof(instrTable[0]),
  qsort(instrTable, sizeof(instrTable)/sizeof(instrTable[0]),
        sizeof(instrTable[0]), cmpInstr);
        sizeof(instrTable[0]), cmpInstr);
}
}
 
 
 
 
Instr *lookupInstr(char *name) {
Instr *lookupInstr(char *name) {
  int lo, hi, tst;
  int lo, hi, tst;
  int res;
  int res;
 
 
  lo = 0;
  lo = 0;
  hi = sizeof(instrTable) / sizeof(instrTable[0]) - 1;
  hi = sizeof(instrTable) / sizeof(instrTable[0]) - 1;
  while (lo <= hi) {
  while (lo <= hi) {
    tst = (lo + hi) / 2;
    tst = (lo + hi) / 2;
    res = strcmp(instrTable[tst].name, name);
    res = strcmp(instrTable[tst].name, name);
    if (res == 0) {
    if (res == 0) {
      return &instrTable[tst];
      return &instrTable[tst];
    }
    }
    if (res < 0) {
    if (res < 0) {
      lo = tst + 1;
      lo = tst + 1;
    } else {
    } else {
      hi = tst - 1;
      hi = tst - 1;
    }
    }
  }
  }
  return NULL;
  return NULL;
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
void roundupSegments(void) {
void roundupSegments(void) {
  while (segPtr[SEGMENT_CODE] & 3) {
  while (segPtr[SEGMENT_CODE] & 3) {
    fputc(0, codeFile);
    fputc(0, codeFile);
    segPtr[SEGMENT_CODE] += 1;
    segPtr[SEGMENT_CODE] += 1;
  }
  }
  while (segPtr[SEGMENT_DATA] & 3) {
  while (segPtr[SEGMENT_DATA] & 3) {
    fputc(0, dataFile);
    fputc(0, dataFile);
    segPtr[SEGMENT_DATA] += 1;
    segPtr[SEGMENT_DATA] += 1;
  }
  }
  while (segPtr[SEGMENT_BSS] & 3) {
  while (segPtr[SEGMENT_BSS] & 3) {
    segPtr[SEGMENT_BSS] += 1;
    segPtr[SEGMENT_BSS] += 1;
  }
  }
}
}
 
 
 
 
void asmModule(void) {
void asmModule(void) {
  Symbol *label;
  Symbol *label;
  Instr *instr;
  Instr *instr;
 
 
  allowSyn = 1;
  allowSyn = 1;
  currSeg = SEGMENT_CODE;
  currSeg = SEGMENT_CODE;
  lineno = 0;
  lineno = 0;
  while (fgets(line, LINE_SIZE, inFile) != NULL) {
  while (fgets(line, LINE_SIZE, inFile) != NULL) {
    lineno++;
    lineno++;
    lineptr = line;
    lineptr = line;
    getToken();
    getToken();
    while (token == TOK_LABEL) {
    while (token == TOK_LABEL) {
      label = deref(lookupEnter(tokenvalString, LOCAL_TABLE));
      label = deref(lookupEnter(tokenvalString, LOCAL_TABLE));
      if (label->status != STATUS_UNKNOWN) {
      if (label->status != STATUS_UNKNOWN) {
        error("label '%s' multiply defined in line %d",
        error("label '%s' multiply defined in line %d",
              label->name, lineno);
              label->name, lineno);
      }
      }
      label->status = STATUS_DEFINED;
      label->status = STATUS_DEFINED;
      label->segment = currSeg;
      label->segment = currSeg;
      label->value = segPtr[currSeg];
      label->value = segPtr[currSeg];
      getToken();
      getToken();
    }
    }
    if (token == TOK_IDENT) {
    if (token == TOK_IDENT) {
      instr = lookupInstr(tokenvalString);
      instr = lookupInstr(tokenvalString);
      if (instr == NULL) {
      if (instr == NULL) {
        error("unknown instruction '%s' in line %d",
        error("unknown instruction '%s' in line %d",
              tokenvalString, lineno);
              tokenvalString, lineno);
      }
      }
      getToken();
      getToken();
      (*instr->func)(instr->code);
      (*instr->func)(instr->code);
    }
    }
    if (token != TOK_EOL) {
    if (token != TOK_EOL) {
      error("garbage in line %d", lineno);
      error("garbage in line %d", lineno);
    }
    }
  }
  }
  roundupSegments();
  roundupSegments();
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
unsigned int read4FromEco(unsigned char *p) {
unsigned int read4FromEco(unsigned char *p) {
  return (unsigned int) p[0] << 24 |
  return (unsigned int) p[0] << 24 |
         (unsigned int) p[1] << 16 |
         (unsigned int) p[1] << 16 |
         (unsigned int) p[2] <<  8 |
         (unsigned int) p[2] <<  8 |
         (unsigned int) p[3] <<  0;
         (unsigned int) p[3] <<  0;
}
}
 
 
 
 
void write4ToEco(unsigned char *p, unsigned int data) {
void write4ToEco(unsigned char *p, unsigned int data) {
  p[0] = data >> 24;
  p[0] = data >> 24;
  p[1] = data >> 16;
  p[1] = data >> 16;
  p[2] = data >>  8;
  p[2] = data >>  8;
  p[3] = data >>  0;
  p[3] = data >>  0;
}
}
 
 
 
 
void conv4FromEcoToNative(unsigned char *p) {
void conv4FromEcoToNative(unsigned char *p) {
  unsigned int data;
  unsigned int data;
 
 
  data = read4FromEco(p);
  data = read4FromEco(p);
  * (unsigned int *) p = data;
  * (unsigned int *) p = data;
}
}
 
 
 
 
void conv4FromNativeToEco(unsigned char *p) {
void conv4FromNativeToEco(unsigned char *p) {
  unsigned int data;
  unsigned int data;
 
 
  data = * (unsigned int *) p;
  data = * (unsigned int *) p;
  write4ToEco(p, data);
  write4ToEco(p, data);
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
static ExecHeader execHeader;
static ExecHeader execHeader;
static int numSymbols;
static int numSymbols;
static int crelSize;
static int crelSize;
static int drelSize;
static int drelSize;
static int symtblSize;
static int symtblSize;
static int stringSize;
static int stringSize;
 
 
 
 
static void walkTree(Symbol *s, void (*fp)(Symbol *sp)) {
static void walkTree(Symbol *s, void (*fp)(Symbol *sp)) {
  if (s == NULL) {
  if (s == NULL) {
    return;
    return;
  }
  }
  walkTree(s->left, fp);
  walkTree(s->left, fp);
  (*fp)(s);
  (*fp)(s);
  walkTree(s->right, fp);
  walkTree(s->right, fp);
}
}
 
 
 
 
void writeDummyHeader(void) {
void writeDummyHeader(void) {
  fwrite(&execHeader, sizeof(ExecHeader), 1, outFile);
  fwrite(&execHeader, sizeof(ExecHeader), 1, outFile);
}
}
 
 
 
 
void writeRealHeader(void) {
void writeRealHeader(void) {
  rewind(outFile);
  rewind(outFile);
  execHeader.magic = EXEC_MAGIC;
  execHeader.magic = EXEC_MAGIC;
  execHeader.csize = segPtr[SEGMENT_CODE];
  execHeader.csize = segPtr[SEGMENT_CODE];
  execHeader.dsize = segPtr[SEGMENT_DATA];
  execHeader.dsize = segPtr[SEGMENT_DATA];
  execHeader.bsize = segPtr[SEGMENT_BSS];
  execHeader.bsize = segPtr[SEGMENT_BSS];
  execHeader.crsize = crelSize;
  execHeader.crsize = crelSize;
  execHeader.drsize = drelSize;
  execHeader.drsize = drelSize;
  execHeader.symsize = symtblSize;
  execHeader.symsize = symtblSize;
  execHeader.strsize = stringSize;
  execHeader.strsize = stringSize;
  conv4FromNativeToEco((unsigned char *) &execHeader.magic);
  conv4FromNativeToEco((unsigned char *) &execHeader.magic);
  conv4FromNativeToEco((unsigned char *) &execHeader.csize);
  conv4FromNativeToEco((unsigned char *) &execHeader.csize);
  conv4FromNativeToEco((unsigned char *) &execHeader.dsize);
  conv4FromNativeToEco((unsigned char *) &execHeader.dsize);
  conv4FromNativeToEco((unsigned char *) &execHeader.bsize);
  conv4FromNativeToEco((unsigned char *) &execHeader.bsize);
  conv4FromNativeToEco((unsigned char *) &execHeader.crsize);
  conv4FromNativeToEco((unsigned char *) &execHeader.crsize);
  conv4FromNativeToEco((unsigned char *) &execHeader.drsize);
  conv4FromNativeToEco((unsigned char *) &execHeader.drsize);
  conv4FromNativeToEco((unsigned char *) &execHeader.symsize);
  conv4FromNativeToEco((unsigned char *) &execHeader.symsize);
  conv4FromNativeToEco((unsigned char *) &execHeader.strsize);
  conv4FromNativeToEco((unsigned char *) &execHeader.strsize);
  fwrite(&execHeader, sizeof(ExecHeader), 1, outFile);
  fwrite(&execHeader, sizeof(ExecHeader), 1, outFile);
}
}
 
 
 
 
void writeCode(void) {
void writeCode(void) {
  int data;
  int data;
 
 
  rewind(codeFile);
  rewind(codeFile);
  while (1) {
  while (1) {
    data = fgetc(codeFile);
    data = fgetc(codeFile);
    if (data == EOF) {
    if (data == EOF) {
      break;
      break;
    }
    }
    fputc(data, outFile);
    fputc(data, outFile);
  }
  }
}
}
 
 
 
 
void writeData(void) {
void writeData(void) {
  int data;
  int data;
 
 
  rewind(dataFile);
  rewind(dataFile);
  while (1) {
  while (1) {
    data = fgetc(dataFile);
    data = fgetc(dataFile);
    if (data == EOF) {
    if (data == EOF) {
      break;
      break;
    }
    }
    fputc(data, outFile);
    fputc(data, outFile);
  }
  }
}
}
 
 
 
 
void transferFixupsForSymbol(Symbol *s) {
void transferFixupsForSymbol(Symbol *s) {
  Fixup *f;
  Fixup *f;
 
 
  if (s->status != STATUS_UNKNOWN && s->status != STATUS_DEFINED) {
  if (s->status != STATUS_UNKNOWN && s->status != STATUS_DEFINED) {
    /* this should never happen */
    /* this should never happen */
    error("global symbol is neither unknown nor defined");
    error("global symbol is neither unknown nor defined");
  }
  }
  if (s->status == STATUS_UNKNOWN && s->fixups == NULL) {
  if (s->status == STATUS_UNKNOWN && s->fixups == NULL) {
    /* this symbol is neither defined here nor referenced here: skip */
    /* this symbol is neither defined here nor referenced here: skip */
    s->skip = 1;
    s->skip = 1;
    return;
    return;
  }
  }
  s->skip = 0;
  s->skip = 0;
  while (s->fixups != NULL) {
  while (s->fixups != NULL) {
    /* get next fixup record */
    /* get next fixup record */
    f = s->fixups;
    f = s->fixups;
    s->fixups = f->next;
    s->fixups = f->next;
    /* use the 'base' component to store the current symbol number */
    /* use the 'base' component to store the current symbol number */
    f->base = MSB | numSymbols;
    f->base = MSB | numSymbols;
    /* transfer the record to the fixup list */
    /* transfer the record to the fixup list */
    f->next = fixupList;
    f->next = fixupList;
    fixupList = f;
    fixupList = f;
  }
  }
  numSymbols++;
  numSymbols++;
}
}
 
 
 
 
void transferFixups(void) {
void transferFixups(void) {
  numSymbols = 0;
  numSymbols = 0;
  walkTree(globalTable, transferFixupsForSymbol);
  walkTree(globalTable, transferFixupsForSymbol);
}
}
 
 
 
 
void writeCodeRelocs(void) {
void writeCodeRelocs(void) {
  Fixup *f;
  Fixup *f;
  RelocRecord relRec;
  RelocRecord relRec;
 
 
  crelSize = 0;
  crelSize = 0;
  f = fixupList;
  f = fixupList;
  while (f != NULL) {
  while (f != NULL) {
    if (f->segment != SEGMENT_CODE && f->segment != SEGMENT_DATA) {
    if (f->segment != SEGMENT_CODE && f->segment != SEGMENT_DATA) {
      /* this should never happan */
      /* this should never happan */
      error("fixup found in a segment other than code or data");
      error("fixup found in a segment other than code or data");
    }
    }
    if (f->segment == SEGMENT_CODE) {
    if (f->segment == SEGMENT_CODE) {
      relRec.offset = f->offset;
      relRec.offset = f->offset;
      relRec.method = f->method;
      relRec.method = f->method;
      relRec.value = f->value;
      relRec.value = f->value;
      relRec.base = f->base;
      relRec.base = f->base;
      conv4FromNativeToEco((unsigned char *) &relRec.offset);
      conv4FromNativeToEco((unsigned char *) &relRec.offset);
      conv4FromNativeToEco((unsigned char *) &relRec.method);
      conv4FromNativeToEco((unsigned char *) &relRec.method);
      conv4FromNativeToEco((unsigned char *) &relRec.value);
      conv4FromNativeToEco((unsigned char *) &relRec.value);
      conv4FromNativeToEco((unsigned char *) &relRec.base);
      conv4FromNativeToEco((unsigned char *) &relRec.base);
      fwrite(&relRec, sizeof(RelocRecord), 1, outFile);
      fwrite(&relRec, sizeof(RelocRecord), 1, outFile);
      crelSize += sizeof(RelocRecord);
      crelSize += sizeof(RelocRecord);
    }
    }
    f = f->next;
    f = f->next;
  }
  }
}
}
 
 
 
 
void writeDataRelocs(void) {
void writeDataRelocs(void) {
  Fixup *f;
  Fixup *f;
  RelocRecord relRec;
  RelocRecord relRec;
 
 
  drelSize = 0;
  drelSize = 0;
  f = fixupList;
  f = fixupList;
  while (f != NULL) {
  while (f != NULL) {
    if (f->segment != SEGMENT_CODE && f->segment != SEGMENT_DATA) {
    if (f->segment != SEGMENT_CODE && f->segment != SEGMENT_DATA) {
      /* this should never happan */
      /* this should never happan */
      error("fixup found in a segment other than code or data");
      error("fixup found in a segment other than code or data");
    }
    }
    if (f->segment == SEGMENT_DATA) {
    if (f->segment == SEGMENT_DATA) {
      relRec.offset = f->offset;
      relRec.offset = f->offset;
      relRec.method = f->method;
      relRec.method = f->method;
      relRec.value = f->value;
      relRec.value = f->value;
      relRec.base = f->base;
      relRec.base = f->base;
      conv4FromNativeToEco((unsigned char *) &relRec.offset);
      conv4FromNativeToEco((unsigned char *) &relRec.offset);
      conv4FromNativeToEco((unsigned char *) &relRec.method);
      conv4FromNativeToEco((unsigned char *) &relRec.method);
      conv4FromNativeToEco((unsigned char *) &relRec.value);
      conv4FromNativeToEco((unsigned char *) &relRec.value);
      conv4FromNativeToEco((unsigned char *) &relRec.base);
      conv4FromNativeToEco((unsigned char *) &relRec.base);
      fwrite(&relRec, sizeof(RelocRecord), 1, outFile);
      fwrite(&relRec, sizeof(RelocRecord), 1, outFile);
      drelSize += sizeof(RelocRecord);
      drelSize += sizeof(RelocRecord);
    }
    }
    f = f->next;
    f = f->next;
  }
  }
}
}
 
 
 
 
void writeSymbol(Symbol *s) {
void writeSymbol(Symbol *s) {
  SymbolRecord symRec;
  SymbolRecord symRec;
 
 
  if (s->skip) {
  if (s->skip) {
    /* this symbol is neither defined here nor referenced here: skip */
    /* this symbol is neither defined here nor referenced here: skip */
    return;
    return;
  }
  }
  symRec.name = stringSize;
  symRec.name = stringSize;
  if (s->status == STATUS_UNKNOWN) {
  if (s->status == STATUS_UNKNOWN) {
    symRec.type = MSB;
    symRec.type = MSB;
    symRec.value = 0;
    symRec.value = 0;
  } else {
  } else {
    symRec.type = s->segment;
    symRec.type = s->segment;
    symRec.value = s->value;
    symRec.value = s->value;
  }
  }
  conv4FromNativeToEco((unsigned char *) &symRec.name);
  conv4FromNativeToEco((unsigned char *) &symRec.name);
  conv4FromNativeToEco((unsigned char *) &symRec.type);
  conv4FromNativeToEco((unsigned char *) &symRec.type);
  conv4FromNativeToEco((unsigned char *) &symRec.value);
  conv4FromNativeToEco((unsigned char *) &symRec.value);
  fwrite(&symRec, sizeof(SymbolRecord), 1, outFile);
  fwrite(&symRec, sizeof(SymbolRecord), 1, outFile);
  symtblSize += sizeof(SymbolRecord);
  symtblSize += sizeof(SymbolRecord);
  stringSize += strlen(s->name) + 1;
  stringSize += strlen(s->name) + 1;
}
}
 
 
 
 
void writeSymbols(void) {
void writeSymbols(void) {
  symtblSize = 0;
  symtblSize = 0;
  stringSize = 0;
  stringSize = 0;
  walkTree(globalTable, writeSymbol);
  walkTree(globalTable, writeSymbol);
}
}
 
 
 
 
void writeString(Symbol *s) {
void writeString(Symbol *s) {
  if (s->skip) {
  if (s->skip) {
    /* this symbol is neither defined here nor referenced here: skip */
    /* this symbol is neither defined here nor referenced here: skip */
    return;
    return;
  }
  }
  fputs(s->name, outFile);
  fputs(s->name, outFile);
  fputc('\0', outFile);
  fputc('\0', outFile);
}
}
 
 
 
 
void writeStrings(void) {
void writeStrings(void) {
  walkTree(globalTable, writeString);
  walkTree(globalTable, writeString);
}
}
 
 
 
 
/**************************************************************/
/**************************************************************/
 
 
 
 
void usage(char *myself) {
void usage(char *myself) {
  fprintf(stderr, "Usage: %s\n", myself);
  fprintf(stderr, "Usage: %s\n", myself);
  fprintf(stderr, "         [-o objfile]     set object file name\n");
  fprintf(stderr, "         [-o objfile]     set object file name\n");
  fprintf(stderr, "         file             source file name\n");
  fprintf(stderr, "         file             source file name\n");
  fprintf(stderr, "         [files...]       additional source files\n");
  fprintf(stderr, "         [files...]       additional source files\n");
  exit(1);
  exit(1);
}
}
 
 
 
 
int main(int argc, char *argv[]) {
int main(int argc, char *argv[]) {
  int i;
  int i;
  char *argp;
  char *argp;
 
 
  sortInstrTable();
  sortInstrTable();
  tmpnam(codeName);
  tmpnam(codeName);
  tmpnam(dataName);
  tmpnam(dataName);
  outName = "a.out";
  outName = "a.out";
  for (i = 1; i < argc; i++) {
  for (i = 1; i < argc; i++) {
    argp = argv[i];
    argp = argv[i];
    if (*argp != '-') {
    if (*argp != '-') {
      break;
      break;
    }
    }
    argp++;
    argp++;
    switch (*argp) {
    switch (*argp) {
      case 'o':
      case 'o':
        if (i == argc - 1) {
        if (i == argc - 1) {
          usage(argv[0]);
          usage(argv[0]);
        }
        }
        outName = argv[++i];
        outName = argv[++i];
        break;
        break;
      default:
      default:
        usage(argv[0]);
        usage(argv[0]);
    }
    }
  }
  }
  if (i == argc) {
  if (i == argc) {
    usage(argv[0]);
    usage(argv[0]);
  }
  }
  codeFile = fopen(codeName, "w+b");
  codeFile = fopen(codeName, "w+b");
  if (codeFile == NULL) {
  if (codeFile == NULL) {
    error("cannot create temporary code file '%s'", codeName);
    error("cannot create temporary code file '%s'", codeName);
  }
  }
  dataFile = fopen(dataName, "w+b");
  dataFile = fopen(dataName, "w+b");
  if (dataFile == NULL) {
  if (dataFile == NULL) {
    error("cannot create temporary data file '%s'", dataName);
    error("cannot create temporary data file '%s'", dataName);
  }
  }
  outFile = fopen(outName, "wb");
  outFile = fopen(outName, "wb");
  if (outFile == NULL) {
  if (outFile == NULL) {
    error("cannot open output file '%s'", outName);
    error("cannot open output file '%s'", outName);
  }
  }
  do {
  do {
    inName = argv[i];
    inName = argv[i];
    if (*inName == '-') {
    if (*inName == '-') {
      usage(argv[0]);
      usage(argv[0]);
    }
    }
    inFile = fopen(inName, "rt");
    inFile = fopen(inName, "rt");
    if (inFile == NULL) {
    if (inFile == NULL) {
      error("cannot open input file '%s'", inName);
      error("cannot open input file '%s'", inName);
    }
    }
    fprintf(stderr, "Assembling module '%s'...\n", inName);
    fprintf(stderr, "Assembling module '%s'...\n", inName);
    asmModule();
    asmModule();
    if (inFile != NULL) {
    if (inFile != NULL) {
      fclose(inFile);
      fclose(inFile);
      inFile = NULL;
      inFile = NULL;
    }
    }
    linkLocals();
    linkLocals();
  } while (++i < argc);
  } while (++i < argc);
  writeDummyHeader();
  writeDummyHeader();
  writeCode();
  writeCode();
  writeData();
  writeData();
  transferFixups();
  transferFixups();
  writeCodeRelocs();
  writeCodeRelocs();
  writeDataRelocs();
  writeDataRelocs();
  writeSymbols();
  writeSymbols();
  writeStrings();
  writeStrings();
  writeRealHeader();
  writeRealHeader();
  if (codeFile != NULL) {
  if (codeFile != NULL) {
    fclose(codeFile);
    fclose(codeFile);
    codeFile = NULL;
    codeFile = NULL;
  }
  }
  if (dataFile != NULL) {
  if (dataFile != NULL) {
    fclose(dataFile);
    fclose(dataFile);
    dataFile = NULL;
    dataFile = NULL;
  }
  }
  if (outFile != NULL) {
  if (outFile != NULL) {
    fclose(outFile);
    fclose(outFile);
    outFile = NULL;
    outFile = NULL;
  }
  }
  if (codeName != NULL) {
  if (codeName != NULL) {
    unlink(codeName);
    unlink(codeName);
  }
  }
  if (dataName != NULL) {
  if (dataName != NULL) {
    unlink(dataName);
    unlink(dataName);
  }
  }
  return 0;
  return 0;
}
}
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.