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; } }
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); }
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; } }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; } }
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; }
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; } }