# HG changeset patch # User Issei Suzuki # Date 1188746335 -32400 # Node ID 0d602a6b23f8bf795a89f27c2f8fccf70c4838f0 # Parent 766a7fce05a4d8a76f3e541d96886d87967b7e9e CScript 実行部を組み込み --- a/.hgignore Sun Sep 02 23:59:43 2007 +0900 +++ b/.hgignore Mon Sep 03 00:18:55 2007 +0900 @@ -14,3 +14,17 @@ (^|/).*\.core($|/) (^|/).*\.d($|/) (^|/).*\.dis($|/) +(^|/).*\.ncb($|/) +(^|/).*\.suo($|/) +(^|/).*\.vcproj\..*\.user($|/) +^data/res\.lnk$ +^data/scr\.lnk$ +^data/fat\.bin$ +^data/packfile\.db$ +^data/packfile\.lst$ +^data/resource\.db$ +^data/resource\.tmp$ +^data/.*\.pack$ +^data/.*\.packh$ +^data/.*\.plst$ +^data/.*\.ptmp$ --- a/GameMain.cpp Sun Sep 02 23:59:43 2007 +0900 +++ b/GameMain.cpp Mon Sep 03 00:18:55 2007 +0900 @@ -33,6 +33,11 @@ #include "PackfileManager.h" #include "RootTask.h" #include "TaskManager.h" +#pragma warning(push) +// 4819:現在のコードページで表示できない文字を含んでいる +#pragma warning(disable : 4819) +#include "vm_sys_ud.h" +#pragma warning(pop) //! ゲームメインループ static boost::scoped_ptr s_spGame; @@ -139,6 +144,9 @@ void GameMain::Impl::exec() break; } g_pack.createSegment(MEM_SEG_DEFAULT, MEM_SEG_DEFAULT_SIZE); + + // CScript初期化 + CScript::VMUserSyscallDispatcher::GetInstance().init(); m_task_manager.addTask(createRootTask()); step(); --- a/GameObj.sln Sun Sep 02 23:59:43 2007 +0900 +++ b/GameObj.sln Mon Sep 03 00:18:55 2007 +0900 @@ -1,6 +1,11 @@ Microsoft Visual Studio Solution File, F Microsoft Visual Studio Solution File, Format Version 9.00 # Visual Studio 2005 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "GameObj", "GameObj.vcproj", "{506F90AF-B7B9-4593-A6E2-8EAE8977EC33}" + ProjectSection(ProjectDependencies) = postProject + {B638D451-C103-4203-81B3-3439C86E77A7} = {B638D451-C103-4203-81B3-3439C86E77A7} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "CScriptVM", "CScriptVM\CScriptVM.vcproj", "{B638D451-C103-4203-81B3-3439C86E77A7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -24,6 +29,15 @@ Global {506F90AF-B7B9-4593-A6E2-8EAE8977EC33}.Release|Win32.Build.0 = Release|Win32 {506F90AF-B7B9-4593-A6E2-8EAE8977EC33}.Release|x64.ActiveCfg = Release|x64 {506F90AF-B7B9-4593-A6E2-8EAE8977EC33}.Release|x64.Build.0 = Release|x64 + {B638D451-C103-4203-81B3-3439C86E77A7}.Debug|Win32.ActiveCfg = Debug|Win32 + {B638D451-C103-4203-81B3-3439C86E77A7}.Debug|Win32.Build.0 = Debug|Win32 + {B638D451-C103-4203-81B3-3439C86E77A7}.Debug|x64.ActiveCfg = Debug|Win32 + {B638D451-C103-4203-81B3-3439C86E77A7}.NoOptimize|Win32.ActiveCfg = Release|Win32 + {B638D451-C103-4203-81B3-3439C86E77A7}.NoOptimize|Win32.Build.0 = Release|Win32 + {B638D451-C103-4203-81B3-3439C86E77A7}.NoOptimize|x64.ActiveCfg = Release|Win32 + {B638D451-C103-4203-81B3-3439C86E77A7}.Release|Win32.ActiveCfg = Release|Win32 + {B638D451-C103-4203-81B3-3439C86E77A7}.Release|Win32.Build.0 = Release|Win32 + {B638D451-C103-4203-81B3-3439C86E77A7}.Release|x64.ActiveCfg = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE --- a/GameObj.vcproj Sun Sep 02 23:59:43 2007 +0900 +++ b/GameObj.vcproj Mon Sep 03 00:18:55 2007 +0900 @@ -54,7 +54,7 @@ + + @@ -851,6 +855,18 @@ RelativePath=".\utils.cpp" > + + + + + + + + + + + + $@ @@ -45,3 +54,12 @@ clean: $(RM) $(RESDB) $(PACKDB) $(PACKLST) $(FAT) $(RM) $(PTMP) $(PLST) $(PACK) $(PACKH) $(RM) res resource.tmp *.d + +depend: $(DEPS) + touch .depend + for i in $(DEPS); do \ + cat $$i >> .depend; \ + echo >> .depend; \ + done + +sinclude .depend --- a/data/packfile.txt Sun Sep 02 23:59:43 2007 +0900 +++ b/data/packfile.txt Mon Sep 03 00:18:55 2007 +0900 @@ -6,3 +6,4 @@ test03.pack test03.pack test04.pack test05.pack +test_scr.pack --- a/data/resource.txt Sun Sep 02 23:59:43 2007 +0900 +++ b/data/resource.txt Mon Sep 03 00:18:55 2007 +0900 @@ -7,3 +7,4 @@ res/test/dummy01.bin res/test/dummy01.bin res/test/dummy02.bin res/test/dummy03.bin +scr/test/for.scb --- a/dbTaskTestMenu.cpp Sun Sep 02 23:59:43 2007 +0900 +++ b/dbTaskTestMenu.cpp Mon Sep 03 00:18:55 2007 +0900 @@ -42,6 +42,7 @@ #include "dbTaskPackfileManagerTest.h" #include "dbTaskPackResTest.h" #include "dbTaskResourceManagerTest.h" +#include "dbTaskScriptTest.h" #include "DIDev.h" #include "ICtxTask.h" @@ -98,6 +99,7 @@ void dbTaskTestMenu::exec(ICtxTask& ctx, { _T("3D camera test"), dbCreateTaskD3DCameraTest }, { _T("3D axis test"), dbCreateTaskD3DAxisTest }, // base + { _T("Script test"), dbCreateTaskScriptTest }, { _T("HSM test"), dbCreateTaskHsmTest }, { _T("packfile handle test"), dbCreateTaskPackfileHandleTest }, { _T("pack/res manager test"), dbCreateTaskPackResTest }, --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/CScriptVM.vcproj Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,267 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/ReadMe.txt Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,37 @@ +======================================================================== +X^eBbN Cu : CScriptVM vWFNg̊Tv +======================================================================== + + CScriptVM Cu vWFNǵAAppWizard ɂ +쐬܂B + +̃t@Cɂ́ACScriptVM AvP[V\et@C +e̊TLqĂ܂B + + +CScriptVM.vcproj + ́AAvP[V EBU[hŐ VC++ vWFNg̃C + vWFNg t@CłB + t@C𐶐 Visual C++ ̃o[WƁAAvP[V + EBU[hőIvbgtH[A\AуvWFNg̋@\Ɋւ + 񂪋LqĂ܂B + + +///////////////////////////////////////////////////////////////////////////// + +StdAfx.h, StdAfx.cpp + ̃t@ĆARpCς݃wb_[ (PCH) t@C + CScriptVM.pch ƃvRpCς݌^t@C StdAfx.obj + rh邽߂Ɏgp܂B + +///////////////////////////////////////////////////////////////////////////// +̑̃ : + +AppWizard ł "TODO:" RggpāA[U[lj܂̓JX^}CY +\[X܂B + +///////////////////////////////////////////////////////////////////////////// + + + + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/common.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,63 @@ +/* + * CScript コンパイラ 共通定義 + * $Id: common.h 414 2007-05-22 11:53:29Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef COMMON_H__INCLUDED +#define COMMON_H__INCLUDED + +#define ANON_NAMESPACE_BEGIN namespace { +#define ANON_NAMESPACE_END } + +#define NELEM(x) (sizeof(x) / sizeof(x[0])) + +#if defined(__GNUC__) || defined(__INTEL_COMPILER) +# define CSCR_IDSTRING(name,string) __asm__(".ident\t\"" string "\"") +#else +# define CSCR_IDSTRING(name,string) static const char name[] = string +#endif + +#ifndef CSCR_RCSID +# ifndef NOCSCR_RCSID +# define CSCR_RCSID(s) CSCR_IDSTRING(cscr__rcsid_ ## __LINE__,s) +# else +# define CSCR_RCSID(s) struct cscr__hack +# endif +#endif + +template +inline T log2(T n) +{ + if (n <= 0) + return -1; + + T i = 0; + while (n > 0) { + ++i; + n >>= 1; + } + return i; +} + +#endif // COMMON_H__INCLUDED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/cscript.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,50 @@ +/* + * CScript コンパイラ + * $Id: cscript.h 425 2007-06-01 16:06:55Z issei $ + * + * Copyright (c) 2006, 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef CSCRIPT_H__INCLUDED +#define CSCRIPT_H__INCLUDED + +#ifdef XXX +# define CSCRIPT_NAMESPACE_BEGIN +# define CSCRIPT_NAMESPACE_END +# define CSCRIPT_NAMESPACE +# define CSCRIPT_NAMESPACE_USING +#else +# define CSCRIPT_NAMESPACE_BEGIN namespace CScript { +# define CSCRIPT_NAMESPACE_END } +# define CSCRIPT_NAMESPACE CScript +# define CSCRIPT_NAMESPACE_USING using namespace CScript; +#endif + +// システム関数呼び出し時に handle の有効チェックを行なう +#define CSCR_VM_SYS_BASE_VALIDATE_HANDLE + +// 1秒間の標準実行回数 +#ifndef CSCR_FRAMES_PER_SEC +# define CSCR_FRAMES_PER_SEC (60.0f) +#endif + +#endif // CSCRIPT_H__INCLUDED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/file.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,202 @@ +/* + * CScript コンパイラ コンパイル済みバイナリファイル + * $Id: file.h 402 2007-05-09 13:42:53Z issei $ + * + * Copyright (c) 2006, 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef FILE_H__INCLUDED +#define FILE_H__INCLUDED + +#include "cscript.h" +#include "vm_cast.h" + +CSCRIPT_NAMESPACE_BEGIN + +namespace File +{ + char const MAGIC[4] = { 0x7f, 's', 'c', 'b' }; + boost::uint32_t const VERSION_MAJOR = 0; + boost::uint32_t const VERSION_MINOR = 2; + + boost::uint32_t const SECTION_ALIGN = 16; // bytes + + enum SECTION_TYPE + { + SECTION_ERROR, // 使用不可 + SECTION_CODE, // 必須 + SECTION_UPCALL, // オプション + SECTION_STATIC_DATA, // オプション + SECTION_LITERAL_DATA, // オプション + SECTION_LITERAL_PTR, // オプション + SECTION_CONST_DATA, // オプション + SECTION_TRAILER, // 必須 + SECTION_MAX, // 使用不可 + }; + + // 特殊セクション + struct Header + { + char magic[4]; + boost::uint32_t version_major; + boost::uint32_t version_minor; + boost::uint8_t _padding[4]; + }; + + // ------------------------------------------------------------------- + // 汎用セクション + // ------------------------------------------------------------------- + struct Info + { + SECTION_TYPE section; + boost::uint32_t size; + boost::uint32_t checksum; + boost::uint8_t _padding[4]; + }; + + // p -> +-------------------+ + // | File::Info | + // q -> +-------------------+ ^ + // | File::Code | p->size (bytes) + // +-------------------+ | ^ + // | code[] | | q->count (words) + // | | | | + // | | | | + // +-------------------+ | v + // | _padding | | + // +-------------------+ v + struct Code + { + vm_psize_t count; + boost::uint8_t _padding[12]; + vm_tword_t code[]; + }; + + // p -> +-------------------+ + // | File::Info | + // q -> +-------------------+ ^ + // | File::Upcall | p->size (bytes) + // +-------------------+ | ^ + // | data[] | | q->count (double words) + // | | | | + // | | | | + // +-------------------+ | v + // | _padding | | + // +-------------------+ v + struct Upcall + { + typedef std::pair Node; + + boost::uint32_t count; + boost::uint8_t _padding[12]; + Node data[]; + }; + + // p -> +-------------------+ + // | File::Info | + // q -> +-------------------+ ^ + // | File::StaticData | p->size (bytes) + // +-------------------+ | ^ + // | init_data[] | | q->init_count (double words) + // | | | | + // | | | | + // +-------------------+ | v + // | _padding | | + // +-------------------+ v + struct StaticData + { + vm_dsize_t count; // 静的データサイズ + vm_dsize_t init_count; // 静的データ初期値数 + boost::uint8_t _padding[12]; + struct Node + { + vm_daddr_t daddr; + boost::uint8_t _padding[2]; + vm_dword_t dword; + } init_data[]; + }; + + // p -> +-------------------+ + // | File::Info | + // q -> +-------------------+ ^ + // | File::LiteralData | p->size (bytes) + // +-------------------+ | ^ + // | data[] | | q->count (bytes) + // | | | | + // | | | | + // +-------------------+ | v + // | _padding | | + // +-------------------+ v + struct LiteralData + { + boost::uint16_t count; + boost::uint8_t _padding[14]; + char data[]; + }; + + // p -> +-------------------+ + // | File::Info | + // q -> +-------------------+ ^ + // | File::LiteralPtr | p->size (bytes) + // +-------------------+ | ^ + // | offset[] | | q->count (hwords) + // | | | | + // | | | | + // +-------------------+ | v + // | _padding | | + // +-------------------+ v + struct LiteralPtr + { + vm_psize_t count; + boost::uint8_t _padding[12]; + boost::uint16_t offset[]; + }; + + // p -> +-------------------+ + // | File::Info | + // q -> +-------------------+ ^ + // | File::Const | p->size (bytes) + // +-------------------+ | ^ + // | data[] | | q->count (words) + // | | | | + // | | | | + // +-------------------+ | v + // | _padding | | + // +-------------------+ v + struct ConstData + { + vm_const_t count; + vm_dword_t data[]; + }; + + // p -> +-------------------+ + // | File::Info | + // +-------------------+ (p->size = 0) + struct Trailer + { + char _dummy[]; + }; +} + +CSCRIPT_NAMESPACE_END + +#endif // FILE_H__INCLUDED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/inst.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,129 @@ +/* + * CScript コンパイラ 仮想機械命令セット + * $Id: inst.h 382 2007-04-19 09:43:45Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "common.h" +#include "cscript.h" +#include "vm_cast.h" + +// ------------------------------------------------------------------- +// サブオペコード +// +// [27:20] 演算適用可能データ型 +// [19:18] -unused- +// [17:16] オペランド数 +// [15: 8] -unused- +// [ 7: 0] 演算命令コード +// [ 7: 6] 演算種別 +// [ 5: 0] 演算命令詳細コード +// ------------------------------------------------------------------- + +// 適用可能データ型 +#define D_GET_CAST(x) ((x) & D_ANY) +#define D_INT (0x00100000) /// 整数 +#define D_FLT (0x00200000) /// 浮動小数点数 +// #define D_VEC (0x00300000) /// 同次ベクトル +// #define D_QTR (0x00400000) /// 四元数 +// #define D_MTX (0x00500000) /// 4x4行列 +#define D_ANY (0x00f00000) /// 全データ型 + +// オペランド数 +#define D_GET_OPRAND(x) ((x) & 0x000f0000) +#define D_OP1 (0x00010000) /// 単項演算 +#define D_OP2 (0x00020000) /// 二項演算 + +#define D_GET_OPR_CODE(x) static_cast((x) & 0xff) + +// 演算種別 +#define D_GET_OPR_TYPE(x) static_cast((x) & 0x000000c0) +#define D_OPL (0x00000000) /// 論理演算 +#define D_OPA (0x00000040) /// 算術演算 +#define D_OPC (0x00000080) /// データ型変換 + +// 二項論理演算種別 +#define D_OPR_EQU (0x00) +#define D_OPR_NEQ (0x01) +#define D_OPR_LSS (0x02) +#define D_OPR_LEQ (0x03) +#define D_OPR_GTR (0x04) +#define D_OPR_GEQ (0x05) +#define D_OPR_AND (0x10) +#define D_OPR_OR (0x11) +#define D_OPR_XOR (0x12) +#define D_OPR_LSH (0x13) +#define D_OPR_RSH (0x14) + +CSCRIPT_NAMESPACE_BEGIN + +typedef vm_tword_opcode_t INST_CODE; +#include "inst2vm.inc" + +typedef vm_tword_oprand_t INST_SUBCODE; +#include "instsub2code_c.inc" + +enum CSCR_OPRAND_TYPE +{ + CSCR_OPRAND_ERROR, /// システム予約 + CSCR_OPRAND_NONE, /// なし + CSCR_OPRAND_TADDR, /// プログラムアドレス + CSCR_OPRAND_BRANCH, /// 条件分岐演算 + プログラムアドレス + CSCR_OPRAND_IMMEDIATE, /// 即値 (プログラム指定) + CSCR_OPRAND_DOFFSET, /// データアドレスオフセット + CSCR_OPRAND_RETURN, /// 関数リターン情報 (引数サイズ, 戻り値サイズ) + CSCR_OPRAND_SYSNO, /// システムコール番号 + CSCR_OPRAND_SUBOP, /// サブオペコード + CSCR_OPRAND_MAX, /// システム予約 +}; + +struct Inst +{ + std::string name; + INST_CODE opcode; + CSCR_OPRAND_TYPE oprand_type; + boost::uint32_t subop_type; +}; + +struct InstSub +{ + std::string name; + std::string text; + INST_SUBCODE subcode; +}; + +class InstTable +{ +public: + CSCR_OPRAND_TYPE getOprandType(INST_CODE code) const; + std::string toString(vm_tword_t tword) const; + +private: + Inst const* _getInst(INST_CODE code) const; + InstSub const* _getInstSub(INST_SUBCODE subcode) const; + static Inst const CSCR_INST[]; + static InstSub const INST_SUB[]; +}; + +CSCRIPT_NAMESPACE_END + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/inst2vm.inc Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,37 @@ + +/* + * DO NOT EDIT + * This file is automatically generated from $0 and inst.m4 + * + * $Id: inst2vm.m4 364 2007-03-28 16:32:22Z issei $ + */ +vm_tword_opcode_t const INST_nop = 0x00; +vm_tword_opcode_t const INST_halt = 0x01; +vm_tword_opcode_t const INST_call = 0x10; +vm_tword_opcode_t const INST_return = 0x11; +vm_tword_opcode_t const INST_lreturn = 0x12; +vm_tword_opcode_t const INST_jump = 0x13; +vm_tword_opcode_t const INST_jump_if0 = 0x14; +vm_tword_opcode_t const INST_jump_if = 0x16; +vm_tword_opcode_t const INST_syscall = 0x18; +vm_tword_opcode_t const INST_enter = 0x20; +vm_tword_opcode_t const INST_shrink = 0x22; +vm_tword_opcode_t const INST_push = 0x30; +vm_tword_opcode_t const INST_sethi = 0x31; +vm_tword_opcode_t const INST_iandi = 0x32; +vm_tword_opcode_t const INST_iori = 0x33; +vm_tword_opcode_t const INST_ixori = 0x34; +vm_tword_opcode_t const INST_irshifti = 0x35; +vm_tword_opcode_t const INST_ilshifti = 0x36; +vm_tword_opcode_t const INST_iaddi = 0x37; +vm_tword_opcode_t const INST_isubi = 0x38; +vm_tword_opcode_t const INST_imuli = 0x39; +vm_tword_opcode_t const INST_idivi = 0x3a; +vm_tword_opcode_t const INST_imodi = 0x3b; +vm_tword_opcode_t const INST_get = 0x40; +vm_tword_opcode_t const INST_set = 0x41; +vm_tword_opcode_t const INST_iinc = 0x42; +vm_tword_opcode_t const INST_idec = 0x43; +vm_tword_opcode_t const INST_opr_int = 0x80; +vm_tword_opcode_t const INST_opr_float = 0x81; + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/instsub2code_c.inc Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,31 @@ +/* + * DO NOT EDIT + * This file is automatically generated from $0 and inst.m4 + * + * $Id: instsub2code_c.m4 364 2007-03-28 16:32:22Z issei $ + */ + + +vm_tword_oprand_t const OPR_test0 = D_OP1 | D_OPL | 0x00; +vm_tword_oprand_t const OPR_not = D_OP1 | D_OPL | 0x10; +vm_tword_oprand_t const OPR_neg = D_OP1 | D_OPA | 0x20; +vm_tword_oprand_t const OPR_abs = D_OP1 | D_OPA | 0x21; +vm_tword_oprand_t const OPR_int = D_OP1 | D_OPC | 0x00; +vm_tword_oprand_t const OPR_float = D_OP1 | D_OPC | 0x01; +vm_tword_oprand_t const OPR_equ = D_OP2 | D_OPL | D_OPR_EQU; +vm_tword_oprand_t const OPR_neq = D_OP2 | D_OPL | D_OPR_NEQ; +vm_tword_oprand_t const OPR_lss = D_OP2 | D_OPL | D_OPR_LSS; +vm_tword_oprand_t const OPR_leq = D_OP2 | D_OPL | D_OPR_LEQ; +vm_tword_oprand_t const OPR_gtr = D_OP2 | D_OPL | D_OPR_GTR; +vm_tword_oprand_t const OPR_geq = D_OP2 | D_OPL | D_OPR_GEQ; +vm_tword_oprand_t const OPR_and = D_OP2 | D_OPL | D_OPR_AND; +vm_tword_oprand_t const OPR_or = D_OP2 | D_OPL | D_OPR_OR; +vm_tword_oprand_t const OPR_xor = D_OP2 | D_OPL | D_OPR_XOR; +vm_tword_oprand_t const OPR_lshift = D_OP2 | D_OPL | D_OPR_LSH; +vm_tword_oprand_t const OPR_rshift = D_OP2 | D_OPL | D_OPR_RSH; +vm_tword_oprand_t const OPR_add = D_OP2 | D_OPA | 0x00; +vm_tword_oprand_t const OPR_sub = D_OP2 | D_OPA | 0x01; +vm_tword_oprand_t const OPR_mul = D_OP2 | D_OPA | 0x02; +vm_tword_oprand_t const OPR_div = D_OP2 | D_OPA | 0x03; +vm_tword_oprand_t const OPR_mod = D_OP2 | D_OPA | 0x04; + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/stdafx.cpp Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,27 @@ +/* + * CScript vRpChwb_쐬p + * $Id: stdafx.h 449 2007-06-06 00:03:04Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "stdafx.h" --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/stdafx.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,78 @@ +/* + * CScript vRpChwb_쐬p + * $Id: stdafx.h 449 2007-06-06 00:03:04Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + +#pragma once +#pragma warning(disable : 4819 4200) + +#ifndef _WIN32_WINNT // Windows XP ȍ~̃o[WɌŗL̋@\̎gp‚܂B +#define _WIN32_WINNT 0x0501 // Windows ̑̃o[WɓK؂ȒlɕύXĂB +#endif + +#define WIN32_LEAN_AND_MEAN // Windows wb_[gpĂȂO܂B +#define _CRT_SECURE_NO_WARNINGS + +#include + +#include +#include +#include +#ifdef HAVE_GETOPT_H +# include +#endif +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#endif +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm.cc Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,1973 @@ +/* + * コンパイラ 仮想機械 + * $Id: vm.cc 454 2007-06-06 13:58:50Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "stdafx.h" +#include "vm.h" +#include "common.h" +#include "cscript.sch" +#include "inst.h" +#include "vm_ctx.h" +#include "vm_loader.h" +#include "vm_sys_vm.h" +#include "vm_sys_d.h" +#include "vm_sys_ud.h" + +#ifndef NDEBUG +// CSCR_VM_DPRINTF でメッセージ表示 +#define CSCR_VM_VERBOSE +// 命令実行の詳細表示 +// #define CSCR_VM_VERBOSE_EXEC +// スレッド生成/終了処理の詳細表示 +// #define CSCR_VM_VERBOSE_THREAD +#endif // !NDEBUG + +#ifdef CSCR_VM_VERBOSE +static int _dprintf(char const* fmt, ...) +{ + int ret; + va_list ap; + va_start(ap, fmt); + ret = vprintf(fmt, ap); + va_end(ap); + return ret; +} + +# define CSCR_VM_DPRINTF(x) \ + do { \ + _dprintf("CSCR_VM_DEBUG: "); \ + _dprintf x; \ + } while (0) +#else +# define CSCR_VM_DPRINTF(x) +#endif + +#ifdef CSCR_VM_VERBOSE_THREAD +# define CSCR_VM_DPRINTF_THREAD(x) CSCR_VM_DPRINTF(x) +#else +# define CSCR_VM_DPRINTF_THREAD(x) +#endif + +#ifdef CSCR_VM_VERBOSE_EXEC +# define CSCR_VM_DPRINTF_EXEC(x) CSCR_VM_DPRINTF(x) +#else +# define CSCR_VM_DPRINTF_EXEC(x) +#endif + +CSCRIPT_NAMESPACE_BEGIN + +ANON_NAMESPACE_BEGIN + +// ------------------------------------------------------------------- +// 例外 +// ------------------------------------------------------------------- +class vm_runtime_exception + : public std::runtime_error +{ +public: + vm_runtime_exception(std::string const& msg) + : std::runtime_error(msg) + {} +}; + +#define CSCR_VM_EXCPT(exception, state, msg) \ +class exception \ + : public vm_runtime_exception \ +{ \ +public: \ + exception(std::string const& s) \ + : vm_runtime_exception(s) \ + {} \ +}; +#include "vm_excpt.h" + +/** + * VMスレッド + * + * VMスレッド固有のリソース (レジスタ、スタック) の保持ならびに + * VMスレッド親子関係の管理を行う。 + */ +class VMThread +{ +public: + typedef vm_int_t Id; //< スレッドを識別する ID 値 + typedef std::set TChildIdList; //< 子スレッドのID値リスト + + static Id const ROOT_THREAD_ID = 0; //< rootスレッドのID値 + static Id const UPCALL_THREAD_ID = -1; //< upcallを実行するスレッドのID値 + + /** + * VMスレッドから VM へのコールバックインターフェース + */ + struct ICtxVirtualMachine + { + virtual ~ICtxVirtualMachine() {} + + /** + * ID 値に対応する VM スレッドのインスタンスを取得する + * + * @param id + * VMスレッド識別子 + * @return + * VM スレッドのインスタンス + * ID 値に対応する VM スレッドが無い場合は NULL + */ + virtual VMThread const* findThread(Id id) const = 0; + }; + + /** + * VM スレッド固有レジスタ + */ + struct Regs + { + vm_tword_t pw; //< 実行中のバイトコード命令 + vm_taddr_t pc; //< プログラムカウンタ + vm_daddr_t fp; //< スタックフレームポインタ + vm_daddr_t sp; //< スタックポインタ + int run; //< 実行回数 + int sleep; //< 実行一時停止時間 (run() 呼び出し必要回数) + bool halt; //< 停止状態フラグ + + Regs(); + }; + + /** + * VM スタック + */ + typedef std::vector Stack; + + /* + * VM スレッド 状態遷移図 + * + * +------------------------------------------+ + * | Alive | + * | +----------+ _runThread1() +----------+ | + * | | Runnable |--------------->| Run | | + * | | | | | | + * | +----------+ +----------+ | + * | ^ _runThread1() | | + * | | (--sleep) sysPass*() | | + * | +----------+ sysWait*() | | + * | | Sleep |<---------------------+ | + * | | sleep>0 | | + * | +----------+ | + * +------------------------------------------+ + * | + * | sysExit() [self] + * | INST_halt [self] + * | sysThreadKill*() [other] + * v + * +----------+ + * | Halt | + * | halt=1 | + * +----------+ + */ + Regs thr_regs; //< VM スレッド固有レジスタ + Stack thr_stack; //< VM スレッドスタック + + /** + * VMスレッドのインスタンスを構築する + * + * @param parent_id + * 親スレッドのID値 + * @param id + * 作成するスレッドのID値 + */ + VMThread(Id parent_id, Id id); + + /** + * VM スレッドが利用するスタックを初期化する + * + * @param size + * スタックのサイズ (ワード単位) + */ + void initStack(vm_dsize_t size); + + /** + * VM スレッドの ID 値を取得する + * + * @return + * VM スレッドの ID 値 + */ + Id getId() const { return thr_id; } + + /** + * 親スレッドの ID 値を取得する + * + * @return + * 親スレッドの ID 値 + */ + Id getParentId() const { return thr_parent_id; } + + /** + * rootスレッドか? + * + * @return + * rootスレッドなら真 + */ + bool isRoot() const { return thr_id == ROOT_THREAD_ID; } + + /** + * upcallスレッドか? + * + * @return + * upcallスレッドなら真 + */ + bool isUpcall() const { return thr_id == UPCALL_THREAD_ID; } + + /** + * 指定した VM スレッドを、このVM スレッドの子として登録 + * + * @param id + * 子スレッドとして登録する VM スレッドの ID 値 + */ + void addChild(Id id); + + /** + * 指定した VM スレッドを、このVM スレッドの子から登録解除 + * + * @param id + * 子スレッドとして登録されている VM スレッドの ID 値 + */ + void eraseChild(Id id); + + /** + * 指定した VM スレッドが、自分の祖先か調べる + * + * @param ctx + * VM スレッド実行コンテクスト + * @param idx + * 調査対象の VM スレッド ID 値 + */ + bool isAncester(ICtxVirtualMachine const& ctx, Id id) const; + + /** + * 自分の親が削除されたことを通知する + * + * @note + * 現 VM スレッドは rootスレッド直下になる + */ + void notifyParentErased(); + + /** + * 子スレッドの一覧を走査するためのイテレータ先頭を取得する + */ + std::set::const_iterator children_begin() const { return thr_child_ids.begin(); } + + /** + * 子スレッドの一覧を走査するためのイテレータ末尾を取得する + */ + std::set::const_iterator children_end() const { return thr_child_ids.end(); } + +private: + Id thr_parent_id; //< 親スレッド ID 値 + Id const thr_id; //< 自スレッド ID 値 + TChildIdList thr_child_ids; //< 子スレッドの一覧 + + /** + * 指定した VM スレッドが、自分の祖先か調べる + * + * @param ctx + * VM スレッド実行コンテクスト + * @param idx + * 調査対象の VM スレッド ID 値 + * @note + * 自スレッドが root スレッド、ならびに調査対象が root スレッドで + * ないこと。 + */ + bool _isAncester(ICtxVirtualMachine const& ctx, Id id) const; +}; +typedef std::map VMThreadMap; + +VMThread::Regs::Regs() + : pw(0) , pc(0) , fp(0) , sp(0) , run(0) , sleep(0) , halt(false) +{} + +VMThread::VMThread(Id parent_id, Id id) + : thr_parent_id(parent_id) + , thr_id(id) +{} + +void VMThread::initStack(vm_dsize_t size) +{ + thr_stack.resize(size); +} + +void VMThread::addChild(Id id) +{ + assert(id != 0); + std::pair::iterator, bool> result = thr_child_ids.insert(id); + assert(result.second); +} + +void VMThread::eraseChild(Id id) +{ + assert(id != 0); +#ifndef NDEBUG + size_t count = +#endif + thr_child_ids.erase(id); + assert(count == 1); +} + +bool VMThread::isAncester(ICtxVirtualMachine const& ctx, Id id) const +{ + if (id == 0 || id == getId()) + return true; + + return _isAncester(ctx, id); +} + +bool VMThread::_isAncester(ICtxVirtualMachine const& ctx, Id id) const +{ + assert(id != 0); + assert(id != getId()); + + if (id == thr_parent_id) + return true; + VMThread const* parent = ctx.findThread(thr_parent_id); + assert(parent != NULL); + return _isAncester(ctx, parent->getId()); +} + +void VMThread::notifyParentErased() +{ + Id new_parent_id = 0; + CSCR_VM_DPRINTF_THREAD(("thread move: id=%d, parent=%d -> %d\n", + static_cast(getId()), + static_cast(getParentId()), + static_cast(new_parent_id))); + + assert(thr_parent_id != 0); + thr_parent_id = new_parent_id; +} + +ANON_NAMESPACE_END + +// ------------------------------------------------------------------- +// 内部実装 +// ------------------------------------------------------------------- +class VirtualMachine::Impl + : private ISyscallVM + , private VMThread::ICtxVirtualMachine +{ +public: + Impl(Param const& param); + virtual ~Impl(); + void setCode(vm_tword_t const* code, size_t size); + void setUpcall(vm_upcall_t upcall_no, vm_taddr_t upcall_addr); + void setConst(vm_dword_t const* const_data, size_t size); + void setStaticDataSize(vm_dsize_t size); + void setStaticData(vm_daddr_t daddr, vm_dword_t dword); + void addLiteral(char const* s); + void setScrArgI(int idx, vm_int_t n); + void setScrArgF(int idx, vm_float_t f); + void setScrArgH(int idx, vm_handle_t h); + + bool run(); + bool upcall(vm_upcall_t upcall_no); + STATE getState() const { return m_common_reg.sw; } + char const* getError() const { return m_errmsg; } + +protected: + // ICtxVirtualMachine + virtual vm_int_t getScrArgI(vm_doffset_t offset) const; + virtual vm_float_t getScrArgF(vm_doffset_t offset) const; + virtual vm_handle_t getScrArgH(vm_doffset_t offset) const; + virtual char const* getScrArgS(vm_doffset_t offset) const; + virtual vm_taddr_t getScrArgT(vm_doffset_t offset) const; + + virtual void setScrRet(); + virtual void setScrRet(vm_int_t n); + virtual void setScrRet(vm_float_t f); + virtual void setScrRet(vm_handle_t h); + + // ISyscallVM + virtual void scr_sysPass(vm_int_t n); + virtual void scr_sysPassSec(vm_float_t sec); + virtual void scr_sysExit(); + virtual vm_int_t scr_sysGetArgI(vm_int_t idx); + virtual vm_float_t scr_sysGetArgF(vm_int_t idx); + virtual vm_handle_t scr_sysGetArgH(vm_int_t idx); + virtual vm_int_t scr_sysGetTime(); + virtual vm_float_t scr_sysGetTimeSec(); + virtual vm_int_t scr_sysThreadBegin(vm_taddr_t th_main); + virtual vm_int_t scr_sysThreadBeginTimeline(vm_taddr_t tl_main); + virtual void scr_sysThreadKill(vm_int_t tid); + virtual void scr_sysThreadKillAll(); + virtual void scr_sysThreadWait(vm_int_t tid); + virtual void scr_sysThreadWaitAll(); + virtual vm_int_t scr_sysThreadGetTime(); + virtual vm_float_t scr_sysThreadGetTimeSec(); +#ifndef NDEBUG + virtual void scr_sysDbStackDump(); + virtual void scr_sysDbTest(vm_int_t /*i*/, vm_float_t /*f*/) {} +#endif + + // VMThread::ICtxVirtualMachine + virtual VMThread const* findThread(VMThread::Id id) const + { + return _findThread(id); + } + +private: + /** + * VM全スレッド共有レジスタ + */ + struct CommonRegs + { + STATE sw; //< VM状態ワード + int run; //< VirtualMachine::run() 呼び出し回数 + int tick; //< 命令実行数 + }; + + /** + * VMデータ型変換用 共用体 + */ + union u + { + vm_dword_t d; + vm_int_t i; + vm_float_t f; + vm_handle_t h; + vm_dword_t d2h[sizeof(vm_handle_t) / sizeof(vm_dword_t)]; + vm_taddr_t t; + }; + + typedef boost::variant TSysArg; + + /** + * m_cur_thread メンバ変数を変数スコースに従ってセット/リセットする + * ヘルパクラス + */ + struct VMThreadResHolder + { + VMThreadResHolder(VirtualMachine::Impl& vm_impl, VMThread& thread) + : m_vm_impl(vm_impl) + { + m_vm_impl._setCurThread(&thread); + } + + ~VMThreadResHolder() + { + m_vm_impl._resetCurThread(); + } + + private: + VirtualMachine::Impl& m_vm_impl; + }; + friend struct VMThreadResHolder; + + Param const& m_param; //< VM実行時パラメタ + VMSyscallDispatcher const& m_vmd; //< VM内部システム関数ディスパッチャ + VMUserSyscallDispatcher const& m_uvmd; //< ユーザ定義システム関数ディスパッチャ + vm_tword_t const* m_code; //< VMバイトコードへのポインタ + size_t m_code_size; //< VMバイトコードへのサイズ (ワード数) + std::vector m_static_data; //< VM共通データ領域 + vm_dword_t const* m_const_data; //< VM共通定数テーブル領域 + size_t m_const_size; //< VM共通定数テーブルサイズ + std::vector m_literal_tbl; //< VM共通文字列リテラル + + CommonRegs m_common_reg; //< VMスレッド共通レジスタ + static size_t const EMSGBUFLEN = 128; //< エラー内容記憶領域のバッファサイズ + char m_errmsg[EMSGBUFLEN]; //< 最後に発生したエラー内容 + + typedef std::map VMUpcallMap; + VMUpcallMap m_upcall_map; //< Upcall番号と VM バイトコードアドレスの対応表 + + TSysArg m_sys_args[CSCR_VM_SYSARG_MAX]; //< C++側からVM実行開始前に渡されるパラメタ + VMThread::Id m_thread_id_next; //< 次回VMスレッド作成時に割り当てるID値 + VMThreadMap m_threads; //< VMスレッド IDとインスタンス対応表 + VMThread* m_cur_thread; //< 現在実行中のスレッド + + + /** + * システム関数番号に対応するシステム関数は VM 内部システム関数か + * + * @param sysno + * システム関数番号 + * @return + * VM 内部システム関数なら真、ユーザ定義システム関数なら偽 + */ + bool _isInternalSyscall(vm_sysno_t sysno) const + { + return + CSCR_VM_SYSNO_SYSFUNC_INTERNAL_BEGIN <= sysno && + sysno <= CSCR_VM_SYSNO_SYSFUNC_INTERNAL_END; + } + + /** + * エラーメッセージの作成 + * + * @param buf + * メッセージを書き込む記憶域 + * @param msg + * エラーメッセージの先頭に付ける内容 + */ + template + void _errmsg(char (&buf)[N], char const* msg) const + { + assert(msg != NULL); + + VMThread::Regs const& regs = _getThreadRegs(); + _snprintf(buf, N, "%s: tid=%d, pc=%d, pw=%08x", + msg, _getThreadId(), regs.pc, regs.pw + ); + } + + /** + * VM に VirtualMachine::setScrArg*() で設定した値を取得する + * + * @param idx + * 引数インデクス + * @return + * 引数値 + */ + template T _scrGetArg(vm_int_t idx) const; + + /** + * 実行中の VM スレッドをメンバ変数に設定する + * + * @param thread + * 実行中スレッド + * @note + * 直接この関数を呼び出さず VMThreadResHolder 経由で利用すること。 + */ + void _setCurThread(VMThread* thread) + { + assert(thread != NULL); + assert(m_cur_thread == NULL); + m_cur_thread = thread; + } + + /** + * 実行中 VM スレッドなしの状態にメンバ変数を設定する + * + * @note + * 直接この関数を呼び出さず VMThreadResHolder 経由で利用すること。 + */ + void _resetCurThread() + { + assert(m_cur_thread != NULL); + m_cur_thread = NULL; + } + + /** + * 実行中 VM スレッドのID値を取得する + * + * @return + * 実行中 VM スレッドのID値 + */ + VMThread::Id _getThreadId() const + { + assert(m_cur_thread != NULL); + return m_cur_thread->getId(); + } + + /** + * 実行中 VM スレッドの親スレッドID値を取得する + * + * @return + * 実行中 VM スレッドの親スレッドID値 + */ + VMThread::Id _getParentThreadId() const + { + assert(m_cur_thread != NULL); + return m_cur_thread->getParentId(); + } + + /** + * 実行中 VM スレッドは root スレッドか + * + * @return + * root upcall スレッドならば真、通常スレッドならば偽 + */ + bool _isRootThread() const + { + assert(m_cur_thread != NULL); + return m_cur_thread->isRoot(); + } + + /** + * 実行中 VM スレッドは upcall スレッドか + * + * @return + * upcall スレッドならば真、通常スレッドならば偽 + */ + bool _isUpcallThread() const + { + assert(m_cur_thread != NULL); + return m_cur_thread->isUpcall(); + } + + /** + * VMスレッドを追加する + * + * @apram parent_id + * 親 VM スレッドのID値 + * @return + * VMスレッドのインスタンス + * エラー時には NULL + */ + VMThread* _addThread(VMThread::Id parent_id); + + /** + * VM スレッドインスタンスを追加し、実行可能な状態に初期化する + * + * @param taddr + * VMスレッドが実行開始するバイトコードのアドレス値 + * @return + * 追加された VM スレッドの ID 値 + */ + VMThread::Id _beginThread(vm_taddr_t taddr); + + /** + * ID値に対応する VM スレッドを取得する + * + * @param id + * VM スレッドを識別する ID 値 + * @return + * VM スレッドのインスタンス + * 存在しない場合には NULL + */ + VMThread* _findThread(VMThread::Id id) + { + VMThreadMap::iterator i = m_threads.find(id); + return i == m_threads.end() ? NULL : &i->second; + } + + /** + * ID値に対応する VM スレッドを取得する + * + * @param id + * VM スレッドを識別する ID 値 + * @return + * VM スレッドのインスタンス + * 存在しない場合には NULL + */ + VMThread const* _findThread(VMThread::Id id) const + { + return const_cast(this)->_findThread(id); + } + + /** + * ID値に対応する VM スレッドが生きているか調べる + * + * @param id + * VM スレッドを識別する ID 値 + * @return + * スレッドが生きていれば真 + * halt 状態、もしくはインスタンス破棄後なら偽 + */ + bool _isThreadAlive(VMThread::Id id) const; + + /** + * ID値に対応する VM スレッドを終了させる + * + * @param id + * VM スレッドを識別する ID 値 + */ + void _haltThread(VMThread::Id id); + + /** + * ID値に対応する VM スレッドの子スレッドを全て再帰的に終了させる + * + * @param id + * VM スレッドを識別する ID 値 + */ + void _killThreadRecursive(VMThread::Id id); + + /** + * VMスレッドを全て実行する + */ + void _runThreads(); + + /** + * VM スレッドを実行する + * + * @param i + * 実行するスレッドを指すイテレータ + * @return + * 次に実行するスレッドのイテレータ + */ + VMThreadMap::iterator _runThread1(VMThreadMap::iterator i); + + /** + * Upcall VMスレッドを実行する + */ + void _runUpcallThread(); + + /** + * 実行中 VM スレッドのスレッド固有レジスタファイルを取得する + * + * @return + * 実行中スレッドのスレッド固有レジスタファイル + */ + VMThread::Regs& _getThreadRegs() + { + assert(m_cur_thread != NULL); + return m_cur_thread->thr_regs; + } + + /** + * 実行中 VM スレッドのスレッド固有レジスタファイルを取得する + * + * @return + * 実行中スレッドのスレッド固有レジスタファイル + */ + VMThread::Regs const& _getThreadRegs() const + { + return const_cast(this)->_getThreadRegs(); + } + + /** + * 実行中 VM スレッドのスタックを取得する + * + * @return + * 実行中 VM スレッドのスタック + */ + VMThread::Stack& _getThreadStack() + { + assert(m_cur_thread != NULL); + return m_cur_thread->thr_stack; + } + + /** + * 実行中 VM スレッドのスタックを取得する + * + * @return + * 実行中 VM スレッドのスタック + */ + VMThread::Stack const& _getThreadStack() const + { + return const_cast(this)->_getThreadStack(); + } + + /** + * 実行中 VM スレッドのスタック中1ワードを取得する + * + * @param addr + * VMスタックのワード取得対象アドレス + * @return + * 実行中 VM スレッドスタック中の指定ワード + */ + vm_dword_t& _getThreadStack(vm_daddr_t addr) + { + if (_getThreadStack().size() <= addr) + _throwStackAddrException(); + return _getThreadStack()[addr]; + } + + /** + * 実行中 VM スレッドのスタック中1ワードを取得する + * + * @param addr + * VMスタックのワード取得対象アドレス + * @return + * 実行中 VM スレッドスタック中の指定ワード + */ + vm_daddr_t _getThreadStack(vm_daddr_t addr) const + { + return const_cast(this)->_getThreadStack(addr); + } + + /** + * 実行中 VM スレッドのスタック中1ワードを取得する + * + * @param offset + * 対象ワード位置のスタックトップ相対アドレス + * @return + * 実行中 VM スレッドスタック中の指定ワード + */ + vm_dword_t& _peekTop(vm_doffset_t offset = 0) + { + return _getThreadStack(_getThreadRegs().sp - offset - 1); + } + + /** + * 実行中 VM スレッドのスタック中1ワードを取得する + * + * @param offset + * 対象ワード位置のスタックトップ相対アドレス + * @return + * 実行中 VM スレッドスタック中の指定ワード + */ + vm_dword_t _peekTop(vm_doffset_t offset = 0) const + { + return const_cast(this)->_peekTop(offset); + } + + /** + * 実行中 VM スレッドのスタックに値を積む + * + * @param n + * スレッドに積む値 + */ + void _push(vm_dword_t n) + { + _getThreadStack(_getThreadRegs().sp++) = n; + } + + /** + * 実行中 VM スレッドのスタックから値を取り除く + * + * @return + * VM スレッドから取り除かれたスタックトップ値 + */ + vm_dword_t _pop() + { + return _getThreadStack(--_getThreadRegs().sp); + } + + /** + * INST_syscall 実行時、 実行中 VM スレッドのスタックから + * INST_syscall オペランドで指定されたサイズの実引数を + * 取り除く。 + */ + void _popSyscallArgs(); + +#ifndef NDEBUG + /** + * 実行中 VM スレッドのスタックダンプを出力する + */ + void _dumpStack() const; +#endif + + /** + * VM実行時に送出される例外を補足して VM 状態ワードレジスタへの + * 値設定ならびにエラーメッセージ文字列設定に変換する。 + * + * @param f + * 実行するメンバ関数へのポインタ + */ + bool _exception_guard(void (Impl::*f)()); + + /** + * VM バイトコード 1 ワードを実行する + * + * @param tword + * 実行する VM バイトコード + */ + void _exec1(vm_tword_t tword); + + /** + * VM バイトコードのうちスタックへの読み書き命令を実行する + * + * @param opcode + * VM バイトコードオペコード部 + * @param opcode + * VM バイトコードオペランド部 + */ + inline void _exec2(vm_tword_opcode_t opcode, vm_tword_oprand_t oprand); + + /** + * VM バイトコードのうち整数演算命令を実行する + * + * @param opcode + * VM バイトコードオペランド部 + */ + inline vm_int_t _execOprInt(vm_tword_oprand_t oprand); + + /** + * VM バイトコードのうち整数からの型変換命令を実行する + * + * @param opcode + * VM バイトコードオペランド部 + */ + inline vm_dword_t _execOprIntConvert(vm_tword_oprand_t oprand); + + /** + * VM バイトコードのうち単精度浮動小数点数演算命令を実行する + * + * @param opcode + * VM バイトコードオペランド部 + */ + inline vm_float_t _execOprFloat(vm_tword_oprand_t oprand); + + /** + * VM バイトコードのうち単精度浮動小数点数からの型変換命令を実行する + * + * @param opcode + * VM バイトコードオペランド部 + */ + inline vm_dword_t _execOprFloatConvert(vm_tword_oprand_t oprand); + + /** + * VM バイトコード実行中 (_exec1 からの呼び出し中) に、実行を取り消し + * 再度同じ命令を実行できる状態に戻す。 + */ + void _rollbackExec(); + + // 例外送出 +#define CSCR_VM_EXCPT(excpt, state, msg) void _throw##excpt() const; +#include "vm_excpt.h" +}; + +template T VirtualMachine::Impl::_scrGetArg(vm_int_t idx) const +{ + if (idx < 0 || CSCR_VM_SYSARG_MAX < idx) + _throwSysargException(); + + T val; + try { + val = boost::get(m_sys_args[idx]); + } catch (boost::bad_get&) { + _throwSysargException(); + } + return val; +} + +VMThread* VirtualMachine::Impl::_addThread(VMThread::Id parent_id) +{ + assert(parent_id != VMThread::UPCALL_THREAD_ID); + // TODO 未使用のスレッドIDを探す + if (m_thread_id_next < 0) + _throwDescriptorException(); + + try { + VMThread vm_thread(parent_id, m_thread_id_next++); + + vm_thread.initStack(m_param.stack_size); + std::pair result = + m_threads.insert(std::make_pair(vm_thread.getId(), vm_thread)); + return result.second ? &result.first->second : NULL; + } catch (std::bad_alloc&) { + _throwBadAllocException(); + } + return NULL; +} + +VirtualMachine::Impl::Impl(Param const& param) + : m_param(param) + , m_vmd(VMSyscallDispatcher::GetInstance()) + , m_uvmd(VMUserSyscallDispatcher::GetInstance()) + , m_code(NULL) + , m_code_size(0) + , m_const_data(NULL) + , m_const_size(0) + , m_thread_id_next(0) + , m_cur_thread(NULL) +{ + memset(&m_common_reg, 0, sizeof(m_common_reg)); + m_errmsg[0] = '\0'; + +#ifndef NDEBUG + VMThread const* thread = +#endif + _addThread(VMThread::ROOT_THREAD_ID); + assert(thread->isRoot()); +} + +VirtualMachine::Impl::~Impl() +{} + +void VirtualMachine::Impl::setCode(vm_tword_t const* code, size_t size) +{ + assert(code != NULL); + assert(size > 0); + + m_code = code; + m_code_size = size; +} + +void VirtualMachine::Impl::setUpcall(vm_upcall_t upcall_no, vm_taddr_t upcall_addr) +{ + if (m_upcall_map.find(upcall_no) != m_upcall_map.end()) + CSCR_VM_DPRINTF(("overreide upcall : %d\n", upcall_no)); + m_upcall_map[upcall_no] = upcall_addr; +} + +void VirtualMachine::Impl::setConst(vm_dword_t const* const_data, size_t size) +{ + assert(const_data != NULL); + assert(size > 0); + + m_const_data = const_data; + m_const_size = size; +} + +void VirtualMachine::Impl::setStaticDataSize(vm_dsize_t size) +{ + m_static_data.resize(size); +} + +void VirtualMachine::Impl::setStaticData(vm_daddr_t daddr, vm_dword_t dword) +{ + if (m_static_data.size() <= daddr) { + assert(0); + return; + } + + m_static_data[daddr] = dword; +} + +void VirtualMachine::Impl::addLiteral(char const* s) +{ + assert(s != NULL); + m_literal_tbl.push_back(s); +} + +void VirtualMachine::Impl::setScrArgI(int idx, vm_int_t n) +{ + assert(0 <= idx); + assert(idx < CSCR_VM_SYSARG_MAX); + m_sys_args[idx] = n; +} + +void VirtualMachine::Impl::setScrArgF(int idx, vm_float_t f) +{ + assert(0 <= idx); + assert(idx < CSCR_VM_SYSARG_MAX); + m_sys_args[idx] = f; +} + +void VirtualMachine::Impl::setScrArgH(int idx, vm_handle_t h) +{ + assert(0 <= idx); + assert(idx < CSCR_VM_SYSARG_MAX); + m_sys_args[idx] = h; +} + +#define CSCR_VM_EXCPT(excpt, state, msg) \ +void VirtualMachine::Impl::_throw##excpt() const \ +{ \ + char buf[EMSGBUFLEN]; \ + _errmsg(buf, msg); \ + throw excpt(buf); \ +} +#include "vm_excpt.h" + +/* + * 仮想マシンの1命令を実行する。 + * + * @param tword + * 実行する命令 + */ +void VirtualMachine::Impl::_exec1(vm_tword_t tword) +{ + VMThread::Regs& regs = _getThreadRegs(); + regs.pw = tword; + vm_tword_opcode_t opcode = CSCR_VM_TWORD_OPCODE_GET(tword); + vm_tword_oprand_t oprand = CSCR_VM_TWORD_OPRAND_GET(tword); + + switch (opcode) { + case INST_nop: + break; + case INST_halt: + _getThreadRegs().halt = true; + break; + case INST_jump: + regs.pc = oprand; + break; + case INST_jump_if0: + if (!_pop()) + regs.pc = CSCR_VM_BRANCH_TADDR_GET(oprand); + break; + case INST_jump_if: + { + union u rhs = { _pop() }; + union u lhs = { _pop() }; + switch (CSCR_VM_BRANCH_OPR_GET(oprand)) { + +#define D(cond, op) \ + case D_OPR_##cond: if (!(lhs.i op rhs.i)) regs.pc = CSCR_VM_BRANCH_TADDR_GET(oprand); break + D(EQU, ==); D(NEQ, !=); D(LSS, <); + D(LEQ, <=); D(GTR, >); D(GEQ, >=); + D(AND, &); D(OR, |); D(XOR, ^); + D(LSH, <<); D(RSH, >>); +#undef D + default: + _throwInvalidOpcodeException(); + break; + } + } + break; + case INST_call: + _push(regs.pc); + regs.pc = oprand; + break; + case INST_lreturn: + { + vm_argsize_t argsize = CSCR_VM_TWORD_RETURN_ARGSIZE_GET(tword); + vm_retsize_t retsize = CSCR_VM_TWORD_RETURN_RETSIZE_GET(tword); + + vm_taddr_t prev_pc = _getThreadStack(regs.fp - 2); + vm_daddr_t prev_fp = _getThreadStack(regs.fp - 1); + vm_daddr_t prev_sp = regs.fp - 2 - argsize + retsize; + + // 戻り値を callee 側スタックトップから caller 側スタックトップにコピー + for (size_t i = 0; i < retsize; ++i) { + vm_daddr_t src = regs.sp - retsize + i; + vm_daddr_t dst = regs.fp - 2 - argsize + i; + _getThreadStack(dst) = _getThreadStack(src); + } + + regs.sp = prev_sp; + regs.fp = prev_fp; + regs.pc = prev_pc; + } + break; + case INST_return: + regs.pc = _pop(); + regs.sp -= CSCR_VM_TWORD_RETURN_ARGSIZE_GET(oprand); + break; + case INST_syscall: + { + vm_sysno_t sysno = CSCR_VM_TWORD_SYSCALL_SYSNO_GET(tword); + if (_isInternalSyscall(sysno)) { + if (!m_vmd.call(*this, sysno)) + _throwInvalidSyscallException(); + } else if (!m_uvmd.call(*this, sysno)) { + _throwInvalidSyscallException(); + } + } + break; + case INST_enter: + _push(regs.fp); + regs.fp = regs.sp; + regs.sp += oprand; + break; + case INST_push: + _push(oprand); + break; + case INST_sethi: + _peekTop() |= (oprand << CSCR_VM_TWORD_OPCODE_SHIFT); + break; + case INST_iandi: + _peekTop() &= oprand; + break; + case INST_iori: + _peekTop() |= oprand; + break; + case INST_ixori: + _peekTop() ^= oprand; + break; + case INST_irshifti: + _peekTop() >>= oprand; + break; + case INST_ilshifti: + _peekTop() <<= oprand; + break; + case INST_iaddi: + _peekTop() += oprand; + break; + case INST_isubi: + _peekTop() -= oprand; + break; + case INST_imuli: + _peekTop() *= oprand; + break; + case INST_idivi: + if (oprand == 0) + _throwDiv0Exception(); + _peekTop() /= oprand; + break; + case INST_imodi: + if (oprand == 0) + _throwDiv0Exception(); + _peekTop() %= oprand; + break; + case INST_shrink: + regs.sp -= oprand; + break; + case INST_get: + case INST_set: + case INST_iinc: + case INST_idec: + _exec2(opcode, oprand); + break; + case INST_opr_int: + if (D_GET_OPR_TYPE(oprand) == D_OPC) { + _push(_execOprIntConvert(oprand)); + } else { + union u u; + u.i = _execOprInt(oprand); + _push(u.d); + } + break; + case INST_opr_float: + if (D_GET_OPR_TYPE(oprand) == D_OPC) { + _push(_execOprFloatConvert(oprand)); + } else { + union u u; + u.f = _execOprFloat(oprand); + _push(u.d); + } + break; + default: + _throwInvalidSyscallException(); + } +} + +/* + * 仮想マシンの get, pop, set 命令を実行する + * + * @param opcode + * 実行対象命令のオペコード部 + * @param oprand + * 実行対象命令のオペランド部 + */ +void VirtualMachine::Impl::_exec2(vm_tword_opcode_t opcode, vm_tword_oprand_t oprand) +{ + VMThread::Regs& regs = _getThreadRegs(); + vm_dword_t* mem = NULL; + vm_dsize_t mem_size = 0; + + vm_doffset_t offset = CSCR_VM_OPRAND_OFFSET_GET(oprand); + vm_dsize_t size = CSCR_VM_OPRAND_SIZE_GET(oprand); + void (Impl::*throw_exception)() const = NULL; + + switch (CSCR_VM_OPRAND_BASEREG_GET(oprand)) { + case CSCR_VM_BASEREG_BP: + mem = &_getThreadStack(0); + mem_size = _getThreadStack().size(); + offset += regs.fp; + throw_exception = &Impl::_throwStackAddrException; + break; + case CSCR_VM_BASEREG_CP: + // 定数テーブルはリードオンリー + if (opcode != INST_get) + _throwInvalidOpcodeException(); + if (m_const_data == NULL) + _throwConstAddrException(); + mem = const_cast(m_const_data); + mem_size = m_const_size; + throw_exception = &Impl::_throwConstAddrException; + break; + case CSCR_VM_BASEREG_GP: + mem = &m_static_data[0]; + mem_size = m_static_data.size(); + throw_exception = &Impl::_throwDataAddrException; + break; + case CSCR_VM_BASEREG_SP: + mem = &_getThreadStack(0); + mem_size = _getThreadStack().size(); + offset += regs.sp; + throw_exception = &Impl::_throwStackAddrException; + break; + default: + _throwInvalidOpcodeException(); + } + + assert(mem != NULL); + assert(mem_size > 0); + assert(throw_exception != NULL); + + if (offset < 0 || mem_size < static_cast(offset) + size) + (this->*throw_exception)(); + + switch (opcode) { + case INST_get: + for (vm_doffset_t i = 0; i < size; ++i) + _push(mem[offset + i]); + break; + case INST_set: + for (vm_doffset_t i = 0; i < size; ++i) + mem[offset + i] = _peekTop(size - i - 1); + if (CSCR_VM_SET_SHRINK_GET(oprand)) + regs.sp -= size; + break; + case INST_iinc: + assert(size == 1); + ++mem[offset]; + break; + case INST_idec: + assert(size == 1); + --mem[offset]; + break; + default: + _throwInvalidOpcodeException(); + } +} + +VMThreadMap::iterator VirtualMachine::Impl::_runThread1(VMThreadMap::iterator i) +{ + VMThreadMap::iterator next_thread_iter = boost::next(i); + + VMThread& thread = i->second; + VMThreadResHolder holder(*this, thread); + VMThread::Regs& regs = _getThreadRegs(); + + for (int loop_count = 0; !regs.halt && regs.sleep == 0; ++m_common_reg.tick) { + if (0 < m_param.loop_count_max && m_param.loop_count_max < loop_count++) + _throwWatchDogException(); + + if (m_code_size <= regs.pc) + _throwCodeAddrException(); + +#ifdef CSCR_VM_VERBOSE_EXEC + printf("TID=%d, REG (pw:%08x pc:%04x bp:%04x sp:%04x run:%04x sleep:%04x tick:%04x)", + _getThreadId(), + static_cast(regs.pw), + static_cast(regs.pc), + regs.fp, regs.sp, m_common_reg.run, regs.sleep, m_common_reg.tick); + _dumpStack(); + printf("\n"); + printf("%d: %s\n\n", regs.pc, InstTable().toString(m_code[regs.pc]).c_str());; +#endif + + _exec1(m_code[regs.pc++]); + if (m_common_reg.sw != STATE_OK) + return next_thread_iter; + + // 実行中に新規スレッドが作成される可能性があるため、次スレッドを再計算 + next_thread_iter = boost::next(i); + } + + if (_getThreadRegs().sleep > 0) + --_getThreadRegs().sleep; + ++regs.run; + + if (_getThreadRegs().halt) { + if (_isRootThread()) { + m_common_reg.sw = STATE_HALT; + } else { + CSCR_VM_DPRINTF_THREAD(("thread exit: id=%d, parent=%d\n", + static_cast(_getThreadId()), + static_cast(_getParentThreadId()))); + + // 親スレッドから、自スレッドの情報削除 + VMThreadMap::iterator parent = m_threads.find(_getParentThreadId()); + assert(parent != m_threads.end()); + parent->second.eraseChild(_getThreadId()); + + // 子スレッドがあれば root スレッド直下に移動 + // XXX 実行終了させるべき? + for (std::set::const_iterator j = thread.children_begin(); + j != thread.children_end(); ++j) { + VMThreadMap::iterator child = m_threads.find(*j); + assert(child != m_threads.end()); + child->second.notifyParentErased(); + } + + // スレッド削除 + m_threads.erase(i); + } + } + + return next_thread_iter; +} + +bool VirtualMachine::Impl::_exception_guard(void (Impl::*f)()) +{ + try { + (this->*f)(); + } +#define CSCR_VM_EXCPT(excpt, state, msg) \ + catch (excpt& e) { \ + m_common_reg.sw = state; \ + _snprintf(m_errmsg, EMSGBUFLEN, "%s", e.what()); \ + } +#define CSCR_VM_EXCPT2(excpt, state) \ + catch (excpt& e) { \ + m_common_reg.sw = state; \ + _snprintf(m_errmsg, EMSGBUFLEN, "%s", e.what()); \ + } +#include "vm_excpt.h" + + ++m_common_reg.run; + return m_common_reg.sw == STATE_OK; +} + +void VirtualMachine::Impl::_runThreads() +{ + for (VMThreadMap::iterator i = m_threads.begin(); + i != m_threads.end() && m_common_reg.sw == STATE_OK; + i = _runThread1(i)) + ; +} + +bool VirtualMachine::Impl::run() +{ + return _exception_guard(&Impl::_runThreads); +} + +void VirtualMachine::Impl::_runUpcallThread() +{ + VMThread::Regs& regs = _getThreadRegs(); + + for (int loop_count = 0; !regs.halt && regs.sleep == 0; ++m_common_reg.tick) { + if (0 < m_param.loop_count_max && m_param.loop_count_max < loop_count++) + _throwWatchDogException(); + + if (m_code_size <= regs.pc) + _throwCodeAddrException(); + + _exec1(m_code[regs.pc++]); + if (m_common_reg.sw != STATE_OK) + return; + } + + // 割り込み処理ではブロッキング関数呼び出し不可 + if (_getThreadRegs().sleep > 0) + _throwInvalidSyscallException(); +} + +bool VirtualMachine::Impl::upcall(vm_upcall_t upcall_no) +{ + if (m_common_reg.sw != STATE_OK) { + CSCR_VM_DPRINTF(("upcall : invalid vm state : %d\n", m_common_reg.sw)); + return false; + } + + VMUpcallMap::const_iterator i = m_upcall_map.find(upcall_no); + if (i == m_upcall_map.end()) { + CSCR_VM_DPRINTF(("upcall : upcall_no not registerd [%d]\n", upcall_no)); + return false; + } + + VMThread thread(0, VMThread::UPCALL_THREAD_ID); + thread.initStack(m_param.stack_size); + + VMThreadResHolder holder(*this, thread); + VMThread::Regs& regs = _getThreadRegs(); + regs.pc = i->second; // upcall entry point (taddr) + _push(1); // taddr of INST_halt + assert(CSCR_VM_TWORD_OPCODE_GET(m_code[1]) == INST_halt); + + return _exception_guard(&Impl::_runUpcallThread); +} + +vm_int_t VirtualMachine::Impl::_execOprInt(vm_tword_oprand_t oprand) +{ + switch (D_GET_OPRAND(oprand)) { + case D_OP1: + { + union u u = { _pop() }; + vm_int_t x = u.i; + switch (D_GET_OPR_CODE(oprand)) { + case D_GET_OPR_CODE(OPR_test0): return !x; + case D_GET_OPR_CODE(OPR_not): return ~x; + case D_GET_OPR_CODE(OPR_neg): return -x; + case D_GET_OPR_CODE(OPR_abs): return std::abs(x); + } + } + break; + case D_OP2: + { + union u rhs = { _pop() }; + union u lhs = { _pop() }; + switch (D_GET_OPR_CODE(oprand)) { +#define D(subcode, opr) case D_GET_OPR_CODE(OPR_##subcode): return lhs.i opr rhs.i + D(equ, ==); D(neq, !=); D(lss, <); D(leq, <=); + D(gtr, >); D(geq, >=); + D(and, &); D(or, |); D(xor, ^); D(lshift, <<); D(rshift, >>); + D(add, +); D(sub, -); D(mul, *); +#undef D + case OPR_div: if (rhs.i == 0) _throwDiv0Exception(); return lhs.i / rhs.i; + case OPR_mod: if (rhs.i == 0) _throwDiv0Exception(); return lhs.i % rhs.i; + } + } + break; + } + + m_common_reg.sw = STATE_INVALID_OPCODE; + return 0; +} + +vm_dword_t VirtualMachine::Impl::_execOprIntConvert(vm_tword_oprand_t oprand) +{ + union u u = { _pop() }; + vm_int_t x = u.i; + switch (D_GET_OPR_CODE(oprand)) { + case OPR_float: + u.f = static_cast(x); + return u.d; + } + + m_common_reg.sw = STATE_INVALID_OPCODE; + return 0; +} + +vm_float_t VirtualMachine::Impl::_execOprFloat(vm_tword_oprand_t oprand) +{ + switch (D_GET_OPRAND(oprand)) { + case D_OP1: + { + union u u = { _pop() }; + vm_float_t x = u.f; + switch (D_GET_OPR_CODE(oprand)) { + case D_GET_OPR_CODE(OPR_neg): return -x; + case D_GET_OPR_CODE(OPR_abs): return std::abs(x); + } + } + break; + case D_OP2: + { + union u rhs = { _pop() }; + union u lhs = { _pop() }; + switch (D_GET_OPR_CODE(oprand)) { +#define D(subcode, opr) case D_GET_OPR_CODE(OPR_##subcode): return lhs.f opr rhs.f + D(equ, ==); D(neq, !=); D(lss, <); D(leq, <=); + D(gtr, >); D(geq, >=); + D(add, +); D(sub, -); D(mul, *); D(div, /); +#undef D + } + } + break; + } + + m_common_reg.sw = STATE_INVALID_OPCODE; + return 0; +} + +vm_dword_t VirtualMachine::Impl::_execOprFloatConvert(vm_tword_oprand_t oprand) +{ + union u u = { _pop() }; + vm_float_t x = u.f; + switch (D_GET_OPR_CODE(oprand)) { + case OPR_int: + u.i = static_cast(x); + return u.d; + } + + m_common_reg.sw = STATE_INVALID_OPCODE; + return 0; +} + +void VirtualMachine::Impl::_haltThread(VMThread::Id id) +{ + if (id == 0) { + CSCR_VM_DPRINTF(("_haltThread : cannot kill root thread\n")); + return; + } + if (id == _getThreadId()) { + CSCR_VM_DPRINTF(("_haltThread : cannot kill myself\n")); + return; + } + + VMThread* thread = _findThread(id); + if (thread == NULL) { + CSCR_VM_DPRINTF(("_haltThread() : thread not found : id=%d\n", id)); + return; + } + if (!thread->isAncester(*this, _getThreadId())) { + CSCR_VM_DPRINTF(("_haltThread(): cannot kill non-descendant thread\n")); + return; + } + if (thread->thr_regs.halt) { + CSCR_VM_DPRINTF(("_haltThread(): thread already halted : id=%d\n", static_cast(id))); + return; + } + + thread->thr_regs.halt = true; +} + +void VirtualMachine::Impl::_rollbackExec() +{ + --_getThreadRegs().pc; + _getThreadRegs().sleep = 1; + + // setScrRet() でシステム関数の実引数が pop() されるのを打ち消す + VMThread::Regs& regs = _getThreadRegs(); + + vm_tword_t tword = regs.pw; + assert(CSCR_VM_TWORD_OPCODE_GET(tword) == INST_syscall); + vm_dsize_t argsize = CSCR_VM_TWORD_SYSCALL_ARGSIZE_GET(tword); + + regs.sp += argsize; +} + +bool VirtualMachine::Impl::_isThreadAlive(VMThread::Id tid) const +{ + VMThread const* thread = _findThread(tid); + if (thread == NULL) + return false; + if (thread->thr_regs.halt) + return false; + return true; +} + +VMThread::Id VirtualMachine::Impl::_beginThread(vm_taddr_t taddr) +{ + VMThread* child = _addThread(_getThreadId()); + if (child == NULL) + return 0; + + assert(_getThreadId() == child->getParentId()); + CSCR_VM_DPRINTF_THREAD(("thread begin: id=%d, parent=%d\n", + static_cast(child->getId()), + static_cast(_getThreadId()))); + + try { + m_cur_thread->addChild(child->getId()); + } catch (std::bad_alloc&) { + _throwBadAllocException(); + } + child->thr_stack[child->thr_regs.sp++] = 1; + child->thr_regs.pc = taddr; + + assert(CSCR_VM_TWORD_OPCODE_GET(m_code[1]) == INST_halt); + return child->getId(); +} + +void VirtualMachine::Impl::_killThreadRecursive(VMThread::Id id) +{ + VMThread* thread = _findThread(id); + assert(thread != NULL); + if (thread->thr_regs.halt) { + CSCR_VM_DPRINTF(("_killThreadRecursive : thread already halted : id=%d\n", static_cast(id))); + return; + } + std::for_each( + thread->children_begin(), + thread->children_end(), + boost::bind(&Impl::_killThreadRecursive, this, ::_1) + ); + _haltThread(id); +} + +// ISyscallVM +void VirtualMachine::Impl::scr_sysPass(vm_int_t n) +{ + if (_isUpcallThread()) + _throwInvalidSyscallException(); + + assert(n > 0); + if (n > 0) + _getThreadRegs().sleep = n; +} + +void VirtualMachine::Impl::scr_sysPassSec(vm_float_t sec) +{ + if (_isUpcallThread()) + _throwInvalidSyscallException(); + + assert(sec > 0); + if (sec > 0.0f) + _getThreadRegs().sleep = static_cast(CSCR_FRAMES_PER_SEC * sec); +} + +void VirtualMachine::Impl::scr_sysExit() +{ + assert(m_cur_thread != NULL); + assert(m_common_reg.sw == STATE_OK); + _getThreadRegs().halt = true; +} + +vm_int_t VirtualMachine::Impl::scr_sysGetArgI(vm_int_t idx) +{ + return _scrGetArg(idx); +} + +vm_float_t VirtualMachine::Impl::scr_sysGetArgF(vm_int_t idx) +{ + return _scrGetArg(idx); +} + +vm_handle_t VirtualMachine::Impl::scr_sysGetArgH(vm_int_t idx) +{ + return _scrGetArg(idx); +} + +vm_int_t VirtualMachine::Impl::scr_sysGetTime() +{ + return m_common_reg.run; +} + +vm_float_t VirtualMachine::Impl::scr_sysGetTimeSec() +{ + return m_common_reg.run / CSCR_FRAMES_PER_SEC; +} + +vm_int_t VirtualMachine::Impl::scr_sysThreadBegin(vm_taddr_t th_main) +{ + if (_isUpcallThread()) + _throwInvalidSyscallException(); + + return _beginThread(th_main); +} + +vm_int_t VirtualMachine::Impl::scr_sysThreadBeginTimeline(vm_taddr_t tl_main) +{ + if (_isUpcallThread()) + _throwInvalidSyscallException(); + + return _beginThread(tl_main); +} + +void VirtualMachine::Impl::scr_sysThreadKill(vm_int_t tid) +{ + if (_isUpcallThread()) + _throwInvalidSyscallException(); + + if (tid == 0) { + CSCR_VM_DPRINTF(("sysThreadKill : cannot kill root thread\n")); + return; + } + _haltThread(tid); +} + +void VirtualMachine::Impl::scr_sysThreadKillAll() +{ + if (_isUpcallThread()) + _throwInvalidSyscallException(); + + std::for_each( + m_cur_thread->children_begin(), + m_cur_thread->children_end(), + boost::bind(&Impl::_killThreadRecursive, this, ::_1) + ); +} + +void VirtualMachine::Impl::scr_sysThreadWait(vm_int_t tid) +{ + if (_isUpcallThread()) + _throwInvalidSyscallException(); + + if (tid == 0) { + CSCR_VM_DPRINTF(("sysThreadWait : cannot wait root thread\n")); + return; + } + CSCR_VM_DPRINTF_THREAD(("sysThreadWait : tid = %d\n", tid)); + if (_isThreadAlive(tid)) + _rollbackExec(); +} + +void VirtualMachine::Impl::scr_sysThreadWaitAll() +{ + if (_isUpcallThread()) + _throwInvalidSyscallException(); + + CSCR_VM_DPRINTF_THREAD(("sysThreadWaitAll\n")); + + if (std::find_if( + m_cur_thread->children_begin(), + m_cur_thread->children_end(), + boost::bind(&Impl::_isThreadAlive, this, ::_1) + ) != m_cur_thread->children_end()) + _rollbackExec(); +} + +vm_int_t VirtualMachine::Impl::scr_sysThreadGetTime() +{ + if (_isUpcallThread()) + _throwInvalidSyscallException(); + + return _getThreadRegs().run; +} + +vm_float_t VirtualMachine::Impl::scr_sysThreadGetTimeSec() +{ + if (_isUpcallThread()) + _throwInvalidSyscallException(); + + return _getThreadRegs().run / CSCR_FRAMES_PER_SEC; +} + +#ifndef NDEBUG +void VirtualMachine::Impl::_dumpStack() const +{ + VMThread::Stack const& tstack = _getThreadStack(); + + for (vm_daddr_t i = 0; i < tstack.size(); ++i) { + if ((i & 0x7) == 0) + printf("\n%04x:", i); + printf(" %08x", static_cast(tstack[i])); + } + putchar('\n'); +} + +void VirtualMachine::Impl::scr_sysDbStackDump() +{ + VMThread::Regs const& regs = _getThreadRegs(); + printf("STACK DUMP\n\n"); + printf("REG (pw:%08x pc:%04x bp:%04x sp:%04x run:%04x sleep:%04x tick:%04x)\n", + static_cast(regs.pw), + static_cast(regs.pc), + regs.fp, regs.sp, m_common_reg.run, regs.sleep, m_common_reg.tick); + + _dumpStack(); +} +#endif // !NDEBUG + +// ICtxVirtualMachine +vm_int_t VirtualMachine::Impl::getScrArgI(vm_doffset_t offset) const +{ + union u u; + u.d = _peekTop(offset); + return u.i; +} + +vm_float_t VirtualMachine::Impl::getScrArgF(vm_doffset_t offset) const +{ + union u u; + u.d = _peekTop(offset); + return u.f; +} + +vm_handle_t VirtualMachine::Impl::getScrArgH(vm_doffset_t offset) const +{ + union u u; + for (size_t i = 0; i < NELEM(u.d2h); ++i) + u.d2h[i] = _peekTop(offset + NELEM(u.d2h) - 1 - i); + return u.h; +} + +char const* VirtualMachine::Impl::getScrArgS(vm_doffset_t offset) const +{ + vm_dword_t no = _peekTop(offset); + if (m_literal_tbl.size() <= no) + _throwLiteralException(); + return m_literal_tbl[no]; +} + +vm_taddr_t VirtualMachine::Impl::getScrArgT(vm_doffset_t offset) const +{ + union u u; + u.d = _peekTop(offset); + return u.t; +} + +void VirtualMachine::Impl::_popSyscallArgs() +{ + VMThread::Regs& regs = _getThreadRegs(); + + vm_tword_t tword = regs.pw; + assert(CSCR_VM_TWORD_OPCODE_GET(tword) == INST_syscall); + vm_dsize_t argsize = CSCR_VM_TWORD_SYSCALL_ARGSIZE_GET(tword); + + regs.sp -= argsize; +} + +void VirtualMachine::Impl::setScrRet() +{ + _popSyscallArgs(); +} + +void VirtualMachine::Impl::setScrRet(vm_int_t n) +{ + _popSyscallArgs(); + + union u u; + u.i = n; + _push(u.d); +} + +void VirtualMachine::Impl::setScrRet(vm_float_t f) +{ + _popSyscallArgs(); + + union u u; + u.f = f; + _push(u.d); +} + +void VirtualMachine::Impl::setScrRet(vm_handle_t h) +{ + _popSyscallArgs(); + + union u u; + u.h = h; + for (size_t i = 0; i < NELEM(u.d2h); ++i) + _push(u.d2h[i]); +} + +// ------------------------------------------------------------------- +// 公開インターフェース +// ------------------------------------------------------------------- +VirtualMachine::VirtualMachine(Param const& param) + : m_impl(new Impl(param)) +{} + +VirtualMachine::~VirtualMachine() +{} + +bool VirtualMachine::setByteCode(void const* p, size_t size) +{ + assert(p != NULL); + + VirtualMachineLoader loader; + if (!loader.load(p, size)) + return false; + + // CODE + m_impl->setCode(loader.getCode(), loader.getCodeSize()); + + // UPCALL + size_t upcall_size = loader.getUpcallSize(); + for (size_t i = 0; i < upcall_size; ++i) { + std::pair d = loader.getUpcall(i); + m_impl->setUpcall(d.first, d.second); + } + + // STATIC_DATA + m_impl->setStaticDataSize(loader.getStaticDataSize()); + size_t static_data_max = loader.getInitDataSize(); + for (size_t i = 0; i < static_data_max; ++i) { + std::pair d = loader.getInitData(i); + m_impl->setStaticData(d.first, d.second); + } + + // CONST_DATA + size_t const_size = loader.getConstSize(); + if (const_size > 0) + m_impl->setConst(loader.getConst(), const_size); + + // LITERAL + vm_literal_t literal_max = loader.getLiteralSize(); + for (vm_literal_t i = 0; i < literal_max; ++i) + m_impl->addLiteral(loader.getLiteral(i)); + + return true; +} + +void VirtualMachine::setScrArgI(int idx, vm_int_t n) +{ + m_impl->setScrArgI(idx, n); +} + +void VirtualMachine::setScrArgF(int idx, vm_float_t f) +{ + m_impl->setScrArgF(idx, f); +} + +void VirtualMachine::setScrArgH(int idx, vm_handle_t h) +{ + m_impl->setScrArgH(idx, h); +} + +bool VirtualMachine::run() +{ + return m_impl->run(); +} + +bool VirtualMachine::upcall(vm_upcall_t upcall_no) +{ + return m_impl->upcall(upcall_no); +} + +VirtualMachine::STATE VirtualMachine::getState() const +{ + return m_impl->getState(); +} + +char const* VirtualMachine::getError() const +{ + return m_impl->getError(); +} + +CSCRIPT_NAMESPACE_END + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,167 @@ +/* + * コンパイラ 仮想機械 + * $Id: vm.h 446 2007-06-05 11:18:59Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef VM_H__INCLUDED +#define VM_H__INCLUDED + +#include "cscript.h" +#include "vm_cast.h" + +CSCRIPT_NAMESPACE_BEGIN + +class VirtualMachine +{ +public: + static size_t const DEFAULT_STACK_SIZE = 64; + static int const DEFAULT_LOOP_COUNT_MAX = 512; + + /** + * 仮想マシン内部状態 + */ + enum STATE + { + STATE_OK = 0, + STATE_HALT = 1, + + STATE_CODE_FAULT = -1, + STATE_STACK_FAULT = -2, + STATE_DATA_FAULT = -3, + STATE_CONST_FAULT = -4, + STATE_SYSARG_FAULT = -5, + STATE_INVALID_SYSCALL = -10, + STATE_INVALID_OPCODE = -11, + STATE_INVALID_LITERAL = -13, + STATE_DIVISION_BY_ZERO = -14, + STATE_INFINITE_LOOP = -20, + STATE_CANNOT_MEMALLOC = -30, + STATE_CANNOT_THRALLOC = -31, + }; + + struct Param + { + vm_dsize_t stack_size; + int loop_count_max; + + Param(vm_dsize_t stack_size0 = DEFAULT_STACK_SIZE, int loop_count_max0 = DEFAULT_LOOP_COUNT_MAX) + : stack_size(stack_size0) + , loop_count_max(loop_count_max0) + {} + }; + + /** + * 仮想マシンのインスタンスを構築する + */ + VirtualMachine(Param const& param = Param()); + + /** + * 仮想マシンのインスタンスを破棄する + */ + ~VirtualMachine(); + + /** + * コンパイル済バイトコードを解析し、仮想マシンが実行を開始できるようにする。 + * + * @param p + * バイトコードの先頭アドレス + * @param size + * バイトコードのサイズ (バイト単位) + * @return + * バイトコードに異常がある場合は偽 + * @note + * 引数で渡したバイトコードは VirtualMachine 実行中常に参照される。 + * インスタンスを破棄するまでバイトコードを解放しないこと。 + */ + bool setByteCode(void const* p, size_t size); + + /** + * 仮想マシンに引き渡す引数を設定する。ここで設定した値は、仮想マシン + * 側でシステム関数 sysGetArgI() を呼び出すことで取得できる。 + * + * @param idx + * 実引数番号 + * @param n + * 実引数値 + */ + void setScrArgI(int idx, vm_int_t n); + + /** + * 仮想マシンに引き渡す引数を設定する。ここで設定した値は、仮想マシン + * 側でシステム関数 sysGetArgF() を呼び出すことで取得できる。 + * + * @param idx + * 実引数番号 + * @param n + * 実引数値 + */ + void setScrArgF(int idx, vm_float_t f); + + /** + * 仮想マシンに引き渡す引数を設定する。ここで設定した値は、仮想マシン + * 側でシステム関数 sysGetArgH() を呼び出すことで取得できる。 + * + * @param idx + * 実引数番号 + * @param n + * 実引数値 + */ + void setScrArgH(int idx, vm_handle_t h); + + /* + * 仮想マシンを実行する + * + * 戻り値 + * 実行継続中の場合は ture, そうでない場合は false + * 正常終了/エラー終了の区別は getState() の戻り値を見て判断すること + */ + bool run(); + + /* + * 仮想マシンに割り込みをかける + * + * @param upcall_no + * 割り込み番号 + */ + bool upcall(vm_upcall_t upcall_no); + + /** + * 仮想マシン状態を取得する + */ + STATE getState() const; + + /** + * 仮想マシンがエラー状態の場合に、エラー情報を取得する + */ + char const* getError() const; + +private: + class Impl; + boost::scoped_ptr m_impl; +}; + +CSCRIPT_NAMESPACE_END + +#endif // VM_H__INCLUDED + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_cast.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,103 @@ +/* + * CScript コンパイラ 仮想マシン + * $Id: vm_cast.h 382 2007-04-19 09:43:45Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef VM_CAST_H__INCLUDED +#define VM_CAST_H__INCLUDED + +#include "cscript.h" + +CSCRIPT_NAMESPACE_BEGIN + +/// 仮想マシンのコード領域アドレス型 +typedef boost::uint32_t vm_taddr_t; +/// 仮想マシンのコード領域アドレスのオフセット値 +typedef boost::int32_t vm_poffset_t; +/// 仮想マシンのコード領域におけるデータサイズ +typedef boost::uint32_t vm_psize_t; + +typedef boost::uint32_t vm_tword_t; // 32bit +typedef boost::uint8_t vm_tword_opcode_t; // 上位8bit +typedef boost::uint32_t vm_tword_oprand_t; // 下位24bit +#define CSCR_VM_TWORD_OPCODE_SHIFT (24) +#define CSCR_VM_TWORD_OPCODE_GET(x) static_cast(((x) >> 24) & 0xff) +#define CSCR_VM_TWORD_OPRAND_GET(x) static_cast((x) & 0x00ffffff) +#define CSCR_VM_TWORD(opcode, oprand) static_cast((opcode) << 24 | (oprand)) + +/// 仮想マシンのデータ領域アドレス型 +typedef boost::uint16_t vm_daddr_t; +/// 仮想マシンのデータ領域アドレスのオフセット値 +typedef boost::int16_t vm_doffset_t; +/// 仮想マシン load/store命令中のベースレジスタ指定値 +enum vm_basereg_t +{ + CSCR_VM_BASEREG_GP, //< グローバルデータ + CSCR_VM_BASEREG_BP, //< スタックフレームポインタ + CSCR_VM_BASEREG_SP, //< スタックポインタ + CSCR_VM_BASEREG_CP, //< 定数テーブルポインタ +}; +/// 仮想マシンのデータ領域におけるデータサイズ +typedef boost::uint16_t vm_dsize_t; +/// 仮想マシンの定数プール領域アドレス +typedef boost::uint16_t vm_const_t; +/// 仮想マシンのリテラルデータ領域アドレス +typedef boost::uint16_t vm_literal_t; +/// 仮想マシンワード型 +typedef boost::uint32_t vm_dword_t; +/// 仮想マシンの引数サイズ +typedef boost::uint8_t vm_argsize_t; +/// 仮想マシンの関数戻り値サイズ +typedef boost::uint8_t vm_retsize_t; +/// 二項論理演算種別 +typedef boost::uint8_t vm_opr2l_t; + +/// 仮想マシンの型に対応する C++ 型 +typedef boost::int32_t vm_int_t; +typedef float vm_float_t; +typedef void* vm_handle_t; +typedef boost::uint16_t vm_sysno_t; +typedef boost::int32_t vm_upcall_t; + +#define CSCR_VM_RETURN_ARGSIZE_MAX (255) +#define CSCR_VM_RETURN_RETSIZE_MAX (255) +#define CSCR_VM_TWORD_RETURN_ARGSIZE_GET(x) static_cast(((x) >> 8) & 0xff) +#define CSCR_VM_TWORD_RETURN_RETSIZE_GET(x) static_cast((x) & 0xff) + +#define CSCR_VM_SYSCALL_ARGSIZE_MAX (255) +#define CSCR_VM_TWORD_SYSCALL_SYSNO_GET(x) static_cast(((x) & 0x0000ffff)) +#define CSCR_VM_TWORD_SYSCALL_ARGSIZE_GET(x) static_cast(((x) >> 16) & 0xff) + +#define CSCR_VM_OPRAND_BASEREG_GET(x) (((x) >> 22) & 0x03) +#define CSCR_VM_OPRAND_SIZE_GET(x) (1U << (((x) >> 16) & 0x03)) +#define CSCR_VM_OPRAND_OFFSET_GET(x) static_cast(((x) & 0xffff)) +#define CSCR_VM_SET_SHRINK_GET(x) (((x) >> 21) & 0x1) +#define CSCR_VM_SET_SHRINK_SET(x) ((x) |= (1U << 21)) + +#define CSCR_VM_BRANCH_OPR_GET(x) static_cast(((x) >> 16) & 0xff) +#define CSCR_VM_BRANCH_TADDR_GET(x) static_cast((x) & 0xffff) + +CSCRIPT_NAMESPACE_END + +#endif // VM_CAST_H__INCLUDED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_ctx.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,75 @@ +/* + * コンパイラ 仮想機械 システム関数実行コンテクスト + * $Id: vm.h 446 2007-06-05 11:18:59Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef VM_CTX_H__INCLUDED +#define VM_CTX_H__INCLUDED + +#include "cscript.h" +#include "vm_cast.h" + +CSCRIPT_NAMESPACE_BEGIN + +class VMUserSyscallDispatcher; + +/** + * システム関数実行コンテクスト + */ +struct ICtxVirtualMachine +{ + virtual ~ICtxVirtualMachine() {} + + /** + * スクリプトからシステム関数への実引数を取得する。 + * + * @param offset + * スタックトップからのオフセット値 + * @return + * 実引数値 + */ + virtual vm_int_t getScrArgI(vm_doffset_t offset) const = 0; + virtual vm_float_t getScrArgF(vm_doffset_t offset) const = 0; + virtual vm_handle_t getScrArgH(vm_doffset_t offset) const = 0; + virtual char const* getScrArgS(vm_doffset_t offset) const = 0; + virtual vm_taddr_t getScrArgT(vm_doffset_t offset) const = 0; + + /** + * スクリプトからシステム関数への実引数を解放し、システム関数からi + * スクリプトへの戻り値を VM に設定する。 + * + * @note + * 1回のシステム関数呼び出しに対して、いずれかの setScrRet() を + * 1回だけ呼ぶこと。 + */ + virtual void setScrRet() = 0; + virtual void setScrRet(vm_int_t n) = 0; + virtual void setScrRet(vm_float_t f) = 0; + virtual void setScrRet(vm_handle_t h) = 0; +}; + +CSCRIPT_NAMESPACE_END + +#endif // VM_CTX_H__INCLUDED + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_excpt.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,45 @@ +/* + * VM 実行時例外 (VM外部には送出されない) + * $Id: vm.cc 454 2007-06-06 13:58:50Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef CSCR_VM_EXCPT +# define CSCR_VM_EXCPT(excpt, state, msg) +#endif + +// VM 内部で定義する例外 +CSCR_VM_EXCPT(CodeAddrException, STATE_CODE_FAULT, "VM code address fault") +CSCR_VM_EXCPT(ConstAddrException, STATE_CONST_FAULT, "VM constant address fault") +CSCR_VM_EXCPT(DataAddrException, STATE_DATA_FAULT, "VM data address fault") +CSCR_VM_EXCPT(DescriptorException, STATE_CANNOT_THRALLOC, "VM thread exhausted") +CSCR_VM_EXCPT(Div0Exception, STATE_DIVISION_BY_ZERO, "VM division by zero") +CSCR_VM_EXCPT(InvalidOpcodeException, STATE_INVALID_OPCODE, "VM invalid opcode") +CSCR_VM_EXCPT(InvalidSyscallException, STATE_INVALID_SYSCALL, "VM invalid syscall") +CSCR_VM_EXCPT(LiteralException, STATE_INVALID_LITERAL, "VM invalid literal") +CSCR_VM_EXCPT(StackAddrException, STATE_STACK_FAULT, "VM stack fault") +CSCR_VM_EXCPT(SysargException, STATE_SYSARG_FAULT, "VM sysarg fault") +CSCR_VM_EXCPT(WatchDogException, STATE_INFINITE_LOOP, "VM watchdog timer exceeded") +CSCR_VM_EXCPT(BadAllocException, STATE_CANNOT_MEMALLOC, "VM cannot allocate memory") + +#undef CSCR_VM_EXCPT --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_loader.cc Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,275 @@ +/* + * CScript コンパイラ バイトコードローダ + * $Id: vm_loader.cc 402 2007-05-09 13:42:53Z issei $ + * + * Copyright (c) 2006, 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "stdafx.h" +#include "vm_loader.h" + +inline void* offset(void* p, size_t len) +{ + return reinterpret_cast(reinterpret_cast(p) + len); +} + +inline void const* offset(void const* p, size_t len) +{ + return reinterpret_cast(reinterpret_cast(p) + len); +} + +CSCRIPT_NAMESPACE_BEGIN + +VirtualMachineLoader::VirtualMachineLoader() + : m_header(NULL) + , m_code(NULL) + , m_upcall(NULL) + , m_static_data(NULL) + , m_literal_ptr(NULL) + , m_literal_data(NULL) + , m_const_data(NULL) +{} + +VirtualMachineLoader::~VirtualMachineLoader() +{} + +bool VirtualMachineLoader::load(void const* p, size_t len) +{ + assert(p != NULL); + + if (!_loadHeader(reinterpret_cast(p), &len)) + return false; + + File::Info const* pInfo = reinterpret_cast(offset(p, sizeof(File::Header))); + for (;;) { + switch (pInfo->section) { +#define D(section, pmv, pmf) \ + case File::section: \ + if (pmv != NULL) { \ + fprintf(stderr, "Duplicate " #section " section\n"); \ + return false; \ + } \ + if (!pmf(pInfo, &len)) \ + return false; \ + break + + D(SECTION_CODE, m_code, _loadCode); + D(SECTION_UPCALL, m_upcall, _loadUpcall); + D(SECTION_STATIC_DATA, m_static_data, _loadStaticData); + D(SECTION_LITERAL_DATA, m_literal_data, _loadLiteralData); + D(SECTION_LITERAL_PTR, m_literal_ptr, _loadLiteralPtr); + D(SECTION_CONST_DATA, m_const_data, _loadConstData); +#undef D + case File::SECTION_TRAILER: + goto out_of_loop; + default: + fprintf(stderr, "Unknown section [%d], skip\n", static_cast(pInfo->section)); + break; + } + pInfo = reinterpret_cast(offset(pInfo, sizeof(File::Info) + pInfo->size)); + } +out_of_loop: + return true; +} + +bool VirtualMachineLoader::_loadHeader(File::Header const* p, size_t* plen) +{ + assert(m_header == NULL); + assert(p != NULL); + assert(plen != NULL); + + if (*plen < sizeof(File::Header)) { + fprintf(stderr, "Header broken\n"); + return false; + } + + if (memcmp(p->magic, File::MAGIC, sizeof(p->magic) != 0)) { + fprintf(stderr, "Invalid magic\n"); + return false; + } + + if (p->version_major != File::VERSION_MAJOR) { + fprintf(stderr, "Version unmatch (major)\n"); + return false; + } + + if (File::VERSION_MINOR < p->version_minor) { + fprintf(stderr, "Version unmatch (minor)\n"); + return false; + } + + m_header = p; + *plen -= sizeof(File::Header); + + return true; +} + +template +static bool _loadSection(T const** pp, File::Info const* p, size_t* plen, File::SECTION_TYPE section) +{ + assert(pp != NULL); + assert(p != NULL); + assert(plen != NULL); + + if (*plen < sizeof(File::Info) + sizeof(T)) { + fprintf(stderr, "Header broken [section=%d]\n", static_cast(section)); + return false; + } + assert(p->section == section); + + T const* q = reinterpret_cast(offset(p, sizeof(File::Info))); + if (*plen < p->size) { + fprintf(stderr, "Body too short [section=%d]\n", static_cast(section)); + return false; + } + + boost::crc_32_type checksum; + checksum.process_bytes(q, p->size); + if (p->checksum != checksum.checksum()) { + fprintf(stderr, "CheckSum mismatch [section=%d]\n", static_cast(section)); + return false; + } + + *plen -= sizeof(File::Info) + p->size; + *pp = q; + return true; +} + +bool VirtualMachineLoader::_loadCode(File::Info const* p, size_t* plen) +{ + return _loadSection(&m_code, p, plen, File::SECTION_CODE); +} + +bool VirtualMachineLoader::_loadUpcall(File::Info const* p, size_t* plen) +{ + return _loadSection(&m_upcall, p, plen, File::SECTION_UPCALL); +} + +bool VirtualMachineLoader::_loadStaticData(File::Info const* p, size_t* plen) +{ + return _loadSection(&m_static_data, p, plen, File::SECTION_STATIC_DATA); +} + +bool VirtualMachineLoader::_loadConstData(File::Info const* p, size_t* plen) +{ + return _loadSection(&m_const_data, p, plen, File::SECTION_CONST_DATA); +} + +bool VirtualMachineLoader::_loadLiteralData(File::Info const* p, size_t* plen) +{ + if (!_loadSection(&m_literal_data, p, plen, File::SECTION_LITERAL_DATA)) + return false; + if (m_literal_data->data[m_literal_data->count - 1] != '\0') + return false; + return true; +} + +bool VirtualMachineLoader::_loadLiteralPtr(File::Info const* p, size_t* plen) +{ + return _loadSection(&m_literal_ptr, p, plen, File::SECTION_LITERAL_PTR); +} + +boost::uint32_t VirtualMachineLoader::getVersionMajor() const +{ + assert(m_header != NULL); + return m_header->version_major; +} + +boost::uint32_t VirtualMachineLoader::getVersionMinor() const +{ + assert(m_header != NULL); + return m_header->version_minor; +} + +vm_tword_t const* VirtualMachineLoader::getCode() const +{ + assert(m_code != NULL); + return m_code->code; +} + +vm_psize_t VirtualMachineLoader::getCodeSize() const +{ + assert(m_code != NULL); + return m_code->count; +} + +size_t VirtualMachineLoader::getUpcallSize() const +{ + return m_upcall == NULL ? 0 : m_upcall->count; +} + +std::pair VirtualMachineLoader::getUpcall(size_t index) const +{ + assert(m_upcall != NULL); + assert(index < m_upcall->count); + return m_upcall->data[index]; +} + +size_t VirtualMachineLoader::getStaticDataSize() const +{ + return m_static_data == NULL ? 0 : m_static_data->count; +} + +size_t VirtualMachineLoader::getInitDataSize() const +{ + return m_static_data == NULL ? 0 : m_static_data->init_count; +} + +std::pair VirtualMachineLoader::getInitData(size_t index) const +{ + assert(m_static_data != NULL); + assert(index < getInitDataSize()); + + File::StaticData::Node const& node = m_static_data->init_data[index]; + return std::make_pair(node.daddr, node.dword); +} + +vm_literal_t VirtualMachineLoader::getLiteralSize() const +{ + return m_literal_ptr == NULL ? 0 : m_literal_ptr->count; +} + +char const* VirtualMachineLoader::getLiteral(vm_literal_t no) const +{ + assert(m_literal_data != NULL); + assert(m_literal_ptr != NULL); + + assert(no < m_literal_ptr->count); + boost::uint16_t offset = m_literal_ptr->offset[no]; + if (m_literal_data->count <= offset) { + assert(0); + return NULL; + } + return &m_literal_data->data[offset]; +} + +vm_dword_t const* VirtualMachineLoader::getConst() const +{ + return m_const_data == NULL ? 0 : m_const_data->data; +} + +vm_const_t VirtualMachineLoader::getConstSize() const +{ + return m_const_data == NULL ? 0 : m_const_data->count; +} + +CSCRIPT_NAMESPACE_END --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_loader.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,83 @@ +/* + * CScript コンパイラ バイトコードローダ + * $Id: vm_loader.h 402 2007-05-09 13:42:53Z issei $ + * + * Copyright (c) 2006, 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "cscript.h" +#include "file.h" + +CSCRIPT_NAMESPACE_BEGIN + +class VirtualMachineLoader +{ +public: + VirtualMachineLoader(); + ~VirtualMachineLoader(); + bool load(void const* p, size_t len); + + boost::uint32_t getVersionMajor() const; + boost::uint32_t getVersionMinor() const; + + vm_tword_t const* getCode() const; + vm_psize_t getCodeSize() const; + + size_t getUpcallSize() const; + std::pair getUpcall(size_t index) const; + + size_t getStaticDataSize() const; + size_t getInitDataSize() const; + std::pair getInitData(size_t index) const; + + vm_literal_t getLiteralSize() const; + char const* getLiteral(vm_literal_t no) const; + + /** + * 定数プールデータを取得する + */ + vm_dword_t const* getConst() const; + + /** + * 定数プールのデータ数を取得する (ワード数) + */ + vm_const_t getConstSize() const; + +private: + File::Header const* m_header; + File::Code const* m_code; + File::Upcall const* m_upcall; + File::StaticData const* m_static_data; + File::LiteralPtr const* m_literal_ptr; + File::LiteralData const* m_literal_data; + File::ConstData const* m_const_data; + + bool _loadHeader(File::Header const* p, size_t* plen); + bool _loadCode(File::Info const* p, size_t* plen); + bool _loadUpcall(File::Info const* p, size_t* plen); + bool _loadStaticData(File::Info const* p, size_t* plen); + bool _loadLiteralData(File::Info const* p, size_t* plen); + bool _loadLiteralPtr(File::Info const* p, size_t* plen); + bool _loadConstData(File::Info const* p, size_t* plen); +}; + +CSCRIPT_NAMESPACE_END --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_stdfunc.cc Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,59 @@ +/* + * CScript コンパイラ システム関数 + * $Id: vm_sys.cc 414 2007-05-22 11:53:29Z issei $ + * + * Copyright (c) 2006, 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "stdafx.h" +#include "vm_stdfunc.h" +#include "common.h" +#include "vm_ctx.h" + +CSCRIPT_NAMESPACE_USING + +// 引数はスタックトップから逆順 + +void scr_sysPrintI(vm_int_t n) +{ + char buf[256]; + _snprintf(buf, sizeof(buf), "%d", n); + ::OutputDebugStringA(buf); +} + +void scr_sysPrintF(vm_float_t f) +{ + char buf[256]; + _snprintf(buf, sizeof(buf), "%f", f); + ::OutputDebugStringA(buf); +} + +void scr_sysPrintS(char const* s) +{ + ::OutputDebugStringA(s); +} + +void scr_sysPrintLn() +{ + ::OutputDebugStringW(L"\n"); +} + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_stdfunc.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,43 @@ +/* + * CScript コンパイラ システム関数 + * $Id: vm_sys.h 369 2007-04-08 17:49:00Z issei $ + * + * Copyright (c) 2006, 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef VM_SYS_H__INCLUDED +#define VM_SYS_H__INCLUDED + +#include "cscript.h" +#include "vm_cast.h" + +CSCRIPT_NAMESPACE_BEGIN +struct ICtxVirtualMachine; + +void scr_sysPrintI(vm_int_t n); +void scr_sysPrintF(vm_float_t f); +void scr_sysPrintS(char const* s); +void scr_sysPrintLn(); + +CSCRIPT_NAMESPACE_END + +#endif // VM_SYS_H__INCLUDED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_sys_base.cc Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,62 @@ +/* + * CScript コンパイラ スクリプト -> C++ 参照用インターフェース + * $Id: sysdecl.cc 445 2007-06-04 23:44:24Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "stdafx.h" +#include "vm_sys_base.h" + +// システム関数呼び出し時に handle の有効チェックを行なう +// #define CSCR_VM_SYS_BASE_VALIDATE_HANDLE + +CSCRIPT_NAMESPACE_BEGIN + +#ifdef CSCR_VM_SYS_BASE_VALIDATE_HANDLE +static std::set s_syscall_base; +#endif // CSCR_VM_SYS_BASE_VALIDATE_HANDLE + +CSyscallBase::CSyscallBase() +{ +#ifdef CSCR_VM_SYS_BASE_VALIDATE_HANDLE + bool result = s_syscall_base.insert(this).second; + assert(result); +#endif // CSCR_VM_SYS_BASE_VALIDATE_HANDLE +} + +CSyscallBase::~CSyscallBase() +{ +#ifdef CSCR_VM_SYS_BASE_VALIDATE_HANDLE + s_syscall_base.erase(this); +#endif // CSCR_VM_SYS_BASE_VALIDATE_HANDLE +} + +#ifdef CSCR_VM_SYS_BASE_VALIDATE_HANDLE +bool CSyscallBase::IsValid(CSyscallBase const* p) +{ + return s_syscall_base.find(p) != s_syscall_base.end(); +} +#endif + +CSCRIPT_NAMESPACE_END + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_sys_base.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,48 @@ +/* + * CScript コンパイラ スクリプト -> C++ 参照用インターフェース + * $Id: sysdecl.cc 445 2007-06-04 23:44:24Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef VM_SYS_BASE_H__INCLUDED +#define VM_SYS_BASE_H__INCLUDED + +#include "cscript.h" + +CSCRIPT_NAMESPACE_BEGIN + +struct CSyscallBase +{ + CSyscallBase(); + virtual ~CSyscallBase() = 0; +#ifdef CSCR_VM_SYS_BASE_VALIDATE_HANDLE + static bool IsValid(CSyscallBase const* p); +#else + static bool IsValid(CSyscallBase const* p) { return true; } +#endif +}; + +CSCRIPT_NAMESPACE_END + +#endif // VM_SYS_BASE_H__INCLUDED + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_sys_d.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,74 @@ +/* + * VM 内部システム関数管理クラス + * $Id: vm_sys_d.h 444 2007-06-04 23:03:03Z issei $ + * + * Copyright (c) 2006, 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "cscript.h" +#include "vm_cast.h" + +#ifndef VM_SYS_D_H__INCLUDED +#define VM_SYS_D_H__INCLUDED + +CSCRIPT_NAMESPACE_BEGIN +struct ISyscallVM; + +/** + * VM 内部システム関数管理クラス + * + * @note + * シングルトン + */ +class VMSyscallDispatcher +{ +public: + /** + * VM 内部システム関数コールバック呼び出し + * + * @param ctx + * VM 実行コンテクスト + * @param sysno + * システム関数番号 + * @return + * コールバック関数呼び出し成功時には真 + */ + bool call(ISyscallVM& ctx, vm_sysno_t sysno) const; + + /** + * シングルトン インスタンス取得 + * + * @return + * VM 内部システム関数管理クラスのインスタンス + */ + static VMSyscallDispatcher const& GetInstance(); + +private: + VMSyscallDispatcher(); + ~VMSyscallDispatcher(); + + class Impl; + boost::scoped_ptr m_impl; +}; +CSCRIPT_NAMESPACE_END + +#endif // VM_SYS_D_H__INCLUDED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_sys_ud.cc Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,169 @@ +/* + * VM ユーザ定義システム関数管理クラス + * $Id: vm_sys_ud.cc 445 2007-06-04 23:44:24Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "stdafx.h" +#include "vm_sys_ud.h" +#include "common.h" + +CSCRIPT_NAMESPACE_BEGIN + +// ------------------------------------------------------------------- +// 内部実装 +// ------------------------------------------------------------------- +class VMUserSyscallDispatcher::Impl +{ +public: + Impl() +#ifndef NDEBUG + : m_db_init(false) +#endif + {} + ~Impl() {} + bool add(vm_sysno_t sysno, VMUserSyscallFunction callabck); + void init(); + bool call(ICtxVirtualMachine& ctx, vm_sysno_t sysno) const; + +private: + /** + * システム関数番号とコールバック関数の対 + */ + struct Entry + { + vm_sysno_t sysno; + VMUserSyscallFunction sys_func; + + explicit Entry(vm_sysno_t sysno, VMUserSyscallFunction sys_func = NULL) + : sysno(sysno) + , sys_func(sys_func) + {} + + Entry() + : sysno(0) + , sys_func(NULL) + {} + }; + + /** + * システム関数番号とコールバック関数を登録するコレクションクラス + * データ構造は sysno をキーとする sorted vector + */ + typedef std::vector TCallbackList; + TCallbackList m_callback_list; + +#ifndef NDEBUG + bool m_db_init; //< m_callback_list はソート済か? +#endif +}; + +bool VMUserSyscallDispatcher::Impl::add(vm_sysno_t sysno, VMUserSyscallFunction sys_func) +{ +#ifndef NDEBUG + m_db_init = false; +#endif + if (CSCR_VM_SYSNO_SYSFUNC_INTERNAL_BEGIN <= sysno && sysno <= CSCR_VM_SYSNO_SYSFUNC_INTERNAL_END) + return false; + + m_callback_list.push_back(Entry(sysno, sys_func)); + return true; +} + +void VMUserSyscallDispatcher::Impl::init() +{ + namespace bl = boost::lambda; + std::sort( + m_callback_list.begin(), + m_callback_list.end(), + bl::bind(&Entry::sysno, bl::_1) < bl::bind(&Entry::sysno, bl::_2) + ); +#ifndef NDEBUG + namespace bl = boost::lambda; + TCallbackList::iterator i = + std::unique( + m_callback_list.begin(), + m_callback_list.end(), + bl::bind(&Entry::sysno, bl::_1) == bl::bind(&Entry::sysno, bl::_2) + ); + if (i != m_callback_list.end()) { + fprintf(stderr, "\tVMUserSyscallDispatcher::init() : Duplicate sysno\n"); + assert(0); + } +#endif + +#ifndef NDEBUG + m_db_init = true; +#endif +} + +bool VMUserSyscallDispatcher::Impl::call(ICtxVirtualMachine& ctx, vm_sysno_t sysno) const +{ + assert(m_db_init); + + namespace bl = boost::lambda; + TCallbackList::const_iterator i = std::lower_bound( + m_callback_list.begin(), + m_callback_list.end(), + Entry(sysno), + bl::bind(&Entry::sysno, bl::_1) < bl::bind(&Entry::sysno, bl::_2)); + + if (i == m_callback_list.end() || i->sysno != sysno) + return false; + + return (*i->sys_func)(ctx); +} + +// ------------------------------------------------------------------- +// 公開インターフェース +// ------------------------------------------------------------------- +VMUserSyscallDispatcher::VMUserSyscallDispatcher() + : m_impl(new Impl) +{} + +VMUserSyscallDispatcher::~VMUserSyscallDispatcher() +{} + +bool VMUserSyscallDispatcher::add(vm_sysno_t sysno, VMUserSyscallFunction sys_func) +{ + return m_impl->add(sysno, sys_func); +} + +void VMUserSyscallDispatcher::init() +{ + return m_impl->init(); +} + +bool VMUserSyscallDispatcher::call(ICtxVirtualMachine& ctx, vm_sysno_t sysno) const +{ + return m_impl->call(ctx, sysno); +} + +VMUserSyscallDispatcher& VMUserSyscallDispatcher::GetInstance() +{ + static VMUserSyscallDispatcher obj; + return obj; +} + +CSCRIPT_NAMESPACE_END + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CScriptVM/vm_sys_ud.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,102 @@ +/* + * VM ユーザ定義システム関数管理クラス + * $Id: vm_sys_ud.h 445 2007-06-04 23:44:24Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef VM_SYS_UD_H__INCLUDED +#define VM_SYS_UD_H__INCLUDED + +#include "cscript.h" +#include "vm_cast.h" +#include "cscript.sch" + +CSCRIPT_NAMESPACE_BEGIN + +struct ICtxVirtualMachine; + +/** + * VM ユーザ定義システム関数 管理クラス + * + * @note + * シングルトン + */ +class VMUserSyscallDispatcher +{ +public: + /** + * ユーザ定義システム関数 コールバック型 + */ + typedef bool (*VMUserSyscallFunction)(ICtxVirtualMachine&); + + /** + * ユーザ定義システム関数 コールバック登録 + * + * @param sysno + * システム関数番号 + * @param sys_func + * コールバック関数 + */ + bool add(vm_sysno_t sysno, VMUserSyscallFunction sys_func); + + /** + * 管理クラス初期化 + * + * @note + * add() でコールバック関数を登録完了後、call() 呼び出し前に + * 呼び出すこと。 + */ + void init(); + + /** + * ユーザ定義システム関数コールバック呼び出し + * + * @param ctx + * VM 実行コンテクスト + * @param sysno + * システム関数番号 + * @return + * コールバック関数呼び出し成功時には真 + */ + bool call(ICtxVirtualMachine& ctx, vm_sysno_t sysno) const; + + /** + * シングルトン インスタンス取得 + * + * @return + * VM ユーザ定義システム関数管理クラスのインスタンス + */ + static VMUserSyscallDispatcher& GetInstance(); + +private: + VMUserSyscallDispatcher(); + ~VMUserSyscallDispatcher(); + + class Impl; + boost::scoped_ptr m_impl; +}; + +CSCRIPT_NAMESPACE_END + +#endif // VM_SYS_UD_H__INCLUDED + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data/test_scr.ptxt Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,4 @@ +# テスト用アーカイブ +scr/test/for.scb + + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dbTaskScriptTest.cpp Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,143 @@ +/* + * XNvgseXg + * $Id: dbTaskScriptTest.cpp 179 2006-10-22 11:51:28Z issei $ + * + * Copyright (c) 2006 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "StdAfx.h" +#include "dbTaskScriptTest.h" +#include "DIDev.h" +#include "PackfileHandle.h" +#include "data/test_scr.packh" +#pragma warning(push) +// 4200:TCY0̔z +// 4819:݂̃R[hy[Wŕ\łȂ܂ł +#pragma warning(disable : 4200 4819) +#include "CScriptVM/vm_loader.h" +#include "CScriptVM/vm.h" +#pragma warning(pop) + +#ifdef _DEBUG + +ANON_NAMESPACE_BEGIN +class dbTaskScriptTest + : public ITask +{ +public: + dbTaskScriptTest(); + virtual ~dbTaskScriptTest(); + virtual TASK_PRIO_TYPE getPrio() const { return TASK_PRIO_DEBUG; } + virtual TASK_DPRIO_TYPE getDPrio() const { return TASK_DPRIO_DEBUG_NORMAL; } + virtual void exec(ICtxTask& /*ctx*/, TASK_PRIO_TYPE prio); + virtual void draw(ICtxTask const& /*ctx*/, TASK_DPRIO_TYPE dprio) const; + virtual bool isTerminated() const { return m_state == STATE_TERM; } + +private: + enum STATE_TYPE { STATE_INIT, STATE_LOAD, STATE_MAIN, STATE_TERM_WAIT, STATE_TERM } m_state; + int m_wait_count; + int m_run_count; + PackfileHandle<> m_pack; + CScript::VirtualMachine m_vm; + + REF_COUNT_IMPL(dbTaskScriptTest) +}; +ANON_NAMESPACE_END + +dbTaskScriptTest::dbTaskScriptTest() + : m_state(STATE_INIT) + , m_wait_count(0) + , m_run_count(0) +{ +} + +dbTaskScriptTest::~dbTaskScriptTest() +{ +} + +void dbTaskScriptTest::exec(ICtxTask& /*ctx*/, TASK_PRIO_TYPE /*prio*/) +{ + switch (m_state) { + case STATE_INIT: + m_pack.load(TEST_SCR_PACK); + m_state = STATE_LOAD; + break; + case STATE_LOAD: + ++m_wait_count; + if (m_pack.isLoaded()) { + void const* scb; + m_pack.getRes(&scb, SCR_TEST_FOR_SCB); + m_vm.setByteCode(scb, m_pack.getResSize(SCR_TEST_FOR_SCB)); + m_state = STATE_MAIN; + } + break; + case STATE_MAIN: + ++m_run_count; + if (!m_vm.run()) + m_state = STATE_TERM_WAIT; + break; + case STATE_TERM_WAIT: + if ((padGetRep() & (PAD_SE | PAD_ST)) == (PAD_SE | PAD_ST)) + m_state = STATE_TERM; + break; + case STATE_TERM: + break; + default: + dbAbort(0, _T("unexpected state")); + break; + } +} + +void dbTaskScriptTest::draw(ICtxTask const& /*ctx*/, TASK_DPRIO_TYPE /*dprio*/) const +{ + switch (m_state) { + case STATE_INIT: + break; + case STATE_LOAD: + dbConsLocate(0,3); + dbConsPrintf(_T("Loading ... %d"), m_wait_count); + break; + case STATE_TERM_WAIT: + dbConsLocate(0,8); + dbConsPrintf(_T("Keep pushing SELECT & START to exit")); + // FALLTHRU + case STATE_MAIN: + dbConsLocate(0,3); + dbConsPrintf(_T("Load OK ... %d"), m_wait_count); + dbConsLocate(0,5); + dbConsPrintf(_T("VM run ... %d"), m_run_count); + dbConsLocate(0,6); + dbConsPrintf(_T("VM state ... %d"), m_vm.getState()); + case STATE_TERM: + break; + default: + dbAbort(0, _T("unexpected state")); + break; + } +} + +boost::intrusive_ptr dbCreateTaskScriptTest() +{ + return boost::intrusive_ptr(new dbTaskScriptTest, false); +} + +#endif // _DEBUG --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dbTaskScriptTest.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,31 @@ +/* + * XNvgseXg + * $Id: dbTaskPad.h 60 2006-01-26 16:09:40Z issei $ + * + * Copyright (c) 2006 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ +#pragma once +#include "task.h" + +#ifdef _DEBUG +boost::intrusive_ptr dbCreateTaskScriptTest(); +#endif --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/Makefile Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,20 @@ +# Makefile + +.PHONY: all sys sysclean test testclean + +TOP=.. +include $(TOP)/scr/scrcfg.mak + +all: sys test + +sys: + $(MAKE) -C sys -f ../scrsys.mak all + +sysclean: + $(MAKE) -C sys -f ../scrsys.mak clean + +test: + $(MAKE) -C test -f ../scrmak.mak TOP=../.. all + +testclean: + $(MAKE) -C test -f ../scrmak.mak TOP=../.. clean --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/cscript/cscript.sch Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,69 @@ +/* + * CScript 共通ヘッダファイル + * $Id: cscript.sch 401 2007-05-08 15:12:02Z issei $ + * + * Copyright (c) 2007 + * Issei Suzuki All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef CSCRIPT_CSCRIPT_SCH__INCLUDED +#define CSCRIPT_CSCRIPT_SCH__INCLUDED + +// -------------------------------------------------------------------- +// VM設定 +// -------------------------------------------------------------------- + +// システム引数の数 +#define CSCR_VM_SYSARG_MAX (4) + +// -------------------------------------------------------------------- +// 内部システム関数 +// -------------------------------------------------------------------- +#define CSCR_VM_SYSNO_SYSFUNC_INTERNAL_BEGIN (1) +#define CSCR_VM_SYSNO_SYSFUNC_INTERNAL_END (127) +#define CSCR_VM_SYSNO_SYSFUNC_INTERNAL_COUNT (CSCR_VM_SYSNO_SYSFUNC_INTERNAL_END - CSCR_VM_SYSNO_SYSFUNC_INTERNAL_BEGIN + 1) + +#define CSCR_VM_SYSNO_SYSFUNC_INTERNAL_THREAD_BEGIN (32) +#define CSCR_VM_SYSNO_SYSFUNC_INTERNAL_THREAD_END (63) +#define CSCR_VM_SYSNO_SYSFUNC_INTERNAL_THREAD_COUNT (CSCR_VM_SYSNO_SYSFUNC_INTERNAL_THREAD_END - CSCR_VM_SYSNO_SYSFUNC_INTERNAL_THREAD_BEGIN + 1) + +#define CSCR_VM_SYSNO_SYSFUNC_INTERNAL_DEBUG_BEGIN (112) +#define CSCR_VM_SYSNO_SYSFUNC_INTERNAL_DEBUG_END (127) +#define CSCR_VM_SYSNO_SYSFUNC_INTERNAL_DEBUG_COUNT (CSCR_VM_SYSNO_SYSFUNC_INTERNAL_DEBUG_END - CSCR_VM_SYSNO_SYSFUNC_INTERNAL_DEBUG_BEGIN + 1) + +#define CSCR_VM_SYSNO_SYSFUNC_EXTERNAL_BEGIN (128) +#define CSCR_VM_SYSNO_SYSFUNC_EXTERNAL_END (255) +#define CSCR_VM_SYSNO_SYSFUNC_EXTERNAL_COUNT (CSCR_VM_SYSNO_SYSFUNC_EXTERNAL_END - CSCR_VM_SYSNO_SYSFUNC_EXTERNAL_BEGIN + 1) + +// -------------------------------------------------------------------- +// ユーザ定義システム関数 +// -------------------------------------------------------------------- +#define CSCR_VM_SYSNO_SYSFUNC_USER_BEGIN (1024) +#define CSCR_VM_SYSNO_SYSFUNC_USER_END (65535) + +// テスト用コード +#define CSCR_VM_SYSNO_SYSFUNC_TEST_BEGIN CSCR_VM_SYSNO_SYSFUNC_USER_BEGIN +#define CSCR_VM_SYSNO_SYSFUNC_TEST_COUNT (32) +#define CSCR_VM_SYSNO_SYSFUNC_TEST_END (CSCR_VM_SYSNO_SYSFUNC_USER_BEGIN + CSCR_VM_SYSNO_SYSFUNC_USER_COUNT - 1) + +#endif // CSCRIPT_CSCRIPT_SCH__INCLUDED + +// vim: syntax=c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/cscript/stdfunc.sch Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,13 @@ +/* + * CScript システム標準関数 + * $Id: stdfunc.sch 444 2007-06-04 23:03:03Z issei $ + */ + +#include + +__system[CSCR_VM_SYSNO_SYSFUNC_EXTERNAL_BEGIN] void sysPrintI(int n); +__system[] void sysPrintF(float f); +__system[] void sysPrintS(string s); +__system[] void sysPrintLn(); + +// vim: syntax=c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/cscript/system.sch Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,168 @@ +/* + * CScript システム関数 + * $Id: system.sch 446 2007-06-05 11:18:59Z issei $ + */ + +#include + +#define sys_timesec_t float /// 時間 (秒) +typedef int sys_thread_t; /// スレッド識別子 +typedef int sys_intr_t; /// 割り込み識別子 + +// ------------------------------------------------------------------- +// 汎用処理 +// ------------------------------------------------------------------- + +/** + システム側で設定した引数を整数型として取得する + + @param idx + 引数のインデクス + @note + システム側で設定した型と異なるデータ型で取得した場合の + 動作は未定義 + */ +__system[CSCR_VM_SYSNO_SYSFUNC_INTERNAL_BEGIN] int sysGetArgI(int idx); + +/** + システム側で設定した引数を浮動小数点数型として取得する + + @param idx + 引数のインデクス + @note + システム側で設定した型と異なるデータ型で取得した場合の + 動作は未定義 + */ +__system[] float sysGetArgF(int idx); + +/** + システム側で設定した引数をハンドル型として取得する + + @param idx + 引数のインデクス + @note + システム側で設定した型と異なるデータ型で取得した場合の + 動作は未定義 + */ +__system[] handle sysGetArgH(int idx); + +/** + スクリプト実行開始からの経過時間を取得する + + @return + 実行経過時間 (VirtualMachine::run() 呼び出し回数) + */ +__system[] int sysGetTime(); + +/** + スクリプト実行開始からの経過時間を取得する + + @return + 実行経過時間 (秒) + */ +__system[] sys_timesec_t sysGetTimeSec(); + +/** + 実行を中断する + + @param n + 中断する時間 (VirtualMachine::run() 呼び出し回数) + */ +__system[] void sysPass(int n); + +/** + 実行を中断する + + @param sec + 中断する時間 (秒) + */ +__system[] void sysPassSec(sys_timesec_t sec); + +/** + 実行を終了する + */ +__system[] void sysExit(); + +// ------------------------------------------------------------------- +// スレッド処理 +// ------------------------------------------------------------------- +/** + スレッドを新規作成する + + @param th_main + スレッドの実行を開始するエントリポイント + */ +__system[CSCR_VM_SYSNO_SYSFUNC_INTERNAL_THREAD_BEGIN] sys_thread_t sysThreadBegin(thread th_main); + +/** + timeline スレッドを新規作成する + + @param tl_main + スレッドの実行を開始するエントリポイント + */ +__system[] sys_thread_t sysThreadBeginTimeline(timeline tl_main); + +/** + 他スレッドを終了させる + + @param tid + 対象のスレッド識別子 + @note + 終了できるスレッドは子スレッドのみ + */ +__system[] void sysThreadKill(sys_thread_t tid); + +/** + 子スレッドを全て終了させる + */ +__system[] void sysThreadKillAll(); + +/** + 指定したスレッド終了まで現スレッドの実行を中断する + + @param tid + 対象のスレッド識別子 + */ +__system[] void sysThreadWait(sys_thread_t tid); + +/** + 子スレッドが全て終了するまで現スレッドの実行を中断する + */ +__system[] void sysThreadWaitAll(); + +/** + スレッド実行開始からの経過時間を取得する + + @return + 実行経過時間 (VirtualMachine::run() 呼び出し回数) + */ +__system[] int sysThreadGetTime(); + +/** + スレッド実行開始からの経過時間を取得する + + @return + 実行経過時間 (秒) + */ +__system[] sys_timesec_t sysThreadGetTimeSec(); + + +// ------------------------------------------------------------------- +// デバッグ用システム関数 +// ------------------------------------------------------------------- +#ifndef NDEBUG +/** + スタックダンプを出力する + */ +__system[CSCR_VM_SYSNO_SYSFUNC_INTERNAL_DEBUG_BEGIN] void sysDbStackDump(); + +/** + 引数テスト用 (意味はない) + */ +__system[] void sysDbTest(int i, float f); +#else +# define sysDbStackDump() +# define sysDbTest(i, f) +#endif + +// vim: syntax=c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/cscript/test.sch Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,16 @@ +/* + * CScript テスト + * $Id: stdfunc.sch 444 2007-06-04 23:03:03Z issei $ + */ + +#include + +typedef handle test_player_t[ISyscallTestPlayer, "scr_sys_test_pl.h"]; + +// コールバックテスト +__system[CSCR_VM_SYSNO_SYSFUNC_TEST_BEGIN] void plNull(test_player_t h); +__system[] int plGetHp(test_player_t h); +__system[] void plCreateShot(test_player_t h, int count); + +// vim: syntax=c + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/scrcfg.mak Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,10 @@ +# CScript config file + +TOOLDIR= $(TOP)/tool +SCRDIR= $(TOP)/scr +SYSDECL= $(TOOLDIR)/sysdecl.exe -O +CSCRC= $(TOOLDIR)/cscrc.exe +CSCDS= $(TOOLDIR)/cscds.exe + +CPP= cpp +CPPFLAGS= -DCSCRIPT -nostdinc -undef -I$(SCRDIR)/cscript --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/scrmak.mak Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,42 @@ +# makefile for cscript code +# $Id: cscript.mak 452 2007-06-06 13:56:38Z issei $ + +.PHONY: clean cleandepend + +include $(TOP)/scr/scrcfg.mak + +SRCS= $(notdir $(wildcard *.scs)) +DEPS= $(addsuffix .scd,$(basename $(SRCS))) +SCPS= $(addsuffix .scp,$(basename $(SRCS))) +SCBS= $(addsuffix .scb,$(basename $(SRCS))) +DISS= $(addsuffix .dis,$(basename $(SRCS))) + +%.scd: %.scs + $(CPP) -MM -MT $(addsuffix .scp,$(basename $<)) $(CPPFLAGS) -o $@ $< + +%.scp: %.scs + $(CPP) $(CPPFLAGS) -o $@ $< + +%.scb: %.scp $(CSCRC) + $(CSCRC) $(CSCRCFLAGS) $< + +%.dis: %.scb $(CSCDS) + $(CSCDS) $< > $@ + +all: $(SCPS) $(SCBS) $(DISS) + +clean: + $(RM) $(SCPS) $(SCBS) $(DISS) + +full: clean all + +depend: $(DEPS) + $(echo-target) + @$(CAT) $^ > .depend + +cleandepend: + $(RM) $(DEPS) .depend + +fulldepend: cleandepend depend + +sinclude .depend --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/scrsys.mak Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,22 @@ +# CScript system function code generation + +.PHONY: all clean + +TOP=../.. +include $(TOP)/scr/scrcfg.mak + +all: vm_sys_vm.h vm_sys_d.cc scr_stdfunc.cc + pwd + +vm_sys_vm.h: vm_sys_d.cc + +vm_sys_d.cc: $(SCRDIR)/cscript/system.sch + $(CPP) $(CPPFLAGS) $< | $(SYSDECL) -s + +scr_stdfunc.cc: $(SCRDIR)/cscript/stdfunc.sch + $(CPP) $(CPPFLAGS) $< | $(SYSDECL) > $@ + +clean: + $(RM) vm_sys_vm.h vm_sys_d.cc scr_stdfunc.cc + + --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/sys/scr_stdfunc.cc Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,61 @@ +// DO NOT EDIT - THIS FILE IS GENERATED AUTOMATICALLY + +#include "stdafx.h" +#include "vm_cast.h" +#include "vm_ctx.h" +#include "vm_sys_ud.h" + +CSCRIPT_NAMESPACE_USING + +void scr_sysPrintI(vm_int_t n); +void scr_sysPrintF(vm_float_t f); +void scr_sysPrintS(char const* s); +void scr_sysPrintLn(); + +namespace { + +bool _scr_sysPrintI(ICtxVirtualMachine& ctx) +{ + vm_int_t n = ctx.getScrArgI(0); + scr_sysPrintI(n); + ctx.setScrRet(); + return true; +} + +bool _scr_sysPrintF(ICtxVirtualMachine& ctx) +{ + vm_float_t f = ctx.getScrArgF(0); + scr_sysPrintF(f); + ctx.setScrRet(); + return true; +} + +bool _scr_sysPrintS(ICtxVirtualMachine& ctx) +{ + char const* s = ctx.getScrArgS(0); + scr_sysPrintS(s); + ctx.setScrRet(); + return true; +} + +bool _scr_sysPrintLn(ICtxVirtualMachine& ctx) +{ + scr_sysPrintLn(); + ctx.setScrRet(); + return true; +} + +static void scrSysFuncRegisterer() +{ + VMUserSyscallDispatcher::GetInstance().add(128, &_scr_sysPrintI); + VMUserSyscallDispatcher::GetInstance().add(129, &_scr_sysPrintF); + VMUserSyscallDispatcher::GetInstance().add(130, &_scr_sysPrintS); + VMUserSyscallDispatcher::GetInstance().add(131, &_scr_sysPrintLn); +} + +static struct sysFuncRegisterer +{ + sysFuncRegisterer() { scrSysFuncRegisterer(); } +} s_sysFuncRegisterer; + +} // namespace anonymous --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/sys/vm_sys_d.cc Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,332 @@ +// DO NOT EDIT - THIS FILE IS GENERATED AUTOMATICALLY + +#include "stdafx.h" +#include "vm_sys_d.h" +#include "cscript.sch" +#include "vm_cast.h" +#include "vm_sys_vm.h" + +CSCRIPT_NAMESPACE_BEGIN +class VMSyscallDispatcher::Impl +{ +public: + bool call(ISyscallVM& ctx, vm_sysno_t sysno) const; + +private: + static bool (Impl::* const FUNC_TBL[])(ISyscallVM& ctx) const; + bool _scr_sysGetArgI(ISyscallVM& ctx) const; + bool _scr_sysGetArgF(ISyscallVM& ctx) const; + bool _scr_sysGetArgH(ISyscallVM& ctx) const; + bool _scr_sysGetTime(ISyscallVM& ctx) const; + bool _scr_sysGetTimeSec(ISyscallVM& ctx) const; + bool _scr_sysPass(ISyscallVM& ctx) const; + bool _scr_sysPassSec(ISyscallVM& ctx) const; + bool _scr_sysExit(ISyscallVM& ctx) const; + bool _scr_sysThreadBegin(ISyscallVM& ctx) const; + bool _scr_sysThreadBeginTimeline(ISyscallVM& ctx) const; + bool _scr_sysThreadKill(ISyscallVM& ctx) const; + bool _scr_sysThreadKillAll(ISyscallVM& ctx) const; + bool _scr_sysThreadWait(ISyscallVM& ctx) const; + bool _scr_sysThreadWaitAll(ISyscallVM& ctx) const; + bool _scr_sysThreadGetTime(ISyscallVM& ctx) const; + bool _scr_sysThreadGetTimeSec(ISyscallVM& ctx) const; + bool _scr_sysDbStackDump(ISyscallVM& ctx) const; + bool _scr_sysDbTest(ISyscallVM& ctx) const; +}; + +bool (VMSyscallDispatcher::Impl::* const VMSyscallDispatcher::Impl::FUNC_TBL[])(ISyscallVM&) const = { + &VMSyscallDispatcher::Impl::_scr_sysGetArgI, // 0x01 + &VMSyscallDispatcher::Impl::_scr_sysGetArgF, // 0x02 + &VMSyscallDispatcher::Impl::_scr_sysGetArgH, // 0x03 + &VMSyscallDispatcher::Impl::_scr_sysGetTime, // 0x04 + &VMSyscallDispatcher::Impl::_scr_sysGetTimeSec, // 0x05 + &VMSyscallDispatcher::Impl::_scr_sysPass, // 0x06 + &VMSyscallDispatcher::Impl::_scr_sysPassSec, // 0x07 + &VMSyscallDispatcher::Impl::_scr_sysExit, // 0x08 + NULL, // 0x09 + NULL, // 0x0a + NULL, // 0x0b + NULL, // 0x0c + NULL, // 0x0d + NULL, // 0x0e + NULL, // 0x0f + NULL, // 0x10 + NULL, // 0x11 + NULL, // 0x12 + NULL, // 0x13 + NULL, // 0x14 + NULL, // 0x15 + NULL, // 0x16 + NULL, // 0x17 + NULL, // 0x18 + NULL, // 0x19 + NULL, // 0x1a + NULL, // 0x1b + NULL, // 0x1c + NULL, // 0x1d + NULL, // 0x1e + NULL, // 0x1f + &VMSyscallDispatcher::Impl::_scr_sysThreadBegin, // 0x20 + &VMSyscallDispatcher::Impl::_scr_sysThreadBeginTimeline, // 0x21 + &VMSyscallDispatcher::Impl::_scr_sysThreadKill, // 0x22 + &VMSyscallDispatcher::Impl::_scr_sysThreadKillAll, // 0x23 + &VMSyscallDispatcher::Impl::_scr_sysThreadWait, // 0x24 + &VMSyscallDispatcher::Impl::_scr_sysThreadWaitAll, // 0x25 + &VMSyscallDispatcher::Impl::_scr_sysThreadGetTime, // 0x26 + &VMSyscallDispatcher::Impl::_scr_sysThreadGetTimeSec, // 0x27 + NULL, // 0x28 + NULL, // 0x29 + NULL, // 0x2a + NULL, // 0x2b + NULL, // 0x2c + NULL, // 0x2d + NULL, // 0x2e + NULL, // 0x2f + NULL, // 0x30 + NULL, // 0x31 + NULL, // 0x32 + NULL, // 0x33 + NULL, // 0x34 + NULL, // 0x35 + NULL, // 0x36 + NULL, // 0x37 + NULL, // 0x38 + NULL, // 0x39 + NULL, // 0x3a + NULL, // 0x3b + NULL, // 0x3c + NULL, // 0x3d + NULL, // 0x3e + NULL, // 0x3f + NULL, // 0x40 + NULL, // 0x41 + NULL, // 0x42 + NULL, // 0x43 + NULL, // 0x44 + NULL, // 0x45 + NULL, // 0x46 + NULL, // 0x47 + NULL, // 0x48 + NULL, // 0x49 + NULL, // 0x4a + NULL, // 0x4b + NULL, // 0x4c + NULL, // 0x4d + NULL, // 0x4e + NULL, // 0x4f + NULL, // 0x50 + NULL, // 0x51 + NULL, // 0x52 + NULL, // 0x53 + NULL, // 0x54 + NULL, // 0x55 + NULL, // 0x56 + NULL, // 0x57 + NULL, // 0x58 + NULL, // 0x59 + NULL, // 0x5a + NULL, // 0x5b + NULL, // 0x5c + NULL, // 0x5d + NULL, // 0x5e + NULL, // 0x5f + NULL, // 0x60 + NULL, // 0x61 + NULL, // 0x62 + NULL, // 0x63 + NULL, // 0x64 + NULL, // 0x65 + NULL, // 0x66 + NULL, // 0x67 + NULL, // 0x68 + NULL, // 0x69 + NULL, // 0x6a + NULL, // 0x6b + NULL, // 0x6c + NULL, // 0x6d + NULL, // 0x6e + NULL, // 0x6f + &VMSyscallDispatcher::Impl::_scr_sysDbStackDump, // 0x70 + &VMSyscallDispatcher::Impl::_scr_sysDbTest, // 0x71 + NULL, // 0x72 + NULL, // 0x73 + NULL, // 0x74 + NULL, // 0x75 + NULL, // 0x76 + NULL, // 0x77 + NULL, // 0x78 + NULL, // 0x79 + NULL, // 0x7a + NULL, // 0x7b + NULL, // 0x7c + NULL, // 0x7d + NULL, // 0x7e + NULL, // 0x7f +}; + +bool VMSyscallDispatcher::Impl::call(ISyscallVM& ctx, vm_sysno_t sysno) const +{ + if (sysno < CSCR_VM_SYSNO_SYSFUNC_INTERNAL_BEGIN) + return false; + if (CSCR_VM_SYSNO_SYSFUNC_INTERNAL_END < sysno) + return false; + size_t idx = sysno - CSCR_VM_SYSNO_SYSFUNC_INTERNAL_BEGIN; + if (FUNC_TBL[idx] == NULL) + return false; + (this->*FUNC_TBL[idx])(ctx); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysGetArgI(ISyscallVM& ctx) const +{ + vm_int_t idx = ctx.getScrArgI(0); + vm_int_t _retval = ctx.scr_sysGetArgI(idx); + ctx.setScrRet(_retval); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysGetArgF(ISyscallVM& ctx) const +{ + vm_int_t idx = ctx.getScrArgI(0); + vm_float_t _retval = ctx.scr_sysGetArgF(idx); + ctx.setScrRet(_retval); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysGetArgH(ISyscallVM& ctx) const +{ + vm_int_t idx = ctx.getScrArgI(0); + vm_handle_t _retval = ctx.scr_sysGetArgH(idx); + ctx.setScrRet(_retval); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysGetTime(ISyscallVM& ctx) const +{ + vm_int_t _retval = ctx.scr_sysGetTime(); + ctx.setScrRet(_retval); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysGetTimeSec(ISyscallVM& ctx) const +{ + vm_float_t _retval = ctx.scr_sysGetTimeSec(); + ctx.setScrRet(_retval); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysPass(ISyscallVM& ctx) const +{ + vm_int_t n = ctx.getScrArgI(0); + ctx.scr_sysPass(n); + ctx.setScrRet(); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysPassSec(ISyscallVM& ctx) const +{ + vm_float_t sec = ctx.getScrArgF(0); + ctx.scr_sysPassSec(sec); + ctx.setScrRet(); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysExit(ISyscallVM& ctx) const +{ + ctx.scr_sysExit(); + ctx.setScrRet(); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysThreadBegin(ISyscallVM& ctx) const +{ + vm_taddr_t th_main = ctx.getScrArgT(0); + vm_int_t _retval = ctx.scr_sysThreadBegin(th_main); + ctx.setScrRet(_retval); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysThreadBeginTimeline(ISyscallVM& ctx) const +{ + vm_taddr_t tl_main = ctx.getScrArgT(0); + vm_int_t _retval = ctx.scr_sysThreadBeginTimeline(tl_main); + ctx.setScrRet(_retval); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysThreadKill(ISyscallVM& ctx) const +{ + vm_int_t tid = ctx.getScrArgI(0); + ctx.scr_sysThreadKill(tid); + ctx.setScrRet(); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysThreadKillAll(ISyscallVM& ctx) const +{ + ctx.scr_sysThreadKillAll(); + ctx.setScrRet(); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysThreadWait(ISyscallVM& ctx) const +{ + vm_int_t tid = ctx.getScrArgI(0); + ctx.scr_sysThreadWait(tid); + ctx.setScrRet(); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysThreadWaitAll(ISyscallVM& ctx) const +{ + ctx.scr_sysThreadWaitAll(); + ctx.setScrRet(); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysThreadGetTime(ISyscallVM& ctx) const +{ + vm_int_t _retval = ctx.scr_sysThreadGetTime(); + ctx.setScrRet(_retval); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysThreadGetTimeSec(ISyscallVM& ctx) const +{ + vm_float_t _retval = ctx.scr_sysThreadGetTimeSec(); + ctx.setScrRet(_retval); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysDbStackDump(ISyscallVM& ctx) const +{ + ctx.scr_sysDbStackDump(); + ctx.setScrRet(); + return true; +} + +bool VMSyscallDispatcher::Impl::_scr_sysDbTest(ISyscallVM& ctx) const +{ + vm_float_t f = ctx.getScrArgF(0); + vm_int_t i = ctx.getScrArgI(1); + ctx.scr_sysDbTest(i, f); + ctx.setScrRet(); + return true; +} + +VMSyscallDispatcher const& VMSyscallDispatcher::GetInstance() +{ + static VMSyscallDispatcher obj; + return obj; +} + +VMSyscallDispatcher::VMSyscallDispatcher() : m_impl(new Impl) {} + +VMSyscallDispatcher::~VMSyscallDispatcher() {} + +bool VMSyscallDispatcher::call(ISyscallVM& ctx, vm_sysno_t sysno) const +{ + return m_impl->call(ctx, sysno); +} + +CSCRIPT_NAMESPACE_END --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/sys/vm_sys_vm.h Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,37 @@ +// DO NOT EDIT - THIS FILE IS GENERATED AUTOMATICALLY + +#ifndef VM_SYS_VM__INCLUDED +#define VM_SYS_VM__INCLUDED + +#include "cscript.h" +#include "vm_ctx.h" + +CSCRIPT_NAMESPACE_BEGIN + +struct ISyscallVM + : public ICtxVirtualMachine +{ + virtual ~ISyscallVM() {} + virtual vm_int_t scr_sysGetArgI(vm_int_t idx) = 0; + virtual vm_float_t scr_sysGetArgF(vm_int_t idx) = 0; + virtual vm_handle_t scr_sysGetArgH(vm_int_t idx) = 0; + virtual vm_int_t scr_sysGetTime() = 0; + virtual vm_float_t scr_sysGetTimeSec() = 0; + virtual void scr_sysPass(vm_int_t n) = 0; + virtual void scr_sysPassSec(vm_float_t sec) = 0; + virtual void scr_sysExit() = 0; + virtual vm_int_t scr_sysThreadBegin(vm_taddr_t th_main) = 0; + virtual vm_int_t scr_sysThreadBeginTimeline(vm_taddr_t tl_main) = 0; + virtual void scr_sysThreadKill(vm_int_t tid) = 0; + virtual void scr_sysThreadKillAll() = 0; + virtual void scr_sysThreadWait(vm_int_t tid) = 0; + virtual void scr_sysThreadWaitAll() = 0; + virtual vm_int_t scr_sysThreadGetTime() = 0; + virtual vm_float_t scr_sysThreadGetTimeSec() = 0; + virtual void scr_sysDbStackDump() = 0; + virtual void scr_sysDbTest(vm_int_t i, vm_float_t f) = 0; +}; + +CSCRIPT_NAMESPACE_END + +#endif // VM_SYS_VM__INCLUDED --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/scr/test/for.scs Mon Sep 03 00:18:55 2007 +0900 @@ -0,0 +1,50 @@ +/* + * for loop + * $Id: for.scs 444 2007-06-04 23:03:03Z issei $ + */ + +#include +#include + +void main() +{ + int i, j; + + sysPrintS("main begin\n"); + + sysPrintS("\n[0]\n"); + for (i = 0; i < 10; ++i) + sysPrintI(i); + sysPass(1); + + sysPrintS("\n[1]\n"); + for (i = 0;; ++i) { + sysPrintI(i); + if (i == 9) + break; + sysPrintI(i); + } + sysPass(1); + + sysPrintS("\n[2]\n"); + sysPrintS("loop begin\n"); + for (i = 0; i < 3; ++i) { + for (j = 0; j < 3; ++j) { + sysPrintS("\n"); + sysPrintI(i); + sysPrintI(j); + if (i == 1 && j == 1) + continue; + else { + sysPrintI(i); + sysPrintI(j); + } + } + sysPass(1); + } + sysPrintS("\n"); + sysPrintS("loop end\n"); + sysPrintS("main end\n"); +} + +// vim: syntax=c