Hi,
Did I make the P-code idea clear? I think a threaded interpreter would be
overkill, and also most of the fast TIL (Threaded Interpretive Language)
interpreters I've worked with would be difficult to make position
independent.
Here's some off-the-cuff code ideas.
Imagine that the device at address DEV_ADDR has bit DEV_INTR and clears the
interrupt when the register is written. So the P-code has to have a "bit
test word" operation, and a "store word" operation. Let's say BTST skips
an instruction when the bit IS set.
#define PCODE_BTST 1 /* Test a bit in a word */
#define PCODE_STZERO 2 /* Store 0 -> word */
#define PCODE_RET_TRUE 3 /* Return boolean true */
#define PCODE_RET_FALSE 4 /* ...false */
#define PCODE_MAX 4 /* Highest legal opcode */
ulong test_device_pcode[] = {
PCODE_BTST, DEV_ADDR, DEV_INTR,
PCODE_RET_FALSE,
PCODE_STZERO, DEV_ADDR,
PCODE_RET_TRUE
};
Now you register it with:
enable_isr(port, irq, test_device_pcode, sizeof(test_device_pcode));
The kernel copies in the code, stores it somewhere, and so forth. The
interpreter would look something like:
/*
* Size of each instruction
*/
static int interp_size[] = {
3, /* BTST */
2, /* STZERO */
1, /* RET_TRUE */
1 /* RET_FALSE */
};
interp_pcode(ulong *pc)
{
ulong instr, *addr;
uint bit;
for (;;) {
instr = *pc++;
switch (instr) {
case PCODE_BTST:
addr = (ulong *)*pc++;
bit = *pc++;
if (*addr & (1 << bit)) {
ASSERT_DEBUG(*pc <= PCODE_MAX, "interp_pcode: bad skip");
pc += interp_size[*pc];
}
break;
case PCODE_RET_FALSE:
return(0);
case PCODE_RET_TRUE:
return(1);
case PCODE_STZERO:
addr = (ulong *)*pc++;
*addr = 0;
break;
default:
ASSERT(0, "interp_pcode: bad instruction");
}
}
}
Regards,
Andy
Received on Fri Nov 11 08:47:55 1994
This archive was generated by hypermail 2.1.8 : Thu Sep 22 2005 - 15:12:10 PDT