📄 bytecode.h
字号:
/* $Id: bytecode.h,v 1.2 2003/09/17 11:26:10 tmoerlan Exp $ */#include <stdio.h>#include <limits.h>#include "config.h"#include "dyncheck.h"#include "wassert.h"#ifndef _SNAP_BYTECODE_H_#define _SNAP_BYTECODE_H_#ifdef CONFIG_IP_SNAP_SMALL_INSTRS#define SMALL_INSTRS#endif#ifdef CONFIG_IP_SNAP_SMALL_VALUES#define SMALL_VALUES#endif#ifdef TAG_CHECK#define DYNCHECK_TAG(v,tag) DYNCHECK(GET_TAG((v)) == (tag))#else#define DYNCHECK_TAG(v,tag) ((void)0)#endif/* having small representation for instructions requires small values as well */#ifdef SMALL_INSTRS#ifndef SMALL_VALUES#define SMALL_VALUES#endif#endif/* enumeration of all value types -- these are the tags for the values */#ifdef SMALL_VALUES#define INTV 0 /* integers (32-bit) */#define ADDRV 1 /* IPv4 addresses (32-bit) */#define STRV 2 /* strings/blobs */#define EXCV 3 /* exceptions */#define TUPLEV 4 /* tuples */#define FLOATV 5 /* 32-bit floats */#define BOGUSV 6 /* for ops that ignore the tag */#define TAG_T int/* not enough space to put addrs as literals when values are small */#ifndef ADDR_IN_HEAP#define ADDR_IN_HEAP#endif#elsetypedef enum { INTV, /* integers (32-bit) */ ADDRV, /* IPv4 addresses (32-bit) */ STRV, /* strings/blobs */ EXCV, /* exceptions */ TUPLEV, /* tuples */ FLOATV /* 32-bit floats */} value_tag_t;#define TAG_T value_tag_t#endif/* heap objects are strings */#define LENTYPE unsigned short#define MAX_HEAPOBJ_SZ (1 << ((sizeof(unsigned short) * 8)))typedef struct { LENTYPE len; /* length of string/exc/tuple in bytes */ unsigned short flag; /* legal values 0 : non-ptr-containing object 1 : ptr-containing object 4,8,12,... : forwarding offset */ char s[0]; /* string (maybe not null terminated) */} heap_obj;/* stack value-- has a type tag plus the value itself */#ifdef SMALL_VALUEStypedef unsigned int value_t;#define ZERO_VALUE_T 0#ifdef SMALL_INSTRS#define TAGSZ 7#else#define TAGSZ 3#endif#define MAX_VINT (1 << ((sizeof(unsigned int) * 8-(TAGSZ+1))))#define MIN_VINT (- MAX_VINT - 1)#define GET_TAG(v) ((v) >> (sizeof(unsigned int)*8-TAGSZ))#define SET_TAG(v,t) ((v) = (((v) << TAGSZ) >> TAGSZ) | ((t) << (sizeof(unsigned int)*8-TAGSZ)))#define GET_INT(v) (((int)((v) << TAGSZ)) >> TAGSZ)#define SET_INT(v,i) ((v) = (((v) >> (sizeof(unsigned int)*8-TAGSZ)) << (sizeof(unsigned int)*8-TAGSZ)) | ((((unsigned int)(i)) << TAGSZ) >> TAGSZ))#define GET_OFFS GET_INT#define SET_OFFS SET_INT#define COPY_VAL(val1,val2) ((val1) = (val2))#define GET_BOXED(res,heap,v,t) \{ \ heap_obj *ho1 = (heap_obj *)((heap) + GET_OFFS(v)); \ DYNCHECK_ADDR_IN_HEAP(ho1); \ wassert(ho1->len == sizeof(t)); \ (res) = *((t *)ho1->s); \}#define GET_ADDR(res,h,v) GET_BOXED(res,h,v,uint32_t)#define GET_FLOAT(res,h,v) GET_BOXED(res,h,v,float32)#define GET_ADDR_VAL(h,v) (*((uint32_t *)(((heap_obj *)((h) + GET_OFFS(v)))->s)))#define GET_FLT_VAL(h,v) (*((float32 *)(((heap_obj *)((h) + GET_OFFS(v)))->s)))#define FLTINTPAIR(f) (int)(f),(int)(((f) - (int)(f)) * 1000000)#define SET_ADDR(val,a,p) \{ int hoffset; \ heap_obj *ho; \ if (!heap_alloc((p),sizeof(uint32_t),0,&ho,&hoffset)) { \ *((uint32_t *)ho->s) = (a); \ SET_OFFS(val,hoffset); \ } \ else return -1; \}#define SET_FLOAT(val,a,p) \{ int hoffset; \ heap_obj *ho; \ if (!heap_alloc((p),sizeof(float32),0,&ho,&hoffset)) {\ *((float32 *)ho->s) = (a); \ SET_OFFS(val,hoffset); \ } \ else return -1; \}#define IS_HEAP_VAL(v) \ ((GET_TAG(v) == ADDRV) || (GET_TAG(v) == STRV) || \ (GET_TAG(v) == TUPLEV) || (GET_TAG(v) == FLOATV))#elsetypedef struct { TAG_T tag; /* type tag */ union { int intval; /* 32-bit integer */#ifndef ADDR_IN_HEAP uint32_t addrval; /* 32-bit IPv4 address */ float32 floatval; /* 32-bit float */#endif int hoffset; /* offset for a heap object */ } v;} value_t;#define ZERO_VALUE_T { 0, { 0 } }#define MAX_VINT INT_MAX#define MIN_VINT INT_MIN#define GET_TAG(val) ((val).tag)#define SET_TAG(val,t) ((val).tag = (t))#define GET_INT(val) ((val).v.intval)#define SET_INT(val,i) ((val).v.intval = (i))#define GET_OFFS(val) ((val).v.hoffset)#define SET_OFFS(val,o) ((val).v.hoffset = (o))#ifndef ADDR_IN_HEAP#define GET_ADDR(res,unused,val) ((res) = (val).v.addrval)#define SET_ADDR(val,a,unused) ((val).v.addrval = (a))#define GET_FLOAT(res,unused,val) ((res) = (val).v.floatval)#define SET_FLOAT(val,a,unused) ((val).v.floatval = (a))#define IS_HEAP_VAL(v) \ ((GET_TAG(v) == STRV) || (GET_TAG(v) == TUPLEV))#else#define GET_BOXED(res,heap,v,t) \{ \ heap_obj *ho1 = (heap_obj *)((heap) + GET_OFFS(v)); \ DYNCHECK_ADDR_IN_HEAP(ho1); \ wassert(ho1->len == sizeof(t)); \ (res) = *((t *)ho1->s); \}#define GET_ADDR(res,h,v) GET_BOXED(res,h,v,uint32_t)#define GET_FLOAT(res,h,v) GET_BOXED(res,h,v,float32)#define GET_ADDR_VAL(h,v) (*((uint32_t *)(((heap_obj *)((h) + GET_OFFS(v)))->s)))#define GET_FLT_VAL(h,v) (*((float32 *)(((heap_obj *)((h) + GET_OFFS(v)))->s)))#define IS_HEAP_VAL(v) \ ((GET_TAG(v) == STRV) || (GET_TAG(v) == TUPLEV) || \ (GET_TAG(v) == ADDRV))#define FLTINTPAIR(f) (int)(f),(int)(((f) - (int)(f)) * 1000000)#define SET_ADDR(val,a,p) \{ int hoffset; \ heap_obj *ho; \ if (!heap_alloc((p),sizeof(uint32_t),0,&ho,&hoffset)) { \ *((uint32_t *)ho->s) = (a); \ SET_OFFS(val,hoffset); \ } \ else return -1; \}#define SET_FLOAT(val,a,p) \{ int hoffset; \ heap_obj *ho; \ if (!heap_alloc((p),sizeof(float32),0,&ho,&hoffset)) {\ *((float32 *)ho->s) = (a); \ SET_OFFS(val,hoffset); \ } \ else return -1; \}#endif#define COPY_VAL(val1,val2) ((val1) = (val2))#endif/* opcodes */#ifdef SMALL_INSTRS#define EXIT 0#define PUSH 1 /* not used */#define POP 2#define POPI 3#define PULL 4#define STORE 5#define PAJ 6#define TPAJ 7#define JI 8#define BEZ 9#define BNE 10#define MKTUP 11#define NTH 12#define LEN 13#define ISTUP 14#define EQ 15#define EQI 16 /* not used */#define NEQ 17#define NEQI 18 /* not used */#define GT 19#define GTI 20#define GEQ 21#define GEQI 22#define LEQ 23#define LEQI 24#define LT 25#define LTI 26#define ADD 27#define ADDI 28#define SUB 29#define SUBI 30#define MULT 31#define MULTI 32#define DIV 33#define DIVI 34#define MOD 35#define MODI 36#define NEG 37#define NOT 38#define LNOT 39#define AND 40#define ANDI 41#define OR 42#define ORI 43#define LSHL 44#define LSHLI 45#define RSHL 46#define RSHLI 47#define RSHA 48#define RSHAI 49#define XOR 50#define XORI 51#define SNET 52#define SNETI 53#define BCAST 54#define BCASTI 55#define ISX 56#define GETRB 57#define GETSRC 58#define GETDST 60#define GETSPT 61#define HERE 62#define ISHERE 63#define ROUTE 64#define RTDEV 65#define SEND 66#define HOP 67/* #define SENDCK 67 *//* #define HOPCK 68 */#define FORW 69#define FORWTO 70#define DEMUX 71#define DEMUXI 72#define PRINT 73#define PINT 74#define PADDR 75#define PTUP 76#define PEXC 77#define PSTR 78#define PFLT 79#define EQINT 80#define EQADR 81#define EQTUP 82#define EQEXC 83#define EQSTR 84#define EQFLT 85#define NQINT 86#define NQADR 87#define NQTUP 88#define NQEXC 89#define NQSTR 90#define NQFLT 91#define SVCV 92#define CALLS 93#define FGTI 94#define FGEQI 95#define FLEQI 96#define FLTI 97#define FADDI 98#define FSUBI 99#define FMULI 100#define FDIVI 101#define GETLD 102#define SETXH 103#define RAISEX 104/* willem's additions */#define DSEND 105 /* direct send (no interpretation on intermediate hops) */#define DFORW 106 /* idem for forw */#define DFORWTO 107 /* idem for forwto */#define STACKEMPTY 108 /* pushes a 1 if the stack is empty, 0 otherwise */#define STACKCOUNT 109 /* pushes the number of elements on the stack */#define PULLSTACK 110 /* PULL using top stack element as index (this value is removed */#define OPCODE_T int/* operations on literals *//* assumes that TAGSZ is set appropriately above */#define GET_OP(v) ((v) >> (sizeof(unsigned int)*8-TAGSZ))#define SET_OP(v,i) ((v) = (((v) << TAGSZ) >> TAGSZ) | ((i) << (sizeof(unsigned int)*8-TAGSZ)))#define GET_LIT(l,t,i) ((l) = (((int)((i) << TAGSZ)) >> TAGSZ))#define SET_LIT(i,t,l) ((i) = (((i) >> (sizeof(unsigned int)*8-TAGSZ)) << (sizeof(unsigned int)*8-TAGSZ)) | ((((unsigned int)(l)) << TAGSZ) >> TAGSZ))#define GET_LIT_VAL(i) (((int)((i) << TAGSZ)) >> TAGSZ)#define GET_STR_VAL(h,v) (((heap_obj *)((h) + GET_OFFS(v)))->s)#define NUM_OPS 87 /* total number of (legal) opcodes */typedef unsigned int instr_t;#elsetypedef enum { /* stack and flow control */ EXIT, PUSH, /* push a value on the stack */ POP, /* pop the top value off the stack */ POPI, /* pop the top n values off the stack */ PULL, /* push a copy of the nth stack value */ STORE, /* store the top of the stack into the nth stack value (thus store 0 is a no-op) */ PAJ, /* jump by the value on the top of the stack (pop and jump) plus the given immediate value */ TPAJ, /* jump by the 2nd value on the top of the stack, plus the immediate value,if the top value is zero (test, pop, and jump) */ JI, /* jump by the immediate value */ BEZ, /* branch x instrs if the top stack value is equal to zero */ BNE, /* branch x instrs if the top stack value is not zero */ /* heap operations */ MKTUP, /* allocates a tuple that holds n values, where n>0 is an immediate. Must be followed by n-1 (JI 1) instructions */ NTH, /* get's the nTH entry of the tuple on the top of the stack, where n is an immediate > 0 */ LEN, /* returns the length of the tuple, that is, how many values it contains. */ ISTUP, /* is the top value a tuple? */ /* relational operators */ EQ, /* are the top two stack values equal? */ EQI, /* is the top stack value equal to the immediate argument? */ NEQ, /* are the top two stack values not equal? */ NEQI, /* is the top stack value not equal to the immediate argument? */ GT, /* comparing top 2 values: v2 > v1 */ GTI, /* top > immediate */ GEQ, /* comparing top 2 values: v2 >= v1 */ GEQI, /* top >= immediate */ LEQ, /* comparing top 2 values: v2 <= v1 */ LEQI, /* top <= immediate */ LT, /* comparing top 2 values: v2 < v1 */ LTI, /* top < immediate */ /* arithmetic */ ADD, /* integer addition */ ADDI, /* integer addition with immediate */ SUB, /* integer subtraction */ SUBI, /* integer subtraction with immediate */ MULT, /* integer multiplication */ MULTI, /* integer multiplication with immediate*/ DIV, /* integer division */ DIVI, /* integer division with immediate */ MOD, /* integer modulus */ MODI, /* integer modulus with immediate */ NEG, /* integer arithmetic negation */ NOT, /* integer boolean negation */ LNOT, /* integer logical negation */ AND, /* integer logical and */ ANDI, /* integer logical and with immediate */ OR, /* integer logical or */ ORI, /* integer logical or with immediate */ LSHL, /* integer left shift logical */ LSHLI, /* integer left shift logical with immediate */ RSHL, /* integer right shift logical */ RSHLI, /* integer right shift logical with immediate */ RSHA, /* integer right shift arithmetic */ RSHAI, /* integer right shift arithmetic with immediate */ XOR, /* integer logical xor */ XORI, /* integer logical xor with immediate */ /* operations on addresses */ SNET, /* given an address and a subnet mask, give the subnet address */ SNETI, /* subnet with immediate mask */ BCAST, /* given an address and a subnet mask, give the broadcast address */ BCASTI, /* broadcast address with immed. mask */ /* operations on exceptions */ ISX, /* is the top value an exception? */ /* core services */ GETRB, /* get the resource bound field */ GETSRC, /* get the source field */ GETDST, /* get the destination field */ GETSPT, /* get the flow id */ HERE, /* push an address of the current host */ ISHERE, /* does the address on top of the stack belong to the current host? */ ROUTE, /* determine the next hop to send to */ RTDEV, /* next hop and outgoing interface */ SEND, /* OnRemote w/ literal: args are: entry point, how many values of stack to take, how much resource bound, destination. side effects the header dest and source fields of outgoing packet */ HOP, /* OnNeighbor w/ literal: args are: entry point, stack amount, resource bound, neighbor */ /* SENDCK, */ /* OnRemote: same as SEND, except (entrypoint,how much stack) args replaced with a chunk. */ /* HOPCK, */ /* OnNeighbor: same as HOP, except (entrypoint,how much stack) args replaced with a chunk. */ FORW, /* if at destination, do nothing. else forward packet towards destination and exit */ FORWTO, /* arg is final destination. if there, do nothing. else set header's src and dst appropriately and forward */ DEMUX, /* application delivery: args are: UDP port, string */ DEMUXI, /* same, but port num is immediate */ PRINT, /* print value to console */ /* general services */ SVCV, /* returns (non-function) value with given name from the service symtab */ CALLS, /* invokes service routine with given string */ /* willem's additions */ , DSEND, /* direct send (no interpretation on intermediate hops) */ DFORW, /* idem for forw */ DFORWTO, /* idem for forwto */ STACKEMPTY, /* pushes a 1 if the stack is empty, 0 otherwise */ STACKCOUNT, /* pushes the number of elements on the stack */ PULLSTACK /* PULL using top stack element as index (this value is removed */} opcode_t;#define OPCODE_T opcode_t/* operations on literals */#define GET_LIT(l,t,i) \ DYNCHECK_TAG((i).arg,t); \ (l) = GET_INT((i).arg); /* assumes this is the same as GET_OFFS */#define SET_LIT(i,t,l) \ SET_INT((i).arg,(l)); /* all ints anyway */ \ SET_TAG((i).arg,(t));#define GET_OP(i) ((i).op)#define SET_OP(i,t) ((i).op = (t))#define NUM_OPS 73 /* total number of opcodes *//* instructions are an opcode with an (optional) argument */typedef struct { OPCODE_T op; value_t arg;} instr_t;#endif#define COPY_LIT(d,t,s) \{ int _lit; \ GET_LIT(_lit,t,(s)); \ SET_INT((d),_lit); \ SET_TAG((d),t); \}#endif /* _SNAP_BYTECODE_H_ */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -