Introduces shared mnemonics file. Adds assembler. Restructures makefile to build into bin/ folder.
This commit is contained in:
parent
5d1d274afd
commit
099e9da694
10 changed files with 2267 additions and 65 deletions
|
@ -1,14 +1,22 @@
|
|||
|
||||
CC = gcc
|
||||
|
||||
all: explink expdump
|
||||
all: explink expdump emulator as
|
||||
|
||||
explink: explink.c
|
||||
$(CC) -g $^ -o explink
|
||||
$(CC) -g -o bin/$@ $^
|
||||
|
||||
expdump: expdump.c
|
||||
$(CC) -g $^ -o expdump
|
||||
expdump: expdump.c mnemonics.c
|
||||
$(CC) -g -o bin/$@ $^
|
||||
|
||||
emulator: emulator.c vm.c
|
||||
$(CC) -g -o bin/$@ $^ -lSDL
|
||||
|
||||
as:
|
||||
make -C as
|
||||
|
||||
test: exp
|
||||
./exp -o test.exp $(ARGS)
|
||||
hexdump -C test.exp
|
||||
|
||||
.PHONY: as
|
12
libvm/as/Makefile
Normal file
12
libvm/as/Makefile
Normal file
|
@ -0,0 +1,12 @@
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
all: as
|
||||
|
||||
as: as.c tokens.c ../mnemonics.c
|
||||
gcc -g -o ../bin/$@ $^
|
||||
|
||||
tokens.c: tokens.y
|
||||
flex -o $@ tokens.y
|
241
libvm/as/as.c
Normal file
241
libvm/as/as.c
Normal file
|
@ -0,0 +1,241 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <getopt.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "tokens.h"
|
||||
#include "../vm.h"
|
||||
#include "../mnemonics.h"
|
||||
|
||||
struct llist
|
||||
{
|
||||
char name[128];
|
||||
uint32_t value;
|
||||
struct llist *next;
|
||||
};
|
||||
|
||||
typedef struct llist llist_t;
|
||||
|
||||
void list_insert(llist_t **list, const char *name, uint32_t value)
|
||||
{
|
||||
llist_t *item = malloc(sizeof(struct llist));
|
||||
strcpy(item->name, name);
|
||||
item->value = value;
|
||||
item->next = *list;
|
||||
*list = item;
|
||||
}
|
||||
|
||||
uint32_t list_find(llist_t **list, const char *name)
|
||||
{
|
||||
for(llist_t *it = *list; it != NULL; it = it->next)
|
||||
{
|
||||
if(strcmp(it->name, name) == 0) {
|
||||
return it->value;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void list_free(llist_t **list)
|
||||
{
|
||||
while((*list) != NULL)
|
||||
{
|
||||
llist_t *next = (*list)->next;
|
||||
free(*list);
|
||||
(*list) = next;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *output;
|
||||
|
||||
int listSymbols = 0;
|
||||
|
||||
// current token
|
||||
int tok;
|
||||
|
||||
void apply_modifiers(instruction_t *i)
|
||||
{
|
||||
while(tok == TOK_MOD)
|
||||
{
|
||||
printf("modifier, ");
|
||||
tok = yylex();
|
||||
}
|
||||
}
|
||||
|
||||
// line format:
|
||||
// TOK_LABEL? TOK_MOD* TOK_MNEMONIC TOK_MOD* ()? TOK_MOD* TOK_NEWLINE
|
||||
void assemble()
|
||||
{
|
||||
uint32_t index = 0;
|
||||
llist_t *labels = NULL;
|
||||
llist_t *patches = NULL;
|
||||
while(true)
|
||||
{
|
||||
tok = yylex();
|
||||
if(tok == TOK_EOF) {
|
||||
break;
|
||||
}
|
||||
if(tok == TOK_LABEL)
|
||||
{
|
||||
int len = strlen(yytext);
|
||||
yytext[len - 1] = '\0'; // remove colon
|
||||
|
||||
list_insert(&labels, yytext, index);
|
||||
|
||||
tok = yylex();
|
||||
}
|
||||
if(tok != TOK_NEWLINE)
|
||||
{
|
||||
instruction_t current = { 0 };
|
||||
|
||||
apply_modifiers(¤t);
|
||||
|
||||
if(tok != TOK_MNEMONIC)
|
||||
{
|
||||
fprintf(stderr, "Expected mnemonic!\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// Gather mnemonic to generate base instruction
|
||||
for(int i = 0; ; i++)
|
||||
{
|
||||
if(mnemonics[i].name == NULL) {
|
||||
fprintf(stderr, "Invalid mnemonic: %s\n", yytext);
|
||||
exit(1);
|
||||
}
|
||||
else if(strcmp(mnemonics[i].name, yytext) == 0) {
|
||||
current = mnemonics[i].instr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
tok = yylex();
|
||||
|
||||
apply_modifiers(¤t);
|
||||
|
||||
if(tok != TOK_NEWLINE)
|
||||
{
|
||||
switch(tok)
|
||||
{
|
||||
case TOK_INT:
|
||||
current.argument = (uint32_t)atoi(yytext);
|
||||
break;
|
||||
case TOK_HEX:
|
||||
current.argument = (uint32_t)strtol(yytext, NULL, 16);
|
||||
break;
|
||||
case TOK_CHAR:
|
||||
current.argument = (uint32_t)yytext[1];
|
||||
break;
|
||||
case TOK_REFERENCE:
|
||||
{
|
||||
// insert patch here for deferred argument modification
|
||||
// (yytext + 1) removes the leading @
|
||||
list_insert(&patches, yytext + 1, index);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Invalid token detected: %d\n", tok);
|
||||
exit(1);
|
||||
}
|
||||
tok = yylex();
|
||||
apply_modifiers(¤t);
|
||||
}
|
||||
if(tok != TOK_NEWLINE)
|
||||
{
|
||||
fprintf(stderr, "Invalid token detected: %d\n", tok);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// write command:
|
||||
fwrite(¤t, sizeof(instruction_t), 1, output);
|
||||
|
||||
// Increase command index by one
|
||||
index += 1;
|
||||
}
|
||||
printf("NEXT\n");
|
||||
}
|
||||
|
||||
if(listSymbols)
|
||||
{
|
||||
printf("Symbols:\n");
|
||||
for(llist_t *it = labels; it != NULL; it = it->next)
|
||||
{
|
||||
printf("%s@%d\n", it->name, it->value);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Patches:\n");
|
||||
for(llist_t *it = patches; it != NULL; it = it->next)
|
||||
{
|
||||
uint32_t target = list_find(&labels, it->name);
|
||||
|
||||
// Seek to the target address
|
||||
fseek(output, sizeof(instruction_t) * it->value + 4, SEEK_SET);
|
||||
fwrite(&target, 1, sizeof(uint32_t), output);
|
||||
|
||||
printf("%d -> %d (%s)\n", it->value, target, it->name);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
output = stdout;
|
||||
|
||||
int c;
|
||||
while ((c = getopt(argc, argv, "o:")) != -1)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 'o':
|
||||
{
|
||||
FILE *f = fopen(optarg, "wb");
|
||||
if(f == NULL) {
|
||||
fprintf(stderr, "%f not found.\n", optarg);
|
||||
abort();
|
||||
}
|
||||
if(output != stdout) {
|
||||
fclose(output);
|
||||
}
|
||||
output = f;
|
||||
break;
|
||||
}
|
||||
case '?':
|
||||
if (optopt == 'o')
|
||||
fprintf(stderr, "Option -%c requires an argument.\n", optopt);
|
||||
else if (isprint(optopt))
|
||||
fprintf(stderr, "Unknown option `-%c'.\n", optopt);
|
||||
else
|
||||
fprintf(stderr, "Unknown option character `\\x%02x'.\n", optopt);
|
||||
return 1;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
for (int index = optind; index < argc; index++)
|
||||
{
|
||||
FILE *f = fopen(argv[index], "r");
|
||||
if(f == NULL) {
|
||||
fprintf(stderr, "%f not found.\n", optarg);
|
||||
abort();
|
||||
}
|
||||
FILE *p = yyget_in();
|
||||
if(p != NULL && p != stdin) {
|
||||
fclose(p);
|
||||
}
|
||||
yyset_in(f);
|
||||
break;
|
||||
}
|
||||
|
||||
assemble();
|
||||
|
||||
FILE *p = yyget_in();
|
||||
if(p != NULL && p != stdin) {
|
||||
fclose(p);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
1835
libvm/as/tokens.c
Normal file
1835
libvm/as/tokens.c
Normal file
File diff suppressed because it is too large
Load diff
60
libvm/as/tokens.h
Normal file
60
libvm/as/tokens.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#define TOK_INVALID -1
|
||||
#define TOK_EOF 0
|
||||
#define TOK_INT 1
|
||||
#define TOK_HEX 2
|
||||
#define TOK_LABEL 3
|
||||
#define TOK_MNEMONIC 4
|
||||
#define TOK_MOD 5
|
||||
#define TOK_NEWLINE 6
|
||||
#define TOK_CHAR 7
|
||||
#define TOK_REFERENCE 8
|
||||
|
||||
|
||||
extern int yylineno;
|
||||
extern char *yytext;
|
||||
|
||||
/** Get the current line number.
|
||||
*
|
||||
*/
|
||||
int yyget_lineno (void);
|
||||
|
||||
/** Get the input stream.
|
||||
*
|
||||
*/
|
||||
FILE *yyget_in (void);
|
||||
|
||||
/** Get the output stream.
|
||||
*
|
||||
*/
|
||||
FILE *yyget_out (void);
|
||||
|
||||
/** Get the current token.
|
||||
*
|
||||
*/
|
||||
char *yyget_text (void);
|
||||
|
||||
/** Set the current line number.
|
||||
* @param _line_number line number
|
||||
*
|
||||
*/
|
||||
void yyset_lineno (int _line_number );
|
||||
|
||||
/** Set the input stream. This does not discard the current
|
||||
* input buffer.
|
||||
* @param _in_str A readable stream.
|
||||
*
|
||||
* @see yy_switch_to_buffer
|
||||
*/
|
||||
void yyset_in (FILE * _in_str );
|
||||
|
||||
void yyset_out (FILE * _out_str );
|
||||
|
||||
int yyget_debug (void);
|
||||
|
||||
void yyset_debug (int _bdebug );
|
||||
|
||||
int yylex();
|
32
libvm/as/tokens.y
Normal file
32
libvm/as/tokens.y
Normal file
|
@ -0,0 +1,32 @@
|
|||
%{
|
||||
#include "tokens.h"
|
||||
#define RETURN(x,y) /* fprintf(stderr, "{" #x "}" y ); */ return x
|
||||
%}
|
||||
comment ;[^\n]*
|
||||
whitespace [ \t]
|
||||
newline [\n]
|
||||
digit [0-9]
|
||||
hexdigit [0-9a-fA-F]
|
||||
intnum {digit}+
|
||||
hexnum "0x"{hexdigit}+
|
||||
mnemonic [a-zA-Z]+
|
||||
labelname [a-zA-Z0-9_]+
|
||||
label {labelname}":"
|
||||
mod \[[^\]]+\]
|
||||
character "'"."'"
|
||||
ref @{labelname}
|
||||
%%
|
||||
{comment} ;
|
||||
{hexnum} RETURN(TOK_HEX,);
|
||||
{intnum} RETURN(TOK_INT,);
|
||||
{whitespace} ;
|
||||
{mnemonic} RETURN(TOK_MNEMONIC,);
|
||||
{label} RETURN(TOK_LABEL,);
|
||||
{mod} RETURN(TOK_MOD,);
|
||||
{character} RETURN(TOK_CHAR, );
|
||||
{ref} RETURN(TOK_REFERENCE, );
|
||||
{newline} RETURN(TOK_NEWLINE, "\n");
|
||||
. RETURN(TOK_INVALID,);
|
||||
%%
|
||||
// This is the end of the file
|
||||
int yywrap() { return 1; }
|
|
@ -1,12 +1,14 @@
|
|||
#define _CRT_SECURE_NO_WARNINGS
|
||||
|
||||
#include <SDL.h>
|
||||
#include <stdbool.h>
|
||||
#include "vm.h"
|
||||
#include "exp.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <SDL.h>
|
||||
#undef main
|
||||
#else
|
||||
#include <SDL/SDL.h>
|
||||
#endif
|
||||
|
||||
bool running = true;
|
||||
|
@ -228,11 +230,13 @@ int main(int argc, char **argv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
FILE * __cdecl __iob_func(void)
|
||||
{
|
||||
static FILE iob[3];
|
||||
iob[0] = *stdin;
|
||||
iob[1] = *stdout;
|
||||
iob[2] = *stderr;
|
||||
return iob;
|
||||
}
|
||||
/*#if defined(_MSC_VER)*/
|
||||
/*FILE * __cdecl __iob_func(void)*/
|
||||
/*{*/
|
||||
/*static FILE iob[3];*/
|
||||
/*iob[0] = *stdin;*/
|
||||
/*iob[1] = *stdout;*/
|
||||
/*iob[2] = *stderr;*/
|
||||
/*return iob;*/
|
||||
/*}*/
|
||||
/*#endif*/
|
|
@ -22,54 +22,7 @@
|
|||
|
||||
#define DEBUG_VAL(x) fprintf(stderr, #x " = %d\n", x)
|
||||
|
||||
struct PredefinedCmd
|
||||
{
|
||||
const char *name;
|
||||
instruction_t instr;
|
||||
};
|
||||
|
||||
struct PredefinedCmd namedCommands[] =
|
||||
{
|
||||
{ "nop",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "push",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "drop",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "dup",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_PEEK, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "jmp",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_JUMP } },
|
||||
{ "jmpi",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_JUMP } },
|
||||
{ "ret",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_JUMP } },
|
||||
{ "load",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_LOAD, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "loadi",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_LOAD, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "store",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_POP, VM_CMD_STORE, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "storei",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_STORE, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "get",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_GET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "geti",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_GET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "set",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_POP, VM_CMD_SET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "seti",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_SET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "bpget",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_BPGET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "bpset",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_BPSET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "spget",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_SPGET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "spset",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_SPSET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "cpget",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_CPGET, 1, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "add",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "sub",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 1, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "cmp",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 1, VM_FLAG_YES, VM_OUTPUT_DISCARD } },
|
||||
{ "mul",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 2, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "div",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 3, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "mod",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 4, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "and",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 5, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "or",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 6, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "xor",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 7, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "not",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_MATH, 8, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "rol",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 9, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "ror",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 10, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "asl",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 11, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "asr",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 12, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "shl",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 13, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "shr",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 14, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "syscall",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_SYSCALL, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "hwio",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_HWIO, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
|
||||
};
|
||||
#include "mnemonics.h"
|
||||
|
||||
const char *commandStrings[] =
|
||||
{
|
||||
|
@ -112,12 +65,12 @@ void disassemble(instruction_t *list, uint32_t count, uint32_t base, FILE *f)
|
|||
|
||||
fprintf(f, "%8X: ", base + i);
|
||||
|
||||
struct PredefinedCmd *knownInstruction = NULL;
|
||||
const mnemonic_t *knownInstruction = NULL;
|
||||
|
||||
for (int j = 0; j < sizeof(namedCommands) / sizeof(struct PredefinedCmd); j++)
|
||||
for (int j = 0; mnemonics[j].name != NULL; j++)
|
||||
{
|
||||
if (memcmp(&instr, &namedCommands[j].instr, sizeof(instruction_t) - sizeof(uint32_t)) == 0) {
|
||||
knownInstruction = &namedCommands[j];
|
||||
if (memcmp(&instr, &mnemonics[j].instr, sizeof(instruction_t) - sizeof(uint32_t)) == 0) {
|
||||
knownInstruction = &mnemonics[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
44
libvm/mnemonics.c
Normal file
44
libvm/mnemonics.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
#include "mnemonics.h"
|
||||
|
||||
const mnemonic_t mnemonics[] =
|
||||
{
|
||||
{ "nop",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "push",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "drop",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "dup",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_PEEK, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "jmp",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_JUMP } },
|
||||
{ "jmpi",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_JUMP } },
|
||||
{ "ret",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_COPY, 0, VM_FLAG_NO, VM_OUTPUT_JUMP } },
|
||||
{ "load",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_LOAD, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "loadi",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_LOAD, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "store",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_POP, VM_CMD_STORE, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "storei",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_STORE, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "get",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_ZERO, VM_CMD_GET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "geti",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_GET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "set",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ARG, VM_INPUT_POP, VM_CMD_SET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "seti",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_SET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "bpget",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_BPGET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "bpset",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_BPSET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "spget",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_SPGET, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "spset",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_SPSET, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "cpget",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_CPGET, 1, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "add",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 0, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "sub",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 1, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "cmp",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 1, VM_FLAG_YES, VM_OUTPUT_DISCARD } },
|
||||
{ "mul",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 2, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "div",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 3, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "mod",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 4, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "and",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 5, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "or",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 6, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "xor",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 7, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "not",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_ZERO, VM_CMD_MATH, 8, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "rol",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 9, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "ror",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 10, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "asl",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 11, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "asr",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 12, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "shl",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 13, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "shr",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_POP, VM_INPUT_POP, VM_CMD_MATH, 14, VM_FLAG_NO, VM_OUTPUT_PUSH } },
|
||||
{ "syscall",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_SYSCALL, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ "hwio",{ VM_EXEC_X, VM_EXEC_X, VM_INPUT_ZERO, VM_INPUT_ZERO, VM_CMD_HWIO, 0, VM_FLAG_NO, VM_OUTPUT_DISCARD } },
|
||||
{ NULL, {0} }, // stop marker
|
||||
};
|
13
libvm/mnemonics.h
Normal file
13
libvm/mnemonics.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "vm.h"
|
||||
|
||||
struct mnemonic
|
||||
{
|
||||
const char *name;
|
||||
instruction_t instr;
|
||||
};
|
||||
|
||||
typedef struct mnemonic mnemonic_t;
|
||||
|
||||
extern const mnemonic_t mnemonics[];
|
Loading…
Reference in a new issue