📄 wsasm.c
字号:
/* * * 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. */ ins->type = WS_ASM_JUMP_FW_W; } else { ins->ws_offset = offset - ins->ws_label->offset; /* Jump backwards. */ if (ins->ws_offset <= 31) { ins->type = WS_ASM_JUMP_BW_S; } else if (ins->ws_offset <= 255) { ins->type = WS_ASM_JUMP_BW; } else { ins->type = WS_ASM_JUMP_BW_W; } } break; case WS_ASM_P_TJUMP: if (ins->ws_label->offset == 0) { /* A forward jump. Let's assume the widest form. */ ins->type = WS_ASM_TJUMP_FW_W; process_again = WS_TRUE; } else { ins->ws_offset = offset - ins->ws_label->offset; /* Jump backwards. */ if (ins->ws_offset <= 255) { ins->type = WS_ASM_TJUMP_BW; } else { ins->type = WS_ASM_TJUMP_BW_W;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -