diff options
Diffstat (limited to 'gfx/graphite2/src/call_machine.cpp')
-rw-r--r-- | gfx/graphite2/src/call_machine.cpp | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/gfx/graphite2/src/call_machine.cpp b/gfx/graphite2/src/call_machine.cpp new file mode 100644 index 0000000000..fcd8a0c2c1 --- /dev/null +++ b/gfx/graphite2/src/call_machine.cpp @@ -0,0 +1,138 @@ +/* GRAPHITE2 LICENSING + + Copyright 2010, SIL International + All rights reserved. + + This library is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should also have received a copy of the GNU Lesser General Public + License along with this library in the file named "LICENSE". + If not, write to the Free Software Foundation, 51 Franklin Street, + Suite 500, Boston, MA 02110-1335, USA or visit their web page on the + internet at http://www.fsf.org/licenses/lgpl.html. + +Alternatively, the contents of this file may be used under the terms of the +Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public +License, as published by the Free Software Foundation, either version 2 +of the License or (at your option) any later version. +*/ +// This call threaded interpreter implmentation for machine.h +// Author: Tim Eves + +// Build either this interpreter or the direct_machine implementation. +// The call threaded interpreter is portable across compilers and +// architectures as well as being useful to debug (you can set breakpoints on +// opcodes) but is slower that the direct threaded interpreter by a factor of 2 + +#include <cassert> +#include <cstring> +#include <graphite2/Segment.h> +#include "inc/Machine.h" +#include "inc/Segment.h" +#include "inc/Slot.h" +#include "inc/Rule.h" + +// Disable the unused parameter warning as th compiler is mistaken since dp +// is always updated (even if by 0) on every opcode. +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wunused-parameter" +#endif + +#define registers const byte * & dp, vm::Machine::stack_t * & sp, \ + vm::Machine::stack_t * const sb, regbank & reg + +// These are required by opcodes.h and should not be changed +#define STARTOP(name) bool name(registers) REGPARM(4);\ + bool name(registers) { +#define ENDOP return (sp - sb)/Machine::STACK_MAX==0; \ + } + +#define EXIT(status) { push(status); return false; } + +// This is required by opcode_table.h +#define do_(name) instr(name) + + +using namespace graphite2; +using namespace vm; + +struct regbank { + slotref is; + slotref * map; + SlotMap & smap; + slotref * const map_base; + const instr * & ip; + uint8 direction; + int8 flags; + Machine::status_t & status; +}; + +typedef bool (* ip_t)(registers); + +// Pull in the opcode definitions +// We pull these into a private namespace so these otherwise common names dont +// pollute the toplevel namespace. +namespace { +#define smap reg.smap +#define seg smap.segment +#define is reg.is +#define ip reg.ip +#define map reg.map +#define mapb reg.map_base +#define flags reg.flags +#define dir reg.direction +#define status reg.status + +#include "inc/opcodes.h" + +#undef smap +#undef seg +#undef is +#undef ip +#undef map +#undef mapb +#undef flags +#undef dir +} + +Machine::stack_t Machine::run(const instr * program, + const byte * data, + slotref * & map) + +{ + assert(program != 0); + + // Declare virtual machine registers + const instr * ip = program-1; + const byte * dp = data; + stack_t * sp = _stack + Machine::STACK_GUARD, + * const sb = sp; + regbank reg = {*map, map, _map, _map.begin()+_map.context(), ip, _map.dir(), 0, _status}; + + // Run the program + while ((reinterpret_cast<ip_t>(*++ip))(dp, sp, sb, reg)) {} + const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0; + + check_final_stack(sp); + map = reg.map; + *map = reg.is; + return ret; +} + +// Pull in the opcode table +namespace { +#include "inc/opcode_table.h" +} + +const opcode_t * Machine::getOpcodeTable() throw() +{ + return opcode_table; +} |