vm
| @@ -1,34 +0,0 @@ | ||
| 1 | -#include "npl.h" | |
| 2 | - | |
| 3 | -int npl_sm_init(npl_sm_t *sm) | |
| 4 | -{ | |
| 5 | - NPL_assert(sm); | |
| 6 | - | |
| 7 | - return 0; | |
| 8 | -} | |
| 9 | - | |
| 10 | -npl_sm_t* npl_sm_new(void) | |
| 11 | -{ | |
| 12 | - npl_sm_t *sm; | |
| 13 | - | |
| 14 | - sm = NPL_SM(npl_object_alloc(npl_sm_type)); | |
| 15 | - if (sm == NULL) | |
| 16 | - return NULL; | |
| 17 | - if (npl_sm_init(sm)) { | |
| 18 | - npl_object_destroy(NPL_OBJECT(sm)); | |
| 19 | - return NULL; | |
| 20 | - } | |
| 21 | - | |
| 22 | - return sm; | |
| 23 | -} | |
| 24 | - | |
| 25 | -// sm クラスの型情報 | |
| 26 | -npl_type_t _npl_sm_type = { | |
| 27 | - .ctype = NPL_CT_OBJECT, | |
| 28 | - .name = L"sm", | |
| 29 | - .parent = &_npl_object_type, | |
| 30 | - .size = sizeof(npl_sm_t), | |
| 31 | -}; | |
| 32 | - | |
| 33 | -npl_type_t *npl_sm_type = &_npl_sm_type; | |
| 34 | - |
| @@ -3,21 +3,22 @@ | ||
| 3 | 3 | libnpl.a: npl.o object.o stream.o str.o mbstr.o type.o sbuf.o \ |
| 4 | 4 | buf.o chunk.o val.o var.o tuple.o func.o \ |
| 5 | 5 | state.o def.o ptr.o \ |
| 6 | -sm.o uniface.o iptr.o file.o iface.o \ | |
| 6 | +vm.o uniface.o iptr.o file.o iface.o \ | |
| 7 | 7 | listener.o args.o struct.o \ |
| 8 | 8 | cmd.o console.o state_event.o cmd_event.o istate.o \ |
| 9 | 9 | vt.o cbuf.o stack.o vstack.o source.o cmdi.o nplu.o list.o \ |
| 10 | -buffer.o value.o dict.o head.o | |
| 10 | +buffer.o value.o dict.o head.o vmi.o | |
| 11 | 11 | ar rcs libnpl.a npl.o object.o stream.o str.o \ |
| 12 | 12 | mbstr.o type.o sbuf.o buf.o \ |
| 13 | 13 | chunk.o val.o var.o tuple.o \ |
| 14 | 14 | func.o state.o \ |
| 15 | 15 | def.o ptr.o \ |
| 16 | - sm.o uniface.o iptr.o file.o iface.o \ | |
| 16 | + vm.o uniface.o iptr.o file.o iface.o \ | |
| 17 | 17 | listener.o args.o struct.o \ |
| 18 | 18 | cmd.o console.o state_event.o cmd_event.o \ |
| 19 | 19 | istate.o vt.o cbuf.o stack.o vstack.o source.o \ |
| 20 | - cmdi.o nplu.o list.o buffer.o value.o dict.o head.o | |
| 20 | + cmdi.o nplu.o list.o buffer.o value.o dict.o head.o \ | |
| 21 | + vmi.o | |
| 21 | 22 | |
| 22 | 23 | npl.o: npl.c npl.h |
| 23 | 24 | gcc -Wall -c npl.c |
| @@ -67,8 +68,8 @@ | ||
| 67 | 68 | ptr.o: ptr.c npl.h |
| 68 | 69 | gcc -Wall -c ptr.c |
| 69 | 70 | |
| 70 | -sm.o: sm.c npl.h | |
| 71 | - gcc -Wall -c sm.c | |
| 71 | +vm.o: vm.c npl.h | |
| 72 | + gcc -Wall -c vm.c | |
| 72 | 73 | |
| 73 | 74 | uniface.o: uniface.c npl.h |
| 74 | 75 | gcc -Wall -c uniface.c |
| @@ -142,6 +143,9 @@ | ||
| 142 | 143 | head.o: head.c npl.h |
| 143 | 144 | gcc -Wall -c head.c |
| 144 | 145 | |
| 146 | +vmi.o: vmi.c npl.h | |
| 147 | + gcc -Wall -c vmi.c | |
| 148 | + | |
| 145 | 149 | clean: |
| 146 | 150 | rm -f *.o |
| 147 | 151 | rm -f libnpl.a |
| @@ -61,3 +61,13 @@ | ||
| 61 | 61 | return m->getter(head, val_r); |
| 62 | 62 | } |
| 63 | 63 | |
| 64 | +int npl_call(npl_head_t *head, npl_member_t *m, npl_vm_t *vm) | |
| 65 | +{ | |
| 66 | + NPL_assert(head); | |
| 67 | + NPL_assert(m); | |
| 68 | + NPL_assert(vm); | |
| 69 | + NPL_assert(m->method); | |
| 70 | + | |
| 71 | + return m->method(head, vm); | |
| 72 | +} | |
| 73 | + |
| @@ -177,3 +177,56 @@ | ||
| 177 | 177 | return NULL; |
| 178 | 178 | } |
| 179 | 179 | |
| 180 | +// ライブラリ・モジュールに存在する型情報 | |
| 181 | +static npl_type_t *_types[] = { | |
| 182 | + &_npl_unset_type, | |
| 183 | + &_npl_bool_type, | |
| 184 | + &_npl_byte_type, | |
| 185 | + &_npl_size_type, | |
| 186 | + &_npl_int_type, | |
| 187 | + &_npl_uint_type, | |
| 188 | + &_npl_long_type, | |
| 189 | + &_npl_ulong_type, | |
| 190 | + &_npl_float_type, | |
| 191 | + &_npl_wchar_type, | |
| 192 | + &_npl_mbchar_type, | |
| 193 | + &_npl_ws_type, | |
| 194 | + &_npl_mbs_type, | |
| 195 | + &_npl_type_type, | |
| 196 | + &_npl_struct_type, | |
| 197 | + &_npl_args_type, | |
| 198 | + &_npl_state_event_type, | |
| 199 | + &_npl_cmd_event_type, | |
| 200 | + &_npl_iface_type, | |
| 201 | + &_npl_uniface_type, | |
| 202 | + &_npl_stream_type, | |
| 203 | + &_npl_iptr_type, | |
| 204 | + &_npl_istate_type, | |
| 205 | + &_npl_object_type, | |
| 206 | + &_npl_chunk_type, | |
| 207 | + &_npl_def_type, | |
| 208 | + &_npl_value_type, | |
| 209 | + &_npl_str_type, | |
| 210 | + &_npl_mbstr_type, | |
| 211 | + &_npl_var_type, | |
| 212 | + &_npl_ptr_type, | |
| 213 | + &_npl_tuple_type, | |
| 214 | + &_npl_buffer_type, | |
| 215 | + &_npl_list_type, | |
| 216 | + &_npl_dict_type, | |
| 217 | + &_npl_func_type, | |
| 218 | + &_npl_listener_type, | |
| 219 | + &_npl_vstack_type, | |
| 220 | + &_npl_state_type, | |
| 221 | + &_npl_file_type, | |
| 222 | + &_npl_cmd_type, | |
| 223 | + NULL, | |
| 224 | +}; | |
| 225 | + | |
| 226 | +// NPLライブラリ・モジュールの設定 | |
| 227 | +npl_mod_t _npl_module = { | |
| 228 | + .types = _types, | |
| 229 | +}; | |
| 230 | + | |
| 231 | +npl_mod_t *npl_module = &_npl_module; | |
| 232 | + |
| @@ -45,7 +45,6 @@ | ||
| 45 | 45 | #define NPL_BUFFER(x) _NPL_CAST(npl_buffer_t, x, npl_buffer_type) |
| 46 | 46 | #define NPL_LIST(x) _NPL_CAST(npl_list_t, x, npl_list_type) |
| 47 | 47 | #define NPL_DICT(x) _NPL_CAST(npl_dict_t, x, npl_dict_type) |
| 48 | -#define NPL_SM(x) _NPL_CAST(npl_sm_t, x, npl_sm_type) | |
| 49 | 48 | #define NPL_FUNC(x) _NPL_CAST(npl_func_t, x, npl_func_type) |
| 50 | 49 | #define NPL_LISTENER(x) _NPL_CAST(npl_listener_t, x, npl_listener_type) |
| 51 | 50 | #define NPL_VSTACK(x) _NPL_CAST(npl_vstack_t, x, npl_vstack_type) |
| @@ -53,12 +52,24 @@ | ||
| 53 | 52 | #define NPL_FILE(x) _NPL_CAST(npl_file_t, x, npl_file_type) |
| 54 | 53 | #define NPL_CMD(x) _NPL_CAST(npl_cmd_t, x, npl_cmd_type) |
| 55 | 54 | |
| 55 | +// 基本データ型 | |
| 56 | +typedef signed char npl_s8_t; | |
| 57 | +typedef signed short npl_s16_t; | |
| 58 | +typedef signed long npl_s32_t; | |
| 59 | +typedef signed long long npl_s64_t; | |
| 60 | +typedef unsigned char npl_u8_t; | |
| 61 | +typedef unsigned short npl_u16_t; | |
| 62 | +typedef unsigned long npl_u32_t; | |
| 63 | +typedef unsigned long long npl_u64_t; | |
| 64 | +typedef void* npl_addr_t; | |
| 65 | +typedef double npl_float_t; | |
| 66 | + | |
| 56 | 67 | // 構造体、列挙型 |
| 57 | 68 | typedef enum npl_bool_t npl_bool_t; |
| 58 | 69 | typedef unsigned char npl_byte_t; |
| 70 | +typedef union npl_reg_t npl_reg_t; | |
| 59 | 71 | typedef enum npl_token_type_t npl_token_type_t; |
| 60 | 72 | typedef struct npl_vfunc_t npl_vfunc_t; |
| 61 | -typedef enum npl_opcode_t npl_opcode_t; | |
| 62 | 73 | typedef struct npl_head_t npl_head_t; |
| 63 | 74 | typedef struct npl_member_t npl_member_t; |
| 64 | 75 | typedef enum npl_class_type_t npl_class_type_t; |
| @@ -72,6 +83,7 @@ | ||
| 72 | 83 | typedef struct npl_command_list_t npl_command_list_t; |
| 73 | 84 | |
| 74 | 85 | // 組込み型構造体 |
| 86 | +typedef struct npl_mod_t npl_mod_t; | |
| 75 | 87 | typedef struct npl_type_t npl_type_t; |
| 76 | 88 | typedef struct npl_val_t npl_val_t; |
| 77 | 89 | typedef struct npl_buf_t npl_buf_t; |
| @@ -78,6 +90,8 @@ | ||
| 78 | 90 | typedef struct npl_cbuf_t npl_cbuf_t; |
| 79 | 91 | typedef struct npl_sbuf_t npl_sbuf_t; |
| 80 | 92 | typedef struct npl_stack_t npl_stack_t; |
| 93 | +typedef struct npl_vmi_t npl_vmi_t; | |
| 94 | +typedef struct npl_vm_t npl_vm_t; | |
| 81 | 95 | typedef struct npl_vt_t npl_vt_t; |
| 82 | 96 | typedef struct npl_source_t npl_source_t; |
| 83 | 97 | typedef struct npl_cmdi_t npl_cmdi_t; |
| @@ -110,7 +124,6 @@ | ||
| 110 | 124 | typedef struct npl_buffer_t npl_buffer_t; |
| 111 | 125 | typedef struct npl_list_t npl_list_t; |
| 112 | 126 | typedef struct npl_dict_t npl_dict_t; |
| 113 | -typedef struct npl_sm_t npl_sm_t; | |
| 114 | 127 | typedef struct npl_func_t npl_func_t; |
| 115 | 128 | typedef struct npl_listener_t npl_listener_t; |
| 116 | 129 | typedef struct npl_vstack_t npl_vstack_t; |
| @@ -142,6 +155,11 @@ | ||
| 142 | 155 | const char *func_name, |
| 143 | 156 | unsigned int line_no); |
| 144 | 157 | |
| 158 | +// NPLライブラリ・モジュール | |
| 159 | +extern npl_mod_t _npl_module; | |
| 160 | + | |
| 161 | +extern npl_mod_t *npl_module; | |
| 162 | + | |
| 145 | 163 | // 基本値の型情報 |
| 146 | 164 | extern npl_type_t _npl_unset_type; |
| 147 | 165 | extern npl_type_t _npl_bool_type; |
| @@ -213,7 +231,6 @@ | ||
| 213 | 231 | extern npl_type_t _npl_buffer_type; |
| 214 | 232 | extern npl_type_t _npl_list_type; |
| 215 | 233 | extern npl_type_t _npl_dict_type; |
| 216 | -extern npl_type_t _npl_sm_type; | |
| 217 | 234 | extern npl_type_t _npl_func_type; |
| 218 | 235 | extern npl_type_t _npl_listener_type; |
| 219 | 236 | extern npl_type_t _npl_vstack_type; |
| @@ -233,7 +250,6 @@ | ||
| 233 | 250 | extern npl_type_t *npl_buffer_type; |
| 234 | 251 | extern npl_type_t *npl_list_type; |
| 235 | 252 | extern npl_type_t *npl_dict_type; |
| 236 | -extern npl_type_t *npl_sm_type; | |
| 237 | 253 | extern npl_type_t *npl_func_type; |
| 238 | 254 | extern npl_type_t *npl_listener_type; |
| 239 | 255 | extern npl_type_t *npl_vstack_type; |
| @@ -247,6 +263,20 @@ | ||
| 247 | 263 | NPL_TRUE, |
| 248 | 264 | }; |
| 249 | 265 | |
| 266 | +// reg (register) | |
| 267 | +union npl_reg_t { | |
| 268 | + npl_s8_t s8; | |
| 269 | + npl_s16_t s16; | |
| 270 | + npl_s32_t s32; | |
| 271 | + npl_s64_t s64; | |
| 272 | + npl_u8_t u8; | |
| 273 | + npl_u16_t u16; | |
| 274 | + npl_u32_t u32; | |
| 275 | + npl_u64_t u64; | |
| 276 | + npl_addr_t addr; | |
| 277 | + npl_float_t f; | |
| 278 | +}; | |
| 279 | + | |
| 250 | 280 | // token |
| 251 | 281 | // 汎用的な予め定義されるトークン。 |
| 252 | 282 | enum npl_token_type_t { |
| @@ -332,19 +362,20 @@ | ||
| 332 | 362 | void *fn; // 呼び出す関数のアドレス |
| 333 | 363 | }; |
| 334 | 364 | |
| 335 | -// opcode | |
| 336 | -enum npl_opcode_t { | |
| 337 | - NPL_OPC_NULL = 0, | |
| 338 | - NPL_OPC_END, | |
| 365 | +// mod | |
| 366 | +struct npl_mod_t { | |
| 367 | + npl_type_t **types; | |
| 339 | 368 | }; |
| 340 | 369 | |
| 341 | 370 | // member (クラスメンバ情報) |
| 342 | 371 | struct npl_member_t { |
| 343 | 372 | npl_type_t *type; // メンバ型、メソッドの返り値型 |
| 373 | + npl_type_t **args; // メソッドの引数型リスト | |
| 344 | 374 | wchar_t *name; |
| 345 | 375 | size_t offset; |
| 346 | 376 | int (*setter)(npl_head_t *head, npl_val_t *val); |
| 347 | 377 | int (*getter)(npl_head_t *head, npl_val_t *val_r); |
| 378 | + int (*method)(npl_head_t *head, npl_vm_t *vm); | |
| 348 | 379 | }; |
| 349 | 380 | |
| 350 | 381 | // type |
| @@ -443,6 +474,7 @@ | ||
| 443 | 474 | void* npl_member_addr(npl_head_t *head, npl_member_t *m); |
| 444 | 475 | int npl_set(npl_head_t *head, npl_member_t *m, npl_val_t *val); |
| 445 | 476 | int npl_get(npl_head_t *head, npl_member_t *m, npl_val_t *val_r); |
| 477 | +int npl_call(npl_head_t *head, npl_member_t *m, npl_vm_t *vm); | |
| 446 | 478 | |
| 447 | 479 | // struct |
| 448 | 480 | struct npl_struct_t { |
| @@ -762,14 +794,50 @@ | ||
| 762 | 794 | npl_tuple_t* npl_tuple_new(size_t len); |
| 763 | 795 | size_t npl_tuple_len(npl_tuple_t *tuple); |
| 764 | 796 | |
| 765 | -// sm class (stack machine) | |
| 766 | -struct npl_sm_t { | |
| 767 | - npl_object_t object; | |
| 797 | +// vm opcode | |
| 798 | +#define NPL_OP_NOP 0 | |
| 799 | +#define NPL_OP_BREAK 1 | |
| 800 | +#define NPL_OP_END 2 | |
| 801 | +#define NPL_OP_SETP 3 | |
| 802 | +#define NPL_OP_ADDP 4 | |
| 803 | +#define NPL_OP_STORE 5 | |
| 804 | +#define NPL_OP_LOAD 6 | |
| 805 | +#define NPL_OP_SET 7 | |
| 806 | +#define NPL_OP_PUSH 8 | |
| 807 | +#define NPL_OP_POP 9 | |
| 808 | + | |
| 809 | +// vmi (virtual machine interpreter) | |
| 810 | +struct npl_vmi_t { | |
| 811 | + void *code; | |
| 812 | + size_t pc; // program counter | |
| 768 | 813 | }; |
| 769 | 814 | |
| 770 | -int npl_sm_init(npl_sm_t *sm); | |
| 771 | -npl_sm_t* npl_sm_new(void); | |
| 815 | +npl_u8_t npl_vmi_u8(npl_vmi_t *vmi); | |
| 816 | +npl_u16_t npl_vmi_u16(npl_vmi_t *vmi); | |
| 817 | +npl_u32_t npl_vmi_u32(npl_vmi_t *vmi); | |
| 818 | +npl_u64_t npl_vmi_u64(npl_vmi_t *vmi); | |
| 819 | +npl_s8_t npl_vmi_s8(npl_vmi_t *vmi); | |
| 820 | +npl_s16_t npl_vmi_s16(npl_vmi_t *vmi); | |
| 821 | +npl_s32_t npl_vmi_s32(npl_vmi_t *vmi); | |
| 822 | +npl_s64_t npl_vmi_s64(npl_vmi_t *vmi); | |
| 823 | +npl_addr_t npl_vmi_addr(npl_vmi_t *vmi); | |
| 824 | +npl_float_t npl_vmi_float(npl_vmi_t *vmi); | |
| 772 | 825 | |
| 826 | +// vm (virtual machine) | |
| 827 | +struct npl_vm_t { | |
| 828 | + void *ptr[2]; | |
| 829 | + void *obj; | |
| 830 | + void *var; | |
| 831 | + npl_buf_t stack; | |
| 832 | + size_t sp; // stack pointer | |
| 833 | + npl_vmi_t vmi; | |
| 834 | +}; | |
| 835 | + | |
| 836 | +int npl_vm_init(npl_vm_t *vm); | |
| 837 | +void npl_vm_final(npl_vm_t *vm); | |
| 838 | +void npl_vm_clear(npl_vm_t *vm); | |
| 839 | +npl_u8_t npl_vm_exec(npl_vm_t *vm); | |
| 840 | + | |
| 773 | 841 | // func class |
| 774 | 842 | enum npl_func_type_t { |
| 775 | 843 | NPL_FNT_LISTENER, |
| @@ -0,0 +1,202 @@ | ||
| 1 | +#include "npl.h" | |
| 2 | + | |
| 3 | +#define SIZE(x) (x & 0x03) | |
| 4 | +#define SIGNE(x) (x & 0x04) | |
| 5 | +#define REG(x) ((x & 0x08) >> 3) | |
| 6 | + | |
| 7 | +static void* _var(npl_vm_t *vm, size_t sp) | |
| 8 | +{ | |
| 9 | + unsigned char *p = vm->var; | |
| 10 | + | |
| 11 | + p = p + sp; | |
| 12 | + return p; | |
| 13 | +} | |
| 14 | + | |
| 15 | +static void _setp(npl_vm_t *vm) | |
| 16 | +{ | |
| 17 | + npl_u8_t code = npl_vmi_u8(&vm->vmi); | |
| 18 | + npl_u16_t sp = npl_vmi_u16(&vm->vmi); | |
| 19 | + void *p = _var(vm, sp); | |
| 20 | + | |
| 21 | + vm->ptr[REG(code)] = p; | |
| 22 | +} | |
| 23 | + | |
| 24 | +static void _addp(npl_vm_t *vm) | |
| 25 | +{ | |
| 26 | + npl_u8_t code = npl_vmi_u8(&vm->vmi); | |
| 27 | + npl_u16_t sp = npl_vmi_u16(&vm->vmi); | |
| 28 | + unsigned char *p; | |
| 29 | + | |
| 30 | + p = (unsigned char*)vm->ptr[REG(code)]; | |
| 31 | + p = p + sp; | |
| 32 | + vm->ptr[REG(code)] = p; | |
| 33 | +} | |
| 34 | + | |
| 35 | +static void _store(npl_vm_t *vm) | |
| 36 | +{ | |
| 37 | + npl_u8_t code = npl_vmi_u8(&vm->vmi); | |
| 38 | + npl_u16_t sp = npl_vmi_u16(&vm->vmi); | |
| 39 | + void *src = vm->ptr[REG(code)]; | |
| 40 | + void *dst = _var(vm, sp); | |
| 41 | + | |
| 42 | + switch (SIZE(code)) { | |
| 43 | + case 0: | |
| 44 | + *((npl_u8_t*)dst) = *((npl_u8_t*)src); | |
| 45 | + break; | |
| 46 | + case 1: | |
| 47 | + *((npl_u16_t*)dst) = *((npl_u16_t*)src); | |
| 48 | + break; | |
| 49 | + case 2: | |
| 50 | + *((npl_u32_t*)dst) = *((npl_u32_t*)src); | |
| 51 | + break; | |
| 52 | + case 3: | |
| 53 | + *((npl_u64_t*)dst) = *((npl_u64_t*)src); | |
| 54 | + break; | |
| 55 | + } | |
| 56 | +} | |
| 57 | + | |
| 58 | +static void _load(npl_vm_t *vm) | |
| 59 | +{ | |
| 60 | + npl_u8_t code = npl_vmi_u8(&vm->vmi); | |
| 61 | + npl_u16_t sp = npl_vmi_u16(&vm->vmi); | |
| 62 | + void *src = _var(vm, sp); | |
| 63 | + void *dst = vm->ptr[REG(code)]; | |
| 64 | + | |
| 65 | + switch (SIZE(code)) { | |
| 66 | + case 0: | |
| 67 | + *((npl_u8_t*)dst) = *((npl_u8_t*)src); | |
| 68 | + break; | |
| 69 | + case 1: | |
| 70 | + *((npl_u16_t*)dst) = *((npl_u16_t*)src); | |
| 71 | + break; | |
| 72 | + case 2: | |
| 73 | + *((npl_u32_t*)dst) = *((npl_u32_t*)src); | |
| 74 | + break; | |
| 75 | + case 3: | |
| 76 | + *((npl_u64_t*)dst) = *((npl_u64_t*)src); | |
| 77 | + break; | |
| 78 | + } | |
| 79 | +} | |
| 80 | + | |
| 81 | +static void _set(npl_vm_t *vm) | |
| 82 | +{ | |
| 83 | + npl_u8_t code = npl_vmi_u8(&vm->vmi); | |
| 84 | + void *dst = vm->ptr[REG(code)]; | |
| 85 | + | |
| 86 | + switch (SIZE(code)) { | |
| 87 | + case 0: | |
| 88 | + *((npl_u8_t*)dst) = npl_vmi_u8(&vm->vmi); | |
| 89 | + break; | |
| 90 | + case 1: | |
| 91 | + *((npl_u16_t*)dst) = npl_vmi_u16(&vm->vmi); | |
| 92 | + break; | |
| 93 | + case 2: | |
| 94 | + *((npl_u32_t*)dst) = npl_vmi_u32(&vm->vmi); | |
| 95 | + break; | |
| 96 | + case 3: | |
| 97 | + *((npl_u64_t*)dst) = npl_vmi_u64(&vm->vmi); | |
| 98 | + break; | |
| 99 | + } | |
| 100 | +} | |
| 101 | + | |
| 102 | +static int _push(npl_vm_t *vm) | |
| 103 | +{ | |
| 104 | + npl_u16_t bytes = npl_vmi_u16(&vm->vmi); | |
| 105 | + size_t new_sp; | |
| 106 | + | |
| 107 | + if (npl_add(vm->sp, bytes, &new_sp)) | |
| 108 | + return 1; // error | |
| 109 | + if (new_sp >= npl_buf_size(&vm->stack)) { | |
| 110 | + if (bytes < 4096) | |
| 111 | + bytes = 4096; | |
| 112 | + if (npl_buf_expand(&vm->stack, bytes)) | |
| 113 | + return 1; // error | |
| 114 | + } | |
| 115 | + | |
| 116 | + vm->sp = new_sp; | |
| 117 | + | |
| 118 | + return 0; | |
| 119 | +} | |
| 120 | + | |
| 121 | +static void _pop(npl_vm_t *vm) | |
| 122 | +{ | |
| 123 | + npl_u16_t bytes = npl_vmi_u16(&vm->vmi); | |
| 124 | + | |
| 125 | + if (vm->sp < bytes) | |
| 126 | + NPL_abort(); | |
| 127 | + vm->sp -= bytes; | |
| 128 | +} | |
| 129 | + | |
| 130 | +int npl_vm_init(npl_vm_t *vm) | |
| 131 | +{ | |
| 132 | + NPL_assert(vm); | |
| 133 | + | |
| 134 | + if (npl_buf_init(&vm->stack, 4096)) | |
| 135 | + return 1; // error | |
| 136 | + vm->sp = 0; | |
| 137 | + vm->var = npl_buf_get_buffer(&vm->stack, 0); | |
| 138 | + | |
| 139 | + return 0; | |
| 140 | +} | |
| 141 | + | |
| 142 | +void npl_vm_final(npl_vm_t *vm) | |
| 143 | +{ | |
| 144 | + NPL_assert(vm); | |
| 145 | + | |
| 146 | + npl_buf_final(&vm->stack); | |
| 147 | +} | |
| 148 | + | |
| 149 | +void npl_vm_clear(npl_vm_t *vm) | |
| 150 | +{ | |
| 151 | + NPL_assert(vm); | |
| 152 | + | |
| 153 | + vm->sp = 0; | |
| 154 | +} | |
| 155 | + | |
| 156 | +npl_u8_t npl_vm_exec(npl_vm_t *vm) | |
| 157 | +{ | |
| 158 | + npl_u8_t code; | |
| 159 | + | |
| 160 | + NPL_assert(vm); | |
| 161 | + | |
| 162 | + while (1) { | |
| 163 | + code = npl_vmi_u8(&vm->vmi); | |
| 164 | + switch (code) { | |
| 165 | + case NPL_OP_NOP: | |
| 166 | + break; | |
| 167 | + case NPL_OP_END: | |
| 168 | + case NPL_OP_BREAK: | |
| 169 | + return code; | |
| 170 | + case NPL_OP_SETP: | |
| 171 | + _setp(vm); | |
| 172 | + break; | |
| 173 | + case NPL_OP_ADDP: | |
| 174 | + _addp(vm); | |
| 175 | + break; | |
| 176 | + case NPL_OP_STORE: | |
| 177 | + _store(vm); | |
| 178 | + break; | |
| 179 | + case NPL_OP_LOAD: | |
| 180 | + _load(vm); | |
| 181 | + break; | |
| 182 | + case NPL_OP_SET: | |
| 183 | + _set(vm); | |
| 184 | + break; | |
| 185 | + case NPL_OP_PUSH: | |
| 186 | + if (_push(vm)) | |
| 187 | + goto ERROR; | |
| 188 | + break; | |
| 189 | + case NPL_OP_POP: | |
| 190 | + _pop(vm); | |
| 191 | + break; | |
| 192 | + default: | |
| 193 | + // 不正なオペコードを検出 | |
| 194 | + NPL_abort(); | |
| 195 | + break; | |
| 196 | + } | |
| 197 | + } | |
| 198 | + | |
| 199 | +ERROR: | |
| 200 | + return 0; | |
| 201 | +} | |
| 202 | + |
| @@ -0,0 +1,65 @@ | ||
| 1 | +#include "npl.h" | |
| 2 | + | |
| 3 | +// vmi utilities | |
| 4 | + | |
| 5 | +static void* _get(npl_vmi_t *vmi, size_t bytes) | |
| 6 | +{ | |
| 7 | + unsigned char *p; | |
| 8 | + | |
| 9 | + p = vmi->code; | |
| 10 | + p = p + vmi->pc; | |
| 11 | + vmi->pc += bytes; | |
| 12 | + | |
| 13 | + return p; | |
| 14 | +} | |
| 15 | + | |
| 16 | +npl_u8_t npl_vmi_u8(npl_vmi_t *vmi) | |
| 17 | +{ | |
| 18 | + return *((npl_u8_t*)_get(vmi, 1)); | |
| 19 | +} | |
| 20 | + | |
| 21 | +npl_u16_t npl_vmi_u16(npl_vmi_t *vmi) | |
| 22 | +{ | |
| 23 | + return *((npl_u16_t*)_get(vmi, 2)); | |
| 24 | +} | |
| 25 | + | |
| 26 | +npl_u32_t npl_vmi_u32(npl_vmi_t *vmi) | |
| 27 | +{ | |
| 28 | + return *((npl_u32_t*)_get(vmi, 4)); | |
| 29 | +} | |
| 30 | + | |
| 31 | +npl_u64_t npl_vmi_u64(npl_vmi_t *vmi) | |
| 32 | +{ | |
| 33 | + return *((npl_u64_t*)_get(vmi, 8)); | |
| 34 | +} | |
| 35 | + | |
| 36 | +npl_s8_t npl_vmi_s8(npl_vmi_t *vmi) | |
| 37 | +{ | |
| 38 | + return *((npl_s8_t*)_get(vmi, 1)); | |
| 39 | +} | |
| 40 | + | |
| 41 | +npl_s16_t npl_vmi_s16(npl_vmi_t *vmi) | |
| 42 | +{ | |
| 43 | + return *((npl_s16_t*)_get(vmi, 2)); | |
| 44 | +} | |
| 45 | + | |
| 46 | +npl_s32_t npl_vmi_s32(npl_vmi_t *vmi) | |
| 47 | +{ | |
| 48 | + return *((npl_s32_t*)_get(vmi, 4)); | |
| 49 | +} | |
| 50 | + | |
| 51 | +npl_s64_t npl_vmi_s64(npl_vmi_t *vmi) | |
| 52 | +{ | |
| 53 | + return *((npl_s64_t*)_get(vmi, 8)); | |
| 54 | +} | |
| 55 | + | |
| 56 | +npl_addr_t npl_vmi_addr(npl_vmi_t *vmi) | |
| 57 | +{ | |
| 58 | + return *((npl_addr_t*)_get(vmi, sizeof(npl_addr_t))); | |
| 59 | +} | |
| 60 | + | |
| 61 | +npl_float_t npl_vmi_float(npl_vmi_t *vmi) | |
| 62 | +{ | |
| 63 | + return *((npl_float_t*)_get(vmi, sizeof(double))); | |
| 64 | +} | |
| 65 | + |