gfx/graphite2/src/inc/opcodes.h

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:d5d510428c87
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 #pragma once
28 // This file will be pulled into and integrated into a machine implmentation
29 // DO NOT build directly and under no circumstances every #include headers in
30 // here or you will break the direct_machine.
31 //
32 // Implementers' notes
33 // ==================
34 // You have access to a few primitives and the full C++ code:
35 // declare_params(n) Tells the interpreter how many bytes of parameter
36 // space to claim for this instruction uses and
37 // initialises the param pointer. You *must* before the
38 // first use of param.
39 // use_params(n) Claim n extra bytes of param space beyond what was
40 // claimed using delcare_param.
41 // param A const byte pointer for the parameter space claimed by
42 // this instruction.
43 // binop(op) Implement a binary operation on the stack using the
44 // specified C++ operator.
45 // NOT_IMPLEMENTED Any instruction body containing this will exit the
46 // program with an assertion error. Instructions that are
47 // not implemented should also be marked NILOP in the
48 // opcodes tables this will cause the code class to spot
49 // them in a live code stream and throw a runtime_error
50 // instead.
51 // push(n) Push the value n onto the stack.
52 // pop() Pop the top most value and return it.
53 //
54 // You have access to the following named fast 'registers':
55 // sp = The pointer to the current top of stack, the last value
56 // pushed.
57 // seg = A reference to the Segment this code is running over.
58 // is = The current slot index
59 // isb = The original base slot index at the start of this rule
60 // isf = The first positioned slot
61 // isl = The last positioned slot
62 // ip = The current instruction pointer
63 // endPos = Position of advance of last cluster
64
65
66 // #define NOT_IMPLEMENTED assert(false)
67 #define NOT_IMPLEMENTED
68
69 #define binop(op) const int32 a = pop(); *sp = int32(*sp) op a
70 #define use_params(n) dp += n
71
72 #define declare_params(n) const byte * param = dp; \
73 use_params(n);
74
75 #define push(n) { *++sp = n; }
76 #define pop() (*sp--)
77 #define slotat(x) (map[(x)])
78 #define DIE { is=seg.last(); EXIT(1); }
79 #define POSITIONED 1
80
81 STARTOP(nop)
82 do {} while (0);
83 ENDOP
84
85 STARTOP(push_byte)
86 declare_params(1);
87 push(int8(*param));
88 ENDOP
89
90 STARTOP(push_byte_u)
91 declare_params(1);
92 push(uint8(*param));
93 ENDOP
94
95 STARTOP(push_short)
96 declare_params(2);
97 const int16 r = int16(param[0]) << 8
98 | uint8(param[1]);
99 push(r);
100 ENDOP
101
102 STARTOP(push_short_u)
103 declare_params(2);
104 const uint16 r = uint16(param[0]) << 8
105 | uint8(param[1]);
106 push(r);
107 ENDOP
108
109 STARTOP(push_long)
110 declare_params(4);
111 const int32 r = int32(param[0]) << 24
112 | uint32(param[1]) << 16
113 | uint32(param[2]) << 8
114 | uint8(param[3]);
115 push(r);
116 ENDOP
117
118 STARTOP(add)
119 binop(+);
120 ENDOP
121
122 STARTOP(sub)
123 binop(-);
124 ENDOP
125
126 STARTOP(mul)
127 binop(*);
128 ENDOP
129
130 STARTOP(div_)
131 if (*sp == 0) DIE;
132 binop(/);
133 ENDOP
134
135 STARTOP(min_)
136 const int32 a = pop(), b = *sp;
137 if (a < b) *sp = a;
138 ENDOP
139
140 STARTOP(max_)
141 const int32 a = pop(), b = *sp;
142 if (a > b) *sp = a;
143 ENDOP
144
145 STARTOP(neg)
146 *sp = uint32(-int32(*sp));
147 ENDOP
148
149 STARTOP(trunc8)
150 *sp = uint8(*sp);
151 ENDOP
152
153 STARTOP(trunc16)
154 *sp = uint16(*sp);
155 ENDOP
156
157 STARTOP(cond)
158 const uint32 f = pop(), t = pop(), c = pop();
159 push(c ? t : f);
160 ENDOP
161
162 STARTOP(and_)
163 binop(&&);
164 ENDOP
165
166 STARTOP(or_)
167 binop(||);
168 ENDOP
169
170 STARTOP(not_)
171 *sp = !*sp;
172 ENDOP
173
174 STARTOP(equal)
175 binop(==);
176 ENDOP
177
178 STARTOP(not_eq_)
179 binop(!=);
180 ENDOP
181
182 STARTOP(less)
183 binop(<);
184 ENDOP
185
186 STARTOP(gtr)
187 binop(>);
188 ENDOP
189
190 STARTOP(less_eq)
191 binop(<=);
192 ENDOP
193
194 STARTOP(gtr_eq)
195 binop(>=);
196 ENDOP
197
198 STARTOP(next)
199 if (map - &smap[0] >= int(smap.size())) DIE
200 if (is)
201 {
202 if (is == smap.highwater())
203 smap.highpassed(true);
204 is = is->next();
205 }
206 ++map;
207 ENDOP
208
209 STARTOP(next_n)
210 use_params(1);
211 NOT_IMPLEMENTED;
212 //declare_params(1);
213 //const size_t num = uint8(*param);
214 ENDOP
215
216 //STARTOP(copy_next)
217 // if (is) is = is->next();
218 // ++map;
219 // ENDOP
220
221 STARTOP(put_glyph_8bit_obs)
222 declare_params(1);
223 const unsigned int output_class = uint8(*param);
224 is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
225 ENDOP
226
227 STARTOP(put_subs_8bit_obs)
228 declare_params(3);
229 const int slot_ref = int8(param[0]);
230 const unsigned int input_class = uint8(param[1]),
231 output_class = uint8(param[2]);
232 uint16 index;
233 slotref slot = slotat(slot_ref);
234 if (slot)
235 {
236 index = seg.findClassIndex(input_class, slot->gid());
237 is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
238 }
239 ENDOP
240
241 STARTOP(put_copy)
242 declare_params(1);
243 const int slot_ref = int8(*param);
244 if (is && (slot_ref ||is != *map))
245 {
246 int16 *tempUserAttrs = is->userAttrs();
247 slotref ref = slotat(slot_ref);
248 if (ref)
249 {
250 memcpy(tempUserAttrs, ref->userAttrs(), seg.numAttrs() * sizeof(uint16));
251 Slot *prev = is->prev();
252 Slot *next = is->next();
253 memcpy(is, slotat(slot_ref), sizeof(Slot));
254 is->userAttrs(tempUserAttrs);
255 is->next(next);
256 is->prev(prev);
257 is->sibling(NULL);
258 }
259 is->markCopied(false);
260 is->markDeleted(false);
261 }
262 ENDOP
263
264 STARTOP(insert)
265 Slot *newSlot = seg.newSlot();
266 if (!newSlot) DIE;
267 Slot *iss = is;
268 while (iss && iss->isDeleted()) iss = iss->next();
269 if (!iss)
270 {
271 if (seg.last())
272 {
273 seg.last()->next(newSlot);
274 newSlot->prev(seg.last());
275 newSlot->before(seg.last()->before());
276 seg.last(newSlot);
277 }
278 else
279 {
280 seg.first(newSlot);
281 seg.last(newSlot);
282 }
283 }
284 else if (iss->prev())
285 {
286 iss->prev()->next(newSlot);
287 newSlot->prev(iss->prev());
288 newSlot->before(iss->prev()->after());
289 }
290 else
291 {
292 newSlot->prev(NULL);
293 newSlot->before(iss->before());
294 seg.first(newSlot);
295 }
296 newSlot->next(iss);
297 if (iss)
298 {
299 iss->prev(newSlot);
300 newSlot->originate(iss->original());
301 newSlot->after(iss->before());
302 }
303 else if (newSlot->prev())
304 {
305 newSlot->originate(newSlot->prev()->original());
306 newSlot->after(newSlot->prev()->after());
307 }
308 else
309 {
310 newSlot->originate(seg.defaultOriginal());
311 }
312 is = newSlot;
313 seg.extendLength(1);
314 if (map != &smap[-1])
315 --map;
316 ENDOP
317
318 STARTOP(delete_)
319 if (!is) DIE
320 is->markDeleted(true);
321 if (is->prev())
322 is->prev()->next(is->next());
323 else
324 seg.first(is->next());
325
326 if (is->next())
327 is->next()->prev(is->prev());
328 else
329 seg.last(is->prev());
330
331 if (is == smap.highwater())
332 smap.highwater(is->next());
333 if (is->prev())
334 is = is->prev();
335 seg.extendLength(-1);
336 ENDOP
337
338 STARTOP(assoc)
339 declare_params(1);
340 unsigned int num = uint8(*param);
341 const int8 * assocs = reinterpret_cast<const int8 *>(param+1);
342 use_params(num);
343 int max = -1;
344 int min = -1;
345
346 while (num-- > 0)
347 {
348 int sr = *assocs++;
349 slotref ts = slotat(sr);
350 if (ts && (min == -1 || ts->before() < min)) min = ts->before();
351 if (ts && ts->after() > max) max = ts->after();
352 }
353 if (min > -1) // implies max > -1
354 {
355 is->before(min);
356 is->after(max);
357 }
358 ENDOP
359
360 STARTOP(cntxt_item)
361 // It turns out this is a cunningly disguised condition forward jump.
362 declare_params(3);
363 const int is_arg = int8(param[0]);
364 const size_t iskip = uint8(param[1]),
365 dskip = uint8(param[2]);
366
367 if (mapb + is_arg != map)
368 {
369 ip += iskip;
370 dp += dskip;
371 push(true);
372 }
373 ENDOP
374
375 STARTOP(attr_set)
376 declare_params(1);
377 const attrCode slat = attrCode(uint8(*param));
378 const int val = int(pop());
379 is->setAttr(&seg, slat, 0, val, smap);
380 ENDOP
381
382 STARTOP(attr_add)
383 declare_params(1);
384 const attrCode slat = attrCode(uint8(*param));
385 const int val = int(pop());
386 if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
387 {
388 seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
389 flags |= POSITIONED;
390 }
391 int res = is->getAttr(&seg, slat, 0);
392 is->setAttr(&seg, slat, 0, val + res, smap);
393 ENDOP
394
395 STARTOP(attr_sub)
396 declare_params(1);
397 const attrCode slat = attrCode(uint8(*param));
398 const int val = int(pop());
399 if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
400 {
401 seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
402 flags |= POSITIONED;
403 }
404 int res = is->getAttr(&seg, slat, 0);
405 is->setAttr(&seg, slat, 0, res - val, smap);
406 ENDOP
407
408 STARTOP(attr_set_slot)
409 declare_params(1);
410 const attrCode slat = attrCode(uint8(*param));
411 const int offset = (map - smap.begin())*int(slat == gr_slatAttTo);
412 const int val = int(pop()) + offset;
413 is->setAttr(&seg, slat, offset, val, smap);
414 ENDOP
415
416 STARTOP(iattr_set_slot)
417 declare_params(2);
418 const attrCode slat = attrCode(uint8(param[0]));
419 const size_t idx = uint8(param[1]);
420 const int val = int(pop()) + (map - smap.begin())*int(slat == gr_slatAttTo);
421 is->setAttr(&seg, slat, idx, val, smap);
422 ENDOP
423
424 STARTOP(push_slot_attr)
425 declare_params(2);
426 const attrCode slat = attrCode(uint8(param[0]));
427 const int slot_ref = int8(param[1]);
428 if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
429 {
430 seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
431 flags |= POSITIONED;
432 }
433 slotref slot = slotat(slot_ref);
434 if (slot)
435 {
436 int res = slot->getAttr(&seg, slat, 0);
437 push(res);
438 }
439 ENDOP
440
441 STARTOP(push_glyph_attr_obs)
442 declare_params(2);
443 const unsigned int glyph_attr = uint8(param[0]);
444 const int slot_ref = int8(param[1]);
445 slotref slot = slotat(slot_ref);
446 if (slot)
447 push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
448 ENDOP
449
450 STARTOP(push_glyph_metric)
451 declare_params(3);
452 const unsigned int glyph_attr = uint8(param[0]);
453 const int slot_ref = int8(param[1]);
454 const signed int attr_level = uint8(param[2]);
455 slotref slot = slotat(slot_ref);
456 if (slot)
457 push(seg.getGlyphMetric(slot, glyph_attr, attr_level));
458 ENDOP
459
460 STARTOP(push_feat)
461 declare_params(2);
462 const unsigned int feat = uint8(param[0]);
463 const int slot_ref = int8(param[1]);
464 slotref slot = slotat(slot_ref);
465 if (slot)
466 {
467 uint8 fid = seg.charinfo(slot->original())->fid();
468 push(seg.getFeature(fid, feat));
469 }
470 ENDOP
471
472 STARTOP(push_att_to_gattr_obs)
473 declare_params(2);
474 const unsigned int glyph_attr = uint8(param[0]);
475 const int slot_ref = int8(param[1]);
476 slotref slot = slotat(slot_ref);
477 if (slot)
478 {
479 slotref att = slot->attachedTo();
480 if (att) slot = att;
481 push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
482 }
483 ENDOP
484
485 STARTOP(push_att_to_glyph_metric)
486 declare_params(3);
487 const unsigned int glyph_attr = uint8(param[0]);
488 const int slot_ref = int8(param[1]);
489 const signed int attr_level = uint8(param[2]);
490 slotref slot = slotat(slot_ref);
491 if (slot)
492 {
493 slotref att = slot->attachedTo();
494 if (att) slot = att;
495 push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level)));
496 }
497 ENDOP
498
499 STARTOP(push_islot_attr)
500 declare_params(3);
501 const attrCode slat = attrCode(uint8(param[0]));
502 const int slot_ref = int8(param[1]),
503 idx = uint8(param[2]);
504 if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
505 {
506 seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
507 flags |= POSITIONED;
508 }
509 slotref slot = slotat(slot_ref);
510 if (slot)
511 {
512 int res = slot->getAttr(&seg, slat, idx);
513 push(res);
514 }
515 ENDOP
516
517 #if 0
518 STARTOP(push_iglyph_attr) // not implemented
519 NOT_IMPLEMENTED;
520 ENDOP
521 #endif
522
523 STARTOP(pop_ret)
524 const uint32 ret = pop();
525 EXIT(ret);
526 ENDOP
527
528 STARTOP(ret_zero)
529 EXIT(0);
530 ENDOP
531
532 STARTOP(ret_true)
533 EXIT(1);
534 ENDOP
535
536 STARTOP(iattr_set)
537 declare_params(2);
538 const attrCode slat = attrCode(uint8(param[0]));
539 const size_t idx = uint8(param[1]);
540 const int val = int(pop());
541 is->setAttr(&seg, slat, idx, val, smap);
542 ENDOP
543
544 STARTOP(iattr_add)
545 declare_params(2);
546 const attrCode slat = attrCode(uint8(param[0]));
547 const size_t idx = uint8(param[1]);
548 const int val = int(pop());
549 if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
550 {
551 seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
552 flags |= POSITIONED;
553 }
554 int res = is->getAttr(&seg, slat, idx);
555 is->setAttr(&seg, slat, idx, val + res, smap);
556 ENDOP
557
558 STARTOP(iattr_sub)
559 declare_params(2);
560 const attrCode slat = attrCode(uint8(param[0]));
561 const size_t idx = uint8(param[1]);
562 const int val = int(pop());
563 if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
564 {
565 seg.positionSlots(0, *smap.begin(), *(smap.end()-1));
566 flags |= POSITIONED;
567 }
568 int res = is->getAttr(&seg, slat, idx);
569 is->setAttr(&seg, slat, idx, res - val, smap);
570 ENDOP
571
572 STARTOP(push_proc_state)
573 use_params(1);
574 push(1);
575 ENDOP
576
577 STARTOP(push_version)
578 push(0x00030000);
579 ENDOP
580
581 STARTOP(put_subs)
582 declare_params(5);
583 const int slot_ref = int8(param[0]);
584 const unsigned int input_class = uint8(param[1]) << 8
585 | uint8(param[2]);
586 const unsigned int output_class = uint8(param[3]) << 8
587 | uint8(param[4]);
588 slotref slot = slotat(slot_ref);
589 if (slot)
590 {
591 int index = seg.findClassIndex(input_class, slot->gid());
592 is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
593 }
594 ENDOP
595
596 #if 0
597 STARTOP(put_subs2) // not implemented
598 NOT_IMPLEMENTED;
599 ENDOP
600
601 STARTOP(put_subs3) // not implemented
602 NOT_IMPLEMENTED;
603 ENDOP
604 #endif
605
606 STARTOP(put_glyph)
607 declare_params(2);
608 const unsigned int output_class = uint8(param[0]) << 8
609 | uint8(param[1]);
610 is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
611 ENDOP
612
613 STARTOP(push_glyph_attr)
614 declare_params(3);
615 const unsigned int glyph_attr = uint8(param[0]) << 8
616 | uint8(param[1]);
617 const int slot_ref = int8(param[2]);
618 slotref slot = slotat(slot_ref);
619 if (slot)
620 push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
621 ENDOP
622
623 STARTOP(push_att_to_glyph_attr)
624 declare_params(3);
625 const unsigned int glyph_attr = uint8(param[0]) << 8
626 | uint8(param[1]);
627 const int slot_ref = int8(param[2]);
628 slotref slot = slotat(slot_ref);
629 if (slot)
630 {
631 slotref att = slot->attachedTo();
632 if (att) slot = att;
633 push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
634 }
635 ENDOP
636
637 STARTOP(temp_copy)
638 slotref newSlot = seg.newSlot();
639 if (!newSlot) DIE;
640 int16 *tempUserAttrs = newSlot->userAttrs();
641 memcpy(newSlot, is, sizeof(Slot));
642 memcpy(tempUserAttrs, is->userAttrs(), seg.numAttrs() * sizeof(uint16));
643 newSlot->userAttrs(tempUserAttrs);
644 newSlot->markCopied(true);
645 *map = newSlot;
646 ENDOP

mercurial