Website Summary Files Commits Branches @commit @diff @stats
path: root / spasm / src / asm / assembler.cpp
diff options
context:
space:
mode:
1 files changed, 88 insertions, 18 deletions
-rw-r--r--spasm/src/asm/assembler.cpp106
diff --git a/spasm/src/asm/assembler.cpp b/spasm/src/asm/assembler.cpp
index aad2911..2ec988f 100644
--- a/spasm/src/asm/assembler.cpp
+++ b/spasm/src/asm/assembler.cpp
@@ -14,6 +14,54 @@ Assembler::Assembler(Lexer::Tokenizer& tokenizer, Bytecode_Stream& bytecode)
{
}
+int get_arg_size(const Lexer::Token args[])
+{
+ int size = 0;
+ for (int i = 0; i < 3; ++i)
+ {
+ switch (args[i].type())
+ {
+ case Lexer::Token::Integer:
+ case Lexer::Token::XInteger:
+ {
+ if (args[i].value_int() > 0xffffffff)
+ {
+ size = std::max(size, 3);
+ }
+ else if (args[i].value_int() > 0xffff)
+ {
+ size = std::max(size, 2);
+ }
+ else if (args[i].value_int() > 0xff)
+ {
+ size = std::max(size, 1);
+ }
+ else if (args[i].value_int() < -0xffffffffLL)
+ {
+ size = std::max(size, 3);
+ }
+ else if (args[i].value_int() < -0xffff)
+ {
+ size = std::max(size, 2);
+ }
+ else if (args[i].value_int() < -0xff)
+ {
+ size = std::max(size, 1);
+ }
+ break;
+ }
+ case Lexer::Token::FloatingPoint:
+ {
+ size = std::max(size, 3);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return size;
+}
+
void Assembler::assemble()
{
Lexer::Token token = _tokenizer->next_token();
@@ -39,42 +87,64 @@ void Assembler::assemble()
}
else
{
- _bytecode->push_opcode((Bytecode_Stream::Opcode_t)token.type());
+ Lexer::Token args[3];
if (type >= Lexer::Token::_OneArgBegin)
{
+ args[0] = _tokenizer->next_token();
+ }
+ if (type >= Lexer::Token::_TwoArgBegin)
+ {
+ args[1] = _tokenizer->next_token();
+ }
+ if (type >= Lexer::Token::_ThreeArgBegin)
+ {
+ args[2] = _tokenizer->next_token();
+ }
+ const auto size = get_arg_size(args);
+ _bytecode->push_opcode((Bytecode_Stream::Opcode_t)((size << 6) |
+ token.type()));
+ const auto arg_size = 1 << size;
+
+ if (args[0].type() != Lexer::Token::NotUsed)
+ {
if (type == Lexer::Token::Call || type == Lexer::Token::Jump)
{
- token = _tokenizer->next_token();
- assert(token.type() == Lexer::Token::Ident);
- assemble_identifier(token);
+ assert(args[0].type() == Lexer::Token::Ident);
+ assemble_identifier(args[0]);
}
else
{
- token = _tokenizer->next_token();
- assert(token.type() == Lexer::Token::Integer);
- _bytecode->push_integer(token.value_int());
+ assert(args[0].type() == Lexer::Token::Integer);
+ _bytecode->push_integer(args[0].value_int(), arg_size);
}
}
- if (type >= Lexer::Token::_TwoArgBegin)
+ if (args[1].type() != Lexer::Token::NotUsed)
{
if (type == Lexer::Token::JumpF || type == Lexer::Token::JumpT)
{
- token = _tokenizer->next_token();
- assert(token.type() == Lexer::Token::Ident);
- assemble_identifier(token);
+ assert(args[1].type() == Lexer::Token::Ident);
+ assemble_identifier(args[1]);
}
else
{
- token = _tokenizer->next_token();
- assert(token.type() == Lexer::Token::Integer);
- _bytecode->push_integer(token.value_int());
+ if (args[1].type() == Lexer::Token::Integer)
+ {
+ _bytecode->push_integer(args[1].value_int(), arg_size);
+ }
+ else if (args[1].type() == Lexer::Token::FloatingPoint)
+ {
+ _bytecode->push_double(args[1].value_double());
+ }
+ else
+ {
+ assert(false && "expected a number type");
+ }
}
}
- if (type >= Lexer::Token::_ThreeArgBegin)
+ if (args[2].type() != Lexer::Token::NotUsed)
{
- token = _tokenizer->next_token();
- assert(token.type() == Lexer::Token::Integer);
- _bytecode->push_integer(token.value_int());
+ assert(args[2].type() == Lexer::Token::Integer);
+ _bytecode->push_integer(args[2].value_int(), arg_size);
}
}