Branch: Tag:

2014-12-04

2014-12-04 19:27:19 by Per Hedbor <ph@opera.com>

Added F_UNDEFINEDP as an opcode

Also added a convenience SVAL(X) macro that returns the offset to
different parts of the svalue X values from the base register.

Also added some usage of the SVAL function in a few places.

Chagned to 32-bit arithmetics for types in a few locations. It saves
on code size, if nothing else (no REX prefix unless R8.. is used)

45:   #define REG_R14 MISSING_P_   #define REG_R15 MISSING_P_    + struct soff { int off; int type; int value; };    -  + static struct soff SVAL(int i) + { +  struct soff res; +  res.off = res.type = i*sizeof(struct svalue); +  res.value = res.type + 8; +  return res; + } +    /* Register encodings */   enum amd64_reg {P_REG_RAX = 0, P_REG_RBX = 3, P_REG_RCX = 1, P_REG_RDX = 2,    P_REG_RSP = 4, P_REG_RBP = 5, P_REG_RSI = 6, P_REG_RDI = 7,
214:    modrm( 3, from_reg, to_reg );   }    + static void mov_reg32_reg(enum amd64_reg from_reg, enum amd64_reg to_reg ) + { +  rex( 0, from_reg, 0, to_reg ); +  opcode( 0x89 ); +  modrm( 3, from_reg, to_reg ); + } +    #define PUSH_INT(X) ins_int((INT32)(X), (void (*)(char))add_to_program)   static void low_mov_mem_reg(enum amd64_reg from_reg, ptrdiff_t offset,    enum amd64_reg to_reg)
1078:      static void mov_sval_type(enum amd64_reg src, enum amd64_reg dst )   { -  mov_mem8_reg( src, OFFSETOF(svalue, tu.t.type), dst); +  mov_mem8_reg( src, SVAL(0).type, dst);   /* and_reg32_imm( dst, 0x1f );*/   }   
1118:   static void amd64_add_sp( int num )   {    amd64_load_sp_reg(); -  add_reg_imm( sp_reg, sizeof(struct svalue)*num); +  add_reg_imm( sp_reg, num * sizeof(struct svalue));    dirty_regs |= 1 << PIKE_SP_REG;    flush_dirty_regs(); /* FIXME: Need to change LABEL handling to remove this */   }
1126:   static void amd64_add_mark_sp( int num )   {    amd64_load_mark_sp_reg(); -  add_reg_imm( mark_sp_reg, sizeof(struct svalue*)*num); +  add_reg_imm( mark_sp_reg, num * sizeof(struct svalue*));    dirty_regs |= 1 << PIKE_MARK_SP_REG;    flush_dirty_regs(); /* FIXME: Need to change LABEL handling to remove this */   }
1140:    amd64_load_sp_reg();    mov_mem_reg(reg, OFFSETOF(svalue, tu.t.type), P_REG_RAX);    mov_mem_reg(reg, OFFSETOF(svalue, u.refs), P_REG_RCX); -  mov_reg_mem(P_REG_RAX, sp_reg, -  spoff*sizeof(struct svalue)+OFFSETOF(svalue, tu.t.type)); -  mov_reg_mem(P_REG_RCX, sp_reg, -  spoff*sizeof(struct svalue)+OFFSETOF(svalue, u.refs)); +  mov_reg_mem(P_REG_RAX, sp_reg, SVAL(spoff).type); +  mov_reg_mem(P_REG_RCX, sp_reg, SVAL(spoff).value);    and_reg32_imm(P_REG_RAX, MIN_REF_TYPE);    jz(&label_A);    add_imm_mem( 1, P_REG_RCX, OFFSETOF(pike_string, refs));
1159:   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, tu.t.type)); -  mov_imm_mem(value, sp_reg, OFFSETOF(svalue, u.integer)); +  mov_imm_mem((subtype<<16) + PIKE_T_INT, sp_reg, SVAL(0).type); +  mov_imm_mem(value, sp_reg, SVAL(0).value);    amd64_add_sp( 1 );   }   
1211:    call_imm(addr);   }    - static void amd64_free_svalue(enum amd64_reg src, int guaranteed_ref ) + static void amd64_free_svalue_off(enum amd64_reg src, int off, int guaranteed_ref )   {    LABELS();    if( src == P_REG_RAX )    Pike_fatal("Clobbering RAX for free-svalue\n");    /* load type -> RAX */ -  mov_sval_type( src, P_REG_RAX ); -  +  mov_mem8_reg( src, off, P_REG_RAX );    and_reg_imm(P_REG_RAX, MIN_REF_TYPE);    jz( &label_A );       /* Load pointer to refs -> RAX */ -  mov_mem_reg( src, OFFSETOF(svalue, u.refs), P_REG_RAX); +  mov_mem_reg( src,off+OFFSETOF(svalue, u.refs), P_REG_RAX);    /* if( !--*RAX ) */    add_mem32_imm( P_REG_RAX, OFFSETOF(pike_string,refs), -1);    if( !guaranteed_ref )
1231:    /* We need to see if refs got to 0. */    jnz( &label_A );    /* if so, call really_free_svalue */ -  if( src != ARG1_REG ) -  mov_reg_reg( src, ARG1_REG ); +  add_reg_imm_reg( src, off, ARG1_REG );    amd64_call_c_function(really_free_svalue);    }    LABEL_A;   }    -  + static void amd64_free_svalue(enum amd64_reg src, int guaranteed_ref ) + { +  amd64_free_svalue_off(src,0,guaranteed_ref); + } +    /* Type already in register. Note: Clobbers the type register. */   static void amd64_free_svalue_type(enum amd64_reg src, enum amd64_reg type,    int guaranteed_ref )
1536:      void amd64_init_interpreter_state(void)   { + #ifdef PIKE_DEBUG +  if( PIKE_T_INT != 0 ) +  Pike_fatal("assumption failed: pike_t_int == 0\n"); +  if( sizeof(struct svalue) != 16 ) +  Pike_fatal("assumption failed: sizeof svalue != 16\n"); +  if( OFFSETOF(svalue,tu.t.type) != 0 ) +  Pike_fatal("assumption failed: offsetof(svalue.tu.t.type) != 0\n"); +  if( OFFSETOF(svalue,u.integer) != 8 ) +  Pike_fatal("assumption failed: offsetof(svalue.u.integer) != 8\n"); + #endif    instrs[F_CATCH - F_OFFSET].address = inter_return_opcode_F_CATCH;   }   
1925:    rel_addr = PIKE_PC;    }    break; +  +  /* sp-1 = undefinedp(sp-1) */ +  case F_UNDEFINEDP: +  { +  LABELS(); +  ins_debug_instr_prologue(b, 0, 0); +  amd64_load_sp_reg(); +  +  mov_mem32_reg( sp_reg, SVAL(-1).type, P_REG_RAX ); +  cmp_reg32_imm( P_REG_RAX, 1<<16 | PIKE_T_INT ); +  jne( &label_A ); +  mov_imm_mem( 1, sp_reg,SVAL(-1).value); +  jmp( &label_B ); +  LABEL_A; +  amd64_free_svalue_off( sp_reg, SVAL(-1).off,0 ); +  mov_imm_mem( 0, sp_reg,SVAL(-1).value); +  LABEL_B; +  mov_imm_mem( PIKE_T_INT, sp_reg,SVAL(-1).type); +  } +  return; +     case F_ZERO_TYPE:    {    LABELS();
1932:    amd64_load_sp_reg();    mov_mem32_reg( sp_reg, -sizeof(struct svalue), P_REG_RAX );    /* Rax now has type + subtype. */ -  mov_reg_reg( P_REG_RAX, P_REG_RBX ); -  and_reg_imm( P_REG_RAX, 0x1f ); +  mov_reg32_reg( P_REG_RAX, P_REG_RBX ); +  and_reg32_imm( P_REG_RAX, 0x1f );    cmp_reg32_imm( P_REG_RAX, PIKE_T_INT );    jne( &label_A );    /* It is an integer. */
2101:    amd64_load_fp_reg();    /* Note: really mem16, but we & with PIKE_FRAME_RETURN_INTERNAL anyway */    mov_mem32_reg( fp_reg, OFFSETOF(pike_frame, flags), P_REG_RAX ); -  and_reg_imm( P_REG_RAX, PIKE_FRAME_RETURN_INTERNAL); +  and_reg32_imm( P_REG_RAX, PIKE_FRAME_RETURN_INTERNAL);    jnz( &label_A );    /* So, it is just a normal return. */    LABEL_B;
2112:    LABEL_A;    /* We should jump to the given address. */    mov_mem32_reg( fp_reg, OFFSETOF(pike_frame, flags), P_REG_RAX ); -  and_reg_imm( P_REG_RAX, PIKE_FRAME_RETURN_POP ); +  and_reg32_imm( P_REG_RAX, PIKE_FRAME_RETURN_POP );    jnz( &label_C );    amd64_call_c_function( low_return );    jmp( &label_D );
2136:    /* NB: We only care about subtype 1! */    cmp_reg32_imm(P_REG_RAX, (1<<16)|PIKE_T_STRING);    jne(&label_A); -  and_reg_imm(P_REG_RAX, 0x1f); +  and_reg32_imm(P_REG_RAX, 0x1f);    mov_reg_mem32(P_REG_RAX,    sp_reg, OFFSETOF(svalue, tu.t.type) - sizeof(struct svalue));    LABEL_A;