This source file includes following definitions.
- inp_uint8
- inp_uint16
- inp_uint32
- inp_uint64
- eff_opr_mode
- eff_adr_mode
- ud_lookup_mnemonic
- decode_prefixes
- modrm
- resolve_operand_size
- resolve_mnemonic
- decode_a
- decode_gpr
- decode_reg
- decode_imm
- decode_mem_disp
- decode_modrm_reg
- decode_modrm_rm
- decode_moffset
- decode_operand
- decode_operands
- clear_insn
- resolve_pfx_str
- resolve_mode
- decode_insn
- decode_3dnow
- decode_ssepfx
- decode_ext
- decode_opcode
- ud_decode
#include "udint.h"
#include "types.h"
#include "input.h"
#include "decode.h"
#ifndef __UD_STANDALONE__
# include <string.h>
#endif
#define MAX_PREFIXES 15
#define REX_W(r) ( ( 0xF & ( r ) ) >> 3 )
#define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 )
#define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 )
#define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 )
#define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \
( P_REXR(n) << 2 ) | \
( P_REXX(n) << 1 ) | \
( P_REXB(n) << 0 ) )
#define SIB_S(b) ( ( b ) >> 6 )
#define SIB_I(b) ( ( ( b ) >> 3 ) & 7 )
#define SIB_B(b) ( ( b ) & 7 )
#define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 )
#define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 )
#define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 )
#define MODRM_RM(b) ( ( b ) & 7 )
static int decode_ext(struct ud *u, uint16_t ptr);
enum reg_class {
REGCLASS_NONE,
REGCLASS_GPR,
REGCLASS_MMX,
REGCLASS_CR,
REGCLASS_DB,
REGCLASS_SEG,
REGCLASS_XMM
};
static uint8_t
inp_uint8(struct ud* u)
{
return ud_inp_next(u);
}
static uint16_t
inp_uint16(struct ud* u)
{
uint16_t r, ret;
ret = ud_inp_next(u);
r = ud_inp_next(u);
return ret | (r << 8);
}
static uint32_t
inp_uint32(struct ud* u)
{
uint32_t r, ret;
ret = ud_inp_next(u);
r = ud_inp_next(u);
ret = ret | (r << 8);
r = ud_inp_next(u);
ret = ret | (r << 16);
r = ud_inp_next(u);
return ret | (r << 24);
}
static uint64_t
inp_uint64(struct ud* u)
{
uint64_t r, ret;
ret = ud_inp_next(u);
r = ud_inp_next(u);
ret = ret | (r << 8);
r = ud_inp_next(u);
ret = ret | (r << 16);
r = ud_inp_next(u);
ret = ret | (r << 24);
r = ud_inp_next(u);
ret = ret | (r << 32);
r = ud_inp_next(u);
ret = ret | (r << 40);
r = ud_inp_next(u);
ret = ret | (r << 48);
r = ud_inp_next(u);
return ret | (r << 56);
}
static inline int
eff_opr_mode(int dis_mode, int rex_w, int pfx_opr)
{
if (dis_mode == 64) {
return rex_w ? 64 : (pfx_opr ? 16 : 32);
} else if (dis_mode == 32) {
return pfx_opr ? 16 : 32;
} else {
UD_ASSERT(dis_mode == 16);
return pfx_opr ? 32 : 16;
}
}
static inline int
eff_adr_mode(int dis_mode, int pfx_adr)
{
if (dis_mode == 64) {
return pfx_adr ? 32 : 64;
} else if (dis_mode == 32) {
return pfx_adr ? 16 : 32;
} else {
UD_ASSERT(dis_mode == 16);
return pfx_adr ? 32 : 16;
}
}
const char*
ud_lookup_mnemonic(enum ud_mnemonic_code c)
{
if (c < UD_MAX_MNEMONIC_CODE) {
return ud_mnemonics_str[c];
} else {
return NULL;
}
}
static int
decode_prefixes(struct ud *u)
{
int done = 0;
uint8_t curr;
UD_RETURN_ON_ERROR(u);
do {
ud_inp_next(u);
UD_RETURN_ON_ERROR(u);
if (inp_len(u) == MAX_INSN_LENGTH) {
UD_RETURN_WITH_ERROR(u, "max instruction length");
}
curr = inp_curr(u);
switch (curr)
{
case 0x2E :
u->pfx_seg = UD_R_CS;
break;
case 0x36 :
u->pfx_seg = UD_R_SS;
break;
case 0x3E :
u->pfx_seg = UD_R_DS;
break;
case 0x26 :
u->pfx_seg = UD_R_ES;
break;
case 0x64 :
u->pfx_seg = UD_R_FS;
break;
case 0x65 :
u->pfx_seg = UD_R_GS;
break;
case 0x67 :
u->pfx_adr = 0x67;
break;
case 0xF0 :
u->pfx_lock = 0xF0;
break;
case 0x66:
u->pfx_opr = 0x66;
break;
case 0xF2:
u->pfx_str = 0xf2;
break;
case 0xF3:
u->pfx_str = 0xf3;
break;
default:
done = 1;
break;
}
} while (!done);
if (u->dis_mode == 64 && (curr & 0xF0) == 0x40) {
u->pfx_rex = curr;
} else {
inp_back(u);
}
return 0;
}
static inline unsigned int modrm( struct ud * u )
{
if ( !u->have_modrm ) {
u->modrm = ud_inp_next( u );
u->have_modrm = 1;
}
return u->modrm;
}
static unsigned int
resolve_operand_size( const struct ud * u, unsigned int s )
{
switch ( s )
{
case SZ_V:
return ( u->opr_mode );
case SZ_Z:
return ( u->opr_mode == 16 ) ? 16 : 32;
case SZ_Y:
return ( u->opr_mode == 16 ) ? 32 : u->opr_mode;
case SZ_RDQ:
return ( u->dis_mode == 64 ) ? 64 : 32;
default:
return s;
}
}
static int resolve_mnemonic( struct ud* u )
{
if ( u->mnemonic == UD_I3dnow ) {
u->mnemonic = ud_itab[ u->le->table[ inp_curr( u ) ] ].mnemonic;
}
if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) {
UDERR(u, "swapgs invalid in 64bits mode");
return -1;
}
if (u->mnemonic == UD_Ixchg) {
if ((u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_AX &&
u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_AX) ||
(u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_EAX &&
u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_EAX)) {
u->operand[0].type = UD_NONE;
u->operand[1].type = UD_NONE;
u->mnemonic = UD_Inop;
}
}
if (u->mnemonic == UD_Inop && u->pfx_repe) {
u->pfx_repe = 0;
u->mnemonic = UD_Ipause;
}
return 0;
}
static void
decode_a(struct ud* u, struct ud_operand *op)
{
if (u->opr_mode == 16) {
op->type = UD_OP_PTR;
op->size = 32;
op->lval.ptr.off = inp_uint16(u);
op->lval.ptr.seg = inp_uint16(u);
} else {
op->type = UD_OP_PTR;
op->size = 48;
op->lval.ptr.off = inp_uint32(u);
op->lval.ptr.seg = inp_uint16(u);
}
}
static enum ud_type
decode_gpr(register struct ud* u, unsigned int s, unsigned char rm)
{
switch (s) {
case 64:
return UD_R_RAX + rm;
case 32:
return UD_R_EAX + rm;
case 16:
return UD_R_AX + rm;
case 8:
if (u->dis_mode == 64 && u->pfx_rex) {
if (rm >= 4)
return UD_R_SPL + (rm-4);
return UD_R_AL + rm;
} else return UD_R_AL + rm;
default:
UD_ASSERT(!"invalid operand size");
return 0;
}
}
static void
decode_reg(struct ud *u,
struct ud_operand *opr,
int type,
int num,
int size)
{
int reg;
size = resolve_operand_size(u, size);
switch (type) {
case REGCLASS_GPR : reg = decode_gpr(u, size, num); break;
case REGCLASS_MMX : reg = UD_R_MM0 + (num & 7); break;
case REGCLASS_XMM : reg = UD_R_XMM0 + num; break;
case REGCLASS_CR : reg = UD_R_CR0 + num; break;
case REGCLASS_DB : reg = UD_R_DR0 + num; break;
case REGCLASS_SEG : {
if ((num & 7) > 5) {
UDERR(u, "invalid segment register value");
return;
} else {
reg = UD_R_ES + (num & 7);
}
break;
}
default:
UD_ASSERT(!"invalid register type");
break;
}
opr->type = UD_OP_REG;
opr->base = reg;
opr->size = size;
}
static void
decode_imm(struct ud* u, unsigned int size, struct ud_operand *op)
{
op->size = resolve_operand_size(u, size);
op->type = UD_OP_IMM;
switch (op->size) {
case 8: op->lval.sbyte = inp_uint8(u); break;
case 16: op->lval.uword = inp_uint16(u); break;
case 32: op->lval.udword = inp_uint32(u); break;
case 64: op->lval.uqword = inp_uint64(u); break;
default: return;
}
}
static void
decode_mem_disp(struct ud* u, unsigned int size, struct ud_operand *op)
{
switch (size) {
case 8:
op->offset = 8;
op->lval.ubyte = inp_uint8(u);
break;
case 16:
op->offset = 16;
op->lval.uword = inp_uint16(u);
break;
case 32:
op->offset = 32;
op->lval.udword = inp_uint32(u);
break;
case 64:
op->offset = 64;
op->lval.uqword = inp_uint64(u);
break;
default:
return;
}
}
static inline void
decode_modrm_reg(struct ud *u,
struct ud_operand *operand,
unsigned int type,
unsigned int size)
{
uint8_t reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u));
decode_reg(u, operand, type, reg, size);
}
static void
decode_modrm_rm(struct ud *u,
struct ud_operand *op,
unsigned char type,
unsigned int size)
{
size_t offset = 0;
unsigned char mod, rm;
mod = MODRM_MOD(modrm(u));
rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(modrm(u));
if (mod == 3) {
decode_reg(u, op, type, rm, size);
return;
}
op->type = UD_OP_MEM;
op->size = resolve_operand_size(u, size);
if (u->adr_mode == 64) {
op->base = UD_R_RAX + rm;
if (mod == 1) {
offset = 8;
} else if (mod == 2) {
offset = 32;
} else if (mod == 0 && (rm & 7) == 5) {
op->base = UD_R_RIP;
offset = 32;
} else {
offset = 0;
}
if ((rm & 7) == 4) {
ud_inp_next(u);
op->scale = (1 << SIB_S(inp_curr(u))) & ~1;
op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3));
op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3));
if (op->index == UD_R_RSP) {
op->index = UD_NONE;
op->scale = UD_NONE;
}
if (op->base == UD_R_RBP || op->base == UD_R_R13) {
if (mod == 0) {
op->base = UD_NONE;
}
if (mod == 1) {
offset = 8;
} else {
offset = 32;
}
}
}
} else if (u->adr_mode == 32) {
op->base = UD_R_EAX + rm;
if (mod == 1) {
offset = 8;
} else if (mod == 2) {
offset = 32;
} else if (mod == 0 && rm == 5) {
op->base = UD_NONE;
offset = 32;
} else {
offset = 0;
}
if ((rm & 7) == 4) {
ud_inp_next(u);
op->scale = (1 << SIB_S(inp_curr(u))) & ~1;
op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3));
op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3));
if (op->index == UD_R_ESP) {
op->index = UD_NONE;
op->scale = UD_NONE;
}
if (op->base == UD_R_EBP) {
if (mod == 0) {
op->base = UD_NONE;
}
if (mod == 1) {
offset = 8;
} else {
offset = 32;
}
}
}
} else {
const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP,
UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX };
const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI,
UD_NONE, UD_NONE, UD_NONE, UD_NONE };
op->base = bases[rm & 7];
op->index = indices[rm & 7];
if (mod == 0 && rm == 6) {
offset = 16;
op->base = UD_NONE;
} else if (mod == 1) {
offset = 8;
} else if (mod == 2) {
offset = 16;
}
}
if (offset) {
decode_mem_disp(u, offset, op);
}
}
static void
decode_moffset(struct ud *u, unsigned int size, struct ud_operand *opr)
{
opr->type = UD_OP_MEM;
opr->size = resolve_operand_size(u, size);
decode_mem_disp(u, u->adr_mode, opr);
}
static int
decode_operand(struct ud *u,
struct ud_operand *operand,
enum ud_operand_code type,
unsigned int size)
{
operand->_oprcode = type;
switch (type) {
case OP_A :
decode_a(u, operand);
break;
case OP_MR:
decode_modrm_rm(u, operand, REGCLASS_GPR,
MODRM_MOD(modrm(u)) == 3 ?
Mx_reg_size(size) : Mx_mem_size(size));
break;
case OP_F:
u->br_far = 1;
case OP_M:
if (MODRM_MOD(modrm(u)) == 3) {
UDERR(u, "expected modrm.mod != 3");
}
case OP_E:
decode_modrm_rm(u, operand, REGCLASS_GPR, size);
break;
case OP_G:
decode_modrm_reg(u, operand, REGCLASS_GPR, size);
break;
case OP_sI:
case OP_I:
decode_imm(u, size, operand);
break;
case OP_I1:
operand->type = UD_OP_CONST;
operand->lval.udword = 1;
break;
case OP_N:
if (MODRM_MOD(modrm(u)) != 3) {
UDERR(u, "expected modrm.mod == 3");
}
case OP_Q:
decode_modrm_rm(u, operand, REGCLASS_MMX, size);
break;
case OP_P:
decode_modrm_reg(u, operand, REGCLASS_MMX, size);
break;
case OP_U:
if (MODRM_MOD(modrm(u)) != 3) {
UDERR(u, "expected modrm.mod == 3");
}
case OP_W:
decode_modrm_rm(u, operand, REGCLASS_XMM, size);
break;
case OP_V:
decode_modrm_reg(u, operand, REGCLASS_XMM, size);
break;
case OP_MU:
decode_modrm_rm(u, operand, REGCLASS_XMM,
MODRM_MOD(modrm(u)) == 3 ?
Mx_reg_size(size) : Mx_mem_size(size));
break;
case OP_S:
decode_modrm_reg(u, operand, REGCLASS_SEG, size);
break;
case OP_O:
decode_moffset(u, size, operand);
break;
case OP_R0:
case OP_R1:
case OP_R2:
case OP_R3:
case OP_R4:
case OP_R5:
case OP_R6:
case OP_R7:
decode_reg(u, operand, REGCLASS_GPR,
(REX_B(u->pfx_rex) << 3) | (type - OP_R0), size);
break;
case OP_AL:
case OP_AX:
case OP_eAX:
case OP_rAX:
decode_reg(u, operand, REGCLASS_GPR, 0, size);
break;
case OP_CL:
case OP_CX:
case OP_eCX:
decode_reg(u, operand, REGCLASS_GPR, 1, size);
break;
case OP_DL:
case OP_DX:
case OP_eDX:
decode_reg(u, operand, REGCLASS_GPR, 2, size);
break;
case OP_ES:
case OP_CS:
case OP_DS:
case OP_SS:
case OP_FS:
case OP_GS:
if (u->dis_mode == 64) {
if (type != OP_FS && type != OP_GS) {
UDERR(u, "invalid segment register in 64bits");
}
}
operand->type = UD_OP_REG;
operand->base = (type - OP_ES) + UD_R_ES;
operand->size = 16;
break;
case OP_J :
decode_imm(u, size, operand);
operand->type = UD_OP_JIMM;
break ;
case OP_R :
if (MODRM_MOD(modrm(u)) != 3) {
UDERR(u, "expected modrm.mod == 3");
}
decode_modrm_rm(u, operand, REGCLASS_GPR, size);
break;
case OP_C:
decode_modrm_reg(u, operand, REGCLASS_CR, size);
break;
case OP_D:
decode_modrm_reg(u, operand, REGCLASS_DB, size);
break;
case OP_I3 :
operand->type = UD_OP_CONST;
operand->lval.sbyte = 3;
break;
case OP_ST0:
case OP_ST1:
case OP_ST2:
case OP_ST3:
case OP_ST4:
case OP_ST5:
case OP_ST6:
case OP_ST7:
operand->type = UD_OP_REG;
operand->base = (type - OP_ST0) + UD_R_ST0;
operand->size = 80;
break;
default :
break;
}
return 0;
}
static int
decode_operands(struct ud* u)
{
decode_operand(u, &u->operand[0],
u->itab_entry->operand1.type,
u->itab_entry->operand1.size);
decode_operand(u, &u->operand[1],
u->itab_entry->operand2.type,
u->itab_entry->operand2.size);
decode_operand(u, &u->operand[2],
u->itab_entry->operand3.type,
u->itab_entry->operand3.size);
return 0;
}
static void
clear_insn(register struct ud* u)
{
u->error = 0;
u->pfx_seg = 0;
u->pfx_opr = 0;
u->pfx_adr = 0;
u->pfx_lock = 0;
u->pfx_repne = 0;
u->pfx_rep = 0;
u->pfx_repe = 0;
u->pfx_rex = 0;
u->pfx_str = 0;
u->mnemonic = UD_Inone;
u->itab_entry = NULL;
u->have_modrm = 0;
u->br_far = 0;
memset( &u->operand[ 0 ], 0, sizeof( struct ud_operand ) );
memset( &u->operand[ 1 ], 0, sizeof( struct ud_operand ) );
memset( &u->operand[ 2 ], 0, sizeof( struct ud_operand ) );
}
static inline int
resolve_pfx_str(struct ud* u)
{
if (u->pfx_str == 0xf3) {
if (P_STR(u->itab_entry->prefix)) {
u->pfx_rep = 0xf3;
} else {
u->pfx_repe = 0xf3;
}
} else if (u->pfx_str == 0xf2) {
u->pfx_repne = 0xf3;
}
return 0;
}
static int
resolve_mode( struct ud* u )
{
if ( u->error ) return -1;
if ( u->dis_mode == 64 ) {
if ( P_INV64( u->itab_entry->prefix ) ) {
UDERR(u, "instruction invalid in 64bits");
return -1;
}
u->pfx_rex = ( u->pfx_rex & 0x40 ) |
( u->pfx_rex & REX_PFX_MASK( u->itab_entry->prefix ) );
u->default64 = P_DEF64( u->itab_entry->prefix );
if ( REX_W( u->pfx_rex ) ) {
u->opr_mode = 64;
} else if ( u->pfx_opr ) {
u->opr_mode = 16;
} else {
u->opr_mode = ( u->default64 ) ? 64 : 32;
}
u->adr_mode = (u->pfx_adr) ? 32 : 64;
} else if ( u->dis_mode == 32 ) {
u->opr_mode = ( u->pfx_opr ) ? 16 : 32;
u->adr_mode = ( u->pfx_adr ) ? 16 : 32;
} else if ( u->dis_mode == 16 ) {
u->opr_mode = ( u->pfx_opr ) ? 32 : 16;
u->adr_mode = ( u->pfx_adr ) ? 32 : 16;
}
u->implicit_addr = P_IMPADDR( u->itab_entry->prefix );
return 0;
}
static inline int
decode_insn(struct ud *u, uint16_t ptr)
{
UD_ASSERT((ptr & 0x8000) == 0);
u->itab_entry = &ud_itab[ ptr ];
u->mnemonic = u->itab_entry->mnemonic;
return (resolve_pfx_str(u) == 0 &&
resolve_mode(u) == 0 &&
decode_operands(u) == 0 &&
resolve_mnemonic(u) == 0) ? 0 : -1;
}
static inline int
decode_3dnow(struct ud* u)
{
uint16_t ptr;
UD_ASSERT(u->le->type == UD_TAB__OPC_3DNOW);
UD_ASSERT(u->le->table[0xc] != 0);
decode_insn(u, u->le->table[0xc]);
ud_inp_next(u);
if (u->error) {
return -1;
}
ptr = u->le->table[inp_curr(u)];
UD_ASSERT((ptr & 0x8000) == 0);
u->mnemonic = ud_itab[ptr].mnemonic;
return 0;
}
static int
decode_ssepfx(struct ud *u)
{
uint8_t idx;
uint8_t pfx;
pfx = u->pfx_str;
if (pfx == 0) {
pfx = u->pfx_opr;
}
idx = ((pfx & 0xf) + 1) / 2;
if (u->le->table[idx] == 0) {
idx = 0;
}
if (idx && u->le->table[idx] != 0) {
u->pfx_str = 0;
if (pfx == 0x66) {
u->pfx_opr = 0;
}
}
return decode_ext(u, u->le->table[idx]);
}
static int
decode_ext(struct ud *u, uint16_t ptr)
{
uint8_t idx = 0;
if ((ptr & 0x8000) == 0) {
return decode_insn(u, ptr);
}
u->le = &ud_lookup_table_list[(~0x8000 & ptr)];
if (u->le->type == UD_TAB__OPC_3DNOW) {
return decode_3dnow(u);
}
switch (u->le->type) {
case UD_TAB__OPC_MOD:
idx = (MODRM_MOD(modrm(u)) + 1) / 4;
break;
case UD_TAB__OPC_MODE:
idx = u->dis_mode != 64 ? 0 : 1;
break;
case UD_TAB__OPC_OSIZE:
idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32;
break;
case UD_TAB__OPC_ASIZE:
idx = eff_adr_mode(u->dis_mode, u->pfx_adr) / 32;
break;
case UD_TAB__OPC_X87:
idx = modrm(u) - 0xC0;
break;
case UD_TAB__OPC_VENDOR:
if (u->vendor == UD_VENDOR_ANY) {
idx = (u->le->table[idx] != 0) ? 0 : 1;
} else if (u->vendor == UD_VENDOR_AMD) {
idx = 0;
} else {
idx = 1;
}
break;
case UD_TAB__OPC_RM:
idx = MODRM_RM(modrm(u));
break;
case UD_TAB__OPC_REG:
idx = MODRM_REG(modrm(u));
break;
case UD_TAB__OPC_SSE:
return decode_ssepfx(u);
default:
UD_ASSERT(!"not reached");
break;
}
return decode_ext(u, u->le->table[idx]);
}
static int
decode_opcode(struct ud *u)
{
uint16_t ptr;
UD_ASSERT(u->le->type == UD_TAB__OPC_TABLE);
ud_inp_next(u);
if (u->error) {
return -1;
}
u->primary_opcode = inp_curr(u);
ptr = u->le->table[inp_curr(u)];
if (ptr & 0x8000) {
u->le = &ud_lookup_table_list[ptr & ~0x8000];
if (u->le->type == UD_TAB__OPC_TABLE) {
return decode_opcode(u);
}
}
return decode_ext(u, ptr);
}
unsigned int
ud_decode(struct ud *u)
{
inp_start(u);
clear_insn(u);
u->le = &ud_lookup_table_list[0];
u->error = decode_prefixes(u) == -1 ||
decode_opcode(u) == -1 ||
u->error;
if (u->error) {
clear_insn(u);
u->itab_entry = &ud_itab[0];
u->mnemonic = u->itab_entry->mnemonic;
}
if ( !P_SEG( u->itab_entry->prefix ) &&
u->operand[0].type != UD_OP_MEM &&
u->operand[1].type != UD_OP_MEM )
u->pfx_seg = 0;
u->insn_offset = u->pc;
u->asm_buf_fill = 0;
u->pc += u->inp_ctr;
return u->inp_ctr;
}