Path: blob/master/thirdparty/graphite/src/inc/opcodes.h
9906 views
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later1// Copyright 2010, SIL International, All rights reserved.23#pragma once4// This file will be pulled into and integrated into a machine implmentation5// DO NOT build directly and under no circumstances ever #include headers in6// here or you will break the direct_machine.7//8// Implementers' notes9// ==================10// You have access to a few primitives and the full C++ code:11// declare_params(n) Tells the interpreter how many bytes of parameter12// space to claim for this instruction uses and13// initialises the param pointer. You *must* before the14// first use of param.15// use_params(n) Claim n extra bytes of param space beyond what was16// claimed using delcare_param.17// param A const byte pointer for the parameter space claimed by18// this instruction.19// binop(op) Implement a binary operation on the stack using the20// specified C++ operator.21// NOT_IMPLEMENTED Any instruction body containing this will exit the22// program with an assertion error. Instructions that are23// not implemented should also be marked NILOP in the24// opcodes tables this will cause the code class to spot25// them in a live code stream and throw a runtime_error26// instead.27// push(n) Push the value n onto the stack.28// pop() Pop the top most value and return it.29//30// You have access to the following named fast 'registers':31// sp = The pointer to the current top of stack, the last value32// pushed.33// seg = A reference to the Segment this code is running over.34// is = The current slot index35// isb = The original base slot index at the start of this rule36// isf = The first positioned slot37// isl = The last positioned slot38// ip = The current instruction pointer39// endPos = Position of advance of last cluster40// dir = writing system directionality of the font414243// #define NOT_IMPLEMENTED assert(false)44// #define NOT_IMPLEMENTED4546#define binop(op) const uint32 a = pop(); *sp = uint32(*sp) op a47#define sbinop(op) const int32 a = pop(); *sp = int32(*sp) op a48#define use_params(n) dp += n4950#define declare_params(n) const byte * param = dp; \51use_params(n);5253#define push(n) { *++sp = n; }54#define pop() (*sp--)55#define slotat(x) (map[(x)])56#define DIE { is=seg.last(); status = Machine::died_early; EXIT(1); }57#define POSITIONED 15859STARTOP(nop)60do {} while (0);61ENDOP6263STARTOP(push_byte)64declare_params(1);65push(int8(*param));66ENDOP6768STARTOP(push_byte_u)69declare_params(1);70push(uint8(*param));71ENDOP7273STARTOP(push_short)74declare_params(2);75const int16 r = int16(param[0]) << 876| uint8(param[1]);77push(r);78ENDOP7980STARTOP(push_short_u)81declare_params(2);82const uint16 r = uint16(param[0]) << 883| uint8(param[1]);84push(r);85ENDOP8687STARTOP(push_long)88declare_params(4);89const int32 r = int32(param[0]) << 2490| uint32(param[1]) << 1691| uint32(param[2]) << 892| uint8(param[3]);93push(r);94ENDOP9596STARTOP(add)97binop(+);98ENDOP99100STARTOP(sub)101binop(-);102ENDOP103104STARTOP(mul)105binop(*);106ENDOP107108STARTOP(div_)109const int32 b = pop();110const int32 a = int32(*sp);111if (b == 0 || (a == std::numeric_limits<int32>::min() && b == -1)) DIE;112*sp = int32(*sp) / b;113ENDOP114115STARTOP(min_)116const int32 a = pop(), b = *sp;117if (a < b) *sp = a;118ENDOP119120STARTOP(max_)121const int32 a = pop(), b = *sp;122if (a > b) *sp = a;123ENDOP124125STARTOP(neg)126*sp = uint32(-int32(*sp));127ENDOP128129STARTOP(trunc8)130*sp = uint8(*sp);131ENDOP132133STARTOP(trunc16)134*sp = uint16(*sp);135ENDOP136137STARTOP(cond)138const uint32 f = pop(), t = pop(), c = pop();139push(c ? t : f);140ENDOP141142STARTOP(and_)143binop(&&);144ENDOP145146STARTOP(or_)147binop(||);148ENDOP149150STARTOP(not_)151*sp = !*sp;152ENDOP153154STARTOP(equal)155binop(==);156ENDOP157158STARTOP(not_eq_)159binop(!=);160ENDOP161162STARTOP(less)163sbinop(<);164ENDOP165166STARTOP(gtr)167sbinop(>);168ENDOP169170STARTOP(less_eq)171sbinop(<=);172ENDOP173174STARTOP(gtr_eq)175sbinop(>=);176ENDOP177178STARTOP(next)179if (map - &smap[0] >= int(smap.size())) DIE180if (is)181{182if (is == smap.highwater())183smap.highpassed(true);184is = is->next();185}186++map;187ENDOP188189//STARTOP(next_n)190// use_params(1);191// NOT_IMPLEMENTED;192//declare_params(1);193//const size_t num = uint8(*param);194//ENDOP195196//STARTOP(copy_next)197// if (is) is = is->next();198// ++map;199// ENDOP200201STARTOP(put_glyph_8bit_obs)202declare_params(1);203const unsigned int output_class = uint8(*param);204is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));205ENDOP206207STARTOP(put_subs_8bit_obs)208declare_params(3);209const int slot_ref = int8(param[0]);210const unsigned int input_class = uint8(param[1]),211output_class = uint8(param[2]);212uint16 index;213slotref slot = slotat(slot_ref);214if (slot)215{216index = seg.findClassIndex(input_class, slot->gid());217is->setGlyph(&seg, seg.getClassGlyph(output_class, index));218}219ENDOP220221STARTOP(put_copy)222declare_params(1);223const int slot_ref = int8(*param);224if (is && !is->isDeleted())225{226slotref ref = slotat(slot_ref);227if (ref && ref != is)228{229int16 *tempUserAttrs = is->userAttrs();230if (is->attachedTo() || is->firstChild()) DIE231Slot *prev = is->prev();232Slot *next = is->next();233memcpy(tempUserAttrs, ref->userAttrs(), seg.numAttrs() * sizeof(uint16));234memcpy(is, ref, sizeof(Slot));235is->firstChild(NULL);236is->nextSibling(NULL);237is->userAttrs(tempUserAttrs);238is->next(next);239is->prev(prev);240if (is->attachedTo())241is->attachedTo()->child(is);242}243is->markCopied(false);244is->markDeleted(false);245}246ENDOP247248STARTOP(insert)249if (smap.decMax() <= 0) DIE;250Slot *newSlot = seg.newSlot();251if (!newSlot) DIE;252Slot *iss = is;253while (iss && iss->isDeleted()) iss = iss->next();254if (!iss)255{256if (seg.last())257{258seg.last()->next(newSlot);259newSlot->prev(seg.last());260newSlot->before(seg.last()->before());261seg.last(newSlot);262}263else264{265seg.first(newSlot);266seg.last(newSlot);267}268}269else if (iss->prev())270{271iss->prev()->next(newSlot);272newSlot->prev(iss->prev());273newSlot->before(iss->prev()->after());274}275else276{277newSlot->prev(NULL);278newSlot->before(iss->before());279seg.first(newSlot);280}281newSlot->next(iss);282if (iss)283{284iss->prev(newSlot);285newSlot->originate(iss->original());286newSlot->after(iss->before());287}288else if (newSlot->prev())289{290newSlot->originate(newSlot->prev()->original());291newSlot->after(newSlot->prev()->after());292}293else294{295newSlot->originate(seg.defaultOriginal());296}297if (is == smap.highwater())298smap.highpassed(false);299is = newSlot;300seg.extendLength(1);301if (map != &smap[-1])302--map;303ENDOP304305STARTOP(delete_)306if (!is || is->isDeleted()) DIE307is->markDeleted(true);308if (is->prev())309is->prev()->next(is->next());310else311seg.first(is->next());312313if (is->next())314is->next()->prev(is->prev());315else316seg.last(is->prev());317318319if (is == smap.highwater())320smap.highwater(is->next());321if (is->prev())322is = is->prev();323seg.extendLength(-1);324ENDOP325326STARTOP(assoc)327declare_params(1);328unsigned int num = uint8(*param);329const int8 * assocs = reinterpret_cast<const int8 *>(param+1);330use_params(num);331int max = -1;332int min = -1;333334while (num-- > 0)335{336int sr = *assocs++;337slotref ts = slotat(sr);338if (ts && (min == -1 || ts->before() < min)) min = ts->before();339if (ts && ts->after() > max) max = ts->after();340}341if (min > -1) // implies max > -1342{343is->before(min);344is->after(max);345}346ENDOP347348STARTOP(cntxt_item)349// It turns out this is a cunningly disguised condition forward jump.350declare_params(3);351const int is_arg = int8(param[0]);352const size_t iskip = uint8(param[1]),353dskip = uint8(param[2]);354355if (mapb + is_arg != map)356{357ip += iskip;358dp += dskip;359push(true);360}361ENDOP362363STARTOP(attr_set)364declare_params(1);365const attrCode slat = attrCode(uint8(*param));366const int val = pop();367is->setAttr(&seg, slat, 0, val, smap);368ENDOP369370STARTOP(attr_add)371declare_params(1);372const attrCode slat = attrCode(uint8(*param));373const uint32_t val = pop();374if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)375{376seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());377flags |= POSITIONED;378}379uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));380is->setAttr(&seg, slat, 0, int32_t(val + res), smap);381ENDOP382383STARTOP(attr_sub)384declare_params(1);385const attrCode slat = attrCode(uint8(*param));386const uint32_t val = pop();387if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)388{389seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());390flags |= POSITIONED;391}392uint32_t res = uint32_t(is->getAttr(&seg, slat, 0));393is->setAttr(&seg, slat, 0, int32_t(res - val), smap);394ENDOP395396STARTOP(attr_set_slot)397declare_params(1);398const attrCode slat = attrCode(uint8(*param));399const int offset = int(map - smap.begin())*int(slat == gr_slatAttTo);400const int val = pop() + offset;401is->setAttr(&seg, slat, offset, val, smap);402ENDOP403404STARTOP(iattr_set_slot)405declare_params(2);406const attrCode slat = attrCode(uint8(param[0]));407const uint8 idx = uint8(param[1]);408const int val = int(pop() + (map - smap.begin())*int(slat == gr_slatAttTo));409is->setAttr(&seg, slat, idx, val, smap);410ENDOP411412STARTOP(push_slot_attr)413declare_params(2);414const attrCode slat = attrCode(uint8(param[0]));415const int slot_ref = int8(param[1]);416if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)417{418seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());419flags |= POSITIONED;420}421slotref slot = slotat(slot_ref);422if (slot)423{424int res = slot->getAttr(&seg, slat, 0);425push(res);426}427ENDOP428429STARTOP(push_glyph_attr_obs)430declare_params(2);431const unsigned int glyph_attr = uint8(param[0]);432const int slot_ref = int8(param[1]);433slotref slot = slotat(slot_ref);434if (slot)435push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));436ENDOP437438STARTOP(push_glyph_metric)439declare_params(3);440const unsigned int glyph_attr = uint8(param[0]);441const int slot_ref = int8(param[1]);442const signed int attr_level = uint8(param[2]);443slotref slot = slotat(slot_ref);444if (slot)445push(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir));446ENDOP447448STARTOP(push_feat)449declare_params(2);450const unsigned int feat = uint8(param[0]);451const int slot_ref = int8(param[1]);452slotref slot = slotat(slot_ref);453if (slot)454{455uint8 fid = seg.charinfo(slot->original())->fid();456push(seg.getFeature(fid, feat));457}458ENDOP459460STARTOP(push_att_to_gattr_obs)461declare_params(2);462const unsigned int glyph_attr = uint8(param[0]);463const int slot_ref = int8(param[1]);464slotref slot = slotat(slot_ref);465if (slot)466{467slotref att = slot->attachedTo();468if (att) slot = att;469push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));470}471ENDOP472473STARTOP(push_att_to_glyph_metric)474declare_params(3);475const unsigned int glyph_attr = uint8(param[0]);476const int slot_ref = int8(param[1]);477const signed int attr_level = uint8(param[2]);478slotref slot = slotat(slot_ref);479if (slot)480{481slotref att = slot->attachedTo();482if (att) slot = att;483push(int32(seg.getGlyphMetric(slot, glyph_attr, attr_level, dir)));484}485ENDOP486487STARTOP(push_islot_attr)488declare_params(3);489const attrCode slat = attrCode(uint8(param[0]));490const int slot_ref = int8(param[1]),491idx = uint8(param[2]);492if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)493{494seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());495flags |= POSITIONED;496}497slotref slot = slotat(slot_ref);498if (slot)499{500int res = slot->getAttr(&seg, slat, idx);501push(res);502}503ENDOP504505#if 0506STARTOP(push_iglyph_attr) // not implemented507NOT_IMPLEMENTED;508ENDOP509#endif510511STARTOP(pop_ret)512const uint32 ret = pop();513EXIT(ret);514ENDOP515516STARTOP(ret_zero)517EXIT(0);518ENDOP519520STARTOP(ret_true)521EXIT(1);522ENDOP523524STARTOP(iattr_set)525declare_params(2);526const attrCode slat = attrCode(uint8(param[0]));527const uint8 idx = uint8(param[1]);528const int val = pop();529is->setAttr(&seg, slat, idx, val, smap);530ENDOP531532STARTOP(iattr_add)533declare_params(2);534const attrCode slat = attrCode(uint8(param[0]));535const uint8 idx = uint8(param[1]);536const uint32_t val = pop();537if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)538{539seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());540flags |= POSITIONED;541}542uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));543is->setAttr(&seg, slat, idx, int32_t(val + res), smap);544ENDOP545546STARTOP(iattr_sub)547declare_params(2);548const attrCode slat = attrCode(uint8(param[0]));549const uint8 idx = uint8(param[1]);550const uint32_t val = pop();551if ((slat == gr_slatPosX || slat == gr_slatPosY) && (flags & POSITIONED) == 0)552{553seg.positionSlots(0, *smap.begin(), *(smap.end()-1), seg.currdir());554flags |= POSITIONED;555}556uint32_t res = uint32_t(is->getAttr(&seg, slat, idx));557is->setAttr(&seg, slat, idx, int32_t(res - val), smap);558ENDOP559560STARTOP(push_proc_state)561use_params(1);562push(1);563ENDOP564565STARTOP(push_version)566push(0x00030000);567ENDOP568569STARTOP(put_subs)570declare_params(5);571const int slot_ref = int8(param[0]);572const unsigned int input_class = uint8(param[1]) << 8573| uint8(param[2]);574const unsigned int output_class = uint8(param[3]) << 8575| uint8(param[4]);576slotref slot = slotat(slot_ref);577if (slot)578{579int index = seg.findClassIndex(input_class, slot->gid());580is->setGlyph(&seg, seg.getClassGlyph(output_class, index));581}582ENDOP583584#if 0585STARTOP(put_subs2) // not implemented586NOT_IMPLEMENTED;587ENDOP588589STARTOP(put_subs3) // not implemented590NOT_IMPLEMENTED;591ENDOP592#endif593594STARTOP(put_glyph)595declare_params(2);596const unsigned int output_class = uint8(param[0]) << 8597| uint8(param[1]);598is->setGlyph(&seg, seg.getClassGlyph(output_class, 0));599ENDOP600601STARTOP(push_glyph_attr)602declare_params(3);603const unsigned int glyph_attr = uint8(param[0]) << 8604| uint8(param[1]);605const int slot_ref = int8(param[2]);606slotref slot = slotat(slot_ref);607if (slot)608push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));609ENDOP610611STARTOP(push_att_to_glyph_attr)612declare_params(3);613const unsigned int glyph_attr = uint8(param[0]) << 8614| uint8(param[1]);615const int slot_ref = int8(param[2]);616slotref slot = slotat(slot_ref);617if (slot)618{619slotref att = slot->attachedTo();620if (att) slot = att;621push(int32(seg.glyphAttr(slot->gid(), glyph_attr)));622}623ENDOP624625STARTOP(temp_copy)626slotref newSlot = seg.newSlot();627if (!newSlot || !is) DIE;628int16 *tempUserAttrs = newSlot->userAttrs();629memcpy(newSlot, is, sizeof(Slot));630memcpy(tempUserAttrs, is->userAttrs(), seg.numAttrs() * sizeof(uint16));631newSlot->userAttrs(tempUserAttrs);632newSlot->markCopied(true);633*map = newSlot;634ENDOP635636STARTOP(band)637binop(&);638ENDOP639640STARTOP(bor)641binop(|);642ENDOP643644STARTOP(bnot)645*sp = ~*sp;646ENDOP647648STARTOP(setbits)649declare_params(4);650const uint16 m = uint16(param[0]) << 8651| uint8(param[1]);652const uint16 v = uint16(param[2]) << 8653| uint8(param[3]);654*sp = ((*sp) & ~m) | v;655ENDOP656657STARTOP(set_feat)658declare_params(2);659const unsigned int feat = uint8(param[0]);660const int slot_ref = int8(param[1]);661slotref slot = slotat(slot_ref);662if (slot)663{664uint8 fid = seg.charinfo(slot->original())->fid();665seg.setFeature(fid, feat, pop());666}667ENDOP668669670