static unsigned long build_opcode (struct itbl_entry *e) { unsigned long opcode; opcode = apply_range (e->value, e->range); opcode |= ITBL_ENCODE_PNUM (e->processor); return opcode; }
static int32_t Rangemap_vstate_render_voice( Voice_state* vstate, Proc_state* proc_state, const Device_thread_state* proc_ts, const Au_state* au_state, const Work_buffers* wbs, int32_t buf_start, int32_t buf_stop, double tempo) { rassert(vstate != NULL); rassert(proc_state != NULL); rassert(proc_ts != NULL); rassert(au_state != NULL); rassert(wbs != NULL); rassert(buf_start >= 0); rassert(buf_stop >= 0); rassert(isfinite(tempo)); rassert(tempo > 0); const Proc_rangemap* rangemap = (const Proc_rangemap*)proc_state->parent.device->dimpl; float mul = 0; float add = 0; get_scalars( &mul, &add, rangemap->from_min, rangemap->from_max, rangemap->min_to, rangemap->max_to); const double range_min = min(rangemap->min_to, rangemap->max_to); const double range_max = max(rangemap->min_to, rangemap->max_to); const float min_val = (float)(rangemap->clamp_dest_min ? range_min : -INFINITY); const float max_val = (float)(rangemap->clamp_dest_max ? range_max : INFINITY); // TODO: Support all ports? // We should only enable the support if we are 100% sure that // we don't need parameter input streams for (int port = 0; port < 2; ++port) { Work_buffer* out_wb = Device_thread_state_get_voice_buffer( proc_ts, DEVICE_PORT_TYPE_SEND, port); if (out_wb == NULL) continue; const Work_buffer* in_wb = Device_thread_state_get_voice_buffer( proc_ts, DEVICE_PORT_TYPE_RECV, port); if (in_wb == NULL) continue; apply_range(in_wb, out_wb, buf_start, buf_stop, mul, add, min_val, max_val); } return buf_stop; }
static struct itbl_entry * find_entry_byval (e_processor processor, e_type type, unsigned long val, struct itbl_range *r) { struct itbl_entry *e, **es; unsigned long eval; es = get_entries (processor, type); for (e = *es; e; e = e->next) /* for each entry, ... */ { if (processor != e->processor) continue; /* For insns, we might not know the range of the opcode, * so a range of 0 will allow this routine to match against * the range of the entry to be compared with. * This could cause ambiguities. * For operands, we get an extracted value and a range. */ /* if range is 0, mask val against the range of the compared entry. */ if (r == 0) /* if no range passed, must be whole 32-bits * so create 32-bit value from entry's range */ { eval = apply_range (e->value, e->range); val &= apply_range (0xffffffff, e->range); } else if ((r->sbit == e->range.sbit && r->ebit == e->range.ebit) || (e->range.sbit == 0 && e->range.ebit == 0)) { eval = apply_range (e->value, *r); val = apply_range (val, *r); } else continue; if (val == eval) return e; } return 0; }
int32_t Rangemap_vstate_render_voice( Voice_state* vstate, Proc_state* proc_state, const Device_thread_state* proc_ts, const Au_state* au_state, const Work_buffers* wbs, int32_t frame_count, double tempo) { rassert(vstate == NULL); rassert(proc_state != NULL); rassert(proc_ts != NULL); rassert(au_state != NULL); rassert(wbs != NULL); rassert(frame_count > 0); rassert(isfinite(tempo)); rassert(tempo > 0); const Proc_rangemap* rangemap = (const Proc_rangemap*)proc_state->parent.device->dimpl; float mul = 0; float add = 0; get_scalars( &mul, &add, rangemap->from_min, rangemap->from_max, rangemap->min_to, rangemap->max_to); const double range_min = min(rangemap->min_to, rangemap->max_to); const double range_max = max(rangemap->min_to, rangemap->max_to); const float min_val = (float)(rangemap->clamp_dest_min ? range_min : -INFINITY); const float max_val = (float)(rangemap->clamp_dest_max ? range_max : INFINITY); Work_buffer* in_wb = Proc_get_voice_input_2ch(proc_ts, 0, frame_count); if (in_wb == NULL) { in_wb = Work_buffers_get_buffer_mut(wbs, RANGEMAP_WB_FIXED_INPUT, 2); Work_buffer_clear_all(in_wb, 0, frame_count); } Work_buffer* out_wb = Proc_get_voice_output_2ch(proc_ts, 0); rassert(out_wb != NULL); apply_range(in_wb, out_wb, frame_count, mul, add, min_val, max_val); return frame_count; }
unsigned long itbl_assemble (char *name, char *s) { unsigned long opcode; struct itbl_entry *e = NULL; struct itbl_field *f; char *n; int processor; if (!name || !*name) return 0; /* error! must have an opcode name/expr */ /* find entry in list of instructions for all processors */ for (processor = 0; processor < e_nprocs; processor++) { e = find_entry_byname (processor, e_insn, name); if (e) break; } if (!e) return 0; /* opcode not in table; invalid instruction */ opcode = build_opcode (e); /* parse opcode's args (if any) */ for (f = e->fields; f; f = f->next) /* for each arg, ... */ { struct itbl_entry *r; unsigned long value; if (!s || !*s) return 0; /* error - not enough operands */ n = itbl_get_field (&s); /* n should be in form $n or 0xhhh (are symbol names valid?? */ switch (f->type) { case e_dreg: case e_creg: case e_greg: /* Accept either a string name * or '$' followed by the register number */ if (*n == '$') { n++; value = strtol (n, 0, 10); /* FIXME! could have "0l"... then what?? */ if (value == 0 && *n != '0') return 0; /* error; invalid operand */ } else { r = find_entry_byname (e->processor, f->type, n); if (r) value = r->value; else return 0; /* error; invalid operand */ } break; case e_addr: /* use assembler's symbol table to find symbol */ /* FIXME!! Do we need this? if so, what about relocs?? my_getExpression (&imm_expr, s); return 0; /-* error; invalid operand *-/ break; */ /* If not a symbol, fall thru to IMMED */ case e_immed: if (*n == '0' && *(n + 1) == 'x') /* hex begins 0x... */ { n += 2; value = strtol (n, 0, 16); /* FIXME! could have "0xl"... then what?? */ } else { value = strtol (n, 0, 10); /* FIXME! could have "0l"... then what?? */ if (value == 0 && *n != '0') return 0; /* error; invalid operand */ } break; default: return 0; /* error; invalid field spec */ } opcode |= apply_range (value, f->range); } if (s && *s) return 0; /* error - too many operands */ return opcode; /* done! */ }
static void append_insns_as_macros (void) { struct ITBL_OPCODE_STRUCT *new_opcodes, *o; struct itbl_entry *e, **es; int n, size, new_size, new_num_opcodes; #ifdef USE_MACROS int id; #endif if (!itbl_have_entries) return; if (!itbl_num_opcodes) /* no new instructions to add! */ { return; } DBG (("previous num_opcodes=%d\n", ITBL_NUM_OPCODES)); new_num_opcodes = ITBL_NUM_OPCODES + itbl_num_opcodes; ASSERT (new_num_opcodes >= itbl_num_opcodes); size = sizeof (struct ITBL_OPCODE_STRUCT) * ITBL_NUM_OPCODES; ASSERT (size >= 0); DBG (("I get=%d\n", size / sizeof (ITBL_OPCODES[0]))); new_size = sizeof (struct ITBL_OPCODE_STRUCT) * new_num_opcodes; ASSERT (new_size > size); /* FIXME since ITBL_OPCODES culd be a static table, we can't realloc or delete the old memory. */ new_opcodes = (struct ITBL_OPCODE_STRUCT *) malloc (new_size); if (!new_opcodes) { printf (_("Unable to allocate memory for new instructions\n")); return; } if (size) /* copy preexisting opcodes table */ memcpy (new_opcodes, ITBL_OPCODES, size); /* FIXME! some NUMOPCODES are calculated expressions. These need to be changed before itbls can be supported. */ #ifdef USE_MACROS id = ITBL_NUM_MACROS; /* begin the next macro id after the last */ #endif o = &new_opcodes[ITBL_NUM_OPCODES]; /* append macro to opcodes list */ for (n = e_p0; n < e_nprocs; n++) { es = get_entries (n, e_insn); for (e = *es; e; e = e->next) { /* name, args, mask, match, pinfo * {"li", "t,i", 0x34000000, 0xffe00000, WR_t }, * {"li", "t,I", 0, (int) M_LI, INSN_MACRO }, * Construct args from itbl_fields. */ o->name = e->name; o->args = strdup (form_args (e)); o->mask = apply_range (e->value, e->range); /* FIXME how to catch during assembly? */ /* mask to identify this insn */ o->match = apply_range (e->value, e->range); o->pinfo = 0; #ifdef USE_MACROS o->mask = id++; /* FIXME how to catch during assembly? */ o->match = 0; /* for macros, the insn_isa number */ o->pinfo = INSN_MACRO; #endif /* Don't add instructions which caused an error */ if (o->args) o++; else new_num_opcodes--; } } ITBL_OPCODES = new_opcodes; ITBL_NUM_OPCODES = new_num_opcodes; /* FIXME At this point, we can free the entries, as they should have been added to the assembler's tables. Don't free name though, since name is being used by the new opcodes table. Eventually, we should also free the new opcodes table itself on exit. */ }
int main(int argc, char** argv) { int i; int npages; char r = 0; char e = 0; char o = 0; char* range = NULL; if (argc == 1) { fprintf(stderr, "%s nofpages [e | o] [r] [range]\n", argv[0]); return -1; } sscanf(argv[1], "%d", &npages); if (npages <= 0) { fprintf(stderr, "Number of pages invalid.\n"); return -1; } for (i = 2; i < argc; ++i) { if (strcmp(argv[i], "r") == 0) { r = 1; } else if (strcmp(argv[i], "e") == 0) { e = 1; } else if (strcmp(argv[i], "o") == 0) { o = 1; } else { range = argv[i]; } } if (e == 1 && o == 1) { e = 0; o = 0; } ++npages; { /* if buffer[i] is zero, i is in the range. */ char* buffer = calloc(1, npages); if (buffer == NULL) { fprintf(stderr, "Sorry, internal error.\n"); return -1; } apply_range(buffer, npages, range); if (e == 1) { for (i = 1; i < npages; i += 2) { buffer[i] = 1; } } if (o == 1) { for (i = 2; i < npages; i += 2) { buffer[i] = 1; } } buffer[0] = 1; /* page zero does not exist. */ if (r == 0) { for (i = 0; i < npages; ++i) { if (buffer[i] == 0) printf("%d ", i); } }else { for (i=npages; i > 0; ) { --i; if (buffer[i] == 0) printf("%d ", i); } } free(buffer); } return 0; }