-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Ensure instruction set does not need to depend on architectures.
- Loading branch information
Showing
7 changed files
with
258 additions
and
70 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#ifndef EXAMPLES_BRAINFUCK_X64_CODE_GENERATOR_H | ||
#define EXAMPLES_BRAINFUCK_X64_CODE_GENERATOR_H | ||
|
||
#include "jasmin/compile/x64/function_emitter.h" | ||
#include "jasmin/compile/x64/location_map.h" | ||
#include "nth/meta/type.h" | ||
|
||
namespace bf { | ||
|
||
struct X64CodeGenerator { | ||
void operator()(decltype(nth::type<Initialize>), | ||
jasmin::x64::FunctionEmitter &gen, | ||
jasmin::LocationMap const &) { | ||
gen.write({0x48, 0x81, 0xec, 0x30, 0x75, 0x00, 0x00}); // sub rsp, 0x7530 | ||
gen.mov(jasmin::x64::Register::rsi, jasmin::x64::Register::rsp); | ||
gen.write({ | ||
0xba, 0x01, 0x00, 0x00, 0x00, // mov edx, 0x1 | ||
0x48, 0x89, 0xe7, // mov rdi, rsp | ||
0x31, 0xc0, // xor eax eax | ||
0x48, 0xc7, 0xc1, 0x30, 0x75, 0x00, 0x00, // mov rcx, 0x1000 | ||
0xf3, 0xaa, // rep stos BYTE PTR es:[rdi],al | ||
}); | ||
} | ||
|
||
void operator()(decltype(nth::type<Increment>), | ||
jasmin::x64::FunctionEmitter &gen, | ||
jasmin::LocationMap const &) { | ||
gen.write({0x80, 0x06, 0x01}); // add BYTE PTR [rsi], 0x1 | ||
} | ||
|
||
void operator()(decltype(nth::type<Decrement>), | ||
jasmin::x64::FunctionEmitter &gen, | ||
jasmin::LocationMap const &) { | ||
gen.write({0x80, 0x2e, 0x01}); // sub BYTE PTR [rsi], 0x1 | ||
} | ||
|
||
void operator()(decltype(nth::type<Left>), jasmin::x64::FunctionEmitter &gen, | ||
jasmin::LocationMap const &) { | ||
gen.write({0x48, 0x8d, 0x76, 0xff}); // lea rsi, [rsi - 1] | ||
} | ||
|
||
void operator()(decltype(nth::type<Right>), jasmin::x64::FunctionEmitter &gen, | ||
jasmin::LocationMap const &) { | ||
gen.write({0x48, 0x8d, 0x76, 0x01}); // lea rsi, [rsi + 1] | ||
} | ||
|
||
void operator()(decltype(nth::type<Output>), | ||
jasmin::x64::FunctionEmitter &gen, | ||
jasmin::LocationMap const &) { | ||
gen.write({ | ||
0x48, 0xc7, 0xc0, 0x01, 0x00, 0x00, 0x00, // mov rax, 0x1 | ||
0x48, 0xc7, 0xc7, 0x01, 0x00, 0x00, 0x00, // mov rdi, 0x1 | ||
0x48, 0xc7, 0xc2, 0x01, 0x00, 0x00, 0x00, // mov rdx, 0x1 | ||
}); | ||
gen.syscall(); | ||
} | ||
|
||
void operator()(decltype(nth::type<Input>), jasmin::x64::FunctionEmitter &gen, | ||
jasmin::LocationMap const &) { | ||
gen.write({ | ||
0x48, 0xc7, 0xc0, 0x00, 0x00, 0x00, 0x00, // mov rax, 0x0 | ||
0x48, 0xc7, 0xc7, 0x00, 0x00, 0x00, 0x00, // mov rdi, 0x0 | ||
0x48, 0xc7, 0xc2, 0x01, 0x00, 0x00, 0x00, // mov rdx, 0x1 | ||
}); | ||
gen.syscall(); | ||
} | ||
|
||
void operator()(decltype(nth::type<Zero>), jasmin::x64::FunctionEmitter &gen, | ||
jasmin::LocationMap const &) { | ||
gen.write({0x8a, 0x06}); // mov al, BYTE PTR [rsi] | ||
} | ||
}; | ||
|
||
} // namespace bf | ||
|
||
#endif // EXAMPLES_BRAINFUCK_X64_CODE_GENERATOR_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
#include "jasmin/compile/x64/function_emitter.h" | ||
|
||
namespace jasmin::x64 { | ||
|
||
void FunctionEmitter::write(std::initializer_list<uint8_t> instructions) { | ||
fn_->write(instructions); | ||
} | ||
|
||
void FunctionEmitter::push(Register reg) { | ||
write({static_cast<uint8_t>(static_cast<uint8_t>(reg) + 0x50)}); | ||
} | ||
|
||
void FunctionEmitter::pop(Register reg) { | ||
write({static_cast<uint8_t>(static_cast<uint8_t>(reg) + 0x58)}); | ||
} | ||
|
||
void FunctionEmitter::mov(Register destination, Register source) { | ||
write({0x48, 0x89, | ||
static_cast<uint8_t>(0xc0 + static_cast<uint8_t>(destination) + | ||
8 * static_cast<uint8_t>(source))}); | ||
} | ||
|
||
void FunctionEmitter::syscall() { write({0x0f, 0x05}); } | ||
|
||
void FunctionEmitter::ret() { write({0xc3}); } | ||
|
||
void FunctionEmitter::emit(SsaFunction const &fn, CompiledFunction &c) { | ||
fn_ = &c; | ||
push(Register::rbp); | ||
mov(Register::rbp, Register::rsp); | ||
|
||
block_starts_.reserve(fn.blocks().size()); | ||
LocationMap loc_map; | ||
for (auto const &block : fn.blocks()) { | ||
block_starts_.push_back(fn_->size()); | ||
for (auto const &inst : block.instructions()) { | ||
generators_[metadata_.opcode(inst.op_code())](generator_, *this, loc_map); | ||
} | ||
switch (block.branch().kind()) { | ||
case SsaBranchKind::Return: | ||
mov(Register::rsp, Register::rbp); | ||
pop(Register::rbp); | ||
ret(); | ||
break; | ||
case SsaBranchKind::Conditional: { | ||
auto const &c = block.branch().AsConditional(); | ||
// TODO: Support arbirtary register choices here. | ||
// TODO: Prefer fallthroughs when we can make that happen. | ||
write({ | ||
0x84, 0xc0, // test al, al | ||
0x0f, 0x84, 0x00, 0x00, 0x00, 0x00, // jz __ | ||
}); | ||
block_jumps_.emplace(fn_->size(), c.true_block); | ||
write({ | ||
0xe9, 0x00, 0x00, 0x00, 0x00, // jmp ___ | ||
}); | ||
block_jumps_.emplace(fn_->size(), c.false_block); | ||
} break; | ||
case SsaBranchKind::Unconditional: { | ||
NTH_UNIMPLEMENTED(); | ||
} break; | ||
case SsaBranchKind::Unreachable: break; | ||
} | ||
} | ||
|
||
for (auto const &[offset, block_number] : block_jumps_) { | ||
fn_->write_at(offset - 4, | ||
static_cast<uint32_t>(block_starts_[block_number] - offset)); | ||
} | ||
|
||
fn_ = nullptr; | ||
} | ||
|
||
} // namespace jasmin::x64 |
Oops, something went wrong.