2019-12-08 18:55:33 +00:00
|
|
|
/* link script support */
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
label opcode operand
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <unordered_map>
|
|
|
|
#include <stdexcept>
|
2019-12-13 04:50:43 +00:00
|
|
|
#include <variant>
|
2019-12-08 18:55:33 +00:00
|
|
|
|
|
|
|
#include <cctype>
|
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdint>
|
|
|
|
|
|
|
|
#include <err.h>
|
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
#include "script.h"
|
|
|
|
|
2019-12-08 18:55:33 +00:00
|
|
|
|
|
|
|
/*!re2c
|
|
|
|
re2c:define:YYCTYPE = char;
|
|
|
|
re2c:yyfill:enable = 0;
|
|
|
|
|
|
|
|
// :-~ includes ; which interferes with comments.
|
|
|
|
ident = [:<-~][0-~]*;
|
|
|
|
ws = [ \t];
|
|
|
|
eof = "\x00";
|
|
|
|
*/
|
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
namespace {
|
|
|
|
std::unordered_map<std::string, int> opcodes = {
|
|
|
|
#define x(op) { #op, OP_##op },
|
|
|
|
|
|
|
|
#include "ops.h"
|
|
|
|
#undef x
|
|
|
|
|
|
|
|
/* aliases */
|
|
|
|
{ "AUX", OP_ADR },
|
|
|
|
{ "REZ", OP_RES },
|
|
|
|
{ "LIN", OP_LNK },
|
|
|
|
{ "KIN", OP_KND },
|
|
|
|
{ "=", OP_EQ }
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
std::unordered_map<std::string, int> types = {
|
|
|
|
|
|
|
|
{ "NON", 0x00 },
|
|
|
|
{ "BAD", 0x01 },
|
|
|
|
{ "BIN", 0x06 },
|
|
|
|
{ "TXT", 0x04 },
|
|
|
|
{ "DIR", 0x0f },
|
|
|
|
{ "ADB", 0x19 },
|
|
|
|
{ "AWP", 0x1a },
|
|
|
|
{ "ASP", 0x1b },
|
|
|
|
{ "GSB", 0xab },
|
|
|
|
{ "TDF", 0xac },
|
|
|
|
{ "BDF", 0xad },
|
|
|
|
{ "SRC", 0xb0 },
|
|
|
|
{ "OBJ", 0xb1 },
|
|
|
|
{ "LIB", 0xb2 },
|
|
|
|
{ "S16", 0xb3 },
|
|
|
|
{ "RTL", 0xb4 },
|
|
|
|
{ "EXE", 0xb5 },
|
|
|
|
{ "PIF", 0xb6 },
|
|
|
|
{ "TIF", 0xb7 },
|
|
|
|
{ "NDA", 0xb8 },
|
|
|
|
{ "CDA", 0xb9 },
|
|
|
|
{ "TOL", 0xba },
|
|
|
|
{ "DRV", 0xbb },
|
|
|
|
{ "DOC", 0xbf },
|
|
|
|
{ "PNT", 0xc0 },
|
|
|
|
{ "PIC", 0xc1 },
|
|
|
|
{ "FON", 0xcb },
|
|
|
|
{ "PAS", 0xef },
|
|
|
|
{ "CMD", 0xf0 },
|
|
|
|
{ "LNK", 0xf8 },
|
|
|
|
{ "BAS", 0xfc },
|
|
|
|
{ "VAR", 0xfd },
|
|
|
|
{ "REL", 0xfe },
|
|
|
|
{ "SYS", 0xff },
|
|
|
|
|
|
|
|
};
|
|
|
|
}
|
2019-12-08 18:55:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
static uint32_t number_operand(const char *YYCURSOR, bool required = true) {
|
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
const char *iter = YYCURSOR;
|
|
|
|
const char *YYMARKER = nullptr;
|
2019-12-08 18:55:33 +00:00
|
|
|
uint32_t rv = 0;
|
|
|
|
/*!re2c
|
|
|
|
* { throw std::invalid_argument("bad operand"); }
|
|
|
|
[;*] | eof {
|
|
|
|
if (!required) return rv;
|
|
|
|
throw std::invalid_argument("missing operand");
|
|
|
|
}
|
|
|
|
'%' [01]+ {
|
|
|
|
++iter;
|
|
|
|
for(;iter < YYCURSOR; ++iter) {
|
|
|
|
rv <<= 1;
|
|
|
|
rv |= *iter - '0';
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
'$' [A-Fa-f0-9]+ {
|
|
|
|
++iter;
|
|
|
|
for(;iter < YYCURSOR; ++iter) {
|
|
|
|
char c = *iter | 0x20;
|
|
|
|
rv <<= 4;
|
|
|
|
if (c <= '9') rv |= c - '0';
|
|
|
|
else rv |= c - 'a' + 10;
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
[0-9]+ {
|
|
|
|
for(;iter < YYCURSOR; ++iter) {
|
|
|
|
rv *= 10;
|
|
|
|
rv += *iter - '0';
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ident {
|
|
|
|
std::string s(iter, YYCURSOR);
|
|
|
|
//look up symbol, verify it's an absolute value, etc
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
exit:
|
|
|
|
char c = *YYCURSOR;
|
|
|
|
if (isspace(c) || c == 0) return rv;
|
|
|
|
|
|
|
|
throw std::invalid_argument("bad operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
static uint32_t type_operand(const char *YYCURSOR, bool required = true) {
|
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
const char *iter = YYCURSOR;
|
|
|
|
const char *YYMARKER = nullptr;
|
2019-12-08 18:55:33 +00:00
|
|
|
uint32_t rv = 0;
|
|
|
|
/*!re2c
|
|
|
|
* { throw std::invalid_argument("bad operand"); }
|
|
|
|
|
|
|
|
[;*] | eof {
|
|
|
|
if (!required) return rv;
|
|
|
|
throw std::invalid_argument("missing operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
'%' [01]+ {
|
|
|
|
++iter;
|
|
|
|
for(;iter < YYCURSOR; ++iter) {
|
|
|
|
rv <<= 1;
|
|
|
|
rv |= *iter - '0';
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
'$' [A-Fa-f0-9]+ {
|
|
|
|
++iter;
|
|
|
|
for(;iter < YYCURSOR; ++iter) {
|
|
|
|
char c = *iter | 0x20;
|
|
|
|
rv <<= 4;
|
|
|
|
if (c <= '9') rv |= c - '0';
|
|
|
|
else rv |= c - 'a' + 10;
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
[0-9]+ {
|
|
|
|
for(;iter < YYCURSOR; ++iter) {
|
|
|
|
rv *= 10;
|
|
|
|
rv += *iter - '0';
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
[A-Za-z][A-Za-z0-9]{2} {
|
|
|
|
std::string s(iter, YYCURSOR);
|
|
|
|
for(char &c : s) c = std::toupper(c);
|
|
|
|
auto iter = types.find(s);
|
2019-12-13 04:50:43 +00:00
|
|
|
if (iter == types.end()) {
|
2019-12-08 18:55:33 +00:00
|
|
|
throw std::invalid_argument("bad operand");
|
|
|
|
}
|
2019-12-13 04:50:43 +00:00
|
|
|
rv = iter->second;
|
2019-12-08 18:55:33 +00:00
|
|
|
}
|
|
|
|
*/
|
|
|
|
exit:
|
|
|
|
char c = *YYCURSOR;
|
|
|
|
if (isspace(c) || c == 0) return rv;
|
|
|
|
|
|
|
|
throw std::invalid_argument("bad operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int x_number_operand(const char *YYCURSOR) {
|
2019-12-13 04:50:43 +00:00
|
|
|
const char *iter = YYCURSOR;
|
|
|
|
const char *YYMARKER = nullptr;
|
2019-12-08 18:55:33 +00:00
|
|
|
uint32_t rv = 0;
|
|
|
|
/*!re2c
|
|
|
|
* { throw std::invalid_argument("bad operand"); }
|
|
|
|
|
|
|
|
'%' [01]+ {
|
|
|
|
++iter;
|
|
|
|
for(;iter < YYCURSOR; ++iter) {
|
|
|
|
rv <<= 1;
|
|
|
|
rv |= *iter - '0';
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
'$' [A-Fa-f0-9]+ {
|
|
|
|
++iter;
|
|
|
|
for(;iter < YYCURSOR; ++iter) {
|
|
|
|
char c = *iter | 0x20;
|
|
|
|
rv <<= 4;
|
|
|
|
if (c <= '9') rv |= c - '0';
|
|
|
|
else rv |= c - 'a' + 10;
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
[0-9]+ {
|
|
|
|
for(;iter < YYCURSOR; ++iter) {
|
|
|
|
rv *= 10;
|
|
|
|
rv += *iter - '0';
|
|
|
|
}
|
|
|
|
goto exit;
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
exit:
|
|
|
|
char c = *YYCURSOR;
|
|
|
|
if (isspace(c) || c == 0) return rv;
|
|
|
|
|
|
|
|
throw std::invalid_argument("bad operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::string x_label_operand(const char *YYCURSOR) {
|
2019-12-13 04:50:43 +00:00
|
|
|
const char *iter = YYCURSOR;
|
|
|
|
const char *YYMARKER = nullptr;
|
2019-12-08 18:55:33 +00:00
|
|
|
std::string rv;
|
|
|
|
/*!re2c
|
|
|
|
* { throw std::invalid_argument("bad operand"); }
|
|
|
|
|
|
|
|
ident {
|
|
|
|
std::string s(iter, YYCURSOR);
|
2019-12-13 04:50:43 +00:00
|
|
|
goto exit;
|
2019-12-08 18:55:33 +00:00
|
|
|
}
|
|
|
|
*/
|
|
|
|
exit:
|
|
|
|
char c = *YYCURSOR;
|
2019-12-13 04:50:43 +00:00
|
|
|
if (isspace(c) || c == 0) {
|
|
|
|
//look up symbol, verify it's an absolute value, etc
|
|
|
|
return rv;
|
|
|
|
}
|
2019-12-08 18:55:33 +00:00
|
|
|
throw std::invalid_argument("bad operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::string x_string_operand(const char *YYCURSOR) {
|
2019-12-13 04:50:43 +00:00
|
|
|
const char *iter = YYCURSOR;
|
2019-12-08 18:55:33 +00:00
|
|
|
std::string rv;
|
|
|
|
/*!re2c
|
|
|
|
* { throw std::invalid_argument("bad operand"); }
|
|
|
|
|
|
|
|
['] [^']* ['] | ["] [^"]* ["] {
|
|
|
|
rv = std::string(iter+1, YYCURSOR-1);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
exit:
|
|
|
|
char c = *YYCURSOR;
|
|
|
|
if (isspace(c) || c == 0) return rv;
|
|
|
|
throw std::invalid_argument("bad operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int ovr_operand(const char *YYCURSOR) {
|
|
|
|
int rv = 0;
|
2019-12-13 04:50:43 +00:00
|
|
|
const char *YYMARKER = nullptr;
|
2019-12-08 18:55:33 +00:00
|
|
|
|
|
|
|
/*!re2c
|
|
|
|
* { throw std::invalid_argument("bad operand"); }
|
|
|
|
[;*] | eof {
|
2019-12-13 04:50:43 +00:00
|
|
|
return OVR_NONE;
|
2019-12-08 18:55:33 +00:00
|
|
|
}
|
|
|
|
'ALL' {
|
2019-12-13 04:50:43 +00:00
|
|
|
rv = OVR_ALL;
|
2019-12-08 18:55:33 +00:00
|
|
|
}
|
|
|
|
'OFF' {
|
2019-12-13 04:50:43 +00:00
|
|
|
rv = OVR_OFF;
|
2019-12-08 18:55:33 +00:00
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
char c = *YYCURSOR;
|
|
|
|
if (isspace(c) || c == 0) return rv;
|
|
|
|
|
|
|
|
throw std::invalid_argument("bad operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
static std::string label_operand(const char *YYCURSOR, bool required = true) {
|
|
|
|
std::string rv;
|
2019-12-13 04:50:43 +00:00
|
|
|
const char *iter = YYCURSOR;
|
|
|
|
const char *YYMARKER = nullptr;
|
2019-12-08 18:55:33 +00:00
|
|
|
/*!re2c
|
|
|
|
* { throw std::invalid_argument("bad operand"); }
|
|
|
|
[;*] | eof {
|
|
|
|
if (!required) return rv;
|
|
|
|
throw std::invalid_argument("missing operand");
|
|
|
|
}
|
|
|
|
ident {
|
|
|
|
rv = std::string(iter, YYCURSOR);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
exit:
|
2019-12-08 18:55:33 +00:00
|
|
|
char c = *YYCURSOR;
|
|
|
|
if (isspace(c) || c == 0) return rv;
|
|
|
|
|
|
|
|
throw std::invalid_argument("bad operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static std::string path_operand(const char *YYCURSOR, bool required = true) {
|
|
|
|
std::string rv;
|
2019-12-13 04:50:43 +00:00
|
|
|
const char *iter = YYCURSOR;
|
|
|
|
const char *YYMARKER = nullptr;
|
2019-12-08 18:55:33 +00:00
|
|
|
/*!re2c
|
|
|
|
* { throw std::invalid_argument("bad operand"); }
|
|
|
|
[;*] | eof {
|
|
|
|
if (!required) return rv;
|
|
|
|
throw std::invalid_argument("missing operand");
|
|
|
|
}
|
|
|
|
// don't allow leading quotes, eof, or comment chars
|
|
|
|
[^;*\x00'"][^ \t]* {
|
|
|
|
rv = std::string(iter, YYCURSOR);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
['] [^']* ['] | ["] [^"]* ["] {
|
|
|
|
rv = std::string(iter+1, YYCURSOR-1);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
exit:
|
2019-12-08 18:55:33 +00:00
|
|
|
char c = *YYCURSOR;
|
|
|
|
if (isspace(c) || c == 0) return rv;
|
|
|
|
|
|
|
|
throw std::invalid_argument("bad operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void no_operand(const char *YYCURSOR) {
|
|
|
|
/*!re2c
|
|
|
|
* { throw std::invalid_argument("bad operand"); }
|
2019-12-13 04:50:43 +00:00
|
|
|
[;*] | eof { return; }
|
2019-12-08 18:55:33 +00:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static std::string string_operand(const char *YYCURSOR, bool required = true) {
|
|
|
|
|
|
|
|
std::string rv;
|
2019-12-13 04:50:43 +00:00
|
|
|
const char *iter = YYCURSOR;
|
|
|
|
const char *YYMARKER = nullptr;
|
2019-12-08 18:55:33 +00:00
|
|
|
/*!re2c
|
|
|
|
* { throw std::invalid_argument("bad operand"); }
|
|
|
|
[;*] | eof {
|
|
|
|
if (!required) return rv;
|
|
|
|
throw std::invalid_argument("missing operand");
|
|
|
|
}
|
|
|
|
['] [^']* ['] | ["] [^"]* ["] {
|
|
|
|
rv = std::string(iter+1, YYCURSOR-1);
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
*/
|
2019-12-13 04:50:43 +00:00
|
|
|
exit:
|
2019-12-08 18:55:33 +00:00
|
|
|
char c = *YYCURSOR;
|
|
|
|
if (isspace(c) || c == 0) return rv;
|
|
|
|
throw std::invalid_argument("bad operand");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
void parse_line(const char *YYCURSOR) {
|
2019-12-08 18:55:33 +00:00
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
label_t label;
|
|
|
|
opcode_t opcode = OP_NONE;
|
|
|
|
operand_t operand;
|
2019-12-08 18:55:33 +00:00
|
|
|
|
|
|
|
const char *iter = YYCURSOR;
|
2019-12-13 04:50:43 +00:00
|
|
|
const char *YYMARKER = nullptr;
|
|
|
|
|
2019-12-08 18:55:33 +00:00
|
|
|
/*!re2c
|
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
* { throw std::invalid_argument("bad label"); }
|
2019-12-08 18:55:33 +00:00
|
|
|
[;*] | eof {
|
|
|
|
return;
|
|
|
|
}
|
2019-12-13 04:50:43 +00:00
|
|
|
ws { goto opcode; }
|
2019-12-08 18:55:33 +00:00
|
|
|
ident / (ws|eof) {
|
2019-12-13 04:50:43 +00:00
|
|
|
label = std::string(iter, YYCURSOR);
|
2019-12-08 18:55:33 +00:00
|
|
|
goto opcode;
|
|
|
|
}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
opcode:
|
|
|
|
|
|
|
|
while (isspace(*YYCURSOR)) ++YYCURSOR;
|
|
|
|
iter = YYCURSOR;
|
|
|
|
|
|
|
|
/*!re2c
|
|
|
|
|
|
|
|
* { throw std::invalid_argument("bad opcode"); }
|
2019-12-13 04:50:43 +00:00
|
|
|
[;*]|eof { return; }
|
2019-12-08 18:55:33 +00:00
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
'=' / (ws|eof) { opcode = OP_EQ; goto operand; }
|
2019-12-08 18:55:33 +00:00
|
|
|
|
|
|
|
[A-Za-z]+ / (ws|eof) {
|
2019-12-13 04:50:43 +00:00
|
|
|
size_t l = YYCURSOR - iter;
|
2019-12-08 18:55:33 +00:00
|
|
|
if (l > 3) l = 3;
|
|
|
|
std::string s(iter, iter + l);
|
2019-12-13 04:50:43 +00:00
|
|
|
for (char &c : s) c = std::toupper(c);
|
|
|
|
auto iter = opcodes.find(s);
|
|
|
|
if (iter == opcodes.end()) {
|
2019-12-08 18:55:33 +00:00
|
|
|
throw std::invalid_argument("bad opcode");
|
|
|
|
}
|
2019-12-13 04:50:43 +00:00
|
|
|
opcode = iter->second;
|
2019-12-08 18:55:33 +00:00
|
|
|
goto operand;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
operand:
|
|
|
|
|
|
|
|
while (isspace(*YYCURSOR)) ++YYCURSOR;
|
|
|
|
iter = YYCURSOR;
|
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
|
|
|
|
switch(opcode) {
|
|
|
|
case OP_LNK:
|
|
|
|
case OP_PUT:
|
|
|
|
case OP_ASM:
|
|
|
|
case OP_SAV:
|
|
|
|
case OP_LIB:
|
|
|
|
case OP_IF:
|
|
|
|
case OP_PFX:
|
|
|
|
case OP_IMP:
|
|
|
|
case OP_RES:
|
|
|
|
case OP_FIL:
|
|
|
|
operand = path_operand(YYCURSOR);
|
2019-12-08 18:55:33 +00:00
|
|
|
break;
|
2019-12-13 04:50:43 +00:00
|
|
|
case OP_ORG:
|
|
|
|
case OP_ADR:
|
|
|
|
case OP_DS:
|
|
|
|
case OP_KND:
|
|
|
|
case OP_VER:
|
|
|
|
case OP_ALI:
|
|
|
|
case OP_LKV:
|
|
|
|
case OP_DO:
|
|
|
|
case OP_EQU:
|
|
|
|
case OP_EQ:
|
|
|
|
case OP_GEQ:
|
|
|
|
operand = number_operand(YYCURSOR);
|
2019-12-08 18:55:33 +00:00
|
|
|
break;
|
2019-12-13 04:50:43 +00:00
|
|
|
case OP_TYP:
|
|
|
|
operand = type_operand(YYCURSOR);
|
2019-12-08 18:55:33 +00:00
|
|
|
break;
|
2019-12-13 04:50:43 +00:00
|
|
|
case OP_OVR:
|
|
|
|
operand = ovr_operand(YYCURSOR);
|
2019-12-08 18:55:33 +00:00
|
|
|
break;
|
2019-12-13 04:50:43 +00:00
|
|
|
case OP_POS:
|
|
|
|
case OP_LEN: {
|
|
|
|
std::string tmp = label_operand(YYCURSOR, false);
|
|
|
|
if (!tmp.empty()) operand = std::move(tmp);
|
2019-12-08 18:55:33 +00:00
|
|
|
break;
|
2019-12-13 04:50:43 +00:00
|
|
|
}
|
|
|
|
case OP_KBD: {
|
|
|
|
std::string tmp = string_operand(YYCURSOR, false);
|
|
|
|
if (!tmp.empty()) operand = std::move(tmp);
|
2019-12-08 18:55:33 +00:00
|
|
|
break;
|
2019-12-13 04:50:43 +00:00
|
|
|
}
|
2019-12-08 18:55:33 +00:00
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
case OP_CMD:
|
|
|
|
str_operand = std::string(YYCURSOR);
|
2019-12-08 18:55:33 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
no_operand(YYCURSOR);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
void evaluate(label_t label, opcode_t opcode, operand_t operand);
|
2019-12-08 18:55:33 +00:00
|
|
|
|
2019-12-13 04:50:43 +00:00
|
|
|
evaluate(label, opcode, opcode);
|
2019-12-08 18:55:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|