示例#1
0
static int tpci200_free_irq(struct ipack_device *dev)
{
    struct slot_irq *slot_irq;
    struct tpci200_board *tpci200;

    tpci200 = check_slot(dev);
    if (tpci200 == NULL)
        return -EINVAL;

    if (mutex_lock_interruptible(&tpci200->mutex))
        return -ERESTARTSYS;

    if (tpci200->slots[dev->slot].irq == NULL) {
        mutex_unlock(&tpci200->mutex);
        return -EINVAL;
    }

    tpci200_disable_irq(tpci200, dev->slot);
    slot_irq = tpci200->slots[dev->slot].irq;
    /* uninstall handler */
    RCU_INIT_POINTER(tpci200->slots[dev->slot].irq, NULL);
    synchronize_rcu();
    kfree(slot_irq);
    mutex_unlock(&tpci200->mutex);
    return 0;
}
int32_t stapi_do_remove_filter(int32_t UNUSED(demux_id), FILTERTYPE *filter, int32_t dev_id) {
	if (filter->fd==0) return 0;

	uint32_t BufferDeallocateError=0, SlotDeallocateError=0;

	if (dev_list[dev_id].SessionHandle==0) return 0;

	int32_t k;
	for (k=0;k<filter->NumSlots;k++) {
		uint32_t checkslot = check_slot(dev_id, filter->SlotHandle[k], filter);

		if (checkslot==0) {
			BufferDeallocateError	= oscam_stapi_BufferDeallocate(filter->BufferHandle[k]);
			SlotDeallocateError		= oscam_stapi_SlotDeallocate(filter->SlotHandle[k]);
		}
	}
	uint32_t FilterDeallocateError		= oscam_stapi_FilterDeallocate(filter->fd);

	memset(filter, 0, sizeof(FILTERTYPE));

	if (BufferDeallocateError||SlotDeallocateError||FilterDeallocateError) {
		cs_log("remove_filter: dev: %d BD: %d SD: %d FDe: %d",
			dev_id, BufferDeallocateError, SlotDeallocateError, FilterDeallocateError);
		return 0;
	} else {
		return 1;
	}
}
示例#3
0
文件: tvme200.c 项目: dcobas/coht
static int tvme200_free_irq(struct ipack_device *dev)
{       
        struct tvme200_board *tvme200;
        
        tvme200 = check_slot(dev);

	return tvme200_free_irq_slot(tvme200, dev->slot);
}
示例#4
0
文件: tvme200.c 项目: dcobas/coht
static int tvme200_request_irq(struct ipack_device *dev, irqreturn_t (*handler)(void *), void *arg)
{

	
	int res = 0;
	struct slot_irq *slot_irq;
	struct tvme200_board *tvme200;
	void *irq_reg;
	
	tvme200 = check_slot(dev);
	if (tvme200 == NULL)
		return -EINVAL;

	if (mutex_lock_interruptible(&tvme200->mutex))
		return -ERESTARTSYS;

	if (tvme200->slots[dev->slot].irq != NULL) {
		dev_err(&dev->dev,
			"Slot [%d:%d] IRQ already registered !\n",
			dev->bus->bus_nr,
			dev->slot);
		res = -EINVAL;
		goto out_unlock;
	}

	slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL);
	if (slot_irq == NULL) {
		dev_err(&dev->dev,
			"Slot [%d:%d] unable to allocate memory for IRQ !\n",
			dev->bus->bus_nr, dev->slot);
		res = -ENOMEM;
		goto out_unlock;
	}

	/*
	 * WARNING: Setup Interrupt Vector in the IndustryPack device
	 * before an IRQ request.
	 * Read the User Manual of your IndustryPack device to know
	 * where to write the vector in memory.
	 */
	slot_irq->vector = irq[(4 * tvme200->number) + dev->slot];
	slot_irq->handler = (int (*)(void *))(handler); /* FIXME: ugly casting, its ok? */
	slot_irq->arg = arg;
	slot_irq->holder = dev;
	sprintf(slot_irq->name, "ipackdev_%d_%d", tvme200->lun, dev->slot);

	rcu_assign_pointer(tvme200->slots[dev->slot].irq, slot_irq);

	irq_reg = ioremap_nocache(tvme200->mod_mem[IPACK_INT_SPACE] + 
			TVME200_INT_SPACE_INTERVAL * dev->slot, TVME200_ID_SPACE_SIZE);

	iowrite8(slot_irq->vector, irq_reg);
	res = vme_request_irq(slot_irq->vector, slot_irq->handler, slot_irq->arg, slot_irq->name);

out_unlock:
	mutex_unlock(&tvme200->mutex);
	return res;
}
int32_t stapi_do_set_filter(int32_t demux_id, FILTERTYPE *filter, uint16_t *pids, int32_t pidcount, uchar *filt, uchar *mask, int32_t dev_id) {
	uint32_t FilterAssociateError=0;
	int32_t k, ret=0;

	filter->fd			= 0;
	filter->BufferHandle[0] 	= 0;
	filter->SlotHandle[0]	= 0;

	if (dev_list[dev_id].SessionHandle==0) return 0;

	uint32_t FilterAllocateError = oscam_stapi_FilterAllocate(dev_list[dev_id].SessionHandle, &filter->fd);

	if (FilterAllocateError != 0) {
		cs_log("FilterAllocate problem");
		filter->fd=0;
		return 0;
	}

	for (k=0;k<pidcount;k++) {
		uint16_t pid = pids[k];

		uint32_t QuerySlot = oscam_stapi_PidQuery(dev_list[dev_id].name, pid);
		int32_t SlotInit=1;

		if (QuerySlot != 0) {
			uint32_t checkslot = check_slot(dev_id, QuerySlot, NULL);
			if (checkslot>0) {
				filter->SlotHandle[k] = QuerySlot;
				filter->BufferHandle[k] = checkslot;
				SlotInit=0;
			} else {
				cs_log("overtake: clear pid: %d", oscam_stapi_SlotClearPid(QuerySlot));
				SlotInit=1;
			}
		}

		if (SlotInit==1) {
			ret = oscam_stapi_SlotInit(dev_list[dev_id].SessionHandle, dev_list[dev_id].SignalHandle, &filter->BufferHandle[k], &filter->SlotHandle[k], pid);
		}

		FilterAssociateError = oscam_stapi_FilterAssociate(filter->fd, filter->SlotHandle[k]);
		filter->NumSlots++;
	}

	uint32_t FilterSetError			= oscam_stapi_FilterSet(filter->fd, filt, mask);

	if (ret || FilterAllocateError || FilterAssociateError || FilterSetError) {
		cs_log("set_filter: dev: %d FAl: %d FAs: %d FS: %d",
			dev_id, FilterAllocateError, FilterAssociateError, FilterSetError);
		stapi_do_remove_filter(demux_id, filter, dev_id);
		return 0;
	} else {
		return 1;
	}
}
示例#6
0
static int tpci200_get_clockrate(struct ipack_device *dev)
{
    struct tpci200_board *tpci200 = check_slot(dev);
    __le16 __iomem *addr;

    if (!tpci200)
        return -ENODEV;

    addr = &tpci200->info->interface_regs->control[dev->slot];
    return (ioread16(addr) & TPCI200_CLK32) ? 32 : 8;
}
示例#7
0
static char *
string_slot(int slot) {

    check_slot(slot, TRUE, TRUE);
    if (stack_slot(slot).store_type != TYPE_STRING) {
        print_dynamic_context();
        fprintf(stderr, "slot %d doesn't contain a string\n", slot);
        found_error = TRUE;
    }

    return stack_slot(slot).string_val;
}
示例#8
0
static float
real_slot(int slot) {

    check_slot(slot, TRUE, TRUE);
    if (stack_slot(slot).store_type != TYPE_REAL) {
        print_dynamic_context();
        fprintf(stderr, "slot %d doesn't contain a real\n", slot);
        found_error = TRUE;
    }

    return stack_slot(slot).real_val;
}
示例#9
0
static int
int_slot(int slot) {

    check_slot(slot, TRUE, TRUE);
    if (stack_slot(slot).store_type != TYPE_INT) {
        print_dynamic_context();
        fprintf(stderr, "slot %d doesn't contain an int\n", slot);
        found_error = TRUE;
    }

    return stack_slot(slot).int_val;
}
示例#10
0
static int tpci200_get_error(struct ipack_device *dev)
{
    struct tpci200_board *tpci200 = check_slot(dev);
    __le16 __iomem *addr;
    u16 mask;

    if (!tpci200)
        return -ENODEV;

    addr = &tpci200->info->interface_regs->status;
    mask = tpci200_status_error[dev->slot];
    return (ioread16(addr) & mask) ? 1 : 0;
}
示例#11
0
static int tpci200_request_irq(struct ipack_device *dev,
                               irqreturn_t (*handler)(void *), void *arg)
{
    int res = 0;
    struct slot_irq *slot_irq;
    struct tpci200_board *tpci200;

    tpci200 = check_slot(dev);
    if (tpci200 == NULL)
        return -EINVAL;

    if (mutex_lock_interruptible(&tpci200->mutex))
        return -ERESTARTSYS;

    if (tpci200->slots[dev->slot].irq != NULL) {
        dev_err(&dev->dev,
                "Slot [%d:%d] IRQ already registered !\n",
                dev->bus->bus_nr,
                dev->slot);
        res = -EINVAL;
        goto out_unlock;
    }

    slot_irq = kzalloc(sizeof(struct slot_irq), GFP_KERNEL);
    if (slot_irq == NULL) {
        dev_err(&dev->dev,
                "Slot [%d:%d] unable to allocate memory for IRQ !\n",
                dev->bus->bus_nr, dev->slot);
        res = -ENOMEM;
        goto out_unlock;
    }

    /*
     * WARNING: Setup Interrupt Vector in the IndustryPack device
     * before an IRQ request.
     * Read the User Manual of your IndustryPack device to know
     * where to write the vector in memory.
     */
    slot_irq->handler = handler;
    slot_irq->arg = arg;
    slot_irq->holder = dev;

    rcu_assign_pointer(tpci200->slots[dev->slot].irq, slot_irq);
    tpci200_enable_irq(tpci200, dev->slot);

out_unlock:
    mutex_unlock(&tpci200->mutex);
    return res;
}
示例#12
0
static int tpci200_reset_timeout(struct ipack_device *dev)
{
    struct tpci200_board *tpci200 = check_slot(dev);
    __le16 __iomem *addr;
    u16 mask;

    if (!tpci200)
        return -ENODEV;

    addr = &tpci200->info->interface_regs->status;
    mask = tpci200_status_timeout[dev->slot];

    iowrite16(mask, addr);
    return 0;
}
示例#13
0
static int32_t stapi_do_remove_filter(int32_t UNUSED(demux_id), FILTERTYPE *filter, int32_t dev_id)
{
    if(filter->fd == 0) {
        return 0;
    }

    uint32_t BufferDeallocateError = 0, SlotDeallocateError = 0, FilterDeallocateError = 0;

    if(dev_list[dev_id].SessionHandle == 0) {
        return 0;
    }

    int32_t k;
    for(k = 0; k < filter->NumSlots; k++)
    {
        uint32_t checkslot = check_slot(dev_id, filter->SlotHandle[k], filter);

        if(checkslot == 0)
        {
            FilterDeallocateError   = oscam_stapi5_FilterDeallocate(filter->fd, filter->BufferHandle[k], filter->SlotHandle[k]);

            oscam_stapi5_SlotClearPid(filter->SlotHandle[k]);
            oscam_stapi5_SlotUnlink(filter->SlotHandle[k]);
            oscam_stapi5_SignalDisassociateBuffer(dev_list[dev_id].SignalHandle, filter->BufferHandle[k]);

            BufferDeallocateError   = oscam_stapi5_BufferDeallocate(filter->BufferHandle[k]);
            SlotDeallocateError     = oscam_stapi5_SlotDeallocate(filter->SlotHandle[k]);

        }
    }

    memset(filter, 0, sizeof(FILTERTYPE));

    if(BufferDeallocateError || SlotDeallocateError || FilterDeallocateError)
    {
        cs_log("remove_filter: dev: %d BD: %d SD: %d FDe: %d",
               dev_id, BufferDeallocateError, SlotDeallocateError, FilterDeallocateError);
        return 0;
    }
    else
    {
        return 1;
    }
}
示例#14
0
static int tpci200_set_clockrate(struct ipack_device *dev, int mherz)
{
    struct tpci200_board *tpci200 = check_slot(dev);
    __le16 __iomem *addr;

    if (!tpci200)
        return -ENODEV;

    addr = &tpci200->info->interface_regs->control[dev->slot];

    switch (mherz) {
    case 8:
        tpci200_clear_mask(tpci200, addr, TPCI200_CLK32);
        break;
    case 32:
        tpci200_set_mask(tpci200, addr, TPCI200_CLK32);
        break;
    default:
        return -EINVAL;
    }
    return 0;
}
示例#15
0
static void
execute_instr_at_pc(void) {

    Instr       *instr;
    int         i1, i2;
    float       r1, r2;
    char        *s1, *s2;
    int         l;
    char        *s;
    const char  *builtin_func;
    int         slot;
    int         offset;
    char        buf[1024];

    if (print_instrs) 
        printf("instr %d, pc %d: ", cur_instr, pc);

    instr = &instrs[pc];
    switch (instr->opcode) {

    case OP_PUSH_STACK_FRAME:
        if (print_instrs) 
            printf("push_stack_frame %d\n", instr->int_const);
        top_slot++;
        if (stack_check_overflow())
            break;
        stack[top_slot].store_valid = TRUE;
        stack[top_slot].store_type = TYPE_FRAME_SIZE;
        stack[top_slot].int_val = cur_frame_size;
        cur_frame_size = instr->int_const;
        top_slot += instr->int_const;
        if (stack_check_overflow())
            break;
        break;

    case OP_POP_STACK_FRAME:
        if (print_instrs) 
            printf("pop_stack_frame %d\n", instr->int_const);

        if (instr->int_const != cur_frame_size) {
            fprintf(stderr, "pop_stack_frame %d doesn't match "
                "previous push_stack_frame %d\n",
                instr->int_const, cur_frame_size);
            found_error = TRUE;
            break;
        }

        for (slot = 0; slot < instr->int_const; slot++) 
            stack_slot(slot).store_valid = FALSE;

        top_slot -= instr->int_const;

        cur_frame_size = stack[top_slot].int_val;
        stack[top_slot].store_valid = FALSE;
        top_slot--;
        break;

    case OP_LOAD:
        if (print_instrs) 
            printf("load r%d, %d\n", instr->rd, instr->int_const);

        check_slot(instr->int_const, TRUE, TRUE);
        regs[instr->rd] = stack_slot(instr->int_const);
        break;

    case OP_STORE:
        if (print_instrs) 
            printf("store %d, r%d\n", instr->int_const, instr->rs1);

        check_reg(instr->rs1);
        check_slot(instr->int_const, FALSE, TRUE);
        stack_slot(instr->int_const) = regs[instr->rs1];
        break;

    case OP_LOAD_ADDRESS:
        if (print_instrs) 
            printf("load_address r%d, %d\n", instr->rd, instr->int_const);

        check_slot(instr->int_const, FALSE, TRUE);
        set_reg_addr(instr->rd, top_slot - instr->int_const);
        break;

    case OP_LOAD_INDIRECT:
         if (print_instrs) 
            printf("load_indirect r%d, r%d\n", instr->rd, instr->rs1);

        offset = addr_reg(instr->rs1);
        check_offset(offset, TRUE, TRUE);       /* Must be valid */
        regs[instr->rd] = stack[offset];
        break;

    case OP_STORE_INDIRECT:
        if (print_instrs) 
            printf("store_indirect r%d, r%d\n", instr->rd, instr->rs1);

        check_reg(instr->rs1);
        offset = addr_reg(instr->rd);
        check_offset(offset, FALSE, TRUE);      /* Need not be valid */
        stack[offset] = regs[instr->rs1];
        break;

    case OP_INT_CONST:
        if (print_instrs) 
            printf("int_const r%d, %d\n", instr->rd, instr->int_const);

        set_reg_int(instr->rd, instr->int_const);
        break;

    case OP_REAL_CONST:
        if (print_instrs) 
            printf("real_const r%d, %f\n", instr->rd, instr->real_const);

        set_reg_real(instr->rd, instr->real_const);
        break;

    case OP_STRING_CONST:
        if (print_instrs) 
            printf("string_const r%d, %s\n", instr->rd, instr->string_const);

        set_reg_string(instr->rd, make_string_const(instr->string_const));
        break;

    case OP_ADD_INT:
        if (print_instrs) 
            printf("add_int r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 + i2);
        break;

    case OP_ADD_REAL:
        if (print_instrs) 
            printf("add_real r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        r1 = real_reg(instr->rs1);
        r2 = real_reg(instr->rs2);
        set_reg_real(instr->rd, r1 + r2);
        break;

    case OP_ADD_OFFSET:
        if (print_instrs) 
            printf("add_offset r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        offset = addr_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        offset += i2;
        check_offset(offset, FALSE, TRUE);
        set_reg_addr(instr->rd, offset);
        break;

    case OP_SUB_INT:
        if (print_instrs) 
            printf("sub_int r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 - i2);
        break;

    case OP_SUB_REAL:
        if (print_instrs) 
            printf("sub_real r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        r1 = real_reg(instr->rs1);
        r2 = real_reg(instr->rs2);
        set_reg_real(instr->rd, r1 - r2);
        break;

    case OP_SUB_OFFSET:
        if (print_instrs) 
            printf("sub_offset r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        offset = addr_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        offset -= i2;
        check_offset(offset, FALSE, TRUE);
        set_reg_addr(instr->rd, offset);
        break;

    case OP_MUL_INT:
        if (print_instrs) 
            printf("mul_int r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 * i2);
        break;

    case OP_MUL_REAL:
        if (print_instrs) 
            printf("mul_real r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        r1 = real_reg(instr->rs1);
        r2 = real_reg(instr->rs2);
        set_reg_real(instr->rd, r1 * r2);
        break;

    case OP_DIV_INT:
        if (print_instrs) 
            printf("div_int r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 / i2);
        break;

    case OP_DIV_REAL:
        if (print_instrs) 
            printf("div_real r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        r1 = real_reg(instr->rs1);
        r2 = real_reg(instr->rs2);
        set_reg_real(instr->rd, r1 / r2);
        break;

    case OP_CMP_EQ_INT:
        if (print_instrs) 
            printf("cmp_eq_int r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 == i2);
        break;

    case OP_CMP_NE_INT:
        if (print_instrs) 
            printf("cmp_ne_int r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 != i2);
        break;

    case OP_CMP_GT_INT:
        if (print_instrs) 
            printf("cmp_gt_int r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 > i2);
        break;

    case OP_CMP_GE_INT:
        if (print_instrs) 
            printf("cmp_ge_int r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 >= i2);
        break;

    case OP_CMP_LT_INT:
        if (print_instrs) 
            printf("cmp_lt_int r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 < i2);
        break;

    case OP_CMP_LE_INT:
        if (print_instrs) 
            printf("cmp_le_int r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 <= i2);
        break;

    case OP_CMP_EQ_REAL:
        if (print_instrs) 
            printf("cmp_eq_real r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        r1 = real_reg(instr->rs1);
        r2 = real_reg(instr->rs2);
        set_reg_int(instr->rd, r1 == r2);
        break;

    case OP_CMP_NE_REAL:
        if (print_instrs) 
            printf("cmp_ne_real r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        r1 = real_reg(instr->rs1);
        r2 = real_reg(instr->rs2);
        set_reg_int(instr->rd, r1 != r2);
        break;

    case OP_CMP_GT_REAL:
        if (print_instrs) 
            printf("cmp_gt_real r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        r1 = real_reg(instr->rs1);
        r2 = real_reg(instr->rs2);
        set_reg_int(instr->rd, r1 > r2);
        break;

    case OP_CMP_GE_REAL:
        if (print_instrs) 
            printf("cmp_ge_real r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        r1 = real_reg(instr->rs1);
        r2 = real_reg(instr->rs2);
        set_reg_int(instr->rd, r1 >= r2);
        break;

    case OP_CMP_LT_REAL:
        if (print_instrs) 
            printf("cmp_lt_real r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        r1 = real_reg(instr->rs1);
        r2 = real_reg(instr->rs2);
        set_reg_int(instr->rd, r1 < r2);
        break;

    case OP_CMP_LE_REAL:
        if (print_instrs) 
            printf("cmp_le_real r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        r1 = real_reg(instr->rs1);
        r2 = real_reg(instr->rs2);
        set_reg_int(instr->rd, r1 <= r2);
        break;

    case OP_CMP_EQ_STRING:
        if (print_instrs) 
            printf("cmp_eq_string r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        s1 = string_reg(instr->rs1);
        s2 = string_reg(instr->rs2);
        set_reg_int(instr->rd, strcmp(s1, s2) == 0);
        break;

    case OP_CMP_NE_STRING:
        if (print_instrs) 
            printf("cmp_ne_string r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        s1 = string_reg(instr->rs1);
        s2 = string_reg(instr->rs2);
        set_reg_int(instr->rd, strcmp(s1, s2) != 0);
        break;

    case OP_CMP_GT_STRING:
        if (print_instrs) 
            printf("cmp_gt_string r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        s1 = string_reg(instr->rs1);
        s2 = string_reg(instr->rs2);
        set_reg_int(instr->rd, strcmp(s1, s2) > 0);
        break;

    case OP_CMP_GE_STRING:
        if (print_instrs) 
            printf("cmp_ge_string r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        s1 = string_reg(instr->rs1);
        s2 = string_reg(instr->rs2);
        set_reg_int(instr->rd, strcmp(s1, s2) >= 0);
        break;

    case OP_CMP_LT_STRING:
        if (print_instrs) 
            printf("cmp_lt_string r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        s1 = string_reg(instr->rs1);
        s2 = string_reg(instr->rs2);
        set_reg_int(instr->rd, strcmp(s1, s2) < 0);
        break;

    case OP_CMP_LE_STRING:
        if (print_instrs) 
            printf("cmp_le_string r%d, r%d, r%d\n",
                instr->rd, instr->rs1, instr->rs2);

        s1 = string_reg(instr->rs1);
        s2 = string_reg(instr->rs2);
        set_reg_int(instr->rd, strcmp(s1, s2) <= 0);
        break;

    case OP_AND:
        if (print_instrs) 
            printf("and r%d, r%d, r%d\n", instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 && i2);
        break;

    case OP_OR:
        if (print_instrs) 
            printf("or r%d, r%d, r%d\n", instr->rd, instr->rs1, instr->rs2);

        i1 = int_reg(instr->rs1);
        i2 = int_reg(instr->rs2);
        set_reg_int(instr->rd, i1 || i2);
        break;

    case OP_NOT:
        if (print_instrs) 
            printf("not r%d, r%d\n", instr->rd, instr->rs1);

        i1 = int_reg(instr->rs1);
        set_reg_int(instr->rd, !i1);
        break;

    case OP_BRANCH_UNCOND:
        if (print_instrs) 
            printf("branch_uncond %s\n", instr->string_const);

        next_pc = lookup_label(instr->string_const);
        break;

    case OP_BRANCH_ON_TRUE:
        if (print_instrs) 
            printf("branch_on_true r%d, %s\n",
                instr->rs1, instr->string_const);

        i1 = int_reg(instr->rs1);
        if (i1) 
            next_pc = lookup_label(instr->string_const);
        break;

    case OP_BRANCH_ON_FALSE:
        if (print_instrs) 
            printf("branch_on_false r%d, %s\n",
                instr->rs1, instr->string_const);

        i1 = int_reg(instr->rs1);
        if (! i1) 
            next_pc = lookup_label(instr->string_const);
        break;

    case OP_RETURN:
        if (print_instrs) 
            printf("return\n");

        check_slot(0, TRUE, FALSE);
        if (stack_slot(0).store_type != TYPE_RETURN_ADDR) {
            print_dynamic_context();
            fprintf(stderr, "top of stack doesn't hold a return address\n");
            found_error = TRUE;
        }

        next_pc = stack_slot(0).int_val;
        top_slot--;
        break;

    case OP_CALL:
        if (print_instrs) 
            printf("call %s\n", instr->string_const);

        top_slot++;
        if (stack_check_overflow())
            break;
        stack[top_slot].store_valid = TRUE;
        stack[top_slot].store_type = TYPE_RETURN_ADDR;
        stack[top_slot].int_val = next_pc;
        next_pc = lookup_label(instr->string_const);
        break;

    case OP_CALL_BUILTIN:
        if (instr->func >= FUNCOP_LAST) 
            report_error_and_exit("bad function in call");

        builtin_func = func_names[instr->func];
        if (print_instrs) 
            printf("call_builtin %s\n", builtin_func);

        switch (instr->func) {
            case FUNCOP_READ_INT:
                init_all_regs();
                if (scanf("%d", &i1) != 1) 
                    report_error_and_exit("cannot read integer");
                set_reg_int(0, i1);
                break;

            case FUNCOP_READ_REAL:
                init_all_regs();
                if (scanf("%f", &r1) != 1) 
                    report_error_and_exit("cannot read real");
                set_reg_real(0, r1);
                break;

            case FUNCOP_READ_BOOL:
                init_all_regs();
                if (scanf("%s", buf) != 1) 
                    report_error_and_exit("cannot read bool");
                if (streq(buf, "true")) 
                    set_reg_int(0, 1);
                else if (streq(buf, "false")) 
                    set_reg_int(0, 0);
                else 
                    report_error_and_exit("read invalid bool");
                break;

            case FUNCOP_READ_STRING:
                init_all_regs();
                if (scanf("%s", buf) != 1) 
                    report_error_and_exit("cannot read string");
                set_reg_string(0, strdup(buf));
                break;

            case FUNCOP_PRINT_INT:
                printf("%d", int_reg(0));
                init_all_regs();
                break;

            case FUNCOP_PRINT_REAL:
                printf("%f", real_reg(0));
                init_all_regs();
                break;

            case FUNCOP_PRINT_BOOL:
                printf("%s", int_reg(0) ? "true" : "false");
                init_all_regs();
                break;

            case FUNCOP_PRINT_STRING:
                printf("%s", string_reg(0));
                init_all_regs();
                break;

            case FUNCOP_STRING_CONCAT:
                s1 = string_reg(0);
                s2 = string_reg(1);
                l = (int) strlen(s1) + (int) strlen(s2) + 1;
                s = checked_malloc(l);
                s = strcpy(s, s1);
                s = strcat(s, s2);
                init_all_regs();
                set_reg_string(0, s);
                break;

            case FUNCOP_STRING_LENGTH:
                s1 = string_reg(0);
                init_all_regs();
                set_reg_int(0, (int) strlen(s1));
                break;

            case FUNCOP_SUBSTRING:
                s1 = string_reg(0);
                i1 = int_reg(1);
                i2 = int_reg(2);
                l = (int) strlen(s1) + 1;
                s = checked_malloc(l);
                if (i1 > l) 
                    report_error_and_exit("substring: invalid start");

                strcpy(s, s1 + i1);
                l = l - i1;
                if (i2 < l) 
                    s[i2] = '\0';
                init_all_regs();
                set_reg_string(0, s);
                break;

            case FUNCOP_SQRT:
                r1 = real_reg(0);
                init_all_regs();
                set_reg_real(0, (float) sqrt(r1));
                break;

            case FUNCOP_TRUNC:
                r1 = real_reg(0);
                init_all_regs();
                set_reg_int(instr->rd, oztrunc(r1));
                break;

            case FUNCOP_ROUND:
                r1 = real_reg(0);
                init_all_regs();
                set_reg_int(instr->rd, ozround(r1));
                break;

            case FUNCOP_LAST:
                report_error_and_exit("call: invalid function");
        }

        break;

    case OP_INT_TO_REAL:
        if (print_instrs) 
            printf("int_to_real r%d, r%d\n", instr->rd, instr->rs1);

        i1 = int_reg(instr->rs1);
        set_reg_real(instr->rd, (float) i1);
        break;

    case OP_MOVE:
        if (print_instrs) 
            printf("move r%d, r%d\n", instr->rd, instr->rs1);

        set_reg_any(instr->rd, instr->rs1);
        break;

    case OP_DEBUG_REG:
        if (print_instrs) 
            printf("debug_reg r%d\n", instr->rs1);

        check_reg(instr->rs1);
        if (quiet) 
            break;

        switch (regs[instr->rs1].store_type) {
            case TYPE_INT:
                printf("register %d: %d\n", instr->rs1, int_reg(instr->rs1));
                break;

            case TYPE_REAL:
                printf("register %d: %f\n", instr->rs1, real_reg(instr->rs1));
                break;

            case TYPE_ADDRESS:
                printf("register %d: @%d\n", instr->rs1,
                    regs[instr->rs1].int_val);
                break;

            case TYPE_STRING:
                printf("register %d: %s\n",
                    instr->rs1, string_reg(instr->rs1));
                break;

            default:
                report_error_and_exit("invalid register type");
                break;
        }

        break;

    case OP_DEBUG_SLOT:
        if (print_instrs) 
            printf("debug_slot %d\n", instr->int_const);

        check_slot(instr->int_const, TRUE, TRUE);
        if (quiet) 
            break;

        switch (stack_slot(instr->int_const).store_type) {
            case TYPE_INT:
                printf("slot %d: %d\n",
                    instr->int_const, int_slot(instr->int_const));
                break;

            case TYPE_REAL:
                printf("slot %d: %f\n",
                    instr->int_const, real_slot(instr->int_const));
                break;

            case TYPE_ADDRESS:
                printf("slot %d: @%d\n",
                    instr->int_const, stack_slot(instr->int_const).int_val);
                break;

            case TYPE_STRING:
                printf("slot %d: %s\n",
                    instr->int_const, string_slot(instr->int_const));
                break;

            case TYPE_FRAME_SIZE:
                report_error_and_exit("frame size slot");
                break;

            case TYPE_RETURN_ADDR:
                report_error_and_exit("return address slot");
                break;

            default:
                report_error_and_exit("invalid slot type");
                break;
        }

        break;

    case OP_DEBUG_STACK:
        if (print_instrs) 
            printf("debug_stack\n");

        if (quiet) 
            break;

        printf("\n");
        printf("cur_frame_size = %d\n", cur_frame_size);
        for (offset = 0; offset <= top_slot; offset++) {
            if (! stack[offset].store_valid) {
                printf("offset %d is invalid\n", offset);
                continue;
            }

            switch (stack[offset].store_type) {

            case TYPE_INT:
                printf("offset %d: %d\n", offset, stack[offset].int_val);
                break;

            case TYPE_REAL:
                printf("offset %d: %f\n", offset, stack[offset].real_val);
                break;

            case TYPE_ADDRESS:
                printf("offset %d: @%d\n", offset, stack[offset].int_val);
                break;

            case TYPE_STRING:
                printf("offset %d: %s\n", offset, stack[offset].string_val);
                break;

            case TYPE_FRAME_SIZE:
                printf("offset %d: frame size %d\n",
                    offset, stack[offset].int_val);
                break;

            case TYPE_RETURN_ADDR:
                printf("offset %d: return address %d\n",
                    offset, stack[offset].int_val);
                break;

            default:
                report_error_and_exit("invalid slot type");
                break;
            }
        }

        printf("\n");
        break;

    case OP_HALT:
        if (print_instrs) 
            printf("halt\n");

        halted = TRUE;
        break;

    default:
        report_internal_error_and_exit("unknown opcode");
        break;
    }
}