C++プログラマのためのアセンブラ入門(続き)
(一記事のサイズ制限を越えてしまうようなので分割。前回の続き)
情報処理の試験で使う casl 2 と comet 2 を実装してみましょう
実装例
#if defined( _MSC_VER ) // C4351 : 新しい動作: 配列 '%1' の要素は既定で初期化されます // C4917 : 'identifier' : GUID はクラス、インターフェイスまたは名前空間のみに関連付けることができます。 // C4571 : catch(...) の意味が Visual C++ 7.1 から変更されています。構造化例外 (SEH) はキャッチされません。 // C4514 : 'function' : 参照されていないインライン関数は削除されました。 // C4710 : 'function' : インライン関数ではありません。 #pragma warning( disable : 4351 4917 4571 4514 4710 ) #include <windows.h> #endif // _MSC_VER #include <stdio.h> #include <stdarg.h> #include <vector> #include <algorithm> #define elementsizeof( a ) sizeof((a)[0]) #define elementsof( a ) (sizeof((a))/elementsizeof((a))) typedef signed char signed_int8_t; typedef unsigned char unsigned_int8_t; typedef signed short signed_int16_t; typedef unsigned short unsigned_int16_t; typedef signed int signed_int32_t; typedef unsigned int unsigned_int32_t; template<typename T> struct is_pointer { static const bool value = false; }; template<typename T> struct is_pointer<T*> { static const bool value = true; }; template<typename T> struct is_pointer<const T*> { static const bool value = true; }; template<typename T> struct is_integral { static const bool value = false; }; template<> struct is_integral<signed_int16_t> { static const bool value = true; }; template<> struct is_integral<unsigned_int16_t> { static const bool value = true; }; //template<> struct is_integral<int> { // static const bool value = true; //}; template<typename T> struct is_int16 { static const bool value = false; }; template<> struct is_int16<signed_int16_t> { static const bool value = true; }; template<> struct is_int16<unsigned_int16_t> { static const bool value = true; }; template<typename T> struct is_int32 { static const bool value = false; }; template<> struct is_int32<signed_int32_t> { static const bool value = true; }; template<> struct is_int32<unsigned_int32_t> { static const bool value = true; }; template<typename lhs, typename rhs> struct is_same { static const bool value = false; }; template<typename T> struct is_same<T,T> { static const bool value = true; }; struct enable_if_result_t {}; template<bool _conditional_value, typename _result_type = enable_if_result_t> struct enable_if_helper_t {}; template<typename _result_type> struct enable_if_helper_t<true,_result_type> { typedef _result_type type; }; template<bool _conditional_value, typename _result_type = enable_if_result_t> struct enable_if : public enable_if_helper_t<_conditional_value,_result_type> {}; enable_if_result_t* enabler = NULL; union union_int16_t { unsigned_int16_t x; unsigned_int8_t h[2]; }; union union_int32_t { unsigned_int32_t e; unsigned_int16_t x[2]; unsigned_int8_t h[4]; }; enum register16_type { register16_type_gr0, register16_type_gr1, register16_type_gr2, register16_type_gr3, register16_type_gr4, register16_type_gr5, register16_type_gr6, register16_type_gr7, register16_type_sp, register16_type_pr, register16_type_fr, register16_types }; struct register16_t { typedef unsigned_int16_t value_type; protected: register16_type m_type; value_type m_value; value_type :16; public: register16_type type() const { return m_type; } register16_t& operator=( value_type rhs ){ m_value = rhs; return *this; } operator const value_type&() const { return m_value; } operator value_type&(){ return m_value; } explicit register16_t( register16_type type ): m_type(type), m_value() { } register16_t& operator=( const register16_t& rhs ){ if( this != &rhs ){ m_value = rhs.m_value; } return *this; } // レジスタは必ずタイプを指定する register16_t() = delete; // レジスタをコピーして実体を作ることはない register16_t( const register16_t& rhs ) = delete; // レジスタを移動して実体を作ることはない register16_t( register16_t&& rhs ) = delete; // レジスタを移動することはない register16_t& operator=( register16_t&& rhs ) = delete; }; #define opcode_nop 0x00 #define opcode_ld 0x10 #define opcode_st 0x11 #define opcode_lad 0x12 #define opcode_adda 0x20 #define opcode_addl 0x21 #define opcode_suba 0x22 #define opcode_subl 0x23 #define opcode_and 0x30 #define opcode_or 0x31 #define opcode_xor 0x32 #define opcode_cpa 0x40 #define opcode_cpl 0x41 #define opcode_sla 0x50 #define opcode_sra 0x51 #define opcode_sll 0x52 #define opcode_srl 0x53 #define opcode_jmi 0x61 #define opcode_jnz 0x62 #define opcode_jne 0x63 #define opcode_jump 0x64 #define opcode_jpl 0x65 #define opcode_jov 0x66 #define opcode_push 0x70 #define opcode_pop 0x71 #define opcode_call 0x80 #define opcode_ret 0x81 #define opcode_1 0x04 // 新しい形式: mnemonic r1, r2 #define opcodes 256 #define COMET2OP_BITSIZEOF_OPCODE 8 #define COMET2OP_BITSIZEOF_GR 4 #define COMET2OP_BITSIZEOF_XR 4 #define COMET2OP_BITSIZEOF_ADDRESS 16 #define COMET2OP16_BITOFFSETOF_OPCODE (COMET2OP_BITSIZEOF_XR+COMET2OP_BITSIZEOF_GR) #define COMET2OP16_BITOFFSETOF_GR (COMET2OP_BITSIZEOF_XR) #define COMET2OP16_BITOFFSETOF_XR 0 #define COMET2OP16_GET_OPCODE( op ) (((op)>>COMET2OP16_BITOFFSETOF_OPCODE) & ((1<<COMET2OP_BITSIZEOF_OPCODE)-1)) #define COMET2OP16_GET_GR( op ) (((op)>>COMET2OP16_BITOFFSETOF_GR) & ((1<<COMET2OP_BITSIZEOF_GR)-1)) #define COMET2OP16_GET_XR( op ) (((op)>>COMET2OP16_BITOFFSETOF_XR) & ((1<<COMET2OP_BITSIZEOF_XR)-1)) #define COMET2OP16_MAKE( opcode, gr, xr ) (static_cast<unsigned_int16_t>(((opcode)<<COMET2OP16_BITOFFSETOF_OPCODE)|((gr)<<COMET2OP16_BITOFFSETOF_GR)|((xr)<<COMET2OP16_BITOFFSETOF_XR))) #define COMET2OP32_BITOFFSETOF_OPCODE COMET2OP16_BITOFFSETOF_OPCODE #define COMET2OP32_BITOFFSETOF_GR COMET2OP16_BITOFFSETOF_GR #define COMET2OP32_BITOFFSETOF_XR COMET2OP16_BITOFFSETOF_XR #define COMET2OP32_BITOFFSETOF_ADDRESS (COMET2OP32_BITOFFSETOF_OPCODE+COMET2OP_BITSIZEOF_OPCODE) #define COMET2OP32_MAKE( opcode, gr, xr, addr ) (((opcode)<<COMET2OP32_BITOFFSETOF_OPCODE)|((gr)<<COMET2OP32_BITOFFSETOF_GR)|((xr)<<COMET2OP32_BITOFFSETOF_XR)|((addr)<<COMET2OP32_BITOFFSETOF_ADDRESS)) #define COMET2OP32_GET_OPCODE( op ) (((op)>>COMET2OP32_BITOFFSETOF_OPCODE) & ((1<<COMET2OP_BITSIZEOF_OPCODE)-1)) #define COMET2OP32_GET_GR( op ) (((op)>>COMET2OP32_BITOFFSETOF_GR) & ((1<<COMET2OP_BITSIZEOF_GR)-1)) #define COMET2OP32_GET_XR( op ) (((op)>>COMET2OP32_BITOFFSETOF_XR) & ((1<<COMET2OP_BITSIZEOF_XR)-1)) #define COMET2OP32_GET_ADDRESS( op ) (static_cast<unsigned_int32_t>(((op)>>COMET2OP32_BITOFFSETOF_ADDRESS) & ((1<<COMET2OP_BITSIZEOF_ADDRESS)-1)) class comet2op_t { const unsigned_int16_t* m_pr; public: unsigned_int16_t opcode() const { return ( unsigned_int16_t )COMET2OP16_GET_OPCODE( m_pr[0] ); } unsigned_int16_t gr() const { return ( unsigned_int16_t )COMET2OP16_GET_GR( m_pr[0] ); } unsigned_int16_t xr() const { return ( unsigned_int16_t )COMET2OP16_GET_XR( m_pr[0] ); } unsigned_int16_t addr() const { return m_pr[1]; } comet2op_t( const unsigned_int16_t* pr ): m_pr(pr) { } }; class mnemonic_data_t : public std::vector<unsigned_int16_t> { unsigned_int32_t m_is_data:1; unsigned_int32_t :31; unsigned_int32_t :32; public: using std::vector<unsigned_int16_t>::push_back; template<typename T> void push_back( T s, typename enable_if<is_same<T,const char*>::value>::type* = 0 ){ if( s ){ while( *s ){ push_back( static_cast<unsigned_int16_t>(*s)); ++s; } } } bool is_data() const { return m_is_data; } explicit mnemonic_data_t( size_t cd, unsigned_int16_t d0, va_list ap ): std::vector<unsigned_int16_t>(), m_is_data(true) { push_back( d0 ); for( size_t n = 0; n < cd-1; ++n ){ unsigned_int16_t d = static_cast<unsigned_int16_t>(va_arg( ap, int )); push_back( d ); } } explicit mnemonic_data_t( size_t cd, const char* d0, va_list ap ): std::vector<unsigned_int16_t>(), m_is_data(true) { push_back( d0 ); for( size_t n = 0; n < cd-1; ++n ){ const char* d = va_arg( ap, const char* ); push_back( d ); } } template<typename T> explicit mnemonic_data_t( T d, typename enable_if<is_int16<T>::value>::type* = 0 ): std::vector<unsigned_int16_t>(), m_is_data(false) { push_back( d ); } template<typename T> explicit mnemonic_data_t( T d, typename enable_if<is_int32<T>::value>::type* = 0 ): std::vector<unsigned_int16_t>(), m_is_data(false) { union_int32_t temp = { d }; push_back( temp.x[0] ); push_back( temp.x[1] ); } mnemonic_data_t(): std::vector<unsigned_int16_t>(), m_is_data(false) { } mnemonic_data_t( const mnemonic_data_t& rhs ): std::vector<unsigned_int16_t>(rhs), m_is_data(rhs.m_is_data) { } mnemonic_data_t& operator=( const mnemonic_data_t& rhs ){ if( this != &rhs ){ std::vector<unsigned_int16_t>::operator=(rhs); m_is_data = rhs.m_is_data; } return *this; } }; class mnemonic_t : public mnemonic_data_t { protected: signed_int16_t* m_addr; public: operator unsigned_int32_t() const { return COMET2OP32_MAKE(opcode(),gr(),xr(),addr()); } unsigned_int32_t opcode() const { return ( unsigned_int32_t )COMET2OP16_GET_OPCODE( (*this)[0] ); } unsigned_int32_t gr() const { return ( unsigned_int32_t )COMET2OP16_GET_GR( (*this)[0] ); } unsigned_int32_t xr() const { return ( unsigned_int32_t )COMET2OP16_GET_XR( (*this)[0] ); } unsigned_int32_t addr() const { return m_addr ? static_cast<unsigned_int32_t>(*m_addr) : static_cast<unsigned_int32_t>((*this)[1]); } bool read( unsigned_int16_t* data, size_t celt_data, size_t* pcelt_read ) const { bool success = true; size_t celt_read = 0; if( !data ||( celt_data < size())){ success = false; } if( success ){ if(( size() == 2 )&& !is_data() && !xr()){ union_int32_t temp = { *this }; data[celt_read] = temp.x[0]; ++celt_read; data[celt_read] = temp.x[1]; ++celt_read; } else{ for( const_iterator p = begin(); p != end(); ++p ){ data[celt_read] = *p; ++celt_read; } } } if( pcelt_read ){ *pcelt_read = celt_read; } return success; } mnemonic_t& operator=( const mnemonic_t& rhs ){ if( this != &rhs ){ mnemonic_data_t::operator=( rhs ); m_addr = rhs.m_addr; } return *this; } mnemonic_t( const mnemonic_t& rhs ): mnemonic_data_t(rhs), m_addr(rhs.m_addr) { } explicit mnemonic_t( unsigned_int32_t opcode ): mnemonic_data_t(COMET2OP16_MAKE(opcode,0,0)), m_addr(NULL) { } explicit mnemonic_t( unsigned_int32_t opcode, register16_t& gr ): mnemonic_data_t(COMET2OP16_MAKE(opcode,gr.type() - register16_type_gr0 + 1,0)), m_addr(NULL) { } template<typename T> explicit mnemonic_t( unsigned_int32_t opcode, T addr, typename enable_if<is_integral<T>::value>::type*& = enabler ): mnemonic_data_t(COMET2OP32_MAKE(opcode,0,0,addr)), m_addr(NULL) { } template<typename T> explicit mnemonic_t( unsigned_int32_t opcode, T addr, typename enable_if<is_pointer<T>::value>::type*& = enabler ): mnemonic_data_t(COMET2OP32_MAKE(opcode,0,0,0)), m_addr(addr) { } explicit mnemonic_t( unsigned_int32_t opcode, unsigned_int16_t offset, register16_t& xr ): mnemonic_data_t(COMET2OP32_MAKE(opcode,0,xr.type() - register16_type_gr0 + 1,offset)), m_addr(NULL) { } explicit mnemonic_t( unsigned_int32_t opcode, signed_int16_t offset, register16_t& xr ): mnemonic_data_t(COMET2OP32_MAKE(opcode,0,xr.type() - register16_type_gr0 + 1,offset)), m_addr(NULL) { } template<typename T> explicit mnemonic_t( unsigned_int32_t opcode, register16_t& gr, T addr, typename enable_if<is_integral<T>::value>::type*& = enabler ): mnemonic_data_t(COMET2OP32_MAKE(opcode,gr.type() - register16_type_gr0 + 1,0,addr)), m_addr(NULL) { } template<typename T> explicit mnemonic_t( unsigned_int32_t opcode, register16_t& gr, T addr, typename enable_if<is_pointer<T>::value>::type*& = enabler ): mnemonic_data_t(COMET2OP32_MAKE(opcode,gr.type() - register16_type_gr0 + 1,0,0)), m_addr(addr) { } explicit mnemonic_t( unsigned_int32_t opcode, register16_t& gr, unsigned_int16_t offset, register16_t& xr ): mnemonic_data_t(COMET2OP32_MAKE(opcode,gr.type() - register16_type_gr0 + 1,xr.type() - register16_type_gr0 + 1,offset)), m_addr(NULL) { } explicit mnemonic_t( unsigned_int32_t opcode, register16_t& gr, signed_int16_t offset, register16_t& xr ): mnemonic_data_t(COMET2OP32_MAKE(opcode,gr.type() - register16_type_gr0 + 1,xr.type() - register16_type_gr0 + 1,offset)), m_addr(NULL) { } // 新しい形式 explicit mnemonic_t( unsigned_int32_t opcode, register16_t& gr, register16_t& xr ): mnemonic_data_t(COMET2OP16_MAKE(opcode|opcode_1,gr.type() - register16_type_gr0 + 1,xr.type() - register16_type_gr0 + 1)), m_addr(NULL) { } // データ用 struct data_tag {}; explicit mnemonic_t( data_tag, size_t cd, int d0, va_list ap ): mnemonic_data_t(cd,static_cast<unsigned_int16_t>(d0),ap), m_addr(NULL) { } explicit mnemonic_t( data_tag, size_t cd, unsigned_int16_t d0, va_list ap ): mnemonic_data_t(cd,d0,ap), m_addr(NULL) { } explicit mnemonic_t( data_tag, size_t cd, const char* d0, va_list ap ): mnemonic_data_t(cd,d0,ap), m_addr(NULL) { } // 直接用 explicit mnemonic_t( unsigned_int32_t opcode, unsigned_int32_t gr, unsigned_int32_t xr, unsigned_int32_t addr ): mnemonic_data_t(COMET2OP32_MAKE(opcode,gr,xr,addr)), m_addr(NULL) { } explicit mnemonic_t( unsigned_int32_t opcode, unsigned_int32_t gr, unsigned_int32_t xr ): mnemonic_data_t(COMET2OP16_MAKE(opcode,gr,xr)), m_addr(NULL) { } private: mnemonic_t(); }; #define FR_BITOFFSET_ZF (0u) #define FR_BITOFFSET_SF (1u) #define FR_BITOFFSET_OF (2u) #define FR_ZF (1u<<FR_BITOFFSET_ZF) #define FR_SF (1u<<FR_BITOFFSET_SF) #define FR_OF (1u<<FR_BITOFFSET_OF) #define FR_ALL static_cast<unsigned_int16_t>(-1) struct fr_t : public register16_t { fr_t():register16_t(register16_type_fr){} bool zf() const { return !!( m_value & FR_ZF ); } bool sf() const { return !!( m_value & FR_SF ); } bool of() const { return !!( m_value & FR_OF ); } void zf( bool value ){ if( value ){ m_value |= FR_ZF; } else{ m_value &= ~FR_ZF; } } void sf( bool value ){ if( value ){ m_value |= FR_SF; } else{ m_value &= ~FR_SF; } } void of( bool value ){ if( value ){ m_value |= FR_OF; } else{ m_value &= ~FR_OF; } } void cpa( unsigned_int16_t lhs, unsigned_int16_t rhs ){ sf( static_cast<signed_int16_t>(lhs) < static_cast<signed_int16_t>(rhs)); zf( lhs == rhs ); } void cpl( unsigned_int16_t lhs, unsigned_int16_t rhs ){ sf( lhs < rhs ); zf( lhs == rhs ); } void cmp( unsigned_int16_t value16 ){ sf( static_cast<signed_int16_t>(value16) < 0 ); zf( !value16 ); } void cpa( unsigned_int32_t value32 ){ unsigned_int16_t value16 = static_cast<unsigned_int16_t>( value32 & 0x0000ffffu ); cmp( value16 ); of(( static_cast<signed_int16_t>(value16) < 0 ) != ( static_cast<signed_int32_t>(value32) < 0 )); } void cpl( unsigned_int32_t value32 ){ unsigned_int16_t value16 = static_cast<unsigned_int16_t>( value32 & 0x0000ffffu ); cmp( value16 ); of( !!( value32 & 0xffff0000u )); } using register16_t::operator=; // レジスタのコピーを作ることはない fr_t( const fr_t& rhs ) = delete; // レジスタを移動することはない fr_t( fr_t&& rhs ) = delete; // レジスタはを移動することはない fr_t& operator=( fr_t&& rhs ) = delete; }; class asm_t { std::vector<mnemonic_t> m_data; unsigned_int16_t m_start; unsigned_int16_t m_end; unsigned_int16_t :16; unsigned_int16_t :16; size_t m_size; void push_back( const mnemonic_t& mnemonic ){ m_data.push_back( mnemonic ); m_size += mnemonic.size(); } public: signed_int16_t label() const { return static_cast<signed_int16_t>(m_size); } void start(){ m_start = static_cast<unsigned_int16_t>(m_size); } void start( unsigned_int16_t addr ){ m_start = addr; } void end(){ m_end = static_cast<unsigned_int16_t>(m_size); } unsigned_int16_t start() const { return m_start; } unsigned_int16_t end() const { return m_end; } signed_int16_t ds( size_t n ){ signed_int16_t result = label(); m_size += n; return result; } template<size_t cd, typename T> signed_int16_t dc( T d0,... ){ signed_int16_t result = label(); va_list ap; va_start( ap, d0 ); push_back( mnemonic_t( mnemonic_t::data_tag(), cd, d0, ap )); va_end( ap ); return result; } void rpush(){ push_back( mnemonic_t( opcode_push, 0, 1+1, 0 )); push_back( mnemonic_t( opcode_push, 0, 2+1, 0 )); push_back( mnemonic_t( opcode_push, 0, 3+1, 0 )); push_back( mnemonic_t( opcode_push, 0, 4+1, 0 )); push_back( mnemonic_t( opcode_push, 0, 5+1, 0 )); push_back( mnemonic_t( opcode_push, 0, 6+1, 0 )); push_back( mnemonic_t( opcode_push, 0, 7+1, 0 )); } void rpop(){ push_back( mnemonic_t( opcode_pop, 7+1, 0 )); push_back( mnemonic_t( opcode_pop, 6+1, 0 )); push_back( mnemonic_t( opcode_pop, 5+1, 0 )); push_back( mnemonic_t( opcode_pop, 4+1, 0 )); push_back( mnemonic_t( opcode_pop, 3+1, 0 )); push_back( mnemonic_t( opcode_pop, 2+1, 0 )); push_back( mnemonic_t( opcode_pop, 1+1, 0 )); } void nop(){ push_back( mnemonic_t( opcode_nop )); } void ld( register16_t& gr, register16_t& xr ){ push_back( mnemonic_t( opcode_ld, gr, xr )); } void ld( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_ld, gr, addr )); } void ld( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_ld, gr, addr )); } void ld( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_ld, gr, offset, xr )); } void st( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_st, gr, addr )); } void st( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_st, gr, addr )); } void st( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_st, gr, offset, xr )); } void lad( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_lad, gr, addr )); } void lad( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_lad, gr, addr )); } void lad( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_lad, gr, offset, xr )); } void adda( register16_t& gr, register16_t& xr ){ push_back( mnemonic_t( opcode_adda, gr, xr )); } void adda( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_adda, gr, addr )); } void adda( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_adda, gr, addr )); } void adda( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_adda, gr, offset, xr )); } void addl( register16_t& gr, register16_t& xr ){ push_back( mnemonic_t( opcode_addl, gr, xr )); } void addl( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_addl, gr, addr )); } void addl( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_addl, gr, addr )); } void addl( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_addl, gr, offset, xr )); } void suba( register16_t& gr, register16_t& xr ){ push_back( mnemonic_t( opcode_suba, gr, xr )); } void suba( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_suba, gr, addr )); } void suba( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_suba, gr, addr )); } void suba( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_suba, gr, offset, xr )); } void subl( register16_t& gr, register16_t& xr ){ push_back( mnemonic_t( opcode_subl, gr, xr )); } void subl( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_subl, gr, addr )); } void subl( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_subl, gr, addr )); } void subl( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_subl, gr, offset, xr )); } void and_( register16_t& gr, register16_t& xr ){ push_back( mnemonic_t( opcode_and, gr, xr )); } void and_( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_and, gr, addr )); } void and_( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_and, gr, addr )); } void and_( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_and, gr, offset, xr )); } void or_( register16_t& gr, register16_t& xr ){ push_back( mnemonic_t( opcode_or, gr, xr )); } void or_( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_or, gr, addr )); } void or_( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_or, gr, addr )); } void or_( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_or, gr, offset, xr )); } void xor_( register16_t& gr, register16_t& xr ){ push_back( mnemonic_t( opcode_xor, gr, xr )); } void xor_( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_xor, gr, addr )); } void xor_( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_xor, gr, addr )); } void xor_( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_xor, gr, offset, xr )); } void cpa( register16_t& gr, register16_t& xr ){ push_back( mnemonic_t( opcode_cpa, gr, xr )); } void cpa( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_cpa, gr, addr )); } void cpa( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_cpa, gr, addr )); } void cpa( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_cpa, gr, offset, xr )); } void cpl( register16_t& gr, register16_t& xr ){ push_back( mnemonic_t( opcode_cpl, gr, xr )); } void cpl( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_cpl, gr, addr )); } void cpl( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_cpl, gr, addr )); } void cpl( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_cpl, gr, offset, xr )); } void sla( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_sla, gr, addr )); } void sla( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_sla, gr, addr )); } void sla( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_sla, gr, offset, xr )); } void sra( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_sra, gr, addr )); } void sra( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_sra, gr, addr )); } void sra( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_sra, gr, offset, xr )); } void sll( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_sll, gr, addr )); } void sll( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_sll, gr, addr )); } void sll( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_sll, gr, offset, xr )); } void srl( register16_t& gr, signed_int16_t addr ){ push_back( mnemonic_t( opcode_srl, gr, addr )); } void srl( register16_t& gr, signed_int16_t* addr ){ push_back( mnemonic_t( opcode_srl, gr, addr )); } void srl( register16_t& gr, signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_srl, gr, offset, xr )); } void jpl( signed_int16_t addr ){ push_back( mnemonic_t( opcode_jpl, addr )); } void jpl( signed_int16_t* addr ){ push_back( mnemonic_t( opcode_jpl, addr )); } void jpl( signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_jpl, offset, xr )); } void jmi( signed_int16_t addr ){ push_back( mnemonic_t( opcode_jmi, addr )); } void jmi( signed_int16_t* addr ){ push_back( mnemonic_t( opcode_jmi, addr )); } void jmi( signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_jmi, offset, xr )); } void jnz( signed_int16_t addr ){ push_back( mnemonic_t( opcode_jnz, addr )); } void jnz( signed_int16_t* addr ){ push_back( mnemonic_t( opcode_jnz, addr )); } void jnz( signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_jnz, offset, xr )); } void jne( signed_int16_t addr ){ push_back( mnemonic_t( opcode_jne, addr )); } void jne( signed_int16_t* addr ){ push_back( mnemonic_t( opcode_jne, addr )); } void jne( signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_jne, offset, xr )); } void jov( signed_int16_t addr ){ push_back( mnemonic_t( opcode_jov, addr )); } void jov( signed_int16_t* addr ){ push_back( mnemonic_t( opcode_jov, addr )); } void jov( signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_jov, offset, xr )); } void jump( signed_int16_t addr ){ push_back( mnemonic_t( opcode_jump, addr )); } void jump( signed_int16_t* addr ){ push_back( mnemonic_t( opcode_jump, addr )); } void jump( signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_jump, offset, xr )); } void push( signed_int16_t addr ){ push_back( mnemonic_t( opcode_push, addr )); } void push( signed_int16_t* addr ){ push_back( mnemonic_t( opcode_push, addr )); } void push( signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_push, offset, xr )); } void pop( register16_t& gr ){ push_back( mnemonic_t( opcode_pop, gr )); } void call( signed_int16_t addr ){ push_back( mnemonic_t( opcode_call, addr )); } void call( signed_int16_t* addr ){ push_back( mnemonic_t( opcode_call, addr )); } void call( signed_int16_t offset, register16_t& xr ){ push_back( mnemonic_t( opcode_call, offset, xr )); } void ret(){ push_back( mnemonic_t( opcode_ret )); } bool read( unsigned_int16_t* data, size_t celt_data, size_t* pcelt_read ) const { bool success = true; size_t celt_read = 0; if( !data ||( celt_data < m_data.size())){ success = false; } if( success ){ for( std::vector<mnemonic_t>::const_iterator p = m_data.begin(); p != m_data.end(); ++p ){ size_t m = 0; success = p->read( &data[celt_read], celt_data - celt_read, &m ); if( !success ){ break; } celt_read += m; } } if( pcelt_read ){ *pcelt_read = celt_read; } return success; } asm_t(): m_data(), m_start(0), m_end(0), m_size(0) { } private: asm_t( const asm_t& ); asm_t& operator=( const asm_t& ); }; class vm_t { protected: static const unsigned_int16_t c_base_address = 0x0100; typedef void (vm_t::*operator_t)( const comet2op_t& ); static operator_t c_operators[opcodes]; static register16_t vm_t::* c_gr[8]; register16_t m_gr0; register16_t m_gr1; register16_t m_gr2; register16_t m_gr3; register16_t m_gr4; register16_t m_gr5; register16_t m_gr6; register16_t m_gr7; register16_t m_sp; register16_t m_pr; fr_t m_fr; unsigned_int16_t m_memory[65536]; unsigned_int16_t m_start; unsigned_int16_t m_end; void output_debug_string1( const char* name, unsigned_int16_t gr, unsigned_int16_t xr ); void output_debug_string2( const char* name, unsigned_int16_t gr, unsigned_int16_t xr, unsigned_int16_t addr ); void output_debug_string1( const char* name, const comet2op_t& op ); void output_debug_string2( const char* name, const comet2op_t& op ); void operator_adda( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ); void operator_addl( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ); void operator_suba( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ); void operator_subl( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ); void operator_and( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ); void operator_or( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ); void operator_xor( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ); void operator_sla( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ); void operator_sra( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ); void operator_sll( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ); void operator_srl( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ); void operator1_nop( const comet2op_t& ); void operator2_ld( const comet2op_t& ); void operator2_st( const comet2op_t& ); void operator2_lad( const comet2op_t& ); void operator2_adda( const comet2op_t& ); void operator2_addl( const comet2op_t& ); void operator2_suba( const comet2op_t& ); void operator2_subl( const comet2op_t& ); void operator2_and( const comet2op_t& ); void operator2_or( const comet2op_t& ); void operator2_xor( const comet2op_t& ); void operator2_cpa( const comet2op_t& ); void operator2_cpl( const comet2op_t& ); void operator2_sla( const comet2op_t& ); void operator2_sra( const comet2op_t& ); void operator2_sll( const comet2op_t& ); void operator2_srl( const comet2op_t& ); void operator2_jpl( const comet2op_t& ); void operator2_jmi( const comet2op_t& ); void operator2_jnz( const comet2op_t& ); void operator2_jne( const comet2op_t& ); void operator2_jov( const comet2op_t& ); void operator2_jump( const comet2op_t& ); void operator2_push( const comet2op_t& ); void operator1_pop( const comet2op_t& ); void operator2_call( const comet2op_t& ); void operator1_ret( const comet2op_t& ); void operator1_ld( const comet2op_t& ); void operator1_adda( const comet2op_t& ); void operator1_addl( const comet2op_t& ); void operator1_suba( const comet2op_t& ); void operator1_subl( const comet2op_t& ); void operator1_and( const comet2op_t& ); void operator1_or( const comet2op_t& ); void operator1_xor( const comet2op_t& ); void operator1_cpa( const comet2op_t& ); void operator1_cpl( const comet2op_t& ); bool load( const asm_t& ); void run(); public: register16_t& gr0(){ return m_gr0; } register16_t& gr1(){ return m_gr1; } register16_t& gr2(){ return m_gr2; } register16_t& gr3(){ return m_gr3; } register16_t& gr4(){ return m_gr4; } register16_t& gr5(){ return m_gr5; } register16_t& gr6(){ return m_gr6; } register16_t& gr7(){ return m_gr7; } register16_t& gr_( unsigned_int16_t n ){ return this->*c_gr[n]; } void reset(); bool load_and_run( const asm_t& asm_ ); vm_t(): m_gr0(register16_type_gr0), m_gr1(register16_type_gr1), m_gr2(register16_type_gr2), m_gr3(register16_type_gr3), m_gr4(register16_type_gr4), m_gr5(register16_type_gr5), m_gr6(register16_type_gr6), m_gr7(register16_type_gr7), m_sp(register16_type_sp), m_pr(register16_type_pr), m_fr(), m_memory(), m_start(), m_end() { reset(); } private: vm_t( const vm_t& ); vm_t& operator=( const vm_t& ); }; vm_t::operator_t vm_t::c_operators[opcodes] = { // 0x00〜 &vm_t::operator1_nop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x10〜 &vm_t::operator2_ld, &vm_t::operator2_st, &vm_t::operator2_lad, NULL, &vm_t::operator1_ld, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x20〜 &vm_t::operator2_adda, &vm_t::operator2_addl, &vm_t::operator2_suba, &vm_t::operator1_subl, &vm_t::operator1_adda, &vm_t::operator1_addl, &vm_t::operator1_suba, &vm_t::operator2_subl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x30〜 &vm_t::operator2_and, &vm_t::operator2_or, &vm_t::operator2_xor, NULL, &vm_t::operator1_and, &vm_t::operator1_or, &vm_t::operator1_xor, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x40〜 &vm_t::operator2_cpa, &vm_t::operator2_cpl, NULL, NULL, &vm_t::operator1_cpa, &vm_t::operator1_cpl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x50〜 &vm_t::operator2_sla, &vm_t::operator2_sra, &vm_t::operator2_sll, &vm_t::operator2_srl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x60〜 NULL, &vm_t::operator2_jmi, &vm_t::operator2_jnz, &vm_t::operator2_jne, &vm_t::operator2_jump, &vm_t::operator2_jpl, &vm_t::operator2_jov, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x70〜 &vm_t::operator2_push, &vm_t::operator1_pop, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x80〜 &vm_t::operator2_call, &vm_t::operator1_ret, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, // 0x90〜 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, }; register16_t vm_t::* vm_t::c_gr[8] = { &vm_t::m_gr0, &vm_t::m_gr1, &vm_t::m_gr2, &vm_t::m_gr3, &vm_t::m_gr4, &vm_t::m_gr5, &vm_t::m_gr6, &vm_t::m_gr7, }; void vm_t::output_debug_string1( const char* name, unsigned_int16_t gr, unsigned_int16_t xr ){ if( gr ){ if( xr ){ debug_printf( "%-4s gr%d,gr%d\n", name, gr-1, xr-1 ); } else{ debug_printf( "%-4s gr%d\n", name, gr-1 ); } } else{ debug_printf( "%-4s\n", name ); } } void vm_t::output_debug_string2( const char* name, unsigned_int16_t gr, unsigned_int16_t xr, unsigned_int16_t addr ){ if( gr ){ if( xr ){ debug_printf( "%-4s gr%d,%d,gr%d\n", name, gr-1, addr, xr-1 ); } else{ debug_printf( "%-4s gr%d,%d\n", name, gr-1, addr ); } } else if( xr ){ debug_printf( "%-4s %d,gr%d\n", name, addr, xr-1 ); } else{ debug_printf( "%-4s %d\n", name, addr ); } } void vm_t::output_debug_string1( const char* name, const comet2op_t& op ){ unsigned_int16_t gr = op.gr(); unsigned_int16_t xr = op.xr(); output_debug_string1( name, gr, xr ); } void vm_t::output_debug_string2( const char* name, const comet2op_t& op ){ unsigned_int16_t gr = op.gr(); unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); output_debug_string2( name, gr, xr, addr ); } void vm_t::operator1_nop( const comet2op_t& op ){ output_debug_string1( "nop", op ); ++m_pr; } void vm_t::operator2_ld( const comet2op_t& op ){ output_debug_string2( "ld", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } gr_( gr ) = m_memory[addr]; m_fr.cmp( gr_( gr )); m_pr += 2; } void vm_t::operator1_ld( const comet2op_t& op ){ output_debug_string1( "ld", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t xr = op.xr()-1u; gr_( gr ) = gr_( xr ); m_fr.cmp( gr_( gr )); ++m_pr; } void vm_t::operator2_st( const comet2op_t& op ){ output_debug_string2( "st", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } m_memory[addr] = gr_( gr ); m_pr += 2; } void vm_t::operator2_lad( const comet2op_t& op ){ output_debug_string2( "lad", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } gr_( gr ) = addr; m_pr += 2; } void vm_t::operator_adda( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ){ unsigned_int32_t temp = static_cast<unsigned_int32_t>(lhs) + static_cast<unsigned_int32_t>(rhs); r = static_cast<unsigned_int16_t>(temp & 0x0000ffffu); m_fr.cpa( temp ); } void vm_t::operator2_adda( const comet2op_t& op ){ output_debug_string2( "adda", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } operator_adda( gr_( gr ), gr_( gr ), m_memory[addr] ); m_pr += 2; } void vm_t::operator1_adda( const comet2op_t& op ){ output_debug_string1( "adda", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t xr = op.xr()-1u; operator_adda( gr_( gr ), gr_( gr ), gr_( xr )); ++m_pr; } void vm_t::operator_addl( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ){ unsigned_int32_t temp = static_cast<unsigned_int32_t>(lhs) + static_cast<unsigned_int32_t>(rhs); r = static_cast<unsigned_int16_t>(temp & 0x0000ffffu); m_fr.cpl( temp ); } void vm_t::operator2_addl( const comet2op_t& op ){ output_debug_string2( "addl", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } operator_addl( gr_( gr ), gr_( gr ), m_memory[addr] ); m_pr += 2; } void vm_t::operator1_addl( const comet2op_t& op ){ output_debug_string1( "addl", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t xr = op.xr()-1u; operator_addl( gr_( gr ), gr_( gr ), gr_( xr )); ++m_pr; } void vm_t::operator_suba( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ){ unsigned_int32_t temp = static_cast<unsigned_int32_t>(lhs) - static_cast<unsigned_int32_t>(rhs); r = static_cast<unsigned_int16_t>(temp & 0x0000ffffu); m_fr.cpa( temp ); } void vm_t::operator2_suba( const comet2op_t& op ){ output_debug_string2( "suba", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } operator_suba( gr_( gr ), gr_( gr ), m_memory[addr] ); m_pr += 2; } void vm_t::operator1_suba( const comet2op_t& op ){ output_debug_string1( "suba", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t xr = op.xr()-1u; operator_suba( gr_( gr ), gr_( gr ), gr_( xr )); ++m_pr; } void vm_t::operator_subl( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ){ unsigned_int32_t temp = static_cast<unsigned_int32_t>(lhs) - static_cast<unsigned_int32_t>(rhs); r = static_cast<unsigned_int16_t>(temp & 0x0000ffffu); m_fr.cpl( temp ); } void vm_t::operator2_subl( const comet2op_t& op ){ output_debug_string2( "subl", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } operator_subl( gr_( gr ), gr_( gr ), m_memory[addr] ); m_pr += 2; } void vm_t::operator1_subl( const comet2op_t& op ){ output_debug_string1( "subl", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t xr = op.xr()-1u; operator_subl( gr_( gr ), gr_( gr ), gr_( xr )); ++m_pr; } void vm_t::operator_and( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ){ r = static_cast<unsigned_int16_t>( lhs & rhs ); m_fr.cmp( r ); } void vm_t::operator2_and( const comet2op_t& op ){ output_debug_string2( "and", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } operator_and( gr_( gr ), gr_( gr ), m_memory[addr] ); m_pr += 2; } void vm_t::operator1_and( const comet2op_t& op ){ output_debug_string1( "and", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t xr = op.xr()-1u; operator_and( gr_( gr ), gr_( gr ), gr_( xr )); ++m_pr; } void vm_t::operator_or( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ){ r = static_cast<unsigned_int16_t>( lhs | rhs ); m_fr.cmp( r ); } void vm_t::operator2_or( const comet2op_t& op ){ output_debug_string2( "or", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } operator_or( gr_( gr ), gr_( gr ), m_memory[addr] ); m_pr += 2; } void vm_t::operator1_or( const comet2op_t& op ){ output_debug_string1( "or", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t xr = op.xr()-1u; operator_or( gr_( gr ), gr_( gr ), gr_( xr )); ++m_pr; } void vm_t::operator_xor( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ){ r = static_cast<unsigned_int16_t>( lhs ^ rhs ); m_fr.cmp( r ); } void vm_t::operator2_xor( const comet2op_t& op ){ output_debug_string2( "xor", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } operator_xor( gr_( gr ), gr_( gr ), m_memory[addr] ); m_pr += 2; } void vm_t::operator1_xor( const comet2op_t& op ){ output_debug_string1( "xor", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t xr = op.xr()-1u; operator_xor( gr_( gr ), gr_( gr ), gr_( xr )); ++m_pr; } void vm_t::operator2_cpa( const comet2op_t& op ){ output_debug_string2( "cpa", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } m_fr.cpa( gr_( gr ), m_memory[addr] ); m_pr += 2; } void vm_t::operator1_cpa( const comet2op_t& op ){ output_debug_string1( "cpa", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t xr = op.xr()-1u; m_fr.cpa( gr_( gr ), gr_( xr )); ++m_pr; } void vm_t::operator2_cpl( const comet2op_t& op ){ output_debug_string2( "cpl", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } m_fr.cpl( gr_( gr ), m_memory[addr] ); m_pr += 2; } void vm_t::operator1_cpl( const comet2op_t& op ){ output_debug_string1( "cpl", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t xr = op.xr()-1u; m_fr.cpl( gr_( gr ), gr_( xr )); ++m_pr; } void vm_t::operator_sla( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ){ unsigned_int16_t temp = static_cast<unsigned_int16_t>( static_cast<signed_int16_t>(lhs) >> rhs ); r = ( static_cast<unsigned_int16_t>(lhs) & 0x8000u ) | ( static_cast<unsigned_int16_t>(temp) & 0x7fffu ); m_fr.cmp( r ); m_fr.of( static_cast<signed_int16_t>(temp) < 0 ); } void vm_t::operator2_sla( const comet2op_t& op ){ output_debug_string2( "sla", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } operator_sla( gr_( gr ), gr_( gr ), addr ); m_pr += 2; } void vm_t::operator_sra( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ){ unsigned_int32_t temp = ( static_cast<unsigned_int32_t>(static_cast<unsigned_int16_t>(lhs)) << 16 ) >> static_cast<unsigned_int32_t>(rhs); r = static_cast<unsigned_int16_t>( temp >> 16 ); m_fr.cmp( r ); m_fr.of( !!( temp & 0x00008000u )); } void vm_t::operator2_sra( const comet2op_t& op ){ output_debug_string2( "sra", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } operator_sra( gr_( gr ), gr_( gr ), addr ); m_pr += 2; } void vm_t::operator_sll( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ){ unsigned_int32_t temp = static_cast<unsigned_int32_t>(lhs) << static_cast<unsigned_int32_t>(rhs); r = static_cast<unsigned_int16_t>( temp & 0x0000ffffu ); m_fr.cmp( r ); m_fr.of( !!( temp & 0x00010000u )); } void vm_t::operator2_sll( const comet2op_t& op ){ output_debug_string2( "sll", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } operator_sll( gr_( gr ), gr_( gr ), addr ); m_pr += 2; } void vm_t::operator_srl( register16_t& r, unsigned_int16_t lhs, unsigned_int16_t rhs ){ unsigned_int32_t temp = ( static_cast<unsigned_int32_t>(lhs) << 16 ) >> static_cast<unsigned_int32_t>(rhs); r = static_cast<unsigned_int16_t>( temp >> 16 ); m_fr.cmp( r ); m_fr.of( !!( temp & 0x00008000u )); } void vm_t::operator2_srl( const comet2op_t& op ){ output_debug_string2( "srl", op ); unsigned_int16_t gr = op.gr()-1u; unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } operator_srl( gr_( gr ), gr_( gr ), addr ); m_pr += 2; } void vm_t::operator2_jpl( const comet2op_t& op ){ output_debug_string2( "jpl", op ); unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } if( m_fr.sf() && m_fr.zf()){ m_pr = addr; } else{ m_pr += 2; } } void vm_t::operator2_jmi( const comet2op_t& op ){ output_debug_string2( "jmi", op ); unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } if( m_fr.sf()){ m_pr = addr; } else{ m_pr += 2; } } void vm_t::operator2_jnz( const comet2op_t& op ){ output_debug_string2( "jnz", op ); unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } if( !m_fr.zf()){ m_pr = addr; } else{ m_pr += 2; } } void vm_t::operator2_jne( const comet2op_t& op ){ output_debug_string2( "jne", op ); unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } if( m_fr.zf()){ m_pr = addr; } else{ m_pr += 2; } } void vm_t::operator2_jov( const comet2op_t& op ){ output_debug_string2( "jov", op ); unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } if( m_fr.of()){ m_pr = addr; } else{ m_pr += 2; } } void vm_t::operator2_jump( const comet2op_t& op ){ output_debug_string2( "jump", op ); unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } m_pr = addr; } void vm_t::operator2_push( const comet2op_t& op ){ output_debug_string2( "push", op ); unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } --m_sp; m_memory[m_sp] = addr; m_pr += 2; } void vm_t::operator1_pop( const comet2op_t& op ){ output_debug_string1( "pop", op ); unsigned_int16_t gr = op.gr()-1u; gr_( gr ) = m_memory[m_sp]; ++m_sp; ++m_pr; } void vm_t::operator2_call( const comet2op_t& op ){ output_debug_string2( "call", op ); unsigned_int16_t addr = op.addr(); unsigned_int16_t xr = op.xr(); if( xr ){ addr += gr_( xr-1u ); } m_pr += 2; --m_sp; m_memory[m_sp] = m_pr; m_pr = addr; } void vm_t::operator1_ret( const comet2op_t& op ){ output_debug_string1( "ret", op ); m_pr = m_memory[m_sp]; ++m_sp; } void vm_t::reset(){ m_gr0 = 0; m_gr1 = 0; m_gr2 = 0; m_gr3 = 0; m_gr4 = 0; m_gr5 = 0; m_gr6 = 0; m_gr7 = 0; m_sp = 0; m_pr = 0; m_fr = 0; } bool vm_t::load( const asm_t& asm_ ){ bool success = true; if( !asm_.end()){ success = false; } if( success ){ m_start = asm_.start(); m_end = asm_.end(); asm_.read( m_memory, elementsof( m_memory ), NULL ); } return success; } void vm_t::run(){ m_sp = 0; m_pr = m_start; while( static_cast<size_t>(static_cast<signed_int16_t>(m_pr)) != m_end ){ comet2op_t op( &m_memory[m_pr] ); (this->*c_operators[op.opcode()])( op ); } } bool vm_t::load_and_run( const asm_t& asm_ ){ bool success = load( asm_ ); if( success ){ run(); } return success; }
使用例
int main(){ vm_t vm; register16_t& gr0 = vm.gr0(); register16_t& gr1 = vm.gr1(); asm_t asm_; asm_.start(); signed_int16_t label2 = 0; signed_int16_t label3 = 0; asm_.lad( gr0, 100 ); asm_.call( &label2 ); asm_.jump( &label3 ); label2 = asm_.label(); asm_.rpush(); asm_.push( 0, gr0 ); asm_.pop( gr1 ); asm_.rpop(); asm_.ret(); signed_int16_t label4 = asm_.dc<3>( 10, 20, 30 ); signed_int16_t label5 = asm_.dc<2>( "aaa", "bbb" ); (void)label5; label3 = asm_.label(); asm_.lad( gr1, 1 ); asm_.ld( gr0, label4, gr1 ); asm_.end(); vm.load_and_run( asm_ ); return 0; }
出力例
lad gr0,100 call 6 push 0,gr1 push 0,gr2 push 0,gr3 push 0,gr4 push 0,gr5 push 0,gr6 push 0,gr7 push 0,gr0 pop gr1 pop gr7 pop gr6 pop gr5 pop gr4 pop gr3 pop gr2 pop gr1 ret jump 40 lad gr1,1 ld gr0,31,gr1
このように自分で実装してみると、レジスタはただの整数のグローバル変数、アセンブラのニーモニックはただの関数とその引数、ポインタはただのアドレスの入れ物、スレッドはメモリはそのままでレジスタだけを丸ごと入れ替えてるだけ、プロセスはメモリもレジスタも丸ごと入れ替えてるだけ、というようなことも理解できるようになったのではないでしょうか