📄 wsasm.c
字号:
/* ==================================================================== * The Kannel Software License, Version 1.0 * * Copyright (c) 2001-2004 Kannel Group * Copyright (c) 1998-2001 WapIT Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Kannel Group (http://www.kannel.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Kannel" and "Kannel Group" must not be used to * endorse or promote products derived from this software without * prior written permission. For written permission, please * contact org@kannel.org. * * 5. Products derived from this software may not be called "Kannel", * nor may "Kannel" appear in their name, without prior written * permission of the Kannel Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Kannel Group. For more information on * the Kannel Group, please see <http://www.kannel.org/>. * * Portions of this software are based upon software originally written at * WapIT Ltd., Helsinki, Finland for the Kannel project. */ /* * * wsasm.c * * Author: Markku Rossi <mtr@iki.fi> * * Copyright (c) 1999-2000 WAPIT OY LTD. * All rights reserved. * * Byte-code assembler. * */#include "wsint.h"#include "wsasm.h"#include "wsstdlib.h"/********************* Macros to fetch items from BC operands ***********/#define WS_OPNAME(op) (operands[(op)].name)#define WS_OPSIZE(op) (operands[(op)].size)/********************* Byte-code operands *******************************/static struct{ char *name; int size;} operands[256] = {#include "wsopcodes.h"};/********************* Symbolic assembler instructions ******************//* General helpers. */void ws_asm_link(WsCompiler *compiler, WsAsmIns *ins){ if (compiler->asm_tail) { compiler->asm_tail->next = ins; ins->prev = compiler->asm_tail; compiler->asm_tail = ins; } else compiler->asm_tail = compiler->asm_head = ins;}void ws_asm_print(WsCompiler *compiler){ WsAsmIns *ins; for (ins = compiler->asm_head; ins; ins = ins->next) { if (ins->type > 0xff) { /* A symbolic operand. */ switch (ins->type) { case WS_ASM_P_LABEL: ws_fprintf(WS_STDOUT, ".L%d:\t\t\t\t/* refcount=%d */\n", ins->ws_label_idx, ins->ws_label_refcount); break; case WS_ASM_P_JUMP: ws_fprintf(WS_STDOUT, "\tjump*\t\tL%d\n", ins->ws_label->ws_label_idx); break; case WS_ASM_P_TJUMP: ws_fprintf(WS_STDOUT, "\ttjump*\t\tL%d\n", ins->ws_label->ws_label_idx); break; case WS_ASM_P_CALL: ws_fprintf(WS_STDOUT, "\tcall*\t\t%s\n", compiler->functions[ins->ws_findex].name); break; case WS_ASM_P_CALL_LIB: { const char *lib; const char *func; ws_stdlib_function_name(ins->ws_lindex, ins->ws_findex, &lib, &func); ws_fprintf(WS_STDOUT, "\tcall_lib*\t%s.%s\n", lib ? lib : "???", func ? func : "???"); } break; case WS_ASM_P_CALL_URL: ws_fprintf(WS_STDOUT, "\tcall_url*\t%u %u %u\n", ins->ws_lindex, ins->ws_findex, ins->ws_args); break; case WS_ASM_P_LOAD_VAR: ws_fprintf(WS_STDOUT, "\tload_var*\t%u\n", ins->ws_vindex); break; case WS_ASM_P_STORE_VAR: ws_fprintf(WS_STDOUT, "\tstore_var*\t%u\n", ins->ws_vindex); break; case WS_ASM_P_INCR_VAR: ws_fprintf(WS_STDOUT, "\tincr_var*\t%u\n", ins->ws_vindex); break; case WS_ASM_P_LOAD_CONST: ws_fprintf(WS_STDOUT, "\tload_const*\t%u\n", ins->ws_cindex); break; } } else { WsUInt8 op = WS_ASM_OP(ins->type); if (operands[op].name) { /* Operands add_asg and sub_asg are special. */ if (op == WS_ASM_ADD_ASG || op == WS_ASM_SUB_ASG) ws_fprintf(WS_STDOUT, "\t%s\t\t%u\n", operands[ins->type].name, ins->ws_vindex); else ws_fprintf(WS_STDOUT, "\t%s\n", operands[ins->type].name); } else ws_fatal("ws_asm_print(): unknown operand 0x%x", op); } }}void ws_asm_dasm(WsCompilerPtr compiler, const unsigned char *code, size_t len){ size_t i = 0; while (i < len) { WsUInt8 byt = code[i]; WsUInt8 op; WsUInt8 arg; WsUInt8 i8, j8, k8; WsUInt16 i16, j16; op = WS_ASM_OP(byt); arg = WS_ASM_ARG(byt); ws_fprintf(WS_STDOUT, "%4x:\t%-16s", i, WS_OPNAME(op)); switch (op) { /* The `short jumps'. */ case WS_ASM_JUMP_FW_S: case WS_ASM_TJUMP_FW_S: ws_fprintf(WS_STDOUT, "%x\n", i + WS_OPSIZE(op) + arg); break; case WS_ASM_JUMP_BW_S: ws_fprintf(WS_STDOUT, "%x\n", i - arg); break; /* Jumps with WsUInt8 argument. */ case WS_ASM_JUMP_FW: case WS_ASM_TJUMP_FW: WS_GET_UINT8(code + i + 1, i8); ws_fprintf(WS_STDOUT, "%x\n", i + WS_OPSIZE(op) + i8); break; case WS_ASM_JUMP_BW: case WS_ASM_TJUMP_BW: WS_GET_UINT8(code + i + 1, i8); ws_fprintf(WS_STDOUT, "%x\n", i - i8); break; /* Jumps with wide argument. */ case WS_ASM_JUMP_FW_W: case WS_ASM_TJUMP_FW_W: WS_GET_UINT16(code + i + 1, i16); ws_fprintf(WS_STDOUT, "%x\n", i + WS_OPSIZE(op) + i16); break; case WS_ASM_JUMP_BW_W: case WS_ASM_TJUMP_BW_W: WS_GET_UINT16(code + i + 1, i16); ws_fprintf(WS_STDOUT, "%x\n", i - i16); break; /* The `short' opcodes. */ case WS_ASM_LOAD_VAR_S: case WS_ASM_STORE_VAR_S: case WS_ASM_INCR_VAR_S: ws_fprintf(WS_STDOUT, "%d\n", arg); break; /* Local script function calls. */ case WS_ASM_CALL_S: ws_fprintf(WS_STDOUT, "%d\n", arg); break; case WS_ASM_CALL: WS_GET_UINT8(code + i + 1, i8); ws_fprintf(WS_STDOUT, "%d\n", i8); break; /* Library calls. */ case WS_ASM_CALL_LIB_S: case WS_ASM_CALL_LIB: case WS_ASM_CALL_LIB_W: { WsUInt8 findex; WsUInt16 lindex; char lnamebuf[64]; char fnamebuf[64]; const char *lname; const char *fname; if (op == WS_ASM_CALL_LIB_S) { WS_GET_UINT8(code + i + 1, lindex); findex = arg; } else if (op == WS_ASM_CALL_LIB) { WS_GET_UINT8(code + i + 1, findex); WS_GET_UINT8(code + i + 2, lindex); } else { WS_GET_UINT8(code + i + 1, findex); WS_GET_UINT16(code + i + 2, lindex); } if (!ws_stdlib_function_name(lindex, findex, &lname, &fname)) { snprintf(lnamebuf, sizeof(lnamebuf), "%d", lindex); snprintf(fnamebuf, sizeof(lnamebuf), "%d", findex); lname = lnamebuf; fname = fnamebuf; } ws_fprintf(WS_STDOUT, "%s.%s\n", lname, fname); } break; /* URL calls. */ case WS_ASM_CALL_URL: WS_GET_UINT8(code + i + 1, i8); WS_GET_UINT8(code + i + 2, j8); WS_GET_UINT8(code + i + 3, k8); ws_fprintf(WS_STDOUT, "%d.%d %d\n", i8, j8, k8); break; case WS_ASM_CALL_URL_W: WS_GET_UINT16(code + i + 1, i16); WS_GET_UINT16(code + i + 3, j16); WS_GET_UINT8(code + i + 5, i8); ws_fprintf(WS_STDOUT, "%d.%d %d\n", i16, j16, i8); break; /* Constant access. */ case WS_ASM_LOAD_CONST_S: case WS_ASM_LOAD_CONST: case WS_ASM_LOAD_CONST_W: if (op == WS_ASM_LOAD_CONST_S) i16 = arg; else if (op == WS_ASM_LOAD_CONST) { WS_GET_UINT8(code + i + 1, i8); i16 = i8; } else WS_GET_UINT16(code + i + 1, i16); ws_fprintf(WS_STDOUT, "%d\n", i16); break; /* Operands with WsUInt8 argument. */ case WS_ASM_LOAD_VAR: case WS_ASM_STORE_VAR: case WS_ASM_INCR_VAR: case WS_ASM_DECR_VAR: case WS_ASM_ADD_ASG: case WS_ASM_SUB_ASG: WS_GET_UINT8(code + i + 1, i8); ws_fprintf(WS_STDOUT, "%d\n", i8); break; /* The trivial cases. */ default: ws_fprintf(WS_STDOUT, "\n"); break; } i += WS_OPSIZE(op); }}voidws_asm_linearize(WsCompiler *compiler){ WsAsmIns *ins; WsBool process_again = WS_TRUE; /* Calculate all offsets and select real assembler instructions for our internal pseudo instructions. This is continued as long as the code changes. */ while (process_again) { WsUInt32 offset = 1; process_again = WS_FALSE; for (ins = compiler->asm_head; ins; ins = ins->next) { ins->offset = offset; switch (ins->type) { case WS_ASM_JUMP_FW_S: ins->ws_offset = (ins->ws_label->offset - (offset + WS_OPSIZE(ins->type))); break; case WS_ASM_JUMP_FW: ins->ws_offset = (ins->ws_label->offset - (offset + WS_OPSIZE(ins->type))); if (ins->ws_offset <= 31) { ins->type = WS_ASM_JUMP_FW_S; process_again = WS_TRUE; } break; case WS_ASM_JUMP_FW_W: ins->ws_offset = (ins->ws_label->offset - (offset + WS_OPSIZE(ins->type))); if (ins->ws_offset <= 31) { ins->type = WS_ASM_JUMP_FW_S; process_again = WS_TRUE; } else if (ins->ws_offset <= 255) { ins->type = WS_ASM_JUMP_FW; process_again = WS_TRUE; } break; case WS_ASM_JUMP_BW_S: ins->ws_offset = offset - ins->ws_label->offset; break; case WS_ASM_JUMP_BW: ins->ws_offset = offset - ins->ws_label->offset; if (ins->ws_offset <= 31) { ins->type = WS_ASM_JUMP_BW_S; process_again = WS_TRUE; } break; case WS_ASM_JUMP_BW_W: ins->ws_offset = offset - ins->ws_label->offset; if (ins->ws_offset <= 31) { ins->type = WS_ASM_JUMP_BW_S; process_again = WS_TRUE; } else if (ins->ws_offset <= 255) { ins->type = WS_ASM_JUMP_BW; process_again = WS_TRUE; } break; case WS_ASM_TJUMP_FW_S: ins->ws_offset = (ins->ws_label->offset - (offset + WS_OPSIZE(ins->type))); break; case WS_ASM_TJUMP_FW: ins->ws_offset = (ins->ws_label->offset - (offset + WS_OPSIZE(ins->type))); if (ins->ws_offset <= 31) { ins->type = WS_ASM_TJUMP_FW_S; process_again = WS_TRUE; } break; case WS_ASM_TJUMP_FW_W: ins->ws_offset = (ins->ws_label->offset - (offset + WS_OPSIZE(ins->type))); if (ins->ws_offset <= 31) { ins->type = WS_ASM_TJUMP_FW_S; process_again = WS_TRUE; } else if (ins->ws_offset <= 255) { ins->type = WS_ASM_TJUMP_FW; process_again = WS_TRUE; } break; case WS_ASM_TJUMP_BW: ins->ws_offset = offset - ins->ws_label->offset; break; case WS_ASM_TJUMP_BW_W: ins->ws_offset = offset - ins->ws_label->offset; if (ins->ws_offset <= 255) { ins->type = WS_ASM_TJUMP_BW; process_again = WS_TRUE; } break; /* * The pseudo instructions. */ case WS_ASM_P_LABEL: /* Nothing here. */ break; case WS_ASM_P_JUMP: if (ins->ws_label->offset == 0) { /* A forward jump. Let's assume the widest form. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -