/src/mozilla-central/gfx/graphite2/src/direct_machine.cpp
Line | Count | Source (jump to first uncovered line) |
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 direct threaded interpreter implmentation for machine.h |
28 | | // Author: Tim Eves |
29 | | |
30 | | // Build either this interpreter or the call_machine implementation. |
31 | | // The direct threaded interpreter is relies upon a gcc feature called |
32 | | // labels-as-values so is only portable to compilers that support the |
33 | | // extension (gcc only as far as I know) however it should build on any |
34 | | // architecture gcc supports. |
35 | | // This is twice as fast as the call threaded model and is likely faster on |
36 | | // inorder processors with short pipelines and little branch prediction such |
37 | | // as the ARM and possibly Atom chips. |
38 | | |
39 | | |
40 | | #include <cassert> |
41 | | #include <cstring> |
42 | | #include "inc/Machine.h" |
43 | | #include "inc/Segment.h" |
44 | | #include "inc/Slot.h" |
45 | | #include "inc/Rule.h" |
46 | | |
47 | 0 | #define STARTOP(name) name: { |
48 | 0 | #define ENDOP }; goto *((sp - sb)/Machine::STACK_MAX ? &&end : *++ip); |
49 | 0 | #define EXIT(status) { push(status); goto end; } |
50 | | |
51 | 0 | #define do_(name) &&name |
52 | | |
53 | | |
54 | | using namespace graphite2; |
55 | | using namespace vm; |
56 | | |
57 | | namespace { |
58 | | |
59 | | const void * direct_run(const bool get_table_mode, |
60 | | const instr * program, |
61 | | const byte * data, |
62 | | Machine::stack_t * stack, |
63 | | slotref * & __map, |
64 | | uint8 _dir, |
65 | | Machine::status_t & status, |
66 | | SlotMap * __smap=0) |
67 | 0 | { |
68 | 0 | // We need to define and return to opcode table from within this function |
69 | 0 | // other inorder to take the addresses of the instruction bodies. |
70 | 0 | #include "inc/opcode_table.h" |
71 | 0 | if (get_table_mode) |
72 | 0 | return opcode_table; |
73 | 0 | |
74 | 0 | // Declare virtual machine registers |
75 | 0 | const instr * ip = program; |
76 | 0 | const byte * dp = data; |
77 | 0 | Machine::stack_t * sp = stack + Machine::STACK_GUARD, |
78 | 0 | * const sb = sp; |
79 | 0 | SlotMap & smap = *__smap; |
80 | 0 | Segment & seg = smap.segment; |
81 | 0 | slotref is = *__map, |
82 | 0 | * map = __map, |
83 | 0 | * const mapb = smap.begin()+smap.context(); |
84 | 0 | uint8 dir = _dir; |
85 | 0 | int8 flags = 0; |
86 | 0 |
|
87 | 0 | // start the program |
88 | 0 | goto **ip; |
89 | 0 |
|
90 | 0 | // Pull in the opcode definitions |
91 | 0 | #include "inc/opcodes.h" |
92 | 0 |
|
93 | 0 | end: |
94 | 0 | __map = map; |
95 | 0 | *__map = is; |
96 | 0 | return sp; |
97 | 0 | } |
98 | | |
99 | | } |
100 | | |
101 | | const opcode_t * Machine::getOpcodeTable() throw() |
102 | 0 | { |
103 | 0 | slotref * dummy; |
104 | 0 | Machine::status_t dumstat = Machine::finished; |
105 | 0 | return static_cast<const opcode_t *>(direct_run(true, 0, 0, 0, dummy, 0, dumstat)); |
106 | 0 | } |
107 | | |
108 | | |
109 | | Machine::stack_t Machine::run(const instr * program, |
110 | | const byte * data, |
111 | | slotref * & is) |
112 | 0 | { |
113 | 0 | assert(program != 0); |
114 | 0 |
|
115 | 0 | const stack_t *sp = static_cast<const stack_t *>( |
116 | 0 | direct_run(false, program, data, _stack, is, _map.dir(), _status, &_map)); |
117 | 0 | const stack_t ret = sp == _stack+STACK_GUARD+1 ? *sp-- : 0; |
118 | 0 | check_final_stack(sp); |
119 | 0 | return ret; |
120 | 0 | } |