Browse Source

[WIP]

master
Eyck Jentzsch 1 month ago
parent
commit
0e06499aa6
4 changed files with 193 additions and 123 deletions
  1. +1
    -0
      CMakeLists.txt
  2. +57
    -20
      incl/iss/tcc/code_builder.h
  3. +0
    -103
      src/llvm_vm_base.cpp
  4. +135
    -0
      src/vm_base.cpp

+ 1
- 0
CMakeLists.txt View File

@@ -19,6 +19,7 @@ endif()
set(LIB_SOURCES
src/dbgsrvbase.cpp
src/gdb_session.cpp
src/vm_base.cpp
src/tcc_jit_helper.cpp
src/cmdhandler.cpp
src/target_adapter_base.cpp


+ 57
- 20
incl/iss/tcc/code_builder.h View File

@@ -14,7 +14,7 @@ struct value {
void set_signed(bool v){if(v) type|=0x100; else type&=0xff;}
unsigned size() const { return type&0xff;}
void set_size(unsigned s){ type = (type&0xff00)+(s&0xff);}
value(std::string const& s, unsigned size, bool sig):str(s), type((sig?0x100:0)+(size&0xff)){}
value(std::string const& s, unsigned size, bool sig = false):str(s), type((sig?0x100:0)+(size&0xff)){}
value() = delete;
value(value const&) = default;
value(value&&) = default;
@@ -70,6 +70,33 @@ struct code_builder {
os<<"extern void pre_instr_sync(void*);\n";
os<<"extern void notify_phase(void*, uint32_t);\n";
os<<"extern void call_plugin(void*, uint64_t) ;\n";
os<<"extern uint32_t fget_flags();\n";
os<<"extern uint32_t fadd_s(uint32_t v1, uint32_t v2, uint8_t mode);\n";
os<<"extern uint32_t fsub_s(uint32_t v1, uint32_t v2, uint8_t mode);\n";
os<<"extern uint32_t fmul_s(uint32_t v1, uint32_t v2, uint8_t mode);\n";
os<<"extern uint32_t fdiv_s(uint32_t v1, uint32_t v2, uint8_t mode);\n";
os<<"extern uint32_t fsqrt_s(uint32_t v1, uint8_t mode);\n";
os<<"extern uint32_t fcmp_s(uint32_t v1, uint32_t v2, uint32_t op) ;\n";
os<<"extern uint32_t fcvt_s(uint32_t v1, uint32_t op, uint8_t mode);\n";
os<<"extern uint32_t fmadd_s(uint32_t v1, uint32_t v2, uint32_t v3, uint32_t op, uint8_t mode);\n";
os<<"extern uint32_t fsel_s(uint32_t v1, uint32_t v2, uint32_t op);\n";
os<<"extern uint32_t fclass_s( uint32_t v1 );\n";
os<<"extern uint32_t fconv_d2f(uint64_t v1, uint8_t mode);\n";
os<<"extern uint64_t fconv_f2d(uint32_t v1, uint8_t mode);\n";
os<<"extern uint64_t fadd_d(uint64_t v1, uint64_t v2, uint8_t mode);\n";
os<<"extern uint64_t fsub_d(uint64_t v1, uint64_t v2, uint8_t mode);\n";
os<<"extern uint64_t fmul_d(uint64_t v1, uint64_t v2, uint8_t mode);\n";
os<<"extern uint64_t fdiv_d(uint64_t v1, uint64_t v2, uint8_t mode);\n";
os<<"extern uint64_t fsqrt_d(uint64_t v1, uint8_t mode);\n";
os<<"extern uint64_t fcmp_d(uint64_t v1, uint64_t v2, uint32_t op);\n";
os<<"extern uint64_t fcvt_d(uint64_t v1, uint32_t op, uint8_t mode);\n";
os<<"extern uint64_t fmadd_d(uint64_t v1, uint64_t v2, uint64_t v3, uint32_t op, uint8_t mode);\n";
os<<"extern uint64_t fsel_d(uint64_t v1, uint64_t v2, uint32_t op) ;\n";
os<<"extern uint64_t fclass_d(uint64_t v1 );\n";
os<<"extern uint64_t fcvt_32_64(uint32_t v1, uint32_t op, uint8_t mode);\n";
os<<"extern uint32_t fcvt_64_32(uint64_t v1, uint32_t op, uint8_t mode);\n";
os<<"extern uint32_t unbox_s(uint64_t v);\n";

//os<<fmt::format("typedef uint{}_t reg_t;\n", arch::traits<ARCH>::XLEN);
os<<fmt::format("uint64_t {}(uint8_t* regs_ptr, void* core_ptr, void* vm_ptr) __attribute__ ((regnum(3))) {{\n", fname);
os<<add_reg_ptr("pc", arch::traits<ARCH>::PC);
@@ -107,12 +134,12 @@ struct code_builder {

template <typename T, typename std::enable_if<std::is_signed<T>::value>::type* = nullptr>
inline value constant(T val, unsigned size) const {
return value(fmt::format("{}", val), sizeof(T)*4, true);
return value(fmt::format("{}", val), size/*of(T)*4*/, true);
}

template <typename T, typename std::enable_if<std::is_unsigned<T>::value>::type* = nullptr>
inline value constant(T val, unsigned size) const {
return value(fmt::format("{}U", val), sizeof(T)*4, false);
return value(fmt::format("{}U", val), size/*of(T)*4*/, false);
}


@@ -134,7 +161,11 @@ struct code_builder {
return value(fmt::format("(uint{}_t)({})", size, val), size, false);
}
else
return val;
if(val.size() != size){
return value(fmt::format("(uint{}_t)({})", size, val), size, false);
} else {
return val;
}
} else {
if(!val.is_signed())
if( val.size() != size){
@@ -143,11 +174,15 @@ struct code_builder {
return value(fmt::format("(int{}_t)({})", size, val), size, true);
}
else
return val;
if(val.size() != size){
return value(fmt::format("(int{}_t)({})", size, val), size, false);
} else {
return val;
}
}
}

inline value assignment(std::string const& name, value const& val, unsigned width = 0){
inline value assignment(std::string const& name, value const& val, unsigned width){
if(width==0) width=val.size();
if(width==1){
lines.push_back(fmt::format("bool {} = {};", name, val));
@@ -158,6 +193,10 @@ struct code_builder {
}
}

inline value assignment(value const& val, unsigned width){
return assignment(fmt::format("tmp{}", lines.size()), val, width);
}

inline value store(value const& val, unsigned reg_num){
switch(reg_num){
case arch::traits<ARCH>::NEXT_PC:
@@ -217,7 +256,7 @@ struct code_builder {
}

inline value mul(value const & left, value const & right){
return value(fmt::format("({}) * ({})", left, right), left.size()+right.size(),
return value(fmt::format("({}) * ({})", left, right), std::max(left.size(), right.size()),
left.is_signed() && right.is_signed());
}

@@ -232,14 +271,12 @@ struct code_builder {
}

inline value srem(value const & left, value const & right){
//TODO: implement
return value(fmt::format("({}) / ({})", left, right), std::max(left.size(), right.size()),
return value(fmt::format("({}) % ({})", left, right), std::max(left.size(), right.size()),
left.is_signed() && right.is_signed());
}

inline value urem(value const & left, value const & right){
//TODO: implement
return value(fmt::format("({}) / ({})", left, right), std::max(left.size(), right.size()),
return value(fmt::format("({}) % ({})", left, right), std::max(left.size(), right.size()),
left.is_signed() && right.is_signed());
}

@@ -275,7 +312,7 @@ struct code_builder {
}

inline value neg(value const & left){
return value(fmt::format("-({})", left), 1, false);
return value(fmt::format("-({})", left), left.size(), false);
}

inline value shl(value const & val,value const & shift){
@@ -403,25 +440,25 @@ struct code_builder {
}
}

template <typename Arg, typename... Args>
inline value callf(std::string const& fn, Arg v1, Args... vals){
return {fmt::format("{}({},{},{},{},{})", fn, collect_args(vals...)), v1.size(), v1.is_signed()};
inline value callf(std::string const& fn){
return {fmt::format("{}()", fn), 32, false};
}

inline value callf(std::string const& fn, value v1){
return {fmt::format("{}({})", fn, v1), v1.size(), v1.is_signed()};
}

inline value callf(std::string const& fn){
return {fmt::format("{}()", fn), 32, false};
template <typename Arg, typename... Args>
inline value callf(std::string const& fn, Arg const& v1, Args const&... vals){
return {fmt::format("{}({})", fn, collect_args(v1, vals...)), v1.size(), v1.is_signed()};
}

inline std::string collect_args(value v) {
inline std::string collect_args(value const& v) {
return v.str;
}

template <typename Arg, typename... Args>
inline std::string collect_args(Arg&& arg, Args&&... args) {
inline std::string collect_args(Arg const& arg, Args const&... args) {
return fmt::format("{}, {}", arg, collect_args(args...));
}
};
@@ -440,6 +477,6 @@ struct fmt::formatter<iss::tcc::value>

template<typename FormatContext>
auto format(iss::tcc::value const& value, FormatContext& ctx) -> decltype(ctx.out()){
return fmt::format_to(ctx.out(), "{}", value);
return fmt::format_to(ctx.out(), "{}", value.str);
}
};

+ 0
- 103
src/llvm_vm_base.cpp View File

@@ -96,106 +96,3 @@ void add_functions_2_module(Module *mod) {
}
}
}


#include <iss/arch_if.h>
#include <iss/iss.h>
#include <util/logging.h>

using namespace iss;
//using this_t = uint8_t *;
using arch_if_ptr_t = arch_if *;
using vm_if_ptr_t = vm_if *;
using vm_plugin_ptr_t = vm_plugin *;

extern "C" {

uint8_t fetch(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
return iface->read((address_type)addr_type, access_type::FETCH, (uint16_t)space, addr, length, data);
}

uint8_t fetch_dbg(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
return iface->read((address_type)addr_type, access_type::DEBUG_FETCH, (uint16_t)space, addr, length, data);
}

uint8_t read_mem(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
return iface->read((address_type)addr_type, access_type::READ, (uint16_t)space, addr, length, data);
}

uint8_t write_mem(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
#ifdef EXEC_LOGGING
LOG(TRACE) << "EXEC: write mem " << (unsigned)type << " of core " << iface << " at addr 0x" << hex << addr
<< " with value 0x" << data << dec << " of len " << length;
#endif
return iface->write((address_type)addr_type, access_type::WRITE, (uint16_t)space, addr, length, data);
}

uint8_t read_mem_dbg(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
return iface->read((address_type)addr_type, access_type::DEBUG_READ, (uint16_t)space, addr, length, data);
}

uint8_t write_mem_dbg(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
return iface->write((address_type)addr_type, access_type::DEBUG_WRITE, (uint16_t)space, addr, length, data);
}

uint64_t enter_trap(arch_if_ptr_t iface, uint64_t flags, uint64_t addr) {
return iface->enter_trap(flags, addr);
}

uint64_t leave_trap(arch_if_ptr_t iface, uint64_t flags) { return iface->leave_trap(flags); }

void wait(arch_if_ptr_t iface, uint64_t flags) { iface->wait_until(flags); }

void print_string(arch_if_ptr_t iface, char *str) { LOG(DEBUG) << "[EXEC] " << str; }

void print_disass(arch_if_ptr_t iface, uint64_t pc, char *str) { iface->disass_output(pc, str); }

void pre_instr_sync(vm_if_ptr_t iface) { iface->pre_instr_sync(); }

void notify_phase(arch_if_ptr_t iface, uint32_t phase) {
iface->notify_phase((arch_if::exec_phase)phase);
}

void call_plugin(vm_plugin_ptr_t iface, uint64_t instr_info) {
iface->callback(instr_info_t(instr_info));
}

uint8_t read_mem1(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr) {
uint8_t buf;
iface->read((address_type)addr_type, access_type::READ, (uint16_t)space, addr, 1, &buf);
return buf;
}

uint16_t read_mem2(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr) {
uint16_t buf;
iface->read((address_type)addr_type, access_type::READ, (uint16_t)space, addr, 2, reinterpret_cast<uint8_t*>(&buf));
return buf;
}

uint32_t read_mem4(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr) {
uint32_t buf;
iface->read((address_type)addr_type, access_type::READ, (uint16_t)space, addr, 4, reinterpret_cast<uint8_t*>(&buf));
return buf;
}


uint64_t read_mem8(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr) {
uint64_t buf;
iface->read((address_type)addr_type, access_type::READ, (uint16_t)space, addr, 8, reinterpret_cast<uint8_t*>(&buf));
return buf;
}

void write_mem1(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint8_t data) {
iface->write((address_type)addr_type, access_type::WRITE, (uint16_t)space, addr, 1, reinterpret_cast<uint8_t*>(&data));
}

void write_mem2(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint16_t data) {
iface->write((address_type)addr_type, access_type::WRITE, (uint16_t)space, addr, 2, reinterpret_cast<uint8_t*>(&data));
}
void write_mem4(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t data) {
iface->write((address_type)addr_type, access_type::WRITE, (uint16_t)space, addr, 4, reinterpret_cast<uint8_t*>(&data));
}
void write_mem8(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint64_t data) {
iface->write((address_type)addr_type, access_type::WRITE, (uint16_t)space, addr, 8, reinterpret_cast<uint8_t*>(&data));
}
}

+ 135
- 0
src/vm_base.cpp View File

@@ -0,0 +1,135 @@
/*******************************************************************************
* Copyright (C) 2017, 2020, MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* Contributors:
* eyck@minres.com - initial API and implementation
******************************************************************************/

#include <iss/arch_if.h>
#include <iss/iss.h>
#include <iss/vm_if.h>
#include <iss/vm_plugin.h>
#include <util/logging.h>

using namespace iss;
using arch_if_ptr_t = arch_if *;
using vm_if_ptr_t = vm_if *;
using vm_plugin_ptr_t = vm_plugin *;

extern "C" {

uint8_t fetch(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
return iface->read((address_type)addr_type, access_type::FETCH, (uint16_t)space, addr, length, data);
}

uint8_t fetch_dbg(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
return iface->read((address_type)addr_type, access_type::DEBUG_FETCH, (uint16_t)space, addr, length, data);
}

uint8_t read_mem(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
return iface->read((address_type)addr_type, access_type::READ, (uint16_t)space, addr, length, data);
}

uint8_t write_mem(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
#ifdef EXEC_LOGGING
LOG(TRACE) << "EXEC: write mem " << (unsigned)type << " of core " << iface << " at addr 0x" << hex << addr
<< " with value 0x" << data << dec << " of len " << length;
#endif
return iface->write((address_type)addr_type, access_type::WRITE, (uint16_t)space, addr, length, data);
}

uint8_t read_mem_dbg(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
return iface->read((address_type)addr_type, access_type::DEBUG_READ, (uint16_t)space, addr, length, data);
}

uint8_t write_mem_dbg(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t length, uint8_t *data) {
return iface->write((address_type)addr_type, access_type::DEBUG_WRITE, (uint16_t)space, addr, length, data);
}

uint64_t enter_trap(arch_if_ptr_t iface, uint64_t flags, uint64_t addr) {
return iface->enter_trap(flags, addr);
}

uint64_t leave_trap(arch_if_ptr_t iface, uint64_t flags) { return iface->leave_trap(flags); }

void wait(arch_if_ptr_t iface, uint64_t flags) { iface->wait_until(flags); }

void print_string(arch_if_ptr_t iface, char *str) { LOG(DEBUG) << "[EXEC] " << str; }

void print_disass(arch_if_ptr_t iface, uint64_t pc, char *str) { iface->disass_output(pc, str); }

void pre_instr_sync(vm_if_ptr_t iface) { iface->pre_instr_sync(); }

void notify_phase(arch_if_ptr_t iface, uint32_t phase) {
iface->notify_phase((arch_if::exec_phase)phase);
}

void call_plugin(vm_plugin_ptr_t iface, uint64_t instr_info) {
iface->callback(instr_info_t(instr_info));
}

uint8_t read_mem1(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr) {
uint8_t buf;
iface->read((address_type)addr_type, access_type::READ, (uint16_t)space, addr, 1, &buf);
return buf;
}

uint16_t read_mem2(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr) {
uint16_t buf;
iface->read((address_type)addr_type, access_type::READ, (uint16_t)space, addr, 2, reinterpret_cast<uint8_t*>(&buf));
return buf;
}

uint32_t read_mem4(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr) {
uint32_t buf;
iface->read((address_type)addr_type, access_type::READ, (uint16_t)space, addr, 4, reinterpret_cast<uint8_t*>(&buf));
return buf;
}


uint64_t read_mem8(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr) {
uint64_t buf;
iface->read((address_type)addr_type, access_type::READ, (uint16_t)space, addr, 8, reinterpret_cast<uint8_t*>(&buf));
return buf;
}

void write_mem1(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint8_t data) {
iface->write((address_type)addr_type, access_type::WRITE, (uint16_t)space, addr, 1, reinterpret_cast<uint8_t*>(&data));
}

void write_mem2(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint16_t data) {
iface->write((address_type)addr_type, access_type::WRITE, (uint16_t)space, addr, 2, reinterpret_cast<uint8_t*>(&data));
}
void write_mem4(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint32_t data) {
iface->write((address_type)addr_type, access_type::WRITE, (uint16_t)space, addr, 4, reinterpret_cast<uint8_t*>(&data));
}
void write_mem8(arch_if_ptr_t iface, uint32_t addr_type, uint32_t space, uint64_t addr, uint64_t data) {
iface->write((address_type)addr_type, access_type::WRITE, (uint16_t)space, addr, 8, reinterpret_cast<uint8_t*>(&data));
}
}

Loading…
Cancel
Save