170 lines
4.7 KiB
C++
170 lines
4.7 KiB
C++
#include "externals.hh"
|
|
#include "control.hh"
|
|
#include "globals.hh"
|
|
#include "sync.hh"
|
|
|
|
using namespace ops;
|
|
using namespace ebcl;
|
|
|
|
|
|
/*= OPCODE INFORMATIONS ========================================================*/
|
|
|
|
namespace {
|
|
|
|
struct T_OpInfo
|
|
{
|
|
char const* name;
|
|
uint32_t nArgs;
|
|
int32_t sdMain{ 0 };
|
|
int32_t sdFPU{ 0 };
|
|
uint32_t fpuReq{ 0 };
|
|
|
|
template< typename ... Mods >
|
|
constexpr T_OpInfo( char const* name ,
|
|
uint32_t nArgs ,
|
|
Mods&&... mods );
|
|
|
|
constexpr T_OpInfo( char const* name );
|
|
};
|
|
|
|
|
|
template< typename ... Mods >
|
|
constexpr void ApplyMods_( T_OpInfo& op , Mods&&... mods );
|
|
|
|
template< >
|
|
constexpr void ApplyMods_( T_OpInfo& )
|
|
{ }
|
|
|
|
template< typename M0 , typename ... Mods >
|
|
constexpr void ApplyMods_(
|
|
T_OpInfo& op ,
|
|
M0&& mod ,
|
|
Mods&&... mods )
|
|
{
|
|
mod.applyTo( op );
|
|
ApplyMods_( op , std::forward< Mods >( mods ) ... );
|
|
}
|
|
|
|
template< typename ... Mods >
|
|
constexpr T_OpInfo::T_OpInfo(
|
|
char const* name ,
|
|
uint32_t nArgs ,
|
|
Mods&&... mods )
|
|
: name( name ) , nArgs( nArgs )
|
|
{
|
|
ApplyMods_( *this , std::forward< Mods >( mods ) ... );
|
|
}
|
|
|
|
constexpr T_OpInfo::T_OpInfo( char const* name )
|
|
: T_OpInfo( name , 0 )
|
|
{}
|
|
|
|
|
|
struct OpStackMain
|
|
{
|
|
int32_t value;
|
|
explicit constexpr OpStackMain( int32_t v ) : value( v ) { }
|
|
constexpr void applyTo( T_OpInfo& op )
|
|
{ op.sdMain = value; }
|
|
};
|
|
|
|
struct OpStackFPU
|
|
{
|
|
int32_t value;
|
|
explicit constexpr OpStackFPU( int32_t v ) : value( v ) { }
|
|
constexpr void applyTo( T_OpInfo& op )
|
|
{ op.sdFPU = value; }
|
|
};
|
|
|
|
|
|
static T_KeyValueTable< E_OpType , T_OpInfo > OpInfoTable_{ ([]() {
|
|
T_KeyValueTable< E_OpType , T_OpInfo > infos;
|
|
|
|
infos.add( E_OpType::OP_END , T_OpInfo{ "end" } );
|
|
//
|
|
infos.add( E_OpType::OP_CALL , T_OpInfo{ "call" , 1 } );
|
|
infos.add( E_OpType::OP_RET , T_OpInfo{ "ret" , 1 , OpStackMain{ -1 } } );
|
|
//
|
|
infos.add( E_OpType::OP_SKIP , T_OpInfo{ "skip" , 1 } );
|
|
infos.add( E_OpType::OP_COND_SKIP , T_OpInfo{ "cond-skip" , 2 } );
|
|
//
|
|
infos.add( E_OpType::OP_RES_STACK , T_OpInfo{ "res-stack" , 1 } );
|
|
infos.add( E_OpType::OP_PUSH , T_OpInfo{ "push" , 0 , OpStackMain{ 1 } } );
|
|
infos.add( E_OpType::OP_POP , T_OpInfo{ "pop" , 1 } );
|
|
//
|
|
infos.add( E_OpType::OP_LOAD , T_OpInfo{ "load" , 1 } );
|
|
infos.add( E_OpType::OP_SLOAD , T_OpInfo{ "load-stack" , 1 } );
|
|
//
|
|
infos.add( E_OpType::OP_FP_LOAD , T_OpInfo{ "fp-load" , 1 , OpStackFPU{ 1 } } );
|
|
infos.add( E_OpType::OP_FP_SLOAD , T_OpInfo{ "fp-load-stack" , 1 , OpStackFPU{ 1 } } );
|
|
infos.add( E_OpType::OP_FP_STORE , T_OpInfo{ "fp-store" , 1 , OpStackFPU{ -1 } } );
|
|
infos.add( E_OpType::OP_FP_SSTORE , T_OpInfo{ "fp-store-stack" , 1 , OpStackFPU{ -1 } } );
|
|
infos.add( E_OpType::OP_FP_SSTORE_INT , T_OpInfo{ "fp-store-stack-int" , 1 , OpStackFPU{ -1 } } );
|
|
//
|
|
infos.add( E_OpType::OP_FP_CMP , T_OpInfo{ "fp-cmp" , 1 , OpStackFPU{ -1 } } );
|
|
infos.add( E_OpType::OP_FP_ADD , T_OpInfo{ "fp-add" , 0 , OpStackFPU{ -1 } } );
|
|
infos.add( E_OpType::OP_FP_SUB , T_OpInfo{ "fp-sub" , 0 , OpStackFPU{ -1 } } );
|
|
infos.add( E_OpType::OP_FP_MUL , T_OpInfo{ "fp-mul" , 0 , OpStackFPU{ -1 } } );
|
|
infos.add( E_OpType::OP_FP_DIV , T_OpInfo{ "fp-div" , 0 , OpStackFPU{ -1 } } );
|
|
infos.add( E_OpType::OP_FP_MUL , T_OpInfo{ "fp-neg" , 0 } );
|
|
infos.add( E_OpType::OP_FP_DIV , T_OpInfo{ "fp-inv" , 0 } );
|
|
//
|
|
infos.add( E_OpType::OP_INIT_PIPELINE , T_OpInfo{ "pipeline" , 1 , OpStackMain{ -1 } } );
|
|
infos.add( E_OpType::OP_INIT_PROGRAM , T_OpInfo{ "program" , 1 , OpStackMain{ -1 } } );
|
|
infos.add( E_OpType::OP_INIT_TEXTURE , T_OpInfo{ "texture" , 2 , OpStackMain{ -3 } } );
|
|
//
|
|
infos.add( E_OpType::OP_FULLSCREEN , T_OpInfo{ "fullscreen" } );
|
|
infos.add( E_OpType::OP_CLEAR , T_OpInfo{ "clear" , 0 , OpStackMain{ -4 } } );
|
|
//
|
|
infos.add( E_OpType::OP_UI_PENTER , T_OpInfo{ "ui-prof-enter" , 1 } );
|
|
infos.add( E_OpType::OP_UI_PEXIT , T_OpInfo{ "ui-prof-exit" } );
|
|
|
|
return infos;
|
|
})( ) };
|
|
|
|
} // namespace
|
|
|
|
uint32_t ops::ArgumentsFor(
|
|
const E_OpType op ) noexcept
|
|
{
|
|
assert( OpInfoTable_.contains( op ) );
|
|
return OpInfoTable_.get( op )->nArgs;
|
|
}
|
|
|
|
int32_t ops::DeltaMainStack(
|
|
const E_OpType op ) noexcept
|
|
{
|
|
assert( OpInfoTable_.contains( op ) );
|
|
return OpInfoTable_.get( op )->sdMain;
|
|
}
|
|
|
|
int32_t ops::DeltaFPUStack(
|
|
const E_OpType op ) noexcept
|
|
{
|
|
assert( OpInfoTable_.contains( op ) );
|
|
return OpInfoTable_.get( op )->sdFPU;
|
|
}
|
|
|
|
|
|
/*= STRING FORMATTING ==========================================================*/
|
|
|
|
T_StringBuilder& ops::operator<<(
|
|
T_StringBuilder& sb ,
|
|
const E_OpType et )
|
|
{
|
|
assert( OpInfoTable_.contains( et ) );
|
|
sb << OpInfoTable_.get( et )->name;
|
|
return sb;
|
|
}
|
|
|
|
T_StringBuilder& ops::operator<<(
|
|
T_StringBuilder& sb ,
|
|
T_Op const& op )
|
|
{
|
|
sb << op.op;
|
|
const auto args{ OpInfoTable_.get( op.op )->nArgs };
|
|
for ( auto i = 0u ; i < args ; i ++ ) {
|
|
sb << ' ' << op.args[ i ];
|
|
}
|
|
return sb;
|
|
}
|