OSDN Git Service

git-svn-id: http://svn.osdn.jp/svnroot/mimic/trunk@28 47198e57-cb75-475f-84c4-a814cd6...
[mimic/MiMicSDK.git] / lib / src / mimicvm / NyLPC_cMiMicVM.c
1 /*********************************************************************************\r
2  * PROJECT: MiMic\r
3  * --------------------------------------------------------------------------------\r
4  *\r
5  * This file is part of MiMic\r
6  * Copyright (C)2011 Ryo Iizuka\r
7  *\r
8  * MiMic is free software: you can redistribute it and/or modify\r
9  * it under the terms of the GNU Lesser General Public License as published\r
10  * by the Free Software Foundation, either version 3 of the License, or\r
11  * (at your option) any later version.\r
12  *\r
13  * This program is distributed in the hope that it will be useful,\r
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
16  * GNU General Public License for more details.\r
17  *\r
18  * You should have received a copy of the GNU Lesser General Public License\r
19  * along with this program.  If not, see <http://www.gnu.org/licenses/>.\r
20  *\r
21  * For further information please contact.\r
22  *      http://nyatla.jp/\r
23  *      <airmail(at)ebony.plala.or.jp> or <nyatla(at)nyatla.jp>\r
24  *\r
25  *********************************************************************************/\r
26 #include <ctype.h>\r
27 #include <stdlib.h>\r
28 #include "NyLPC_cMiMicVM_protected.h"\r
29 \r
30 static NyLPC_TUInt8 process_instruction(NyLPC_TcMiMicVM_t* i_inst,const union NyLPC_TcMiMicVM_TInstruction* ist);\r
31 \r
32 \r
33 \r
34 void NyLPC_cMiMicVM_initialize(NyLPC_TcMiMicVM_t* i_inst,struct NyLPC_TcMiMicVM_TEvent* i_handler)\r
35 {\r
36         NyLPC_Assert(i_inst!=NULL);\r
37         NyLPC_Assert(i_handler!=NULL);\r
38         NyLPC_Assert(i_handler->get_stream!=NULL);\r
39         NyLPC_Assert(i_handler->put_stream!=NULL);\r
40         NyLPC_Assert(i_handler->sleep!=NULL);\r
41         i_inst->_event_handler=i_handler;\r
42         return;\r
43 }\r
44 \r
45 \r
46 /**\r
47  * 固定長命令+固定長データを実行します。\r
48  * 関数の終了条件は、1.EXIT命令に到達する。2.インストラクションの終端に到達する。3.エラーが発生する。です。\r
49  * \r
50  */\r
51 NyLPC_TBool NyLPC_cMiMicVM_run(NyLPC_TcMiMicVM_t* i_inst,const NyLPC_TUInt32* i_instruction,const NyLPC_TUInt16 i_size_of_instruction)\r
52 {\r
53         //データ部をgetstreamと連動させること。\r
54         NyLPC_TUInt16 pc=0;\r
55         NyLPC_TUInt8 proc_in_byte;\r
56         i_inst->ret_code=0;\r
57         if(i_size_of_instruction>0){\r
58                 proc_in_byte=process_instruction(i_inst,(const union NyLPC_TcMiMicVM_TInstruction*)(i_instruction+pc));\r
59                 pc+=proc_in_byte;\r
60                 //プログラムの終端に到達するか、0バイト処理の場合にブレーク。\r
61                 while(proc_in_byte>0 && pc<i_size_of_instruction){\r
62                         proc_in_byte=process_instruction(i_inst,(const union NyLPC_TcMiMicVM_TInstruction*)(i_instruction+pc));\r
63                         pc+=proc_in_byte;\r
64                 }\r
65         }\r
66         return i_inst->ret_code==0?NyLPC_TBool_TRUE:NyLPC_TBool_FALSE;\r
67 }\r
68 \r
69 \r
70 \r
71 \r
72 /**\r
73  * インストラクションを1個処理し、処理したバイト数を返す。\r
74  * インストラクションの境界値はチェックされないので、コンパイル時にチェックしておくこと。\r
75  * @return\r
76  * 処理したインストラクションのワード数(UInt32単位)。\r
77  * 終了した場合は0を返す。0を返したときは、ret_codeメンバをチェックして、理由を調べること。\r
78  */\r
79 static NyLPC_TUInt8 process_instruction(NyLPC_TcMiMicVM_t* i_inst,const union NyLPC_TcMiMicVM_TInstruction* ist)\r
80 {\r
81         switch(ist->op.opc){\r
82         case NyLPC_TcMiMicVM_OP_TYPE_AND:\r
83                 switch(ist->op.oprtype){\r
84                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_WM:\r
85                         i_inst->wm[ist->wmwm_32.wm1]&=i_inst->wm[ist->wmwm_32.wm2];\r
86                         break;\r
87                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_H32:\r
88                         i_inst->wm[ist->wmh32_64.wm]&=ist->wmh32_64.h32;\r
89                         break;\r
90                 default:\r
91                         NyLPC_OnErrorGoto(ERROR);\r
92                 }\r
93                 break;\r
94         case NyLPC_TcMiMicVM_OP_TYPE_OR:\r
95                 switch(ist->op.oprtype){\r
96                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_WM:\r
97                         i_inst->wm[ist->wmwm_32.wm1]|=i_inst->wm[ist->wmwm_32.wm2];\r
98                         break;\r
99                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_H32:\r
100                         i_inst->wm[ist->wmh32_64.wm]|=ist->wmh32_64.h32;\r
101                         break;\r
102                 default:\r
103                         NyLPC_OnErrorGoto(ERROR);\r
104                 }\r
105                 break;\r
106         case NyLPC_TcMiMicVM_OP_TYPE_XOR:\r
107                 switch(ist->op.oprtype){\r
108                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_WM:\r
109                         i_inst->wm[ist->wmwm_32.wm1]^=i_inst->wm[ist->wmwm_32.wm2];\r
110                         break;\r
111                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_H32:\r
112                         i_inst->wm[ist->wmh32_64.wm]^=ist->wmh32_64.h32;\r
113                         break;\r
114                 default:\r
115                         NyLPC_OnErrorGoto(ERROR);\r
116                 }\r
117                 break;\r
118         case NyLPC_TcMiMicVM_OP_TYPE_NOT:\r
119                 switch(ist->op.oprtype){\r
120                 case NyLPC_TcMiMicVM_OPR_TYPE_WM:\r
121                         i_inst->wm[ist->wm_32.wm]=~i_inst->wm[ist->wm_32.wm];\r
122                         break;\r
123                 default:\r
124                         NyLPC_OnErrorGoto(ERROR);\r
125                 }\r
126                 break;\r
127         case NyLPC_TcMiMicVM_OP_TYPE_SHL:\r
128                 switch(ist->op.oprtype){\r
129                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_H08:\r
130                         i_inst->wm[ist->wmh08_32.wm]=i_inst->wm[ist->wmh08_32.wm]<<ist->wmh08_32.h8;\r
131                         break;\r
132                 default:\r
133                         NyLPC_OnErrorGoto(ERROR);\r
134                 }\r
135                 break;\r
136         case NyLPC_TcMiMicVM_OP_TYPE_SHR:\r
137                 switch(ist->op.oprtype){\r
138                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_H08:\r
139                         i_inst->wm[ist->wmh08_32.wm]=i_inst->wm[ist->wmh08_32.wm]>>ist->wmh08_32.h8;\r
140                         break;\r
141                 default:\r
142                         NyLPC_OnErrorGoto(ERROR);\r
143                 }\r
144                 break;\r
145         case NyLPC_TcMiMicVM_OP_TYPE_ADD:\r
146                 switch(ist->op.oprtype){\r
147                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_WM:\r
148                         i_inst->wm[ist->wmwm_32.wm1]+=i_inst->wm[ist->wmwm_32.wm2];\r
149                         break;\r
150                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_H32:\r
151                         i_inst->wm[ist->wmh32_64.wm]+=ist->wmh32_64.h32;\r
152                         break;\r
153                 default:\r
154                         NyLPC_OnErrorGoto(ERROR);\r
155                 }\r
156                 break;\r
157         case NyLPC_TcMiMicVM_OP_TYPE_SUB:\r
158                 switch(ist->op.oprtype){\r
159                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_WM:\r
160                         i_inst->wm[ist->wmwm_32.wm1]-=i_inst->wm[ist->wmwm_32.wm2];\r
161                         break;\r
162                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_H32:\r
163                         i_inst->wm[ist->wmh32_64.wm]-=ist->wmh32_64.h32;\r
164                         break;\r
165                 default:\r
166                         NyLPC_OnErrorGoto(ERROR);\r
167                 }\r
168                 break;\r
169         case NyLPC_TcMiMicVM_OP_TYPE_MUL:\r
170                 switch(ist->op.oprtype){\r
171                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_WM:\r
172                         i_inst->wm[ist->wmwm_32.wm1]*=i_inst->wm[ist->wmwm_32.wm2];\r
173                         break;\r
174                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_H32:\r
175                         i_inst->wm[ist->wmh32_64.wm]*=ist->wmh32_64.h32;\r
176                         break;\r
177                 default:\r
178                         NyLPC_OnErrorGoto(ERROR);\r
179                 }\r
180                 break;\r
181         case NyLPC_TcMiMicVM_OP_TYPE_MGET:\r
182                 switch(ist->op.oprtype){\r
183                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_H32:\r
184                         i_inst->wm[ist->wmh32_64.wm]=*((NyLPC_TUInt32*)(ist->wmh32_64.h32));\r
185                         break;\r
186                 default:\r
187                         NyLPC_OnErrorGoto(ERROR);\r
188                 }\r
189                 break;\r
190         case NyLPC_TcMiMicVM_OP_TYPE_MPUT:\r
191                 switch(ist->op.oprtype){\r
192                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_H32:\r
193                         *((NyLPC_TUInt32*)(ist->wmh32_64.h32))=i_inst->wm[ist->wmh32_64.wm];\r
194                         break;\r
195                 default:\r
196                         NyLPC_OnErrorGoto(ERROR);\r
197                 }\r
198                 break;\r
199         case NyLPC_TcMiMicVM_OP_TYPE_SGET:\r
200                 switch(ist->op.oprtype){\r
201                 case NyLPC_TcMiMicVM_OPR_TYPE_WM:\r
202                         if(!i_inst->_event_handler->get_stream(i_inst->_event_handler,&(i_inst->wm[ist->wm_32.wm]))){\r
203                                 NyLPC_OnErrorGoto(ERROR);\r
204                         }\r
205                         break;\r
206                 default:\r
207                         NyLPC_OnErrorGoto(ERROR);\r
208                 }\r
209                 break;\r
210         case NyLPC_TcMiMicVM_OP_TYPE_SPUT:\r
211                 switch(ist->op.oprtype){\r
212                 case NyLPC_TcMiMicVM_OPR_TYPE_WM:\r
213                         if(!i_inst->_event_handler->put_stream(i_inst->_event_handler,i_inst->wm[ist->wm_32.wm])){\r
214                                 NyLPC_OnErrorGoto(ERROR);\r
215                         }\r
216                         break;\r
217                 case NyLPC_TcMiMicVM_OPR_TYPE_H32:\r
218                         if(!i_inst->_event_handler->put_stream(i_inst->_event_handler,ist->h32_64.h32)){\r
219                                 NyLPC_OnErrorGoto(ERROR);\r
220                         }\r
221                         break;\r
222                 default:\r
223                         NyLPC_OnErrorGoto(ERROR);\r
224                 }\r
225                 break;\r
226         case NyLPC_TcMiMicVM_OP_TYPE_LD:\r
227                 switch(ist->op.oprtype){\r
228                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_WM:\r
229                         i_inst->wm[ist->wmwm_32.wm1]=i_inst->wm[ist->wmwm_32.wm2];\r
230                         break;\r
231                 case NyLPC_TcMiMicVM_OPR_TYPE_WM_H32:\r
232                         i_inst->wm[ist->wmh32_64.wm]=ist->wmh32_64.h32;\r
233                         break;\r
234                 default:\r
235                         NyLPC_OnErrorGoto(ERROR);\r
236                 }\r
237                 break;\r
238         case NyLPC_TcMiMicVM_OP_TYPE_NOP:\r
239                 switch(ist->op.oprtype){\r
240                 case NyLPC_TcMiMicVM_OPR_TYPE_NONE:\r
241                         break;\r
242                 case NyLPC_TcMiMicVM_OPR_TYPE_H08:\r
243                         i_inst->_event_handler->sleep(i_inst->_event_handler,ist->h8_32.h8);\r
244                         break;\r
245                 default:\r
246                         NyLPC_OnErrorGoto(ERROR);\r
247                 }\r
248                 break;\r
249         case NyLPC_TcMiMicVM_OP_TYPE_EXIT:\r
250                 i_inst->ret_code=0;\r
251                 return 0;\r
252         default:\r
253                 NyLPC_OnErrorGoto(ERROR);\r
254         }\r
255         //実行したコードのワード長を返す。\r
256         switch(ist->op.oprtype){\r
257         case NyLPC_TcMiMicVM_OPR_TYPE_NONE:\r
258         case NyLPC_TcMiMicVM_OPR_TYPE_WM_WM:\r
259         case NyLPC_TcMiMicVM_OPR_TYPE_WM_H08:\r
260         case NyLPC_TcMiMicVM_OPR_TYPE_WM:\r
261         case NyLPC_TcMiMicVM_OPR_TYPE_H08:\r
262         case NyLPC_TcMiMicVM_OPR_TYPE_H16:\r
263                 return 1;\r
264         case NyLPC_TcMiMicVM_OPR_TYPE_WM_H16:\r
265         case NyLPC_TcMiMicVM_OPR_TYPE_WM_H32:\r
266         case NyLPC_TcMiMicVM_OPR_TYPE_H32:\r
267                 return 2;\r
268         }\r
269 ERROR:\r
270         i_inst->ret_code=1;\r
271         return 0;\r
272 }\r
273 \r
274 #define TEST\r
275 #ifndef TEST\r
276 \r
277 #include "NyLPC_cMiMicTxtCompiler.h"\r
278 void main(void)\r
279 {\r
280         struct NyLPC_TcMiMicVM_TEvent eh;\r
281         NyLPC_TUInt32 ap;\r
282         NyLPC_TcMiMicVM_t vm;\r
283         struct NyLPC_TCharArrayPtr bc;\r
284         NyLPC_TcMiMicTxtCompiler_t inst;\r
285         struct NyLPC_TUInt32ArrayPtr bin;\r
286         char BC[1024];\r
287         int ist_len;\r
288 \r
289         NyLPC_TUInt16 l,bl;\r
290         NyLPC_TUInt32 obuf[1024];\r
291         NyLPC_cMiMicBcCompiler_initialize(&inst);\r
292         sprintf(BC,"AA0102AB0100000001AE0203AF0200000003AI0304AJ0300000004AM07BA0505BE0607CA0304CB0300000005CE0304CF0300000005CI0304CJ0300000005ZA.E",&ap,&ap);\r
293         bc.ptr=(char* )BC;\r
294         bc.len=strlen(BC);\r
295         bin.ptr=obuf;\r
296         bin.len=100;\r
297         ist_len=0;\r
298 \r
299         for(;;){\r
300 \r
301                 switch(NyLPC_cMiMicBcCompiler_compileFragment(&inst,&bc,&bin,&bl,&l))\r
302                 {\r
303                 case NyLPC_TcMiMicTxtCompiler_RET_OK:\r
304                         //命令確定。\r
305                         NyLPC_TCharArrayPtr_seek(&bc,l);\r
306                         ist_len+=bl;\r
307                         break;\r
308                 case NyLPC_TcMiMicTxtCompiler_RET_OK_END:\r
309                         //命令終端\r
310                         NyLPC_cMiMicVM_initialize(&vm,&eh);\r
311                         if(!NyLPC_cMiMicVM_run(&vm,obuf,ist_len)){\r
312                                 printf("エンダァ");\r
313                         }\r
314                         printf("OK");\r
315                         break;\r
316                 case NyLPC_TcMiMicTxtCompiler_RET_CONTINUE:\r
317                         //蓄積中。\r
318                         NyLPC_TCharArrayPtr_seek(&bc,l);\r
319                         break;\r
320                 case NyLPC_TcMiMicTxtCompiler_RET_NG:\r
321                         printf("エラー");\r
322                         return;\r
323                 default:\r
324                         break;\r
325                 }\r
326         }\r
327 }\r
328 #endif\r