ArgUnion getImm(PC const origPC, int idx, const Unit* unit) { auto pc = origPC; auto const UNUSED op = decode_op(pc); assert(idx >= 0 && idx < numImmediates(op)); ArgUnion retval; retval.u_NA = 0; int cursor = 0; for (cursor = 0; cursor < idx; cursor++) { // Advance over this immediate. pc += immSize(origPC, cursor); } always_assert(cursor == idx); auto const type = immType(op, idx); if (type == IVA || type == LA || type == IA) { retval.u_IVA = decodeVariableSizeImm(&pc); } else if (type == KA) { assert(unit != nullptr); retval.u_KA = decode_member_key(pc, unit); } else if (!immIsVector(op, cursor)) { always_assert(type != RATA); // Decode RATAs with a different function. memcpy(&retval.bytes, pc, immSize(origPC, idx)); } always_assert(numImmediates(op) > idx); return retval; }
ArgUnion getImm(const PC origPC, int idx, const Unit* unit) { auto pc = origPC; auto const op = decode_op(pc); assertx(idx >= 0 && idx < numImmediates(op)); ArgUnion retval; retval.u_NA = 0; int cursor = 0; for (cursor = 0; cursor < idx; cursor++) { // Advance over this immediate. pc += immSize(immType(op, cursor), pc); } always_assert(cursor == idx); auto const type = immType(op, idx); if (type == IVA || type == LA || type == IA || type == CAR || type == CAW) { retval.u_IVA = decode_iva(pc); } else if (type == KA) { assertx(unit != nullptr); retval.u_KA = decode_member_key(pc, unit); } else if (type == LAR) { retval.u_LAR = decodeLocalRange(pc); } else if (type == FCA) { retval.u_FCA = decodeFCallArgs(pc); } else if (type == RATA) { assertx(unit != nullptr); retval.u_RATA = decodeRAT(unit, pc); } else if (!argTypeIsVector(type)) { memcpy(&retval.bytes, pc, immSize(type, pc)); } always_assert(numImmediates(op) > idx); return retval; }
int instrLen(const Opcode* opcode) { int len = 1; int nImm = numImmediates(*opcode); for (int i = 0; i < nImm; i++) { len += immSize(opcode, i); } return len; }
int instrLen(PC const origPC) { auto pc = origPC; auto op = decode_op(pc); int nImm = numImmediates(op); for (int i = 0; i < nImm; i++) { pc += immSize(origPC, i); } return pc - origPC; }
ArgUnion* getImmPtr(const Opcode* opcode, int idx) { assert(immType(*opcode, idx) != IVA); assert(immType(*opcode, idx) != HA); assert(immType(*opcode, idx) != IA); const Opcode* ptr = opcode + 1; for (int i = 0; i < idx; i++) { ptr += immSize(opcode, i); } return (ArgUnion*)ptr; }
ArgUnion getImm(const Opcode* opcode, int idx) { const Opcode* p = opcode + 1; assert(idx >= 0 && idx < numImmediates(*opcode)); ArgUnion retval; retval.u_NA = 0; int cursor = 0; for (cursor = 0; cursor < idx; cursor++) { // Advance over this immediate. p += immSize(opcode, cursor); } always_assert(cursor == idx); ArgType type = immType(*opcode, idx); if (type == IVA || type == HA || type == IA) { retval.u_IVA = decodeVariableSizeImm(&p); } else if (!immIsVector(*opcode, cursor)) { memcpy(&retval.bytes, p, immSize(opcode, idx)); } always_assert(numImmediates(*opcode) > idx); return retval; }
ArgUnion getImm(const Op* opcode, int idx) { const Op* p = opcode + 1; assert(idx >= 0 && idx < numImmediates(*opcode)); ArgUnion retval; retval.u_NA = 0; int cursor = 0; for (cursor = 0; cursor < idx; cursor++) { // Advance over this immediate. p += immSize(opcode, cursor); } always_assert(cursor == idx); auto const type = immType(*opcode, idx); if (type == IVA || type == LA || type == IA) { retval.u_IVA = decodeVariableSizeImm((const uint8_t**)&p); } else if (!immIsVector(*opcode, cursor)) { always_assert(type != RATA); // Decode RATAs with a different function. memcpy(&retval.bytes, p, immSize(opcode, idx)); } always_assert(numImmediates(*opcode) > idx); return retval; }
ArgUnion* getImmPtr(PC const origPC, int idx) { auto pc = origPC; auto const UNUSED op = decode_op(pc); assert(immType(op, idx) != IVA); assert(immType(op, idx) != LA); assert(immType(op, idx) != IA); assert(immType(op, idx) != RATA); for (int i = 0; i < idx; i++) { pc += immSize(origPC, i); } return (ArgUnion*)pc; }
int immSize(const Opcode* opcode, int idx) { ASSERT(idx >= 0 && idx < numImmediates(*opcode)); assert(idx < 3); // No opcodes have more than three immediates static const int8_t argTypeToSizes[] = { #define ARGTYPE(nm, type) sizeof(type), #define ARGTYPEVEC(nm, type) 0, ARGTYPES #undef ARGTYPE #undef ARGTYPEVEC }; if (immType(*opcode, idx) == IVA || immType(*opcode, idx) == HA || immType(*opcode, idx) == IA) { intptr_t offset = 1; if (idx >= 1) offset += immSize(opcode, 0); if (idx >= 2) offset += immSize(opcode, 1); // variable size unsigned char imm = *(unsigned char*)(opcode + offset); // Low order bit set => 4-byte. return (imm & 0x1 ? sizeof(int32_t) : sizeof(unsigned char)); } else if (immIsVector(*opcode, idx)) { intptr_t offset = 1; if (idx >= 1) offset += immSize(opcode, 0); if (idx >= 2) offset += immSize(opcode, 1); int prefixes, vecElemSz; if (immType(*opcode, idx) == MA) { prefixes = 2; vecElemSz = sizeof(uint8_t); } else { ASSERT(immType(*opcode, idx) == ILA); prefixes = 1; vecElemSz = sizeof(int32_t); } return prefixes * sizeof(int32_t) + vecElemSz * *(int32_t*)((int8_t*)opcode + offset); } else { ArgType type = immType(*opcode, idx); return (type >= 0) ? argTypeToSizes[type] : 0; } }
ArgUnion* getImmPtr(const PC origPC, int idx) { auto pc = origPC; auto const op = decode_op(pc); assertx(immType(op, idx) != IVA); assertx(immType(op, idx) != LA); assertx(immType(op, idx) != IA); assertx(immType(op, idx) != CAR); assertx(immType(op, idx) != CAW); assertx(immType(op, idx) != RATA); for (int i = 0; i < idx; i++) { pc += immSize(immType(op, i), pc); } return (ArgUnion*)pc; }
int immSize(const Op* opcode, int idx) { assert(idx >= 0 && idx < numImmediates(*opcode)); always_assert(idx < 4); // No opcodes have more than four immediates static const int8_t argTypeToSizes[] = { #define ARGTYPE(nm, type) sizeof(type), #define ARGTYPEVEC(nm, type) 0, ARGTYPES #undef ARGTYPE #undef ARGTYPEVEC }; if (immType(*opcode, idx) == IVA || immType(*opcode, idx) == LA || immType(*opcode, idx) == IA) { intptr_t offset = 1; if (idx >= 1) offset += immSize(opcode, 0); if (idx >= 2) offset += immSize(opcode, 1); if (idx >= 3) offset += immSize(opcode, 2); unsigned char imm = *(const unsigned char*)(opcode + offset); // Low order bit set => 4-byte. return (imm & 0x1 ? sizeof(int32_t) : sizeof(unsigned char)); } if (immType(*opcode, idx) == RATA) { intptr_t offset = 1; if (idx >= 1) offset += immSize(opcode, 0); if (idx >= 2) offset += immSize(opcode, 1); if (idx >= 3) offset += immSize(opcode, 2); return encodedRATSize(reinterpret_cast<PC>(opcode) + offset); } if (immIsVector(*opcode, idx)) { intptr_t offset = 1; if (idx >= 1) offset += immSize(opcode, 0); if (idx >= 2) offset += immSize(opcode, 1); if (idx >= 3) offset += immSize(opcode, 2); int prefixes, vecElemSz; auto itype = immType(*opcode, idx); if (itype == MA) { prefixes = 2; vecElemSz = sizeof(uint8_t); } else if (itype == BLA) { prefixes = 1; vecElemSz = sizeof(Offset); } else if (itype == ILA) { prefixes = 1; vecElemSz = 2 * sizeof(uint32_t); } else if (itype == VSA) { prefixes = 1; vecElemSz = sizeof(Id); } else { assert(itype == SLA); prefixes = 1; vecElemSz = sizeof(StrVecItem); } return prefixes * sizeof(int32_t) + vecElemSz * *(int32_t*)((int8_t*)opcode + offset); } ArgType type = immType(*opcode, idx); return (type >= 0) ? argTypeToSizes[type] : 0; }
int immSize(PC origPC, int idx) { auto pc = origPC; auto const op = decode_op(pc); assert(idx >= 0 && idx < numImmediates(op)); always_assert(idx < 4); // No origPCs have more than four immediates static const int8_t argTypeToSizes[] = { #define ARGTYPE(nm, type) sizeof(type), #define ARGTYPEVEC(nm, type) 0, ARGTYPES #undef ARGTYPE #undef ARGTYPEVEC }; if (immType(op, idx) == IVA || immType(op, idx) == LA || immType(op, idx) == IA) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); return encoded_iva_size(decode_raw<uint8_t>(pc)); } if (immType(op, idx) == KA) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); switch (decode_raw<MemberCode>(pc)) { case MW: return 1; case MEL: case MPL: case MEC: case MPC: return 1 + encoded_iva_size(decode_raw<uint8_t>(pc)); case MEI: return 1 + sizeof(int64_t); case MET: case MPT: case MQT: return 1 + sizeof(Id); } not_reached(); } if (immType(op, idx) == RATA) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); return encodedRATSize(pc); } if (immIsVector(op, idx)) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); int vecElemSz; auto itype = immType(op, idx); if (itype == BLA) { vecElemSz = sizeof(Offset); } else if (itype == ILA) { vecElemSz = 2 * sizeof(uint32_t); } else if (itype == VSA) { vecElemSz = sizeof(Id); } else { assert(itype == SLA); vecElemSz = sizeof(StrVecItem); } return sizeof(int32_t) + vecElemSz * decode_raw<int32_t>(pc); } ArgType type = immType(op, idx); return (type >= 0) ? argTypeToSizes[type] : 0; }
int immSize(PC origPC, int idx) { auto pc = origPC; auto const op = decode_op(pc); assert(idx >= 0 && idx < numImmediates(op)); always_assert(idx < 4); // No origPCs have more than four immediates static const int8_t argTypeToSizes[] = { #define ARGTYPE(nm, type) sizeof(type), #define ARGTYPEVEC(nm, type) 0, ARGTYPES #undef ARGTYPE #undef ARGTYPEVEC }; if (immType(op, idx) == IVA || immType(op, idx) == LA || immType(op, idx) == IA) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); auto const imm = decode_raw<uint8_t>(pc); // Low order bit set => 4-byte. return (imm & 0x1 ? sizeof(int32_t) : sizeof(unsigned char)); } if (immType(op, idx) == RATA) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); return encodedRATSize(pc); } if (immIsVector(op, idx)) { if (idx >= 1) pc += immSize(origPC, 0); if (idx >= 2) pc += immSize(origPC, 1); if (idx >= 3) pc += immSize(origPC, 2); int prefixes, vecElemSz; auto itype = immType(op, idx); if (itype == MA) { prefixes = 2; vecElemSz = sizeof(uint8_t); } else if (itype == BLA) { prefixes = 1; vecElemSz = sizeof(Offset); } else if (itype == ILA) { prefixes = 1; vecElemSz = 2 * sizeof(uint32_t); } else if (itype == VSA) { prefixes = 1; vecElemSz = sizeof(Id); } else { assert(itype == SLA); prefixes = 1; vecElemSz = sizeof(StrVecItem); } return prefixes * sizeof(int32_t) + vecElemSz * decode_raw<int32_t>(pc); } ArgType type = immType(op, idx); return (type >= 0) ? argTypeToSizes[type] : 0; }