diff --git a/as/input.c b/as/input.c index 819f99d..cc4e118 100644 --- a/as/input.c +++ b/as/input.c @@ -71,6 +71,36 @@ static int do_dot_globl(struct scan_state *scan_state, struct tunit *tunit, stru return 0; } +static int do_dot_size(struct scan_state *scan_state, struct tunit *tunit, struct stmt *stmt) +{ + struct symbol *symbol; + + symbol = tunit_symbol_enter(tunit, stmt->u.symbol.name); + if (!symbol) + return -1; + + if (!symbol->section + || !symbol->defined) { + fprintf(stderr, "%s: %s line %u: symbol %s undefined\n", + scan_state->progname, scan_state->filename, scan_state->linenr, stmt->u.symbol.name); + return -1; + } + if (symbol->st_size) { + fprintf(stderr, "%s: %s line %u: size of symbol %s already defined\n", + scan_state->progname, scan_state->filename, scan_state->linenr, stmt->u.symbol.name); + return -1; + } + if (symbol->section != tunit->cursect) { + fprintf(stderr, "%s: %s line %u: symbol %s is not defined in current section\n", + scan_state->progname, scan_state->filename, scan_state->linenr, stmt->u.symbol.name); + return -1; + } + + symbol->st_size = tunit->cursect->dot - symbol->st_value; + + return 0; +} + static int do_dot_text(struct scan_state *scan_state, struct tunit *tunit, struct stmt *stmt) { struct section *section; @@ -152,6 +182,8 @@ static int interpret(struct scan_state *scan_state, struct tunit *tunit, struct return do_dot_file(scan_state, tunit, stmt); case S_DOT_GLOBL: return do_dot_globl(scan_state, tunit, stmt); + case S_DOT_SIZE: + return do_dot_size(scan_state, tunit, stmt); case S_DOT_TEXT: return do_dot_text(scan_state, tunit, stmt); case S_DOT_TYPE_FUNCTION: diff --git a/as/parse.c b/as/parse.c index f7e2eb6..439570b 100644 --- a/as/parse.c +++ b/as/parse.c @@ -53,6 +53,37 @@ static int parse_dot_globl(struct scan_state *scan_state, struct stmt *stmt) return error(scan_state, "junk after .globl directive", token, &token_attr); } +/* for now, accepts: .size ,.- */ +static int parse_dot_size(struct scan_state *scan_state, struct stmt *stmt) +{ + enum token token; + union token_attribute token_attr; + + token = scan_token(scan_state, &token_attr); + if (token == T_SYMBOL) { + stmt->u.symbol.name = token_attr.text; + token = scan_token(scan_state, &token_attr); + if (token == T_COMMA) { + token = scan_token(scan_state, &token_attr); + if (token == T_DOT) { + token = scan_token(scan_state, &token_attr); + if (token == T_MINUS) { + token = scan_token(scan_state, &token_attr); + if (token == T_SYMBOL + && strcmp(token_attr.text, stmt->u.symbol.name) == 0) { + token = scan_token(scan_state, &token_attr); + if (token == T_NEWLINE) { + stmt->tag = S_DOT_SIZE; + return 1; + } + } + } + } + } + } + return error(scan_state, "junk after .size directive", token, &token_attr); +} + static int parse_dot_text(struct scan_state *scan_state, struct stmt *stmt) { enum token token; @@ -378,6 +409,8 @@ int parse_stmt(struct scan_state *scan_state, struct stmt *stmt) return parse_dot_file(scan_state, stmt); case T_DOT_GLOBL: return parse_dot_globl(scan_state, stmt); + case T_DOT_SIZE: + return parse_dot_size(scan_state, stmt); case T_DOT_TEXT: return parse_dot_text(scan_state, stmt); case T_DOT_TYPE: diff --git a/as/scan.c b/as/scan.c index 25deed2..6bcceb1 100644 --- a/as/scan.c +++ b/as/scan.c @@ -220,6 +220,9 @@ static enum token do_symbol(struct scan_state *scan_state, union token_attribute if (charbuf[0] == '.') { enum token low, high; + if (charbuf[1] == '\0') + return T_DOT; + /* see token.def, reserved symbols occupy tokens [0,T_SYMBOL[ */ low = 0; high = T_SYMBOL; @@ -322,6 +325,8 @@ enum token scan_token(struct scan_state *scan_state, union token_attribute *toke return T_RPAREN; case '"': return do_string(scan_state, token_attr); + case '-': + return T_MINUS; case '.': /* Dot may start a floating point literal, but tests show that gcc always outputs floating point values as integer literals, diff --git a/as/token.def b/as/token.def index fa778d5..b7e921e 100644 --- a/as/token.def +++ b/as/token.def @@ -7,6 +7,7 @@ /* reserved symbols including directives; MUST come first and MUST be listed in increasing alphanumeric order */ TOKEN(T_DOT_FILE, ".file", TAFMT_NONE) TOKEN(T_DOT_GLOBL, ".globl", TAFMT_NONE) +TOKEN(T_DOT_SIZE, ".size", TAFMT_NONE) TOKEN(T_DOT_TEXT, ".text", TAFMT_NONE) TOKEN(T_DOT_TYPE, ".type", TAFMT_NONE) /* non-reserved symbols; T_SYMBOL MUST be the first token after the list of reserved symbols */ @@ -18,7 +19,9 @@ TOKEN(T_STRING, "", TAFMT_STRING) TOKEN(T_AT, "@", TAFMT_NONE) TOKEN(T_COLON, ":", TAFMT_NONE) TOKEN(T_COMMA, ",", TAFMT_NONE) +TOKEN(T_DOT, ".", TAFMT_NONE) TOKEN(T_LPAREN, "(", TAFMT_NONE) +TOKEN(T_MINUS, "-", TAFMT_NONE) TOKEN(T_RPAREN, ")", TAFMT_NONE) /* synthetic symbols */ TOKEN(T_NEWLINE, "", TAFMT_NONE) @@ -50,7 +53,6 @@ TOKEN(T_DOT_RODATA, ".rodata", TAFMT_NONE) TOKEN(T_DOT_SECTION, ".section", TAFMT_NONE) TOKEN(T_DOT_SET, ".set", TAFMT_NONE) TOKEN(T_DOT_SHORT, ".short", TAFMT_NONE) -TOKEN(T_DOT_SIZE, ".size", TAFMT_NONE) TOKEN(T_DOT_SUBSECTION, ".subsection", TAFMT_NONE) TOKEN(T_DOT_SYMVER, ".symver", TAFMT_NONE) TOKEN(T_DOT_WEAK, ".weak", TAFMT_NONE) @@ -71,7 +73,6 @@ TOKEN(T_AND, "&", TAFMT_NONE) TOKEN(T_CARET, "^", TAFMT_NONE) TOKEN(T_BANG, "!", TAFMT_NONE) TOKEN(T_PLUS, "+", TAFMT_NONE) -TOKEN(T_MINUS, "-", TAFMT_NONE) TOKEN(T_EQ, "=", TAFMT_NONE) TOKEN(T_EQEQ, "==", TAFMT_NONE) TOKEN(T_NEQ, "!=", TAFMT_NONE) diff --git a/as/tunit.h b/as/tunit.h index ab7c826..2b510c3 100644 --- a/as/tunit.h +++ b/as/tunit.h @@ -17,6 +17,7 @@ enum stmt_tag { /* directives */ S_DOT_FILE, S_DOT_GLOBL, + S_DOT_SIZE, S_DOT_TEXT, S_DOT_TYPE_FUNCTION, /* non-directives */ @@ -31,7 +32,7 @@ struct stmt { struct { /* S_DOT_FILE */ const char *text; /* XXX: should be pdp10_uint9_t* */ } string; - struct { /* S_DOT_GLOBL, S_LABEL, S_DOT_TYPE_FUNCTION */ + struct { /* S_DOT_GLOBL, S_LABEL, S_DOT_SIZE, S_DOT_TYPE_FUNCTION */ const char *name; } symbol; struct { /* S_INSN */