Line data Source code
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 : // dir = writing system directionality of the font
65 :
66 :
67 : // #define NOT_IMPLEMENTED assert(false)
68 : #define NOT_IMPLEMENTED
69 :
70 : #define binop(op) const uint32 a = pop(); *sp = uint32(*sp) op a
71 : #define sbinop(op) const int32 a = pop(); *sp = int32(*sp) op a
72 : #define use_params(n) dp += n
73 :
74 : #define declare_params(n) const byte * param = dp; \
75 : use_params(n);
76 :
77 : #define push(n) { *++sp = n; }
78 : #define pop() (*sp--)
79 : #define slotat(x) (map[(x)])
80 : #define DIE { is=seg.last(); status = Machine::died_early; EXIT(1); }
81 : #define POSITIONED 1
82 :
83 : STARTOP(nop)
84 : do {} while (0);
85 0 : ENDOP
86 :
87 : STARTOP(push_byte)
88 0 : declare_params(1);
89 0 : push(int8(*param));
90 0 : ENDOP
91 :
92 : STARTOP(push_byte_u)
93 0 : declare_params(1);
94 0 : push(uint8(*param));
95 0 : ENDOP
96 :
97 : STARTOP(push_short)
98 0 : declare_params(2);
99 0 : const int16 r = int16(param[0]) << 8
100 0 : | uint8(param[1]);
101 0 : push(r);
102 0 : ENDOP
103 :
104 : STARTOP(push_short_u)
105 0 : declare_params(2);
106 0 : const uint16 r = uint16(param[0]) << 8
107 0 : | uint8(param[1]);
108 0 : push(r);
109 0 : ENDOP
110 :
111 : STARTOP(push_long)
112 0 : declare_params(4);
113 0 : const int32 r = int32(param[0]) << 24
114 0 : | uint32(param[1]) << 16
115 0 : | uint32(param[2]) << 8
116 0 : | uint8(param[3]);
117 0 : push(r);
118 0 : ENDOP
119 :
120 : STARTOP(add)
121 0 : binop(+);
122 0 : ENDOP
123 :
124 : STARTOP(sub)
125 0 : binop(-);
126 0 : ENDOP
127 :
128 : STARTOP(mul)
129 0 : binop(*);
130 0 : ENDOP
131 :
132 : STARTOP(div_)
133 0 : if (*sp == 0) DIE;
134 0 : sbinop(/);
135 0 : ENDOP
136 :
137 : STARTOP(min_)
138 0 : const int32 a = pop(), b = *sp;
139 0 : if (a < b) *sp = a;
140 0 : ENDOP
141 :
142 : STARTOP(max_)
143 0 : const int32 a = pop(), b = *sp;
144 0 : if (a > b) *sp = a;
145 0 : ENDOP
146 :
147 : STARTOP(neg)
148 0 : *sp = uint32(-int32(*sp));
149 0 : ENDOP
150 :
151 : STARTOP(trunc8)
152 0 : *sp = uint8(*sp);
153 0 : ENDOP
154 :
155 : STARTOP(trunc16)
156 0 : *sp = uint16(*sp);
157 0 : ENDOP
158 :
159 : STARTOP(cond)
160 0 : const uint32 f = pop(), t = pop(), c = pop();
161 0 : push(c ? t : f);
162 0 : ENDOP
163 :
164 : STARTOP(and_)
165 0 : binop(&&);
166 0 : ENDOP
167 :
168 : STARTOP(or_)
169 0 : binop(||);
170 0 : ENDOP
171 :
172 : STARTOP(not_)
173 0 : *sp = !*sp;
174 0 : ENDOP
175 :
176 : STARTOP(equal)
177 0 : binop(==);
178 0 : ENDOP
179 :
180 : STARTOP(not_eq_)
181 0 : binop(!=);
182 0 : ENDOP
183 :
184 : STARTOP(less)
185 0 : sbinop(<);
186 0 : ENDOP
187 :
188 : STARTOP(gtr)
189 0 : sbinop(>);
190 0 : ENDOP
191 :
192 : STARTOP(less_eq)
193 0 : sbinop(<=);
194 0 : ENDOP
195 :
196 : STARTOP(gtr_eq)
197 0 : sbinop(>=);
198 0 : ENDOP
199 :
200 : STARTOP(next)
201 0 : if (map - &smap[0] >= int(smap.size())) DIE
202 0 : if (is)
203 : {
204 0 : if (is == smap.highwater())
205 0 : smap.highpassed(true);
206 0 : is = is->next();
207 : }
208 0 : ++map;
209 0 : ENDOP
210 :
211 : STARTOP(next_n)
212 0 : use_params(1);
213 : NOT_IMPLEMENTED;
214 : //declare_params(1);
215 : //const size_t num = uint8(*param);
216 0 : ENDOP
217 :
218 : //STARTOP(copy_next)
219 : // if (is) is = is->next();
220 : // ++map;
221 : // ENDOP
222 :
223 : STARTOP(put_glyph_8bit_obs)
224 0 : declare_params(1);
225 0 : const unsigned int output_class = uint8(*param);
226 0 : is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
227 0 : ENDOP
228 :
229 : STARTOP(put_subs_8bit_obs)
230 0 : declare_params(3);
231 0 : const int slot_ref = int8(param[0]);
232 0 : const unsigned int input_class = uint8(param[1]),
233 0 : output_class = uint8(param[2]);
234 : uint16 index;
235 0 : slotref slot = slotat(slot_ref);
236 0 : if (slot)
237 : {
238 0 : index = seg.findClassIndex(input_class, slot->gid());
239 0 : is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
240 : }
241 0 : ENDOP
242 :
243 : STARTOP(put_copy)
244 0 : declare_params(1);
245 0 : const int slot_ref = int8(*param);
246 0 : if (is && !is->isDeleted())
247 : {
248 0 : slotref ref = slotat(slot_ref);
249 0 : if (ref && ref != is)
250 : {
251 0 : int16 *tempUserAttrs = is->userAttrs();
252 0 : if (is->attachedTo() || is->firstChild()) DIE
253 0 : Slot *prev = is->prev();
254 0 : Slot *next = is->next();
255 0 : memcpy(tempUserAttrs, ref->userAttrs(), seg.numAttrs() * sizeof(uint16));
256 0 : memcpy(is, ref, sizeof(Slot));
257 0 : is->firstChild(NULL);
258 0 : is->nextSibling(NULL);
259 0 : is->userAttrs(tempUserAttrs);
260 0 : is->next(next);
261 0 : is->prev(prev);
262 0 : if (is->attachedTo())
263 0 : is->attachedTo()->child(is);
264 : }
265 0 : is->markCopied(false);
266 0 : is->markDeleted(false);
267 : }
268 0 : ENDOP
269 :
270 : STARTOP(insert)
271 0 : if (smap.decMax() <= 0) DIE;
272 0 : Slot *newSlot = seg.newSlot();
273 0 : if (!newSlot) DIE;
274 0 : Slot *iss = is;
275 0 : while (iss && iss->isDeleted()) iss = iss->next();
276 0 : if (!iss)
277 : {
278 0 : if (seg.last())
279 : {
280 0 : seg.last()->next(newSlot);
281 0 : newSlot->prev(seg.last());
282 0 : newSlot->before(seg.last()->before());
283 0 : seg.last(newSlot);
284 : }
285 : else
286 : {
287 0 : seg.first(newSlot);
288 0 : seg.last(newSlot);
289 : }
290 : }
291 0 : else if (iss->prev())
292 : {
293 0 : iss->prev()->next(newSlot);
294 0 : newSlot->prev(iss->prev());
295 0 : newSlot->before(iss->prev()->after());
296 : }
297 : else
298 : {
299 0 : newSlot->prev(NULL);
300 0 : newSlot->before(iss->before());
301 0 : seg.first(newSlot);
302 : }
303 0 : newSlot->next(iss);
304 0 : if (iss)
305 : {
306 0 : iss->prev(newSlot);
307 0 : newSlot->originate(iss->original());
308 0 : newSlot->after(iss->before());
309 : }
310 0 : else if (newSlot->prev())
311 : {
312 0 : newSlot->originate(newSlot->prev()->original());
313 0 : newSlot->after(newSlot->prev()->after());
314 : }
315 : else
316 : {
317 0 : newSlot->originate(seg.defaultOriginal());
318 : }
319 0 : if (is == smap.highwater())
320 0 : smap.highpassed(false);
321 0 : is = newSlot;
322 0 : seg.extendLength(1);
323 0 : if (map != &smap[-1])
324 0 : --map;
325 0 : ENDOP
326 :
327 : STARTOP(delete_)
328 0 : if (!is || is->isDeleted()) DIE
329 0 : is->markDeleted(true);
330 0 : if (is->prev())
331 0 : is->prev()->next(is->next());
332 : else
333 0 : seg.first(is->next());
334 :
335 0 : if (is->next())
336 0 : is->next()->prev(is->prev());
337 : else
338 0 : seg.last(is->prev());
339 :
340 0 : if (is == smap.highwater())
341 0 : smap.highwater(is->next());
342 0 : if (is->prev())
343 0 : is = is->prev();
344 0 : seg.extendLength(-1);
345 0 : ENDOP
346 :
347 : STARTOP(assoc)
348 0 : declare_params(1);
349 0 : unsigned int num = uint8(*param);
350 0 : const int8 * assocs = reinterpret_cast<const int8 *>(param+1);
351 0 : use_params(num);
352 0 : int max = -1;
353 0 : int min = -1;
354 :
355 0 : while (num-- > 0)
356 : {
357 0 : int sr = *assocs++;
358 0 : slotref ts = slotat(sr);
359 0 : if (ts && (min == -1 || ts->before() < min)) min = ts->before();
360 0 : if (ts && ts->after() > max) max = ts->after();
361 : }
362 0 : if (min > -1) // implies max > -1
363 : {
364 0 : is->before(min);
365 0 : is->after(max);
366 : }
367 0 : ENDOP
368 :
369 : STARTOP(cntxt_item)
370 : // It turns out this is a cunningly disguised condition forward jump.
371 0 : declare_params(3);
372 0 : const int is_arg = int8(param[0]);
373 0 : const size_t iskip = uint8(param[1]),
374 0 : dskip = uint8(param[2]);
375 :
376 0 : if (mapb + is_arg != map)
377 : {
378 0 : ip += iskip;
379 0 : dp += dskip;
380 0 : push(true);
381 : }
382 0 : ENDOP
383 :
384 : STARTOP(attr_set)
385 0 : declare_params(1);
386 0 : const attrCode slat = attrCode(uint8(*param));
387 0 : const int val = int(pop());
388 0 : is->setAttr(&seg, slat, 0, val, smap);
389 0 : ENDOP
390 :
391 : STARTOP(attr_add)
392 0 : declare_params(1);
393 0 : const attrCode slat = attrCode(uint8(*param));
394 0 : const int val = int(pop());
395 0 : if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
396 : {
397 0 : seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
398 0 : flags |= POSITIONED;
399 : }
400 0 : int res = is->getAttr(&seg, slat, 0);
401 0 : is->setAttr(&seg, slat, 0, val + res, smap);
402 0 : ENDOP
403 :
404 : STARTOP(attr_sub)
405 0 : declare_params(1);
406 0 : const attrCode slat = attrCode(uint8(*param));
407 0 : const int val = int(pop());
408 0 : if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
409 : {
410 0 : seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
411 0 : flags |= POSITIONED;
412 : }
413 0 : int res = is->getAttr(&seg, slat, 0);
414 0 : is->setAttr(&seg, slat, 0, res - val, smap);
415 0 : ENDOP
416 :
417 : STARTOP(attr_set_slot)
418 0 : declare_params(1);
419 0 : const attrCode slat = attrCode(uint8(*param));
420 0 : const int offset = (map - smap.begin())*int(slat == gr_slatAttTo);
421 0 : const int val = int(pop()) + offset;
422 0 : is->setAttr(&seg, slat, offset, val, smap);
423 0 : ENDOP
424 :
425 : STARTOP(iattr_set_slot)
426 0 : declare_params(2);
427 0 : const attrCode slat = attrCode(uint8(param[0]));
428 0 : const size_t idx = uint8(param[1]);
429 0 : const int val = int(pop()) + (map - smap.begin())*int(slat == gr_slatAttTo);
430 0 : is->setAttr(&seg, slat, idx, val, smap);
431 0 : ENDOP
432 :
433 : STARTOP(push_slot_attr)
434 0 : declare_params(2);
435 0 : const attrCode slat = attrCode(uint8(param[0]));
436 0 : const int slot_ref = int8(param[1]);
437 0 : if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
438 : {
439 0 : seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
440 0 : flags |= POSITIONED;
441 : }
442 0 : slotref slot = slotat(slot_ref);
443 0 : if (slot)
444 : {
445 0 : int res = slot->getAttr(&seg, slat, 0);
446 0 : push(res);
447 : }
448 0 : ENDOP
449 :
450 : STARTOP(push_glyph_attr_obs)
451 0 : declare_params(2);
452 0 : const unsigned int glyph_attr = uint8(param[0]);
453 0 : const int slot_ref = int8(param[1]);
454 0 : slotref slot = slotat(slot_ref);
455 0 : if (slot)
456 0 : push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
457 0 : ENDOP
458 :
459 : STARTOP(push_glyph_metric)
460 0 : declare_params(3);
461 0 : const unsigned int glyph_attr = uint8(param[0]);
462 0 : const int slot_ref = int8(param[1]);
463 0 : const signed int attr_level = uint8(param[2]);
464 0 : slotref slot = slotat(slot_ref);
465 0 : if (slot)
466 0 : push(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir));
467 0 : ENDOP
468 :
469 : STARTOP(push_feat)
470 0 : declare_params(2);
471 0 : const unsigned int feat = uint8(param[0]);
472 0 : const int slot_ref = int8(param[1]);
473 0 : slotref slot = slotat(slot_ref);
474 0 : if (slot)
475 : {
476 0 : uint8 fid = seg.charinfo(slot->original())->fid();
477 0 : push(seg.getFeature(fid, feat));
478 : }
479 0 : ENDOP
480 :
481 : STARTOP(push_att_to_gattr_obs)
482 0 : declare_params(2);
483 0 : const unsigned int glyph_attr = uint8(param[0]);
484 0 : const int slot_ref = int8(param[1]);
485 0 : slotref slot = slotat(slot_ref);
486 0 : if (slot)
487 : {
488 0 : slotref att = slot->attachedTo();
489 0 : if (att) slot = att;
490 0 : push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
491 : }
492 0 : ENDOP
493 :
494 : STARTOP(push_att_to_glyph_metric)
495 0 : declare_params(3);
496 0 : const unsigned int glyph_attr = uint8(param[0]);
497 0 : const int slot_ref = int8(param[1]);
498 0 : const signed int attr_level = uint8(param[2]);
499 0 : slotref slot = slotat(slot_ref);
500 0 : if (slot)
501 : {
502 0 : slotref att = slot->attachedTo();
503 0 : if (att) slot = att;
504 0 : push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir)));
505 : }
506 0 : ENDOP
507 :
508 : STARTOP(push_islot_attr)
509 0 : declare_params(3);
510 0 : const attrCode slat = attrCode(uint8(param[0]));
511 0 : const int slot_ref = int8(param[1]),
512 0 : idx = uint8(param[2]);
513 0 : if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
514 : {
515 0 : seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
516 0 : flags |= POSITIONED;
517 : }
518 0 : slotref slot = slotat(slot_ref);
519 0 : if (slot)
520 : {
521 0 : int res = slot->getAttr(&seg, slat, idx);
522 0 : push(res);
523 : }
524 0 : ENDOP
525 :
526 : #if 0
527 : STARTOP(push_iglyph_attr) // not implemented
528 : NOT_IMPLEMENTED;
529 : ENDOP
530 : #endif
531 :
532 : STARTOP(pop_ret)
533 0 : const uint32 ret = pop();
534 0 : EXIT(ret);
535 : ENDOP
536 :
537 : STARTOP(ret_zero)
538 0 : EXIT(0);
539 : ENDOP
540 :
541 : STARTOP(ret_true)
542 0 : EXIT(1);
543 : ENDOP
544 :
545 : STARTOP(iattr_set)
546 0 : declare_params(2);
547 0 : const attrCode slat = attrCode(uint8(param[0]));
548 0 : const size_t idx = uint8(param[1]);
549 0 : const int val = int(pop());
550 0 : is->setAttr(&seg, slat, idx, val, smap);
551 0 : ENDOP
552 :
553 : STARTOP(iattr_add)
554 0 : declare_params(2);
555 0 : const attrCode slat = attrCode(uint8(param[0]));
556 0 : const size_t idx = uint8(param[1]);
557 0 : const int val = int(pop());
558 0 : if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
559 : {
560 0 : seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
561 0 : flags |= POSITIONED;
562 : }
563 0 : int res = is->getAttr(&seg, slat, idx);
564 0 : is->setAttr(&seg, slat, idx, val + res, smap);
565 0 : ENDOP
566 :
567 : STARTOP(iattr_sub)
568 0 : declare_params(2);
569 0 : const attrCode slat = attrCode(uint8(param[0]));
570 0 : const size_t idx = uint8(param[1]);
571 0 : const int val = int(pop());
572 0 : if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)
573 : {
574 0 : seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());
575 0 : flags |= POSITIONED;
576 : }
577 0 : int res = is->getAttr(&seg, slat, idx);
578 0 : is->setAttr(&seg, slat, idx, res - val, smap);
579 0 : ENDOP
580 :
581 : STARTOP(push_proc_state)
582 0 : use_params(1);
583 0 : push(1);
584 0 : ENDOP
585 :
586 : STARTOP(push_version)
587 0 : push(0x00030000);
588 0 : ENDOP
589 :
590 : STARTOP(put_subs)
591 0 : declare_params(5);
592 0 : const int slot_ref = int8(param[0]);
593 0 : const unsigned int input_class = uint8(param[1]) << 8
594 0 : | uint8(param[2]);
595 0 : const unsigned int output_class = uint8(param[3]) << 8
596 0 : | uint8(param[4]);
597 0 : slotref slot = slotat(slot_ref);
598 0 : if (slot)
599 : {
600 0 : int index = seg.findClassIndex(input_class, slot->gid());
601 0 : is->setGlyph(&seg, seg.getClassGlyph(output_class, index));
602 : }
603 0 : ENDOP
604 :
605 : #if 0
606 : STARTOP(put_subs2) // not implemented
607 : NOT_IMPLEMENTED;
608 : ENDOP
609 :
610 : STARTOP(put_subs3) // not implemented
611 : NOT_IMPLEMENTED;
612 : ENDOP
613 : #endif
614 :
615 : STARTOP(put_glyph)
616 0 : declare_params(2);
617 0 : const unsigned int output_class = uint8(param[0]) << 8
618 0 : | uint8(param[1]);
619 0 : is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));
620 0 : ENDOP
621 :
622 : STARTOP(push_glyph_attr)
623 0 : declare_params(3);
624 0 : const unsigned int glyph_attr = uint8(param[0]) << 8
625 0 : | uint8(param[1]);
626 0 : const int slot_ref = int8(param[2]);
627 0 : slotref slot = slotat(slot_ref);
628 0 : if (slot)
629 0 : push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
630 0 : ENDOP
631 :
632 : STARTOP(push_att_to_glyph_attr)
633 0 : declare_params(3);
634 0 : const unsigned int glyph_attr = uint8(param[0]) << 8
635 0 : | uint8(param[1]);
636 0 : const int slot_ref = int8(param[2]);
637 0 : slotref slot = slotat(slot_ref);
638 0 : if (slot)
639 : {
640 0 : slotref att = slot->attachedTo();
641 0 : if (att) slot = att;
642 0 : push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));
643 : }
644 0 : ENDOP
645 :
646 : STARTOP(temp_copy)
647 0 : slotref newSlot = seg.newSlot();
648 0 : if (!newSlot || !is) DIE;
649 0 : int16 *tempUserAttrs = newSlot->userAttrs();
650 0 : memcpy(newSlot, is, sizeof(Slot));
651 0 : memcpy(tempUserAttrs, is->userAttrs(), seg.numAttrs() * sizeof(uint16));
652 0 : newSlot->userAttrs(tempUserAttrs);
653 0 : newSlot->markCopied(true);
654 0 : *map = newSlot;
655 0 : ENDOP
656 :
657 : STARTOP(band)
658 0 : binop(&);
659 0 : ENDOP
660 :
661 : STARTOP(bor)
662 0 : binop(|);
663 0 : ENDOP
664 :
665 : STARTOP(bnot)
666 0 : *sp = ~*sp;
667 0 : ENDOP
668 :
669 : STARTOP(setbits)
670 0 : declare_params(4);
671 0 : const uint16 m = uint16(param[0]) << 8
672 0 : | uint8(param[1]);
673 0 : const uint16 v = uint16(param[2]) << 8
674 0 : | uint8(param[3]);
675 0 : *sp = ((*sp) & ~m) | v;
676 0 : ENDOP
677 :
678 : STARTOP(set_feat)
679 0 : declare_params(2);
680 0 : const unsigned int feat = uint8(param[0]);
681 0 : const int slot_ref = int8(param[1]);
682 0 : slotref slot = slotat(slot_ref);
683 0 : if (slot)
684 : {
685 0 : uint8 fid = seg.charinfo(slot->original())->fid();
686 0 : seg.setFeature(fid, feat, pop());
687 : }
688 0 : ENDOP
689 :
|