pike.git / src / code / amd64.c

version» Context lines:

pike.git/src/code/amd64.c:531:    }    }    else    {    opcode( 0x83 );    modrm( 3,7,reg);    ib( imm32 );    }   }    + static void cmp_reg32_imm( enum amd64_reg reg, int imm32 ) + { +  rex(0, 0, 0, reg); +  if( imm32 > 0x7f || imm32 < -0x80 ) +  { +  if( reg == REG_RAX ) +  { +  opcode( 0x3d ); +  id( imm32 ); +  } +  else +  { +  opcode( 0x81 ); +  modrm(3,7,reg); +  id( imm32 ); +  } +  } +  else +  { +  opcode( 0x83 ); +  modrm( 3,7,reg); +  ib( imm32 ); +  } + } +    static void cmp_reg_reg( enum amd64_reg reg1, enum amd64_reg reg2 )   {    rex(1, reg1, 0, reg2);    opcode( 0x39 );    modrm( 3, reg1, reg2 );   }      static int jmp_rel_imm32( int rel )   {    int res;
pike.git/src/code/amd64.c:883:   static void amd64_push_svaluep(int reg)   {    LABELS();       amd64_load_sp_reg();    mov_mem_reg(reg, OFFSETOF(svalue, type), REG_RAX);    mov_mem_reg(reg, OFFSETOF(svalue, u.refs), REG_RCX);    mov_reg_mem(REG_RAX, sp_reg, OFFSETOF(svalue, type));    and_reg_imm(REG_RAX, 0x1f);    mov_reg_mem(REG_RCX, sp_reg, OFFSETOF(svalue, u.refs)); -  cmp_reg_imm(REG_RAX, MAX_REF_TYPE); +  cmp_reg32_imm(REG_RAX, MAX_REF_TYPE);    jg(&label_A);    add_imm_mem( 1, REG_RCX,OFFSETOF(pike_string, refs));    LABEL_A;    amd64_add_sp( 1 );   }      static void amd64_push_int(INT64 value, int subtype)   {    amd64_load_sp_reg();    mov_imm_mem((subtype<<16) + PIKE_T_INT, sp_reg, OFFSETOF(svalue, type));
pike.git/src/code/amd64.c:941:      static void amd64_free_svalue(enum amd64_reg src, int guaranteed_ref )   {    LABELS();    if( src == REG_RAX )    Pike_fatal("Clobbering RAX for free-svalue\n");    /* load type -> RAX */    mov_sval_type( src, REG_RAX );       /* if RAX > MAX_REF_TYPE+1 */ -  cmp_reg_imm( REG_RAX,MAX_REF_TYPE); +  cmp_reg32_imm( REG_RAX,MAX_REF_TYPE);    jg( &label_A );       /* Load pointer to refs -> RAX */    mov_mem_reg( src, OFFSETOF(svalue, u.refs), REG_RAX);    /* if( !--*RAX ) */    add_mem32_imm( REG_RAX, OFFSETOF(pike_string,refs), -1);    if( !guaranteed_ref )    {    /* We need to see if refs got to 0. */    jnz( &label_A );
pike.git/src/code/amd64.c:969:      /* Type already in RAX */   static void amd64_free_svalue_type(enum amd64_reg src, enum amd64_reg type,    int guaranteed_ref )   {    LABELS();    /* if type > MAX_REF_TYPE+1 */    if( src == REG_RAX )    Pike_fatal("Clobbering RAX for free-svalue\n");    -  cmp_reg_imm(type,MAX_REF_TYPE); +  cmp_reg32_imm(type,MAX_REF_TYPE);    jg( &label_A );       /* Load pointer to refs -> RAX */    mov_mem_reg( src, OFFSETOF(svalue, u.refs), REG_RAX);    /* if( !--*RAX ) */    add_mem32_imm( REG_RAX, OFFSETOF(pike_string,refs), -1);    if( !guaranteed_ref )    {    /* We need to see if refs got to 0. */    jnz( &label_A );
pike.git/src/code/amd64.c:998:   void amd64_ref_svalue( enum amd64_reg src, int already_have_type )   {    LABELS();    if( src == REG_RAX ) Pike_fatal("Clobbering src in ref_svalue\n");    if( !already_have_type )    mov_sval_type( src, REG_RAX );    else    and_reg_imm( REG_RAX, 0x1f );       /* if RAX > MAX_REF_TYPE+1 */ -  cmp_reg_imm(REG_RAX, MAX_REF_TYPE ); +  cmp_reg32_imm(REG_RAX, MAX_REF_TYPE );    jg( &label_A );    /* Load pointer to refs -> RAX */    mov_mem_reg( src, OFFSETOF(svalue, u.refs), REG_RAX);    /* *RAX++ */    add_mem32_imm( REG_RAX, OFFSETOF(pike_string,refs), 1);    LABEL_A;   }      void amd64_assign_local( int b )   {
pike.git/src/code/amd64.c:1278:       addr=instrs[b].address;    switch(b + F_OFFSET)    {    case F_DUP:    amd64_load_sp_reg();    ins_debug_instr_prologue(b, 0, 0);    add_reg_imm_reg(sp_reg, -sizeof(struct svalue), REG_R10 );    amd64_push_svaluep( REG_R10 );    return; -  + #if 0    case F_EXIT_CATCH:    ins_f_byte( F_ESCAPE_CATCH );    amd64_load_sp_reg();    amd64_push_int( 0, 1 );    return; -  + #endif    case F_ADD_INTS:    {    amd64_load_sp_reg();    ins_debug_instr_prologue(b, 0, 0);    mov_mem8_reg( sp_reg, -sizeof(struct svalue)*2, REG_RAX );    shl_reg_imm( REG_RAX, 8 );    mov_mem8_reg( sp_reg,-sizeof(struct svalue), REG_RBX );    /* and_reg_imm( REG_RBX, 0x1f );*/    add_reg_reg( REG_RAX, REG_RBX );    /* and_reg_imm( REG_RAX, 0x1f1f ); */ -  cmp_reg_imm( REG_RAX, (PIKE_T_INT<<8)|PIKE_T_INT ); +  cmp_reg32_imm( REG_RAX, (PIKE_T_INT<<8)|PIKE_T_INT );    jne( &label_A );    /* So. Both are actually integers. */    mov_mem_reg( sp_reg,    -sizeof(struct svalue)+OFFSETOF(svalue,u.integer),    REG_RAX );       add_reg_mem( REG_RAX,    sp_reg,    -sizeof(struct svalue)*2+OFFSETOF(svalue,u.integer)    );
pike.git/src/code/amd64.c:1368:    }    break;    case F_ZERO_TYPE:    {    LABELS();    amd64_load_sp_reg();    mov_mem32_reg( sp_reg, -sizeof(struct svalue), REG_RAX );    /* Rax now has type + subtype. */    mov_reg_reg( REG_RAX, REG_RBX );    and_reg_imm( REG_RAX, 0x1f ); -  cmp_reg_imm( REG_RAX, PIKE_T_INT ); +  cmp_reg32_imm( REG_RAX, PIKE_T_INT );    jne( &label_A );    /* It is an integer. */    shr_reg_imm( REG_RBX, 16 );    /* subtype in RBX. */    mov_imm_mem( PIKE_T_INT, sp_reg, -sizeof(struct svalue) );    mov_reg_mem( REG_RBX, sp_reg,    -sizeof(struct svalue)+OFFSETOF(svalue,u.integer) );    jmp( &label_B );    LABEL_A;    /* not an integer. Use C version for simplicitly.. */
pike.git/src/code/amd64.c:1489:   #endif    jmp_reg(REG_RAX);    }    return;    case F_CLEAR_STRING_SUBTYPE:    ins_debug_instr_prologue(b, 0, 0);    amd64_load_sp_reg();    mov_mem32_reg(sp_reg, OFFSETOF(svalue, type) - sizeof(struct svalue),    REG_RAX);    /* NB: We only care about subtype 1! */ -  cmp_reg_imm(REG_RAX, (1<<16)|PIKE_T_STRING); +  cmp_reg32_imm(REG_RAX, (1<<16)|PIKE_T_STRING);    jne(&label_A);    and_reg_imm(REG_RAX, 0x1f);    mov_reg_mem32(REG_RAX,    sp_reg, OFFSETOF(svalue, type) - sizeof(struct svalue));    LABEL_A;    return;    }       amd64_call_c_opcode(addr,flags);   
pike.git/src/code/amd64.c:1532:    }    if (flags & I_JUMP) {    jmp_reg(REG_RAX);       if (b + F_OFFSET == F_CATCH) {    upd_pointer(rel_addr - 4, PIKE_PC - rel_addr);    }    }   }    + static void ALIGN() + { +  while( PIKE_PC & 7 ) +  ib( 0x90 ); + } +    int amd64_ins_f_jump(unsigned int op, int backward_jump)   {    int flags;    void *addr;    int off = op - F_OFFSET;    int ret = -1;    LABELS();      #ifdef PIKE_DEBUG    if(off>255)
pike.git/src/code/amd64.c:1567:    case F_QUICK_BRANCH_WHEN_ZERO:    case F_QUICK_BRANCH_WHEN_NON_ZERO:    START_JUMP();    amd64_load_sp_reg();    amd64_add_sp( -1 );    mov_mem_reg( sp_reg, 8, REG_RAX );    test_reg(REG_RAX);    if( op == F_QUICK_BRANCH_WHEN_ZERO )    return jz_imm_rel32(0);    return jnz_imm_rel32(0); +     case F_BRANCH_WHEN_ZERO:    case F_BRANCH_WHEN_NON_ZERO:    START_JUMP();    amd64_load_sp_reg(); -  mov_mem8_reg( sp_reg, -sizeof(struct svalue), REG_RAX ); -  cmp_reg_imm( REG_RAX, PIKE_T_OBJECT ); -  je( &label_A ); -  amd64_add_sp( -1 ); -  cmp_reg_imm( REG_RAX, PIKE_T_INT ); -  /* The add_sp above is not likely to have the zero-flag set -  * after operation (since pike-sp is seldom 0). -  */ -  jne( &label_C ); -  /* integer */ -  mov_mem_reg( sp_reg, OFFSETOF(svalue,u.integer), REG_RBX ); -  test_reg( REG_RBX ); +  mov_mem8_reg( sp_reg, -sizeof(struct svalue), REG_RCX ); +  cmp_reg32_imm( REG_RCX, PIKE_T_INT ); +  je( &label_C ); +  LABEL_A; +  /* not an integer. Use svalue_is_true. */ +  add_reg_imm_reg(sp_reg, -sizeof(struct svalue), ARG1_REG ); +  amd64_call_c_function(svalue_is_true); +  mov_reg_reg( REG_RAX, REG_RBX ); +  amd64_add_sp( -1 ); /* Pop the stack. */ +  amd64_free_svalue( sp_reg, 0 );    jmp( &label_B );    -  LABEL_A; /* It is an object. Use the C version. */ -  amd64_call_c_opcode(instrs[F_BRANCH_WHEN_NON_ZERO-F_OFFSET].address, -  instrs[F_BRANCH_WHEN_NON_ZERO-F_OFFSET].flags ); -  amd64_load_sp_reg(); -  test_reg( REG_RAX ); -  jmp( &label_B ); +     LABEL_C; -  /* not int or object. */ -  amd64_free_svalue_type( sp_reg, REG_RAX, 0 ); -  test_reg( sp_reg ); /* not zero. :) */ +  /* integer */ +  mov_mem_reg( sp_reg, +  -sizeof(struct svalue)+OFFSETOF(svalue,u.integer), +  REG_RBX ); +  amd64_add_sp(-1);       LABEL_B; /* Branch or not? */ -  +  test_reg( REG_RBX );    if( op == F_BRANCH_WHEN_ZERO )    return jz_imm_rel32(0);    return jnz_imm_rel32(0); -  +     case F_LOOP:    /* counter in pike_sp-1 */    /* decrement until 0. */    /* if not 0, branch */    /* otherwise, pop */    START_JUMP();    amd64_load_sp_reg();    mov_mem32_reg( sp_reg, -sizeof(struct svalue), REG_RAX );    /* Is it a normal integer? subtype -> 0, type -> PIKE_T_INT */ -  cmp_reg_imm( REG_RAX, PIKE_T_INT ); +  cmp_reg32_imm( REG_RAX, PIKE_T_INT );    jne( &label_A );       /* if it is, is it 0? */    mov_mem_reg( sp_reg, -sizeof(struct svalue)+8, REG_RAX );    test_reg(REG_RAX);    jz( &label_B ); /* it is. */       add_reg_imm( REG_RAX, -1 );    mov_reg_mem( REG_RAX, sp_reg, -sizeof(struct svalue)+8);    mov_imm_reg( 1, REG_RAX );
pike.git/src/code/amd64.c:1649:    return jnz_imm_rel32(0);       case F_BRANCH_WHEN_EQ: /* sp[-2] != sp[-1] */    case F_BRANCH_WHEN_NE: /* sp[-2] != sp[-1] */   /* START_JUMP();*/    amd64_load_sp_reg();    mov_mem16_reg( sp_reg, -sizeof(struct svalue), REG_RAX );    mov_mem16_reg( sp_reg, -sizeof(struct svalue)*2,REG_RBX );    cmp_reg_reg( REG_RAX, REG_RBX );    jnz( &label_A ); /* Types differ */ -  cmp_reg_imm( REG_RAX, PIKE_T_OBJECT ); +  cmp_reg32_imm( REG_RAX, PIKE_T_OBJECT );    je( &label_A ); /* Do not even bother with objects.. */       mov_mem_reg( sp_reg, -sizeof(struct svalue)+8, REG_RBX );    sub_reg_mem( REG_RBX, sp_reg, -sizeof(struct svalue)*2+8);    /* RBX will now be 0 if they are equal.*/       /* Optimization: The types are equal, pop_stack can be greatly    * simplified if they are < max_reg_type */ -  cmp_reg_imm( REG_RAX,MAX_REF_TYPE+1); +  cmp_reg32_imm( REG_RAX,MAX_REF_TYPE+1);    jl( &label_B );    /* cheap pop. We know that both are >= max_ref_type */    amd64_add_sp( -2 );    jmp( &label_D );       LABEL_A; /* Fallback - call opcode. */    amd64_call_c_opcode( instrs[F_BRANCH_WHEN_NE-F_OFFSET].address,    instrs[F_BRANCH_WHEN_NE-F_OFFSET].flags );    amd64_load_sp_reg();    /* Opcode returns 0 if equal, -1 if not. */
pike.git/src/code/amd64.c:1759:    break; /* Fallback to C-version. */       case F_ADD_NEG_INT:    b = -b;       case F_ADD_INT:    {    LABELS();    amd64_load_sp_reg();    mov_mem16_reg( sp_reg, -sizeof(struct svalue), REG_RAX ); -  cmp_reg_imm( REG_RAX,PIKE_T_INT ); +  cmp_reg32_imm( REG_RAX,PIKE_T_INT );    jne( &label_A );    mov_mem_reg(sp_reg,    -sizeof(struct svalue)+OFFSETOF(svalue,u.integer),    REG_RAX );    test_reg( REG_RAX );    jz( &label_C );       add_reg_imm( REG_RAX, b );    jo( &label_A ); /* if overflow, use f_add */    mov_reg_mem( REG_RAX,sp_reg,
pike.git/src/code/amd64.c:1899:    {    LABELS();    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_load_fp_reg();    amd64_load_sp_reg();       mov_mem_reg( fp_reg, OFFSETOF(pike_frame,locals), ARG1_REG);    add_reg_imm( ARG1_REG, b*sizeof(struct svalue));    mov_sval_type( ARG1_REG, REG_RAX );    /* type in RAX, svalue in ARG1 */ -  cmp_reg_imm( REG_RAX, PIKE_T_ARRAY ); +  cmp_reg32_imm( REG_RAX, PIKE_T_ARRAY );    jne( &label_A );    /* It's an array */    /* move arg to point to the array */    mov_mem_reg( ARG1_REG, OFFSETOF(svalue, u.array ), ARG1_REG);    /* load size -> RAX*/    mov_mem32_reg( ARG1_REG,OFFSETOF(array, size), REG_RAX );    jmp( &label_C );    LABEL_A; -  cmp_reg_imm( REG_RAX, PIKE_T_STRING ); +  cmp_reg32_imm( REG_RAX, PIKE_T_STRING );    jne( &label_B );    /* It's a string */    /* move arg to point to the string */    mov_mem_reg( ARG1_REG, OFFSETOF(svalue, u.string ), ARG1_REG);    /* load size ->RAX*/    mov_mem32_reg( ARG1_REG,OFFSETOF(pike_string, len ), REG_RAX );    jmp( &label_C );    LABEL_B;    /* It's something else, svalue already in ARG1. */    amd64_call_c_function( pike_sizeof );
pike.git/src/code/amd64.c:1934:    return;       case F_GLOBAL:    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_load_fp_reg();    amd64_load_sp_reg();    mov_mem_reg(fp_reg, OFFSETOF(pike_frame, context), ARG3_REG);    mov_mem_reg(fp_reg, OFFSETOF(pike_frame, current_object),    ARG2_REG);    mov_reg_reg(sp_reg, ARG1_REG); -  mov_mem32_reg(ARG3_REG, OFFSETOF(inherit, identifier_level), +  mov_mem16_reg(ARG3_REG, OFFSETOF(inherit, identifier_level),    ARG3_REG); -  and_reg_imm(ARG3_REG, 0xffff); +     add_reg_imm(ARG3_REG, b);    flush_dirty_regs(); /* In case an error is thrown. */    call_imm(low_object_index_no_free);    /* NB: We know that low_object_index_no_free() doesn't    * mess with the stack pointer. */    amd64_add_sp(1);    return;       case F_LOCAL:    ins_debug_instr_prologue(a-F_OFFSET, b, 0);
pike.git/src/code/amd64.c:1972:    return;       case F_INC_LOCAL_AND_POP:    {    LABELS();    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_load_fp_reg();    mov_mem_reg(fp_reg, OFFSETOF(pike_frame, locals), REG_RCX);    add_reg_imm(REG_RCX, b*sizeof(struct svalue));    mov_sval_type(REG_RCX, REG_RAX); -  cmp_reg_imm(REG_RAX, PIKE_T_INT); +  cmp_reg32_imm(REG_RAX, PIKE_T_INT);    jne(&label_A);    /* Integer - Zap subtype and try just incrementing it. */    mov_reg_mem32(REG_RAX, REG_RCX, OFFSETOF(svalue, type));    add_imm_mem(1, REG_RCX, OFFSETOF(svalue, u.integer));    jno(&label_B);    add_imm_mem(-1, REG_RCX, OFFSETOF(svalue, u.integer));    LABEL_A;    /* Fallback to the C-implementation. */    update_arg1(b);    amd64_call_c_opcode(instrs[a-F_OFFSET].address,
pike.git/src/code/amd64.c:2006:    return;       case F_DEC_LOCAL_AND_POP:    {    LABELS();    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_load_fp_reg();    mov_mem_reg(fp_reg, OFFSETOF(pike_frame, locals), REG_RCX);    add_reg_imm(REG_RCX, b*sizeof(struct svalue));    mov_sval_type(REG_RCX, REG_RAX); -  cmp_reg_imm(REG_RAX, PIKE_T_INT); +  cmp_reg32_imm(REG_RAX, PIKE_T_INT);    jne(&label_A);    /* Integer - Zap subtype and try just decrementing it. */    mov_reg_mem32(REG_RAX, REG_RCX, OFFSETOF(svalue, type));    add_imm_mem(-1, REG_RCX, OFFSETOF(svalue, u.integer));    jno(&label_B);    add_imm_mem(1, REG_RCX, OFFSETOF(svalue, u.integer));    LABEL_A;    /* Fallback to the C-implementation. */    update_arg1(b);    amd64_call_c_opcode(instrs[a-F_OFFSET].address,
pike.git/src/code/amd64.c:2111:   {    LABELS();    if (!(instrs[op - F_OFFSET].flags & I_BRANCH)) return -1;       switch( op )    {    case F_BRANCH_IF_NOT_LOCAL:    case F_BRANCH_IF_LOCAL:    ins_debug_instr_prologue(op-F_OFFSET, a, 0);    amd64_load_fp_reg(); -  mov_mem_reg( fp_reg, OFFSETOF(pike_frame, locals), REG_RAX); -  add_reg_imm( REG_RAX, a*sizeof(struct svalue)); -  /* if( type == PIKE_T_OBJECT ) -  call c version... -  else if( integer ) +  mov_mem_reg( fp_reg, OFFSETOF(pike_frame, locals), ARG1_REG); +  add_reg_imm( ARG1_REG, a*sizeof(struct svalue)); +  /* if( type == PIKE_T_INT )    u.integer -> RAX -  +  else if( type == PIKE_T_OBJECT || type == PIKE_T_FUNCTION ) +  call svalue_is_true(&local)    else    1 -> RAX -  +  +  The tests are ordered assuming integers are most commonly +  checked. That is not nessasarily true.    */ -  mov_sval_type( REG_RAX, REG_RCX ); -  cmp_reg_imm( REG_RCX, PIKE_T_OBJECT ); -  jne( &label_A ); -  cmp_reg_imm( REG_RCX, PIKE_T_INT ); -  jne( &label_B ); /* RAX is already true (pointer to local) */ +  mov_sval_type( ARG1_REG, REG_RCX ); +  cmp_reg32_imm( REG_RCX, PIKE_T_INT ); je( &label_C ); + #if 0 +  cmp_reg32_imm( REG_RCX, PIKE_T_OBJECT ); je( &label_A ); +  cmp_reg32_imm( REG_RCX, PIKE_T_FUNCTION ); je( &label_A ); +  /* Not object, int or function. Always true. */    -  update_arg1(a); -  /* Note: Always call IF_LOCAL, the negation is done below. */ -  amd64_call_c_opcode( instrs[F_BRANCH_IF_LOCAL-F_OFFSET].address, -  instrs[F_BRANCH_IF_LOCAL-F_OFFSET].flags ); +  mov_imm_reg( 1, REG_RAX );    jmp( &label_B ); -  LABEL_A; -  mov_mem_reg( REG_RAX, OFFSETOF(svalue, u.integer ), REG_RAX ); + #endif +  amd64_call_c_function(svalue_is_true); +  jmp( &label_B ); +  +  LABEL_C; +  mov_mem_reg( ARG1_REG, OFFSETOF(svalue, u.integer ), REG_RAX ); +  /* integer. */ +     LABEL_B;    test_reg( REG_RAX );    if( op == F_BRANCH_IF_LOCAL )    return jnz_imm_rel32(0);    return jz_imm_rel32(0);    }       maybe_update_pc();    update_arg1(a);    return amd64_ins_f_jump(op, backward_jump);
pike.git/src/code/amd64.c:2172:    LABELS();    ins_debug_instr_prologue(a-F_OFFSET, b, 0);    amd64_load_fp_reg();    mov_mem_reg( fp_reg, OFFSETOF(pike_frame, locals), ARG1_REG);    add_reg_imm( ARG1_REG, b*sizeof(struct svalue) );       /* arg1 = dst    arg2 = int    */    mov_sval_type( ARG1_REG, REG_RAX ); -  cmp_reg_imm( REG_RAX, PIKE_T_INT ); +  cmp_reg32_imm( REG_RAX, PIKE_T_INT );    jne(&label_A); /* Fallback */    mov_imm_mem( PIKE_T_INT, ARG1_REG, OFFSETOF(svalue,type));    add_imm_mem( c, ARG1_REG,OFFSETOF(svalue,u.integer));    jno( &label_B);    add_imm_mem( -c, ARG1_REG,OFFSETOF(svalue,u.integer));    /* Overflow. Use C version */    LABEL_A;    update_arg2(c);    update_arg1(b);    ins_f_byte(a);
pike.git/src/code/amd64.c:2214:    add_reg_imm( ARG1_REG, b*sizeof(struct svalue) );    add_reg_imm_reg( ARG1_REG,(c-b)*sizeof(struct svalue), ARG2_REG );       /* arg1 = dst    arg2 = src    */    mov_sval_type( ARG1_REG, REG_RAX );    mov_sval_type( ARG2_REG, REG_RBX );    shl_reg_imm( REG_RAX, 8 );    add_reg_reg( REG_RAX, REG_RBX ); -  cmp_reg_imm( REG_RAX, (PIKE_T_INT<<8) | PIKE_T_INT ); +  cmp_reg32_imm( REG_RAX, (PIKE_T_INT<<8) | PIKE_T_INT );    jne(&label_A); /* Fallback */    mov_mem_reg( ARG2_REG, OFFSETOF(svalue,u.integer), REG_RAX );    add_reg_mem( REG_RAX, ARG1_REG, OFFSETOF(svalue,u.integer));    jo( &label_A);    /* Clear subtype */    mov_imm_mem( PIKE_T_INT, ARG1_REG,OFFSETOF(svalue,type));    mov_reg_mem( REG_RAX, ARG1_REG, OFFSETOF(svalue,u.integer));    jmp( &label_B );       LABEL_A;