[insert project logo here (125x200px max)]

Navigator

Mailinglists

Please report any errors or ommissions you find to our `Help' mailinglist, or post a message in the Forums.

Copyright and Licensing Information

Snap is (c) Jonathan T. Moore, 1999-2002 and licensed under the GNU General Public License (GPL).

All other parts of Splash are (c) Willem de Bruijn, 2002-2003 and licensed under the BSD Open Source License.

All sourcecode is made publicly available.

Acknowledgement

Splash and the Splash website are hosted by SourceForge.net

SourceForge.net Logo

osi-open source certified logo

Splash - Documentation

SNMP Plus a Lightweight API for SNAP Handling

Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

snap-1.1-wjdb/lib/bytecode.h

Go to the documentation of this file.
00001 /* $Id: bytecode.h,v 1.7 2003/04/02 17:01:14 wdebruij Exp $ */
00002 
00003 #include <stdio.h>
00004 #include <limits.h>
00005 #include "config.h"
00006 #include "dyncheck.h"
00007 #include "wassert.h"
00008 
00009 #ifndef _SNAP_BYTECODE_H_
00010 #define _SNAP_BYTECODE_H_
00011 
00012 #ifdef CONFIG_IP_SNAP_SMALL_INSTRS
00013 #define SMALL_INSTRS
00014 #endif
00015 #ifdef CONFIG_IP_SNAP_SMALL_VALUES
00016 #define SMALL_VALUES
00017 #endif
00018 
00019 #ifdef TAG_CHECK
00020 #define DYNCHECK_TAG(v,tag) DYNCHECK(GET_TAG((v)) == (tag))
00021 #else
00022 #define DYNCHECK_TAG(v,tag) ((void)0)
00023 #endif
00024 
00025 /* having small representation for instructions requires small values
00026    as well */
00027 #ifdef SMALL_INSTRS
00028 #ifndef SMALL_VALUES
00029 #define SMALL_VALUES
00030 #endif
00031 #endif
00032 
00033 /* enumeration of all value types -- these are the tags for the values */
00034 #ifdef SMALL_VALUES
00035 #define INTV    0       /* integers (32-bit) */
00036 #define ADDRV   1       /* IPv4 addresses (32-bit) */
00037 #define STRV    2       /* strings/blobs */
00038 #define EXCV    3       /* exceptions */
00039 #define TUPLEV  4       /* tuples */
00040 #define FLOATV  5       /* 32-bit floats */
00041 #define BOGUSV  6       /* for ops that ignore the tag */
00042 #define TAG_T int
00043 
00044 
00045 /* not enough space to put addrs as literals when values are small */
00046 #ifndef ADDR_IN_HEAP
00047 #define ADDR_IN_HEAP
00048 #endif
00049 
00050 #else
00051 typedef enum {
00052   INTV,             /* integers (32-bit) */
00053   ADDRV,            /* IPv4 addresses (32-bit) */
00054   STRV,             /* strings/blobs */
00055   EXCV,             /* exceptions */
00056   TUPLEV,           /* tuples */
00057   FLOATV            /* 32-bit floats */
00058 } value_tag_t;
00059 #define TAG_T value_tag_t
00060 #endif
00061 
00062 /* heap objects are strings */
00063 #define LENTYPE unsigned short
00064 #define MAX_HEAPOBJ_SZ (1 << ((sizeof(unsigned short) * 8)))
00065 typedef struct {
00066   LENTYPE len;          /* length of string/exc/tuple in bytes */
00067   unsigned short flag;      /* legal values
00068                    0          : non-ptr-containing object
00069                    1          : ptr-containing object
00070                    4,8,12,... : forwarding offset */
00071   char s[0];            /* string (maybe not null terminated) */
00072 } heap_obj;
00073 
00074 /* stack value-- has a type tag plus the value itself */
00075 #ifdef SMALL_VALUES
00076 typedef unsigned int value_t;
00077 #define ZERO_VALUE_T 0
00078 
00079 #ifdef SMALL_INSTRS
00080 #define TAGSZ 7
00081 #else
00082 #define TAGSZ 3
00083 #endif
00084 
00085 #define MAX_VINT (1 << ((sizeof(unsigned int) * 8-(TAGSZ+1))))
00086 #define MIN_VINT (- MAX_VINT - 1)
00087 
00088 #define GET_TAG(v) ((v) >> (sizeof(unsigned int)*8-TAGSZ))
00089 #define SET_TAG(v,t) ((v) = (((v) << TAGSZ) >> TAGSZ) | ((t) << (sizeof(unsigned int)*8-TAGSZ)))
00090 
00091 #define GET_INT(v) (((int)((v) << TAGSZ)) >> TAGSZ)
00092 #define SET_INT(v,i) ((v) = (((v) >> (sizeof(unsigned int)*8-TAGSZ)) << (sizeof(unsigned int)*8-TAGSZ)) | ((((unsigned int)(i)) << TAGSZ) >> TAGSZ))
00093 
00094 #define GET_OFFS GET_INT
00095 #define SET_OFFS SET_INT
00096 
00097 #define COPY_VAL(val1,val2) ((val1) = (val2))
00098 
00099 #define GET_BOXED(res,heap,v,t)                 \
00100 {                               \
00101   heap_obj *ho1 = (heap_obj *)((heap) + GET_OFFS(v));       \
00102   DYNCHECK_ADDR_IN_HEAP(ho1);                   \
00103   wassert(ho1->len == sizeof(t));               \
00104   (res) = *((t *)ho1->s);                   \
00105 }
00106 
00107 #define GET_ADDR(res,h,v) GET_BOXED(res,h,v,uint32_t)
00108 
00109 #define GET_FLOAT(res,h,v) GET_BOXED(res,h,v,float32)
00110 
00111 #define GET_ADDR_VAL(h,v) (*((uint32_t *)(((heap_obj *)((h) + GET_OFFS(v)))->s)))
00112 
00113 #define GET_FLT_VAL(h,v) (*((float32 *)(((heap_obj *)((h) + GET_OFFS(v)))->s)))
00114 
00115 #define FLTINTPAIR(f) (int)(f),(int)(((f) - (int)(f)) * 1000000)
00116 
00117 #define SET_ADDR(val,a,p)               \
00118 { int hoffset;                      \
00119   heap_obj *ho;                     \
00120   if (!heap_alloc((p),sizeof(uint32_t),0,&ho,&hoffset)) {   \
00121     *((uint32_t *)ho->s) = (a);             \
00122     SET_OFFS(val,hoffset);              \
00123   }                         \
00124   else return -1;                   \
00125 }
00126 #define SET_FLOAT(val,a,p)              \
00127 { int hoffset;                      \
00128   heap_obj *ho;                     \
00129   if (!heap_alloc((p),sizeof(float32),0,&ho,&hoffset)) {\
00130     *((float32 *)ho->s) = (a);              \
00131     SET_OFFS(val,hoffset);              \
00132   }                         \
00133   else return -1;                   \
00134 }
00135 #define IS_HEAP_VAL(v) \
00136   ((GET_TAG(v) == ADDRV) || (GET_TAG(v) == STRV) || \
00137    (GET_TAG(v) == TUPLEV) || (GET_TAG(v) == FLOATV))
00138 
00139 #else
00140 typedef struct {
00141   TAG_T tag;            /* type tag */
00142   union {
00143     int intval;         /* 32-bit integer */
00144 #ifndef ADDR_IN_HEAP
00145     uint32_t addrval;   /* 32-bit IPv4 address */
00146     float32 floatval;       /* 32-bit float */
00147 #endif
00148     int hoffset;        /* offset for a heap object */
00149   } v;
00150 } value_t;
00151 #define ZERO_VALUE_T { 0, { 0 } }
00152 
00153 #define MAX_VINT INT_MAX
00154 #define MIN_VINT INT_MIN
00155 
00156 #define GET_TAG(val) ((val).tag)
00157 #define SET_TAG(val,t) ((val).tag = (t))
00158 
00159 #define GET_INT(val) ((val).v.intval)
00160 #define SET_INT(val,i) ((val).v.intval = (i))
00161 
00162 #define GET_OFFS(val) ((val).v.hoffset)
00163 #define SET_OFFS(val,o) ((val).v.hoffset = (o))
00164 
00165 #ifndef ADDR_IN_HEAP
00166 #define GET_ADDR(res,unused,val) ((res) = (val).v.addrval)
00167 #define SET_ADDR(val,a,unused) ((val).v.addrval = (a))
00168 
00169 #define GET_FLOAT(res,unused,val) ((res) = (val).v.floatval)
00170 #define SET_FLOAT(val,a,unused) ((val).v.floatval = (a))
00171 
00172 #define IS_HEAP_VAL(v) \
00173   ((GET_TAG(v) == STRV) || (GET_TAG(v) == TUPLEV))
00174 
00175 #else
00176 #define GET_BOXED(res,heap,v,t)                 \
00177 {                               \
00178   heap_obj *ho1 = (heap_obj *)((heap) + GET_OFFS(v));       \
00179   DYNCHECK_ADDR_IN_HEAP(ho1);                   \
00180   wassert(ho1->len == sizeof(t));               \
00181   (res) = *((t *)ho1->s);                   \
00182 }
00183 
00184 #define GET_ADDR(res,h,v) GET_BOXED(res,h,v,uint32_t)
00185 #define GET_FLOAT(res,h,v) GET_BOXED(res,h,v,float32)
00186 #define GET_ADDR_VAL(h,v) (*((uint32_t *)(((heap_obj *)((h) + GET_OFFS(v)))->s)))
00187 #define GET_FLT_VAL(h,v) (*((float32 *)(((heap_obj *)((h) + GET_OFFS(v)))->s)))
00188 
00189 #define IS_HEAP_VAL(v) \
00190   ((GET_TAG(v) == STRV) || (GET_TAG(v) == TUPLEV) || \
00191    (GET_TAG(v) == ADDRV))
00192 
00193 #define FLTINTPAIR(f) (int)(f),(int)(((f) - (int)(f)) * 1000000)
00194 
00195 #define SET_ADDR(val,a,p)               \
00196 { int hoffset;                      \
00197   heap_obj *ho;                     \
00198   if (!heap_alloc((p),sizeof(uint32_t),0,&ho,&hoffset)) {   \
00199     *((uint32_t *)ho->s) = (a);             \
00200     SET_OFFS(val,hoffset);              \
00201   }                         \
00202   else return -1;                   \
00203 }
00204 
00205 #define SET_FLOAT(val,a,p)              \
00206 { int hoffset;                      \
00207   heap_obj *ho;                     \
00208   if (!heap_alloc((p),sizeof(float32),0,&ho,&hoffset)) {\
00209     *((float32 *)ho->s) = (a);              \
00210     SET_OFFS(val,hoffset);              \
00211   }                         \
00212   else return -1;                   \
00213 }
00214 #endif
00215 
00216 #define COPY_VAL(val1,val2) ((val1) = (val2))
00217 
00218 #endif
00219 
00220 /* opcodes */
00221 #ifdef SMALL_INSTRS
00222 
00223 #define  EXIT   0
00224 #define  PUSH   1 /* not used */
00225 #define  POP    2
00226 #define  POPI   3
00227 #define  PULL   4
00228 #define  STORE  5
00229 #define  PAJ    6
00230 #define  TPAJ   7
00231 #define  JI 8
00232 #define  BEZ    9
00233 #define  BNE    10
00234 #define  MKTUP  11
00235 #define  NTH    12
00236 #define  LEN    13
00237 #define  ISTUP  14
00238 #define  EQ 15
00239 #define  EQI    16 /* not used */
00240 #define  NEQ    17
00241 #define  NEQI   18 /* not used */
00242 #define  GT 19
00243 #define  GTI    20
00244 #define  GEQ    21
00245 #define  GEQI   22
00246 #define  LEQ    23
00247 #define  LEQI   24
00248 #define  LT 25
00249 #define  LTI    26
00250 #define  ADD    27
00251 #define  ADDI   28
00252 #define  SUB    29
00253 #define  SUBI   30
00254 #define  MULT   31
00255 #define  MULTI  32
00256 #define  DIV    33
00257 #define  DIVI   34
00258 #define  MOD    35
00259 #define  MODI   36
00260 #define  NEG    37
00261 #define  NOT    38
00262 #define  LNOT   39
00263 #define  AND    40
00264 #define  ANDI   41
00265 #define  OR 42
00266 #define  ORI    43
00267 #define  LSHL   44
00268 #define  LSHLI  45
00269 #define  RSHL   46
00270 #define  RSHLI  47
00271 #define  RSHA   48
00272 #define  RSHAI  49
00273 #define  XOR    50
00274 #define  XORI   51
00275 #define  SNET   52
00276 #define  SNETI  53
00277 #define  BCAST  54
00278 #define  BCASTI 55
00279 #define  ISX    56
00280 #define  GETRB  57
00281 #define  GETSRC 58
00282 #define  GETDST 60
00283 #define  GETSPT 61
00284 #define  HERE   62
00285 #define  ISHERE 63
00286 #define  ROUTE  64
00287 #define  RTDEV  65
00288 #define  SEND   66
00289 #define  HOP    67
00290 /*  #define  SENDCK 67 */
00291 /*  #define  HOPCK  68 */
00292 #define  FORW   69
00293 #define  FORWTO 70
00294 #define  DEMUX  71
00295 #define  DEMUXI 72
00296 #define  PRINT  73
00297 
00298 #define  PINT   74
00299 #define  PADDR  75
00300 #define  PTUP   76
00301 #define  PEXC   77
00302 #define  PSTR   78
00303 #define  PFLT   79
00304 
00305 #define  EQINT  80
00306 #define  EQADR  81
00307 #define  EQTUP  82
00308 #define  EQEXC  83
00309 #define  EQSTR  84
00310 #define  EQFLT  85
00311 
00312 #define  NQINT  86
00313 #define  NQADR  87
00314 #define  NQTUP  88
00315 #define  NQEXC  89
00316 #define  NQSTR  90
00317 #define  NQFLT  91
00318 
00319 #define  SVCV   92
00320 #define  CALLS  93
00321 
00322 #define  FGTI   94
00323 #define  FGEQI  95
00324 #define  FLEQI  96
00325 #define  FLTI   97
00326 #define  FADDI  98
00327 #define  FSUBI  99
00328 #define  FMULI  100
00329 #define  FDIVI  101
00330 
00331 #define  GETLD  102
00332 #define  SETXH  103
00333 #define  RAISEX 104
00334 
00335 /* willem's additions */
00336 
00337 #define  DSEND      105     /* direct send (no interpretation on intermediate hops) */
00338 #define  DFORW      106     /* idem for forw */
00339 #define  DFORWTO    107     /* idem for forwto */
00340 
00341 #define STACKEMPTY 108      /* pushes a 1 if the stack is empty, 0 otherwise */
00342 #define STACKCOUNT 109      /* pushes the number of elements on the stack */
00343 
00344 #define PULLSTACK 110       /* PULL using top stack element as index (this value is removed */
00345 #define OPCODE_T int
00346 
00347 /* operations on literals */
00348 /* assumes that TAGSZ is set appropriately above */
00349 
00350 #define GET_OP(v) ((v) >> (sizeof(unsigned int)*8-TAGSZ))
00351 #define SET_OP(v,i) ((v) = (((v) << TAGSZ) >> TAGSZ) | ((i) << (sizeof(unsigned int)*8-TAGSZ)))
00352 
00353 #define GET_LIT(l,t,i) ((l) = (((int)((i) << TAGSZ)) >> TAGSZ))
00354 #define SET_LIT(i,t,l) ((i) = (((i) >> (sizeof(unsigned int)*8-TAGSZ)) << (sizeof(unsigned int)*8-TAGSZ)) | ((((unsigned int)(l)) << TAGSZ) >> TAGSZ))
00355 
00356 #define GET_LIT_VAL(i) (((int)((i) << TAGSZ)) >> TAGSZ)
00357 
00358 #define GET_STR_VAL(h,v) (((heap_obj *)((h) + GET_OFFS(v)))->s)
00359 
00360 #define NUM_OPS     87  /* total number of (legal) opcodes */
00361 
00362 typedef unsigned int instr_t;
00363 
00364 #else
00365 typedef enum {
00366   /* stack and flow control */
00367   EXIT,
00368   PUSH,             /* push a value on the stack */
00369   POP,              /* pop the top value off the stack */
00370   POPI,             /* pop the top n values off the stack */
00371   PULL,             /* push a copy of the nth stack value */
00372   STORE,            /* store the top of the stack into the
00373                    nth stack value (thus store 0 is
00374                    a no-op) */
00375   PAJ,              /* jump by the value on the top of the
00376                    stack (pop and jump) plus the given
00377                    immediate value */
00378   TPAJ,             /* jump by the 2nd value on the top of
00379                    the stack, plus the immediate
00380                    value,if the top value is zero 
00381                    (test, pop, and jump) */
00382   JI,               /* jump by the immediate value */
00383   BEZ,              /* branch x instrs if the top stack
00384                    value is equal to zero */
00385   BNE,              /* branch x instrs if the top stack
00386                    value is not zero */
00387 
00388   /* heap operations */
00389   MKTUP,            /* allocates a tuple that holds n
00390                    values, where n>0 is an immediate.
00391                    Must be followed by n-1 (JI 1)
00392                    instructions */
00393   NTH,              /* get's the nTH entry of the tuple
00394                    on the top of the stack, where
00395                    n is an immediate > 0 */
00396   LEN,              /* returns the length of the tuple,
00397                    that is, how many values it
00398                    contains. */
00399   ISTUP,            /* is the top value a tuple? */
00400                    
00401   /* relational operators */
00402   EQ,               /* are the top two stack values equal? */
00403   EQI,              /* is the top stack value equal to the
00404                    immediate argument? */
00405   NEQ,              /* are the top two stack values not equal? */
00406   NEQI,             /* is the top stack value not equal to the
00407                    immediate argument? */
00408   GT,               /* comparing top 2 values: v2 > v1 */
00409   GTI,              /* top > immediate */
00410   GEQ,              /* comparing top 2 values: v2 >= v1 */
00411   GEQI,             /* top >= immediate */
00412   LEQ,              /* comparing top 2 values: v2 <= v1 */
00413   LEQI,             /* top <= immediate */
00414   LT,               /* comparing top 2 values: v2 < v1 */
00415   LTI,              /* top < immediate */
00416 
00417   /* arithmetic */
00418   ADD,              /* integer addition */
00419   ADDI,             /* integer addition with immediate */
00420   SUB,              /* integer subtraction */
00421   SUBI,             /* integer subtraction with immediate */
00422   MULT,             /* integer multiplication */
00423   MULTI,            /* integer multiplication with immediate*/
00424   DIV,              /* integer division */
00425   DIVI,             /* integer division with immediate */
00426   MOD,              /* integer modulus */
00427   MODI,             /* integer modulus with immediate */
00428   NEG,              /* integer arithmetic negation */
00429   NOT,              /* integer boolean negation */
00430   LNOT,             /* integer logical negation */
00431   AND,              /* integer logical and */
00432   ANDI,             /* integer logical and with immediate */
00433   OR,               /* integer logical or */
00434   ORI,              /* integer logical or with immediate */
00435   LSHL,             /* integer left shift logical */
00436   LSHLI,            /* integer left shift logical with immediate */
00437   RSHL,             /* integer right shift logical */
00438   RSHLI,            /* integer right shift logical with
00439                    immediate */
00440   RSHA,             /* integer right shift arithmetic */
00441   RSHAI,            /* integer right shift arithmetic with
00442                    immediate */
00443   XOR,              /* integer logical xor */
00444   XORI,             /* integer logical xor with immediate */
00445 
00446   /* operations on addresses */
00447   SNET,             /* given an address and a subnet mask,
00448                    give the subnet address */
00449   SNETI,            /* subnet with immediate mask */
00450   BCAST,            /* given an address and a subnet mask,
00451                    give the broadcast address */
00452   BCASTI,           /* broadcast address with immed. mask */
00453 
00454   /* operations on exceptions */
00455   ISX,              /* is the top value an exception? */
00456 
00457   /* core services */
00458   GETRB,            /* get the resource bound field */
00459   GETSRC,           /* get the source field */
00460   GETDST,           /* get the destination field */
00461   GETSPT,           /* get the flow id */
00462   HERE,             /* push an address of the current host */
00463   ISHERE,           /* does the address on top of the
00464                    stack belong to the current host? */
00465   ROUTE,            /* determine the next hop to send to */
00466   RTDEV,            /* next hop and outgoing interface */
00467   SEND,             /* OnRemote w/ literal: args are:
00468                    entry point, how many values of
00469                    stack to take, how much resource
00470                    bound, destination. side effects
00471                    the header dest and source fields of
00472                    outgoing packet */
00473   HOP,              /* OnNeighbor w/ literal: args are:
00474                      entry point,
00475                      stack amount,
00476                      resource bound,
00477                      neighbor */
00478   /* SENDCK, */         /* OnRemote: same as SEND, except
00479                    (entrypoint,how much stack) args
00480                    replaced with a chunk. */
00481   /* HOPCK, */          /* OnNeighbor: same as HOP, except
00482                    (entrypoint,how much stack) args
00483                    replaced with a chunk. */
00484   FORW,             /* if at destination, do nothing. else
00485                    forward packet towards destination
00486                    and exit */
00487   FORWTO,           /* arg is final destination. if there,
00488                    do nothing. else set header's src
00489                    and dst appropriately and forward */
00490 
00491   DEMUX,            /* application delivery: args are:
00492                      UDP port, string */
00493   DEMUXI,           /* same, but port num is immediate */
00494   PRINT,            /* print value to console */
00495 
00496   /* general services */
00497   SVCV,             /* returns (non-function) value with
00498                    given name from the service symtab */
00499   CALLS,            /* invokes service routine with given
00500                    string */
00501 
00502   /* willem's additions */
00503   ,
00504   DSEND,            /* direct send (no interpretation on intermediate hops) */
00505   DFORW,            /* idem for forw */
00506   DFORWTO,          /* idem for forwto */
00507   
00508   STACKEMPTY,       /* pushes a 1 if the stack is empty, 0 otherwise */
00509   STACKCOUNT,       /* pushes the number of elements on the stack */
00510   
00511   PULLSTACK         /* PULL using top stack element as index (this value is removed */
00512 } opcode_t;
00513 
00514 #define OPCODE_T opcode_t
00515 
00516 /* operations on literals */
00517 
00518 #define GET_LIT(l,t,i)                          \
00519   DYNCHECK_TAG((i).arg,t);                      \
00520   (l) = GET_INT((i).arg); /* assumes this is the same as GET_OFFS */
00521 
00522 #define SET_LIT(i,t,l)              \
00523   SET_INT((i).arg,(l)); /* all ints anyway */   \
00524   SET_TAG((i).arg,(t));
00525 
00526 #define GET_OP(i) ((i).op)
00527 #define SET_OP(i,t) ((i).op = (t))
00528 
00529 #define NUM_OPS     73  /* total number of opcodes */
00530 
00531 /* instructions are an opcode with an (optional) argument */
00532 typedef struct {
00533   OPCODE_T op;
00534   value_t arg;
00535 } instr_t;
00536 
00537 #endif
00538 
00539 #define COPY_LIT(d,t,s)         \
00540 { int _lit;             \
00541   GET_LIT(_lit,t,(s));          \
00542   SET_INT((d),_lit);            \
00543   SET_TAG((d),t);           \
00544 }
00545 
00546 #endif /* _SNAP_BYTECODE_H_ */