< November 2005 >
SuMoTuWeThFrSa
   1 2 3 4 5
6 7 8 9101112
13141516171819
20212223242526
27282930   
Thu, 03 Nov 2005:

More work on the unroller. Mainly comparison, shift and conditionals for AMD64. The code is pretty simple. It is for all practical purposes identical to the x86 versions. For example, the shift code looks something like this.


md_inst_ptr _md_amd64_shift(md_inst_ptr inst, 
                            int opc, 
                            int reg1, 
                            int reg2)
{
    if(reg2 == AMD64_RCX)
    {
        /* The shift value is already in ECX */
        amd64_shift_reg_size(inst, opc, reg1, 4);
    }
    else if(reg1 == AMD64_RCX)
    {
        /* The value to be shifted is in ECX, so swap the order */
        amd64_xchg_reg_reg(inst, reg1, reg2, 4);
        amd64_shift_reg_size(inst, opc, reg2, 4);
        amd64_mov_reg_reg(inst, reg1, reg2, 4);
    }
    else
    {
        /* Save ECX, perform the shift, and then restore ECX */
        amd64_push_reg(inst, AMD64_RCX);
        amd64_mov_reg_reg(inst, AMD64_RCX, reg2, 4);
        amd64_shift_reg_size(inst, opc, reg1, 4);
        amd64_pop_reg(inst, AMD64_RCX);
    }
    return inst;
}

Now, who can complain that I don't comment my code (like War2 did the last time I showed him some of my PPC JIT code). The reason the above code i so long is simply due to the fact that the shift instruction has RCX as the implied value to shift. Are there anybody here who didn't actually understand what the above code does to work around that ? :). Ok, so let's look at the PPC equivalent, shall we ?

#define	md_shl_reg_reg_word_32(inst,reg1,reg2)	\
			ppc_alu_reg_sds((inst), PPC_SL, (reg1), (reg1), (reg2))

It is a single instruction - PPC_SL, which accepts 3 registers. Do you see how much cleaner PowerPC is in comparison to the implied argument shit in x86. And all registers are equal in PPC - so I can probably do R7 = R7 << R7 and have it work directly. I can imagine the amount of heartburn the guys who did the x86 optimizations went through. For now, I am one of them.

--
If code is poetry, I write limericks.

posted at: 20:50 | path: /dotgnu | permalink | Tags:

Yesterday evening (as in 7:30 PM) I started writing a gaim plugin for myself. This thing would tell me who exactly is talking to me. For example, if I wanted to talk to lunatech3007, I get the following.

It will tell me what this guy who's pinging me does in Yahoo !. The plugin was pretty simple enough to write - except of doubts about what to do with the g_free vs free functions. Did you know that all memory allocated with g_new0 has to be g_free'd. In hindsight, it does make a lot of sense. Here's some code for the coding oriented. I hook into the "conversation-created" signal with the gaim_new_conversation callback.

gaim_signal_connect(conv_handle, "conversation-created", plugin, 
                    GAIM_CALLBACK(gaim_new_conversation), NULL);

In the conversation-created, I use libcurl to fetch the HTML of the employee search. Use regex.h to extract the name, title and email-id. It's pretty much standard POSIX regex to extract the data required.

reg_err = regexec(&title_pattern, html, 3, matches, 0);
if(!reg_err)
{
    int start, len;
    start = matches[1].rm_so;
    len = matches[1].rm_eo - matches[1].rm_so;
    if(len != 0)
    {
        data->title = calloc(len+1, sizeof(char));
        memcpy(data->title, &html[start], len);
    }
}

Finally having got all the data, it is written out to the user as a system-message.

gaim_conversation_write(conv, NULL, message,
                        GAIM_MESSAGE_SYSTEM,
                        time(NULL));

Also add an in-memory cache so that it doesn't hit the webpage for each and every conversation. Had to spend quite some time fiddling with the hash functions till I got the hang of it. I already had a string hash function that I use regularly in C when I need hashtables - but sometimes it is better to go with the standard stuff.


user_data_cache = g_cache_new(get_user_data,
                              destroy_user_data,
                              (GCacheDupFunc)g_strdup,
                              g_free,
                              g_str_hash,
                              user_data_hash_func, 
                              g_str_equal);
....
static guint user_data_hash_func(gconstpointer key)
{
	if(key == NULL) return 0;

	return g_str_hash(((user_data *)key)->id);
}

Finally compile it up, push it into ~/.gaim/plugins/ and restart gaim. Navigate to the gaim plugin configuration and turn it on.

Starting from a simple sample, it didn't take me any time at all to get a working plugin. I have never written an easier plugin, the hard work was mainly to handle curl and get the regexes just right. I am too lazy to trim out the Yahoo! specific peices and throw out a really generic version, otherwise I'd have just pushed the code here.

posted at: 18:44 | path: /hacks | permalink | Tags: