2010-03-22 07:49:57 +08:00
|
|
|
/*
|
2013-10-09 17:06:40 +08:00
|
|
|
* Virtual machine of finsh shell.
|
2010-03-22 07:49:57 +08:00
|
|
|
*
|
2013-03-30 16:14:38 +08:00
|
|
|
* COPYRIGHT (C) 2006 - 2013, RT-Thread Development Team
|
|
|
|
*
|
|
|
|
* This file is part of RT-Thread (http://www.rt-thread.org)
|
|
|
|
* Maintainer: bernard.xiong <bernard.xiong at gmail.com>
|
|
|
|
*
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
2010-03-22 07:49:57 +08:00
|
|
|
*
|
|
|
|
* Change Logs:
|
|
|
|
* Date Author Notes
|
|
|
|
* 2010-03-22 Bernard first version
|
|
|
|
*/
|
2009-07-03 06:48:23 +08:00
|
|
|
#include <finsh.h>
|
|
|
|
|
|
|
|
#include "finsh_vm.h"
|
|
|
|
#include "finsh_ops.h"
|
|
|
|
#include "finsh_var.h"
|
|
|
|
|
|
|
|
/* stack */
|
|
|
|
union finsh_value finsh_vm_stack[FINSH_STACK_MAX];
|
|
|
|
/* text segment */
|
2017-10-10 14:27:34 +08:00
|
|
|
uint8_t text_segment[FINSH_TEXT_MAX];
|
2009-07-03 06:48:23 +08:00
|
|
|
|
|
|
|
union finsh_value* finsh_sp; /* stack pointer */
|
2017-10-10 14:27:34 +08:00
|
|
|
uint8_t* finsh_pc; /* PC */
|
2009-07-03 06:48:23 +08:00
|
|
|
|
|
|
|
/* syscall list, for dynamic system call register */
|
|
|
|
struct finsh_syscall_item* global_syscall_list = NULL;
|
|
|
|
|
2013-10-09 17:06:40 +08:00
|
|
|
// #define FINSH_VM_DISASSEMBLE
|
2009-07-03 06:48:23 +08:00
|
|
|
void finsh_vm_run()
|
|
|
|
{
|
2017-10-10 14:27:34 +08:00
|
|
|
uint8_t op;
|
2009-07-03 06:48:23 +08:00
|
|
|
|
2013-10-09 17:06:40 +08:00
|
|
|
/* if you want to disassemble the byte code, please define FINSH_VM_DISASSEMBLE */
|
|
|
|
#ifdef FINSH_VM_DISASSEMBLE
|
2009-07-03 06:48:23 +08:00
|
|
|
void finsh_disassemble();
|
|
|
|
finsh_disassemble();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* set sp(stack pointer) to the beginning of stack */
|
|
|
|
finsh_sp = &finsh_vm_stack[0];
|
|
|
|
|
|
|
|
/* set pc to the beginning of text segment */
|
|
|
|
finsh_pc = &text_segment[0];
|
|
|
|
|
|
|
|
while ((finsh_pc - &text_segment[0] >= 0) &&
|
|
|
|
(finsh_pc - &text_segment[0] < FINSH_TEXT_MAX))
|
|
|
|
{
|
|
|
|
/* get op */
|
|
|
|
op = *finsh_pc++;
|
|
|
|
|
|
|
|
/* call op function */
|
|
|
|
op_table[op]();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef RT_USING_HEAP
|
|
|
|
void finsh_syscall_append(const char* name, syscall_func func)
|
|
|
|
{
|
|
|
|
/* create the syscall */
|
|
|
|
struct finsh_syscall_item* item;
|
|
|
|
|
|
|
|
item = (struct finsh_syscall_item*)rt_malloc(sizeof(struct finsh_syscall_item));
|
|
|
|
if (item != RT_NULL)
|
|
|
|
{
|
|
|
|
item->next = NULL;
|
2014-01-04 06:02:33 +08:00
|
|
|
item->syscall.name = rt_strdup(name);
|
2009-07-03 06:48:23 +08:00
|
|
|
item->syscall.func = func;
|
|
|
|
|
|
|
|
if (global_syscall_list == NULL)
|
|
|
|
{
|
|
|
|
global_syscall_list = item;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
item->next = global_syscall_list;
|
|
|
|
global_syscall_list = item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-01-22 12:44:47 +08:00
|
|
|
#if defined(_MSC_VER) || (defined(__GNUC__) && defined(__x86_64__))
|
2012-12-29 16:11:38 +08:00
|
|
|
struct finsh_syscall* finsh_syscall_next(struct finsh_syscall* call)
|
2012-10-22 11:12:21 +08:00
|
|
|
{
|
|
|
|
unsigned int *ptr;
|
|
|
|
ptr = (unsigned int*) (call + 1);
|
|
|
|
while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _syscall_table_end))
|
|
|
|
ptr ++;
|
|
|
|
|
|
|
|
return (struct finsh_syscall*)ptr;
|
|
|
|
}
|
2013-01-22 12:44:47 +08:00
|
|
|
|
|
|
|
struct finsh_sysvar* finsh_sysvar_next(struct finsh_sysvar* call)
|
|
|
|
{
|
|
|
|
unsigned int *ptr;
|
|
|
|
ptr = (unsigned int*) (call + 1);
|
|
|
|
while ((*ptr == 0) && ((unsigned int*)ptr < (unsigned int*) _sysvar_table_end))
|
|
|
|
ptr ++;
|
|
|
|
|
|
|
|
return (struct finsh_sysvar*)ptr;
|
|
|
|
}
|
2012-10-22 11:12:21 +08:00
|
|
|
#endif
|
|
|
|
|
2009-07-03 06:48:23 +08:00
|
|
|
struct finsh_syscall* finsh_syscall_lookup(const char* name)
|
|
|
|
{
|
|
|
|
struct finsh_syscall* index;
|
|
|
|
struct finsh_syscall_item* item;
|
|
|
|
|
2012-12-29 16:11:38 +08:00
|
|
|
for (index = _syscall_table_begin; index < _syscall_table_end; FINSH_NEXT_SYSCALL(index))
|
2009-07-03 06:48:23 +08:00
|
|
|
{
|
|
|
|
if (strcmp(index->name, name) == 0)
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* find on syscall list */
|
|
|
|
item = global_syscall_list;
|
|
|
|
while (item != NULL)
|
|
|
|
{
|
|
|
|
if (strncmp(item->syscall.name, name, strlen(name)) == 0)
|
|
|
|
{
|
|
|
|
return &(item->syscall);
|
|
|
|
}
|
|
|
|
|
|
|
|
item = item->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-10-09 17:06:40 +08:00
|
|
|
#ifdef FINSH_VM_DISASSEMBLE
|
2009-07-03 06:48:23 +08:00
|
|
|
void finsh_disassemble()
|
|
|
|
{
|
2017-10-10 14:27:34 +08:00
|
|
|
uint8_t *pc, op;
|
2009-07-03 06:48:23 +08:00
|
|
|
|
|
|
|
pc = &text_segment[0];
|
|
|
|
while (*pc != 0)
|
|
|
|
{
|
|
|
|
op = *pc;
|
|
|
|
switch (op)
|
|
|
|
{
|
|
|
|
case FINSH_OP_ADD_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("addb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_SUB_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("subb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_DIV_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("divb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_MOD_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("modb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_MUL_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("mulb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_AND_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("andb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_OR_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("orb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_XOR_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("xorb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_BITWISE_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("bwb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_SHL_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("shlb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_SHR_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("shrb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_LD_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("ldb %d\n", *pc++);
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_LD_VALUE_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("ldb [0x%x]\n", FINSH_GET32(pc));
|
2009-07-03 06:48:23 +08:00
|
|
|
pc += 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_ST_BYTE:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("stb\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_ADD_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("addw\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_SUB_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("subw\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_DIV_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("divw\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_MOD_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("modw\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_MUL_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("mulw\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_AND_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("andw\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_OR_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("orw\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_XOR_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("xorw\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_BITWISE_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("bww\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_SHL_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("shlw\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_SHR_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("shrw\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_LD_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("ldw %d\n", FINSH_GET16(pc));
|
2009-07-03 06:48:23 +08:00
|
|
|
pc += 2;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_LD_VALUE_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("ldw [0x%x]\n", FINSH_GET32(pc));
|
2009-07-03 06:48:23 +08:00
|
|
|
pc += 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_ST_WORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("stw\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_ADD_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("addd\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_SUB_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("subd\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_DIV_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("divd\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_MOD_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("modd\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_MUL_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("muld\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_AND_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("andd\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_OR_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("ord\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_XOR_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("xord\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_BITWISE_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("bwd\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_SHL_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("shld\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_SHR_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("shrd\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_LD_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("ldd 0x%x\n", FINSH_GET32(pc));
|
2009-07-03 06:48:23 +08:00
|
|
|
pc += 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_LD_VALUE_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("ldd [0x%x]\n", FINSH_GET32(pc));
|
2009-07-03 06:48:23 +08:00
|
|
|
pc += 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_ST_DWORD:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("std\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_POP:
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("pop\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
pc ++;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_SYSCALL:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("syscall %d\n", *pc++);
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_LD_VALUE_BYTE_STACK:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("ldb [sp]\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_LD_VALUE_WORD_STACK:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("ldw [sp]\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case FINSH_OP_LD_VALUE_DWORD_STACK:
|
|
|
|
pc ++;
|
2010-03-30 00:21:18 +08:00
|
|
|
rt_kprintf("ldd [sp]\n");
|
2009-07-03 06:48:23 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|