From 3ce342b97b6c22b7ce6dded7be7b5c6bf9edcc04 Mon Sep 17 00:00:00 2001 From: Dimitar Trendafilov Date: Mon, 19 Nov 2018 23:49:15 +0200 Subject: Support for doubles in the assembler --- spasm/src/asm/assembler.cpp | 106 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 18 deletions(-) (limited to 'spasm/src/asm/assembler.cpp') 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); } } -- cgit v1.3.1-23-gd82d