
1: ;;; 2: ;;; vminsn.scm - Virtual machine instruction definition 3: ;;; 4: ;;; Copyright (c) 2000-2007 Shiro Kawai <shiro@acm.org> 5: ;;; 6: ;;; Redistribution and use in source and binary forms, with or without 7: ;;; modification, are permitted provided that the following conditions 8: ;;; are met: 9: ;;; 10: ;;; 1. Redistributions of source code must retain the above copyright 11: ;;; notice, this list of conditions and the following disclaimer. 12: ;;; 13: ;;; 2. Redistributions in binary form must reproduce the above copyright 14: ;;; notice, this list of conditions and the following disclaimer in the 15: ;;; documentation and/or other materials provided with the distribution. 16: ;;; 17: ;;; 3. Neither the name of the authors nor the names of its contributors 18: ;;; may be used to endorse or promote products derived from this 19: ;;; software without specific prior written permission. 20: ;;; 21: ;;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22: ;;; "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23: ;;; LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24: ;;; A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25: ;;; OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26: ;;; SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 27: ;;; TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 28: ;;; PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 29: ;;; LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30: ;;; NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31: ;;; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32: ;;; 33: ;;; $Id: vminsn.scm,v 1.10 2007/04/18 02:26:45 shirok Exp $ 34: ;;; 35: 36: ;;; This file is processed by geninsn to produce a couple of C files: 37: ;;; gauche/vminsn.h and vminsn.c, which are then included in vm.c. 38: ;;; This file is also used by the compiler. 39: ;;; 40: ;;; 41: ;;; (define-insn <name> <num-params> <operand-type> [<combination>]) 42: ;;; 43: ;;; <name> - instruction name. In C, an enum SCM_VM_<name> is defined. 44: ;;; 45: ;;; <num-params> - # of parameters the instruction takes. 46: ;;; 47: ;;; <operand-type> - none : the insn doesn't take an operand. 48: ;;; obj : an ScmObj operand. 49: ;;; addr : an address the next pc points. 50: ;;; code : an ScmCompiledCode operand. 51: ;;; codes: a list of ScmCompiledCodes. 52: ;;; 53: ;;; If this insn is a combined insn, <combination> gives a list of 54: ;;; insns that combines into this one. It is used to generate a 55: ;;; code-emitting table. 56: 57: 58: ;; NOP 59: ;; Used for placeholder. Won't appear in the final compiled code. 60: ;; 61: (define-insn NOP 0 none) 62: 63: ;; CONST <obj> 64: ;; Set <obj> to val0. 65: ;; 66: (define-insn CONST 0 obj) 67: 68: ;; Some immediate constants 69: (define-insn CONSTI 1 none) ; constant small integer 70: (define-insn CONSTN 0 none) ; constant () 71: (define-insn CONSTF 0 none) ; constant #f 72: (define-insn CONSTU 0 none) ; constant #<undef> 73: 74: ;; Combined insn 75: (define-insn CONST-PUSH 0 obj (CONST PUSH)) 76: (define-insn CONSTI-PUSH 1 none (CONSTI PUSH)) 77: (define-insn CONSTN-PUSH 0 none (CONSTN PUSH)) 78: (define-insn CONSTF-PUSH 0 none (CONSTF PUSH)) 79: (define-insn CONST-RET 0 obj (CONST RET)) 80: (define-insn CONSTF-RET 0 none (CONSTF RET)) 81: (define-insn CONSTU-RET 0 none (CONSTU RET)) 82: 83: ;; push 84: ;; Push value of val0 to the stack top 85: ;; *sp++ = val0 86: ;; 87: (define-insn PUSH 0 none) 88: 89: ;; PRE-CALL(nargs) <cont> 90: ;; Prepare for a normal call. Push a continuation that resumes 91: ;; execution from <cont>. 92: ;; 93: (define-insn PRE-CALL 1 addr) 94: 95: ;; combined insn 96: (define-insn PUSH-PRE-CALL 1 addr (PUSH PRE-CALL)) 97: 98: ;; CHECK-STACK(size) 99: ;; Check for stack overflow 100: ;; 101: (define-insn CHECK-STACK 1 none) 102: 103: ;; CALL(NARGS) 104: ;; Call procedure in val0. The continuation of this call is already 105: ;; pushed by PRE-CALL, so this instruction is always the end of a graph. 106: ;; 107: (define-insn CALL 1 none) 108: 109: ;; TAIL-CALL(NARGS) 110: ;; Call procedure in val0. Same as CALL except this discards the 111: ;; caller's arugment frame and shift the callee's argument frame. 112: ;; 113: (define-insn TAIL-CALL 1 none) 114: 115: ;; JUMP <addr> 116: ;; Jump to <addr>. 117: ;; 118: (define-insn JUMP 0 addr) 119: 120: ;; RET 121: ;; Pop the continuation stack. 122: ;; 123: (define-insn RET 0 none) 124: 125: ;; DEFINE(flag) <symbol> 126: ;; Defines global binding of SYMBOL in the current module. 127: ;; The value is taken from the input stack. 128: ;; This instruction only appears at the toplevel. Internal defines 129: ;; are recognized and eliminated by the compiling process. 130: ;; If flag == 1, the definition becomes 'constant'. 131: ;; 132: (define-insn DEFINE 1 obj) 133: 134: ;; CLOSURE <code> 135: ;; Create a closure capturing current environment. 136: ;; CODE is the compiled code. Leaves created closure in val0. 137: ;; 138: (define-insn CLOSURE 0 code) 139: 140: ;; LOCAL-ENV(NLOCALS) 141: ;; Create a new environment frame from the current arg frame. 142: ;; Used for let. 143: (define-insn LOCAL-ENV 1 none) 144: 145: ;; combined insn 146: (define-insn PUSH-LOCAL-ENV 1 none (PUSH LOCAL-ENV)) 147: 148: ;; LOCAL-ENV-CLOSURES(nlocals) <codelist> 149: ;; Used for letrec. 150: ;; Similar to LOCAL-ENV, but this doesn't use the current arg frame. 151: ;; The operand contains a literal list of compiled codes. This instruction 152: ;; creates a frame of NLOCALS size, then creates closures 153: ;; with the new environment and the given compiled codes, and fills the 154: ;; new frame with the created closures. CODELIST can have 'holes', i.e. 155: ;; if it has #f instead of a compiled code, the corresponding frame entry 156: ;; is left undefined. 157: ;; This instruction also leaves the last closure in VAL0. 158: (define-insn LOCAL-ENV-CLOSURES 1 codes) 159: 160: ;; POP-LOCAL-ENV 161: ;; Pop one environment frame created by LOCAL-ENV. In practice, 162: ;; this is only used if 'let' is in the non-tail bottom position 163: ;; (for other cases, the env frame is discarded along other frame 164: ;; operations). 165: (define-insn POP-LOCAL-ENV 0 none) 166: 167: ;; LOCAL-ENV-JUMP(DEPTH) <addr> 168: ;; This instruction appears when local function call is optimized. 169: ;; The stack already has NLOCALS values. This instruction creates an 170: ;; env frame with them (just like LOCAL-ENV), then jump to <addr>. 171: ;; (# of arguments can be known by SP - ARGP). 172: (define-insn LOCAL-ENV-JUMP 1 addr) 173: 174: ;; LOCAL-ENV-CALL(DEPTH) 175: ;; LOCAL-ENV-TAIL-CALL(DEPTH) 176: ;; This instruction appears when local function call is optimized. 177: ;; VAL0 has a closure to call, and the stack already has the arguments. 178: ;; 179: ;; This instruction creates an env frame with the existing 180: ;; values (just like LOCAL-ENV), then jump to the entrance point of 181: ;; the closure in VAL0. The point is that we can bypass the generic 182: ;; CALL sequence, since the arguments are already adjusted and we 183: ;; know the called closure is not a generic function. 184: ;; (# of arguments can be known by SP - ARGP). 185: (define-insn LOCAL-ENV-CALL 1 none) 186: (define-insn LOCAL-ENV-TAIL-CALL 1 none) 187: 188: ;; BF <else-offset> ; branch if VAL0 is false 189: ;; BT <else-offset> ; branch if VAL0 is true 190: ;; BNNULL <else-offset> ; branch if VAL0 is not null 191: ;; BNEQ <else-offset> ; branch if VAL0 is not eq? to (POP) 192: ;; BNEQV <else-offset> ; branch if VAL0 is not eqv? to (POP) 193: ;; BNUMNE <else-offset> ; branch if (VAL0 != (POP)) 194: ;; BNLT <else-offset> ; branch if !((POP) < VAL0) 195: ;; BNLE <else-offset> ; branch if !((POP) <= VAL0) 196: ;; BNGT <else-offset> ; branch if !((POP) > VAL0) 197: ;; BNGE <else-offset> ; branch if !((POP) >= VAL0) 198: ;; Conditional branches. 199: ;; The combined operations leave the boolean value of the test result 200: ;; in VAL0. 201: (define-insn BF 0 addr) 202: (define-insn BT 0 addr) 203: (define-insn BNEQ 0 addr) 204: (define-insn BNEQV 0 addr) 205: (define-insn BNNULL 0 addr) 206: 207: (define-insn BNUMNE 0 addr) 208: (define-insn BNLT 0 addr) 209: (define-insn BNLE 0 addr) 210: (define-insn BNGT 0 addr) 211: (define-insn BNGE 0 addr) 212: 213: ;; BNUMNEI(i) <else-offset> ; combined CONSTI(i) + BNUMNE 214: ;; BNEQC <else-offset> ; branch if immediate constant is not eq? to VAL0 215: ;; BNEQVC <else-offset> ; branch if immediate constant is not eqv? to VAL0 216: ;; NB: we tried other variations of constant op + branch combination, 217: ;; notably BNEQVI, BNUMNEF, BNLTF etc, but they did't show any 218: ;; improvement. 219: (define-insn BNUMNEI 1 addr) 220: (define-insn BNEQC 0 obj+addr) 221: (define-insn BNEQVC 0 obj+addr) 222: 223: ;; RF 224: ;; RT 225: ;; RNNULL 226: ;; RNEQ 227: ;; RNEQV 228: ;; Conditional returns. 229: (define-insn RF 0 none) 230: (define-insn RT 0 none) 231: (define-insn RNEQ 0 none) 232: (define-insn RNEQV 0 none) 233: (define-insn RNNULL 0 none) 234: 235: ;; RECEIVE(nargs,restarg) <cont-offset> 236: ;; Primitive operation for receive and call-with-values. 237: ;; Turn the value(s) into an environment. 238: ;; Like LET, this pushes the continuation frame to resume the 239: ;; operation from CONT-OFFSET. 240: ;; 241: (define-insn RECEIVE 2 addr) 242: 243: ;; TAIL-RECEIVE(nargs,restarg) 244: ;; Tail position of receive. No need to push the continuation. 245: ;; Actually, TAIL-RECEIVE can be used anywhere if there's no 246: ;; argument pushed after the last continuation frame. See TAIL-LET. 247: ;; 248: (define-insn TAIL-RECEIVE 2 none) 249: 250: ;; LSET(depth, offset) 251: ;; Local set 252: ;; 253: (define-insn LSET 2 none) 254: 255: ;; shortcut for the first frame, small offset 256: ;; NB: this doesn't help much. will go away. 257: (define-insn LSET0 0 none) 258: (define-insn LSET1 0 none) 259: (define-insn LSET2 0 none) 260: (define-insn LSET3 0 none) 261: (define-insn LSET4 0 none) 262: 263: ;; GSET <location> 264: ;; LOCATION may be a symbol or gloc 265: ;; 266: (define-insn GSET 0 obj) 267: 268: ;; LREF(depth,offset) 269: ;; Retrieve local value. 270: ;; 271: (define-insn LREF 2 none) 272: 273: ;; Shortcut for the frequent depth/offset. 274: ;; From statistics, we found that the following depth/offset combinations 275: ;; are quite frequent: 276: ;; (0,0) (0,1) (0,2) (0,3) 277: ;; (1,0) (1,1) (1,2) 278: ;; (2,0) (2,1) 279: ;; (3,0) 280: ;; 281: 282: (define-insn LREF0 0 none) 283: (define-insn LREF1 0 none) 284: (define-insn LREF2 0 none) 285: (define-insn LREF3 0 none) 286: (define-insn LREF10 0 none) 287: (define-insn LREF11 0 none) 288: (define-insn LREF12 0 none) 289: (define-insn LREF20 0 none) 290: (define-insn LREF21 0 none) 291: (define-insn LREF30 0 none) 292: 293: ;; these will go away: 294: (define-insn LREF4 0 none) 295: (define-insn LREF13 0 none) 296: (define-insn LREF14 0 none) 297: 298: ;; combined instrction 299: (define-insn LREF-PUSH 2 none (LREF PUSH)) 300: (define-insn LREF0-PUSH 0 none (LREF0 PUSH)) 301: (define-insn LREF1-PUSH 0 none (LREF1 PUSH)) 302: (define-insn LREF2-PUSH 0 none (LREF2 PUSH)) 303: (define-insn LREF3-PUSH 0 none (LREF3 PUSH)) 304: (define-insn LREF10-PUSH 0 none (LREF10 PUSH)) 305: (define-insn LREF11-PUSH 0 none (LREF11 PUSH)) 306: (define-insn LREF12-PUSH 0 none (LREF12 PUSH)) 307: (define-insn LREF20-PUSH 0 none (LREF20 PUSH)) 308: (define-insn LREF21-PUSH 0 none (LREF21 PUSH)) 309: (define-insn LREF30-PUSH 0 none (LREF30 PUSH)) 310: 311: ;; these will go away: 312: (define-insn LREF4-PUSH 0 none) 313: (define-insn LREF13-PUSH 0 none) 314: (define-insn LREF14-PUSH 0 none) 315: 316: ;; GREF <location> 317: ;; LOCATION may be a symbol or GLOC object. 318: ;; Retrieve global value in the current module. 319: ;; 320: (define-insn GREF 0 obj) 321: 322: ;; combined instructions 323: ;; NB: PUSH-GREF itself isn't a very useful form, but it works as a 324: ;; transient state to PUSH-GREF-CALL / PUSH-GREF-TAIL-CALL, which are 325: ;; very frequent operation, during instruction combining. 326: 327: (define-insn GREF-PUSH 0 obj (GREF PUSH)) 328: (define-insn GREF-CALL 1 obj (GREF CALL)) 329: (define-insn GREF-TAIL-CALL 1 obj (GREF TAIL-CALL)) 330: 331: (define-insn PUSH-GREF 0 obj (PUSH GREF)) 332: (define-insn PUSH-GREF-CALL 1 obj (PUSH GREF CALL)) 333: (define-insn PUSH-GREF-TAIL-CALL 1 obj (PUSH GREF TAIL-CALL)) 334: 335: (define-insn LREF0-PUSH-GREF 0 obj (LREF0 PUSH GREF)) 336: (define-insn LREF0-PUSH-GREF-CALL 1 obj (LREF0 PUSH GREF CALL)) 337: (define-insn LREF0-PUSH-GREF-TAIL-CALL 1 obj (LREF0 PUSH GREF TAIL-CALL)) 338: 339: ;; PROMISE 340: ;; Delay syntax emits this instruction. Wrap a procedure into a promise 341: ;; object. 342: ;; 343: (define-insn PROMISE 0 none) 344: 345: ;; CONST_APPLY(nargs) <form> 346: ;; This instruction should only appear in the code generated dynamically 347: ;; by Scm_Apply. This is used to pass the application information across 348: ;; the boundary frame (see user_eval_inner() in vm.c). 349: ;; <form> is a constant list (<proc> <arg> ...). <proc> is called with 350: ;; <arg>s. 351: (define-insn CONST-APPLY 1 obj) 352: 353: ;; Inlined operators 354: ;; They work the same as corresponding Scheme primitives, but they are 355: ;; directly interpreted by VM, skipping argument processing part. 356: ;; Compiler may insert these in order to fulfill the operation (e.g. 357: ;; `case' needs MEMV). If the optimization level is high, global 358: ;; reference of those primitive calls in the user code are replaced 359: ;; as well. 360: ;; 361: (define-insn CONS 0 none) 362: (define-insn CONS-PUSH 0 none (CONS PUSH)) 363: (define-insn CAR 0 none) 364: (define-insn CAR-PUSH 0 none (CAR PUSH)) 365: (define-insn CDR 0 none) 366: (define-insn CDR-PUSH 0 none (CDR PUSH)) 367: (define-insn CAAR 0 none) 368: (define-insn CAAR-PUSH 0 none (CAAR PUSH)) 369: (define-insn CADR 0 none) 370: (define-insn CADR-PUSH 0 none (CADR PUSH)) 371: (define-insn CDAR 0 none) 372: (define-insn CDAR-PUSH 0 none (CDAR PUSH)) 373: (define-insn CDDR 0 none) 374: (define-insn CDDR-PUSH 0 none (CDDR PUSH)) 375: 376: (define-insn LIST 1 none) 377: (define-insn LIST-STAR 1 none) ; list* 378: (define-insn LENGTH 0 none) ; length 379: (define-insn MEMQ 0 none) 380: (define-insn MEMV 0 none) 381: (define-insn ASSQ 0 none) 382: (define-insn ASSV 0 none) 383: (define-insn EQ 0 none) ; eq? 384: (define-insn EQV 0 none) ; eqv? 385: (define-insn APPEND 1 none) 386: (define-insn NOT 0 none) 387: (define-insn REVERSE 0 none) 388: (define-insn APPLY 1 none) 389: (define-insn TAIL-APPLY 1 none) ; apply at the tail position 390: (define-insn IS-A 0 none) ; is-a? 391: 392: (define-insn NULLP 0 none) ; null? 393: (define-insn PAIRP 0 none) ; pair? 394: (define-insn CHARP 0 none) ; char? 395: (define-insn EOFP 0 none) ; eof? 396: (define-insn STRINGP 0 none) ; string? 397: (define-insn SYMBOLP 0 none) ; symbol? 398: (define-insn VECTORP 0 none) ; vector? 399: (define-insn IDENTIFIERP 0 none) 400: 401: (define-insn SETTER 0 none) 402: 403: (define-insn VALUES 1 none) 404: 405: (define-insn VEC 1 none) ; vector 406: (define-insn LIST2VEC 0 none) ; list->vector 407: (define-insn APP-VEC 1 none) ; (compose list->vector append) 408: (define-insn VEC-LEN 0 none) ; vector-length 409: (define-insn VEC-REF 0 none) ; vector-ref 410: (define-insn VEC-SET 0 none) ; vector-set 411: ;; VEC-REF and VEC-SET with immediate index. VAL0 must be a vector. 412: (define-insn VEC-REFI 1 none) 413: (define-insn VEC-SETI 1 none) 414: 415: (define-insn NUMEQ2 0 none) ; = 416: (define-insn NUMLT2 0 none) ; < 417: (define-insn NUMLE2 0 none) ; <= 418: (define-insn NUMGT2 0 none) ; > 419: (define-insn NUMGE2 0 none) ; >= 420: (define-insn NUMADD2 0 none) ; + 421: (define-insn NUMSUB2 0 none) ; - (binary) 422: (define-insn NUMMUL2 0 none) ; * 423: (define-insn NUMDIV2 0 none) ; / 424: (define-insn NEGATE 0 none) ; - (unary) 425: 426: (define-insn NUMIADD2 0 none) ; +. 427: (define-insn NUMISUB2 0 none) ; -. (binary) 428: (define-insn NUMIMUL2 0 none) ; *. 429: (define-insn NUMIDIV2 0 none) ; /. (binary) 430: 431: (define-insn NUMADDI 1 none) ; +, if one of op is small int 432: (define-insn NUMSUBI 1 none) ; -, if one of op is small int 433: 434: ;(define-insn NUMQUOT 0 none) ; quotient 435: ;(define-insn NUMMOD 0 none) ; modulo 436: ;(define-insn NUMREM 0 none) ; remainder 437: ;(define-insn ASH 0 none) ; ash 438: ;(define-insn LOGAND 0 none) ; logand 439: ;(define-insn LOGIOR 0 none) ; logior 440: ;(define-insn LOGXOR 0 none) ; logxor 441: ;(define-insn LOGNOT 0 none) ; lognot 442: ;(define-insn LOGANDI 1 none) ; logand w/ immediate small int 443: ;(define-insn LOGIORI 1 none) ; logior w/ immediate small int 444: ;(define-insn LOGXORI 1 none) ; logxor w/ immediate small int 445: 446: (define-insn READ-CHAR 1 none) ; read-char 447: (define-insn PEEK-CHAR 1 none) ; peek-char 448: (define-insn WRITE-CHAR 1 none) ; write-char 449: 450: (define-insn CURIN 0 none) ; current-input-port 451: (define-insn CUROUT 0 none) ; current-output-port 452: (define-insn CURERR 0 none) ; current-error-port 453: 454: (define-insn SLOT-REF 0 none) ; slot-ref 455: (define-insn SLOT-SET 0 none) ; slot-set! 456: (define-insn SLOT-REFC 0 obj) ; slot-ref with constant slot name 457: (define-insn SLOT-SETC 0 obj) ; slot-set! with constant slot name 458: 459: ;; combined 460: ;(define-insn LREF0-NUMADDI 1 none) 461: ;(define-insn LREF1-NUMADDI 1 none) 462: ;(define-insn LREF2-NUMADDI 1 none) 463: ;(define-insn LREF3-NUMADDI 1 none) 464: ;(define-insn LREF4-NUMADDI 1 none) 465: 466: ;;; 467: ;;; Additional instructions 468: ;;; 469: ;;; [SK] Note for myself: They're here not to change instruction 470: ;;; numbers, so that building from CVS won't be complicated. 471: ;;; Need to put them in appropriate places just before 0.8.7-pre1 472: ;;; packaging. 473: ;;; 474: 475: ;; RECEIVE-ALL <cont> 476: ;; A special version of RECEIVE that pushes all the current values 477: ;; into the stack and makes them into an environment. 478: ;; It is used primarily for the occasions that compiler knows it needs 479: ;; to save the values temporarily (e.g. for evaluate 'after' thunk of 480: ;; dynamic-wind, the results of its body needs to be saved). 481: ;; This must be twined with VALUES-N, which reverses the effects, i.e. 482: ;; turn the values in the env frame into values. 483: (define-insn RECEIVE-ALL 0 addr) 484: 485: ;; TAIL-RECEIVE-ALL 486: ;; Tail version of RECEIVE-ALL. 487: (define-insn TAIL-RECEIVE-ALL 0 none) 488: 489: ;; VALUES-N 490: ;; Inverse of RECEIVE-ALL. Transfer the current environment content 491: ;; to the values register, and pop the env. 492: ;; Differ from VALUES since this one doesn't know # of values beforehand. 493: (define-insn VALUES-N 0 none) 494: 495: ;; PUSH-HANDLERS 496: ;; POP-HANDLERS 497: ;; Used for dynamic-wind and alike. 498: 499: (define-insn PUSH-HANDLERS 0 none) ; push dynamic handlers 500: (define-insn POP-HANDLERS 0 none) ; pop dynamic handlers 501: 502: ;; experiment 503: ;(define-insn LREF-NUMADD2 2 none)