Files
MP-SPDZ/Processor/Instruction.h
2025-05-30 13:35:02 +10:00

431 lines
9.1 KiB
C++

#ifndef _Instruction
#define _Instruction
/* Class to read and decode an instruction
*/
#include <iostream>
#include <fstream>
#include <vector>
using namespace std;
#include "Math/bigint.h"
template<class sint, class sgf2n> class Machine;
template<class sint, class sgf2n> class Processor;
template<class T> class SubProcessor;
template<class T> class MemoryPart;
template<class T> class StackedVector;
class ArithmeticProcessor;
class SwitchableOutput;
/*
* Opcode constants
*
* Whenever these are changed the corresponding dict in Compiler/instructions_base.py
* MUST also be changed. (+ the documentation)
*/
enum
{
CISC = 0,
// Load/store
LDI = 0x1,
LDSI = 0x2,
LDMC = 0x3,
LDMS = 0x4,
STMC = 0x5,
STMS = 0x6,
LDMCI = 0x7,
LDMSI = 0x8,
STMCI = 0x9,
STMSI = 0xA,
MOVC = 0xB,
MOVS = 0xC,
PROTECTMEMS = 0xD,
PROTECTMEMC = 0xE,
PROTECTMEMINT = 0xF,
LDMINT = 0xCA,
STMINT = 0xCB,
LDMINTI = 0xCC,
STMINTI = 0xCD,
PUSHINT = 0xCE,
POPINT = 0xCF,
MOVINT = 0xD0,
// Machine
LDTN = 0x10,
LDARG = 0x11,
REQBL = 0x12,
STARG = 0x13,
TIME = 0x14,
START = 0x15,
STOP = 0x16,
USE = 0x17,
USE_INP = 0x18,
RUN_TAPE = 0x19,
JOIN_TAPE = 0x1A,
CRASH = 0x1B,
USE_PREP = 0x1C,
STARTGRIND = 0x1D,
STOPGRIND = 0x1E,
NPLAYERS = 0xE2,
THRESHOLD = 0xE3,
PLAYERID = 0xE4,
USE_EDABIT = 0xE5,
USE_MATMUL = 0x1F,
ACTIVE = 0xE9,
CMDLINEARG = 0xEB,
CALL_TAPE = 0xEC,
CALL_ARG = 0xED,
// Addition
ADDC = 0x20,
ADDS = 0x21,
ADDM = 0x22,
ADDCI = 0x23,
ADDSI = 0x24,
SUBC = 0x25,
SUBS = 0x26,
SUBML = 0x27,
SUBMR = 0x28,
SUBCI = 0x29,
SUBSI = 0x2A,
SUBCFI = 0x2B,
SUBSFI = 0x2C,
PREFIXSUMS = 0x2D,
PICKS = 0x2E,
CONCATS = 0x2F,
ZIPS = 0x3F,
// Multiplication/division/other arithmetic
MULC = 0x30,
MULM = 0x31,
MULCI = 0x32,
MULSI = 0x33,
DIVC = 0x34,
DIVCI = 0x35,
MODC = 0x36,
MODCI = 0x37,
LEGENDREC = 0x38,
DIGESTC = 0x39,
INV2M = 0x3a,
FLOORDIVC = 0x3b,
// Open
OPEN = 0xA5,
MULS = 0xA6,
MULRS = 0xA7,
DOTPRODS = 0xA8,
TRUNC_PR = 0xA9,
MATMULS = 0xAA,
MATMULSM = 0xAB,
CONV2DS = 0xAC,
CHECK = 0xAF,
PRIVATEOUTPUT = 0xAD,
// Shuffling
SECSHUFFLE = 0xFA,
GENSECSHUFFLE = 0xFB,
APPLYSHUFFLE = 0xFC,
DELSHUFFLE = 0xFD,
INVPERM = 0xFE,
// Data access
TRIPLE = 0x50,
BIT = 0x51,
SQUARE = 0x52,
INV = 0x53,
INPUTMASK = 0x56,
INPUTMASKREG = 0x5C,
PREP = 0x57,
DABIT = 0x58,
EDABIT = 0x59,
SEDABIT = 0x5A,
RANDOMS = 0x5B,
RANDOMFULLS = 0x5D,
UNSPLIT = 0x5E,
// Input
INPUT = 0x60,
INPUTFIX = 0xF0,
INPUTFLOAT = 0xF1,
INPUTMIXED = 0xF2,
INPUTMIXEDREG = 0xF3,
RAWINPUT = 0xF4,
INPUTPERSONAL = 0xF5,
SENDPERSONAL = 0xF6,
STARTINPUT = 0x61,
STOPINPUT = 0x62,
READSOCKETC = 0x63,
READSOCKETS = 0x64,
WRITESOCKETC = 0x65,
WRITESOCKETS = 0x66,
READSOCKETINT = 0x69,
WRITESOCKETINT = 0x6a,
WRITESOCKETSHARE = 0x6b,
LISTEN = 0x6c,
ACCEPTCLIENTCONNECTION = 0x6d,
CLOSECLIENTCONNECTION = 0x6e,
INITCLIENTCONNECTION = 0x6f,
// Bitwise logic
ANDC = 0x70,
XORC = 0x71,
ORC = 0x72,
ANDCI = 0x73,
XORCI = 0x74,
ORCI = 0x75,
NOTC = 0x76,
// Bitwise shifts
SHLC = 0x80,
SHRC = 0x81,
SHLCI = 0x82,
SHRCI = 0x83,
SHRSI = 0x84,
// Branching and comparison
JMP = 0x90,
JMPNZ = 0x91,
JMPEQZ = 0x92,
EQZC = 0x93,
LTZC = 0x94,
LTC = 0x95,
GTC = 0x96,
EQC = 0x97,
JMPI = 0x98,
// Integers
BITDECINT = 0x99,
LDINT = 0x9A,
ADDINT = 0x9B,
SUBINT = 0x9C,
MULINT = 0x9D,
DIVINT = 0x9E,
PRINTINT = 0x9F,
INCINT = 0xD1,
SHUFFLE = 0xD2,
// Conversion
CONVINT = 0xC0,
CONVMODP = 0xC1,
// IO
PRINTMEM = 0xB0,
PRINTREG = 0XB1,
RAND = 0xB2,
PRINTREGPLAIN = 0xB3,
PRINTREGPLAINS = 0xEA,
PRINTCHR = 0xB4,
PRINTSTR = 0xB5,
PUBINPUT = 0xB6,
RAWOUTPUT = 0xB7,
STARTPRIVATEOUTPUT = 0xB8,
STOPPRIVATEOUTPUT = 0xB9,
PRINTCHRINT = 0xBA,
PRINTSTRINT = 0xBB,
PRINTFLOATPLAIN = 0xBC,
WRITEFILESHARE = 0xBD,
READFILESHARE = 0xBE,
CONDPRINTSTR = 0xBF,
PRINTFLOATPREC = 0xE0,
CONDPRINTPLAIN = 0xE1,
INTOUTPUT = 0xE6,
FLOATOUTPUT = 0xE7,
FIXINPUT = 0xE8,
// GF(2^n) versions
// Load/store
GLDI = 0x101,
GLDSI = 0x102,
GLDMC = 0x103,
GLDMS = 0x104,
GSTMC = 0x105,
GSTMS = 0x106,
GLDMCI = 0x107,
GLDMSI = 0x108,
GSTMCI = 0x109,
GSTMSI = 0x10A,
GMOVC = 0x10B,
GMOVS = 0x10C,
GPROTECTMEMS = 0x10D,
GPROTECTMEMC = 0x10E,
// Machine
GREQBL = 0x112,
GUSE_PREP = 0x11C,
// Addition
GADDC = 0x120,
GADDS = 0x121,
GADDM = 0x122,
GADDCI = 0x123,
GADDSI = 0x124,
GSUBC = 0x125,
GSUBS = 0x126,
GSUBML = 0x127,
GSUBMR = 0x128,
GSUBCI = 0x129,
GSUBSI = 0x12A,
GSUBCFI = 0x12B,
GSUBSFI = 0x12C,
// Multiplication/division
GMULC = 0x130,
GMULM = 0x131,
GMULCI = 0x132,
GMULSI = 0x133,
GDIVC = 0x134,
GDIVCI = 0x135,
GMULBITC = 0x136,
GMULBITM = 0x137,
// Open
GOPEN = 0x1A5,
GMULS = 0x1A6,
GMULRS = 0x1A7,
GDOTPRODS = 0x1A8,
GMATMULS = 0x1AA,
GMATMULSM = 0x1AB,
GSECSHUFFLE = 0x1FA,
// Data access
GTRIPLE = 0x150,
GBIT = 0x151,
GSQUARE = 0x152,
GINV = 0x153,
GBITTRIPLE = 0x154,
GBITGF2NTRIPLE = 0x155,
GINPUTMASK = 0x156,
GPREP = 0x157,
// Input
GINPUT = 0x160,
GSTARTINPUT = 0x161,
GSTOPINPUT = 0x162,
GREADSOCKETS = 0x164,
GWRITESOCKETS = 0x166,
GRAWINPUT = 0x1F4,
// Bitwise logic
GANDC = 0x170,
GXORC = 0x171,
GORC = 0x172,
GANDCI = 0x173,
GXORCI = 0x174,
GORCI = 0x175,
GNOTC = 0x176,
// Bitwise shifts
GSHLCI = 0x182,
GSHRCI = 0x183,
GSHRSI = 0x184,
GBITDEC = 0x18A,
GBITCOM = 0x18B,
// Conversion
GCONVINT = 0x1C0,
GCONVGF2N = 0x1C1,
// IO
GPRINTMEM = 0x1B0,
GPRINTREG = 0X1B1,
GPRINTREGPLAIN = 0x1B3,
GPRINTREGPLAINS = 0x1EA,
GRAWOUTPUT = 0x1B7,
GSTARTPRIVATEOUTPUT = 0x1B8,
GSTOPPRIVATEOUTPUT = 0x1B9,
GWRITEFILESHARE = 0x1BD,
GREADFILESHARE = 0x1BE,
// Commsec ops
INITSECURESOCKET = 0x1BA,
RESPSECURESOCKET = 0x1BB
};
// Register types
enum RegType {
INT,
SBIT,
CBIT,
DYN_SBIT,
SINT,
CINT,
SGF2N,
CGF2N,
NONE,
MAX_REG_TYPE,
};
template<class sint, class sgf2n>
struct TempVars {
typename sgf2n::clear ans2;
typename sint::clear ansp;
sint Sansp;
bigint aa,aa2;
typename sint::open_type rrp, xip;
};
class BaseInstruction
{
friend class Program;
template<class T> friend class RepRingOnlyEdabitPrep;
protected:
int opcode; // The code
int size; // Vector size
int r[4]; // Fixed parameter registers
size_t n; // Possible immediate value
vector<int> start; // Values for a start/stop open
string str;
void bytecode_assert(bool condition) const;
public:
BaseInstruction() : opcode(0), size(0), n(0) {}
virtual ~BaseInstruction() {};
int get_r(int i) const { return r[i]; }
size_t get_n() const { return n; }
const vector<int>& get_start() const { return start; }
int get_opcode() const { return opcode; }
int get_size() const { return size; }
// Reads a single instruction from the istream
void parse(istream& s, int inst_pos);
void parse_operands(istream& s, int pos, int file_pos);
bool is_gf2n_instruction() const { return ((opcode&0x100)!=0); }
virtual int get_reg_type() const;
bool is_direct_memory_access() const;
// Returns the memory size used if applicable and known
size_t get_mem(RegType reg_type) const;
// Returns the maximal register used
unsigned get_max_reg(int reg_type) const;
string get_name() const;
};
class DataPositions;
class Instruction : public BaseInstruction
{
public:
// Return whether usage is known
bool get_offline_data_usage(DataPositions& usage);
friend ostream& operator<<(ostream& s,const Instruction& instr);
// Execute this instruction, updateing the processor and memory
// and streams pointing to the triples etc
template<class sint, class sgf2n>
void execute(Processor<sint, sgf2n>& Proc) const;
template<class cgf2n>
void execute_clear_gf2n(StackedVector<cgf2n>& registers, MemoryPart<cgf2n>& memory,
ArithmeticProcessor& Proc) const;
template<class cgf2n>
void gbitdec(StackedVector<cgf2n>& registers) const;
template<class cgf2n>
void gbitcom(StackedVector<cgf2n>& registers) const;
void execute_regint(ArithmeticProcessor& Proc, MemoryPart<Integer>& Mi) const;
void shuffle(ArithmeticProcessor& Proc) const;
void bitdecint(ArithmeticProcessor& Proc) const;
template<class T>
void print(SwitchableOutput& out, T* v, T* p = 0, T* s = 0, T* z = 0,
T* nan = 0) const;
template<class T>
typename T::clear sanitize(SubProcessor<T>& proc, int reg) const;
};
#endif