call_machine.cpp (4272B)
1 /* GRAPHITE2 LICENSING 2 3 Copyright 2010, SIL International 4 All rights reserved. 5 6 This library is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as published 8 by the Free Software Foundation; either version 2.1 of License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should also have received a copy of the GNU Lesser General Public 17 License along with this library in the file named "LICENSE". 18 If not, write to the Free Software Foundation, 51 Franklin Street, 19 Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 20 internet at http://www.fsf.org/licenses/lgpl.html. 21 22 Alternatively, the contents of this file may be used under the terms of the 23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public 24 License, as published by the Free Software Foundation, either version 2 25 of the License or (at your option) any later version. 26 */ 27 // This call threaded interpreter implmentation for machine.h 28 // Author: Tim Eves 29 30 // Build either this interpreter or the direct_machine implementation. 31 // The call threaded interpreter is portable across compilers and 32 // architectures as well as being useful to debug (you can set breakpoints on 33 // opcodes) but is slower that the direct threaded interpreter by a factor of 2 34 35 #include <cassert> 36 #include <cstring> 37 #include <graphite2/Segment.h> 38 #include "inc/Machine.h" 39 #include "inc/Segment.h" 40 #include "inc/Slot.h" 41 #include "inc/Rule.h" 42 43 // Disable the unused parameter warning as th compiler is mistaken since dp 44 // is always updated (even if by 0) on every opcode. 45 #ifdef __GNUC__ 46 #pragma GCC diagnostic ignored "-Wunused-parameter" 47 #endif 48 49 #define registers const byte * & dp, vm::Machine::stack_t * & sp, \ 50 vm::Machine::stack_t * const sb, regbank & reg 51 52 // These are required by opcodes.h and should not be changed 53 #define STARTOP(name) bool name(registers) REGPARM(4);\ 54 bool name(registers) { 55 #define ENDOP return (sp - sb)/Machine::STACK_MAX==0; \ 56 } 57 58 #define EXIT(status) { push(status); return false; } 59 60 // This is required by opcode_table.h 61 #define do_(name) instr(name) 62 63 64 using namespace graphite2; 65 using namespace vm; 66 67 struct regbank { 68 slotref is; 69 slotref * map; 70 SlotMap & smap; 71 slotref * const map_base; 72 const instr * & ip; 73 uint8 direction; 74 int8 flags; 75 Machine::status_t & status; 76 }; 77 78 typedef bool (* ip_t)(registers); 79 80 // Pull in the opcode definitions 81 // We pull these into a private namespace so these otherwise common names dont 82 // pollute the toplevel namespace. 83 namespace { 84 #define smap reg.smap 85 #define seg smap.segment 86 #define is reg.is 87 #define ip reg.ip 88 #define map reg.map 89 #define mapb reg.map_base 90 #define flags reg.flags 91 #define dir reg.direction 92 #define status reg.status 93 94 #include "inc/opcodes.h" 95 96 #undef smap 97 #undef seg 98 #undef is 99 #undef ip 100 #undef map 101 #undef mapb 102 #undef flags 103 #undef dir 104 } 105 106 Machine::stack_t Machine::run(const instr * program, 107 const byte * data, 108 slotref * & map) 109 110 { 111 assert(program != 0); 112 113 // Declare virtual machine registers 114 const instr * ip = program-1; 115 const byte * dp = data; 116 stack_t * sp = _stack + Machine::STACK_GUARD, 117 * const sb = sp; 118 regbank reg = {*map, map, _map, _map.begin()+_map.context(), ip, _map.dir(), 0, _status}; 119 120 // Run the program 121 while ((reinterpret_cast<ip_t>(*++ip))(dp, sp, sb, reg)) {} 122 const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0; 123 124 check_final_stack(sp); 125 map = reg.map; 126 *map = reg.is; 127 return ret; 128 } 129 130 // Pull in the opcode table 131 namespace { 132 #include "inc/opcode_table.h" 133 } 134 135 const opcode_t * Machine::getOpcodeTable() throw() 136 { 137 return opcode_table; 138 }