/*
|
/*
|
* 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;
|
}
|
}
|
|
|