* needs ability to specify location for code or data
* needs ability to specify label as relative to another label
* short labels not correctly computed
+ * in label struct, store index of instruction rather than ptr, ptrs for iteration in addr calculation are ugly
*/
static const char * const src_id_ = "$Id$";
l = (struct label_ *)DYNARRAY_ITEM(*labels, i);
+ DEBUG_PRINTFQ("%s: calculating address of label '%s'\n", __func__, l->label);
+
+#if 0
+force full resolution while debugging
/* if it's already calculated, great. */
if (l->ready)
continue;
+#endif
/*
* starting at the instruction for this label,
* until we get to the start or a known prior label address.
* update our label with the freshly calculated addr
*/
- for (instr = ((struct label_ *)DYNARRAY_ITEM(*labels, i))->instr;
- instr >= (struct instruction_ **)DYNARRAY_ITEM(*instructionps, 0);
- instr--) {
- if ((*instr)->ready)
- DEBUG_PRINTF("%s: instr not ready\n", __func__);
+ /* first fetch the instruction associated with the label we want to know about.. */
+ /* the addr of this instruction will be whatever follows all the preceding instructions */
+ /* so back up one before counting instruction lengths... */
+ instr = ((struct label_ *)DYNARRAY_ITEM(*labels, i))->instr;
+ /* is it the first one? */
+ if (instr == (struct instruction_ **)DYNARRAY_ITEM(*instructionps, 0))
+ break;
+
+ instr--;
+
+ while (instr >= (struct instruction_ **)DYNARRAY_ITEM(*instructionps, 0)) {
+ if ((*instr)->ready == 0)
+ DEBUG_PRINTF("%s: instr '%s' not ready\n", __func__, (*instr)->opcode);
word_count += (*instr)->length;
+ DEBUG_PRINTF("%s: instr '%s' takes '%u' bytes\n", __func__, (*instr)->opcode, (*instr)->length);
+
/* have we come across an instruction which a label points to?
it should already be calculated, so just add that on and be done */
if ((*instr)->label
word_count += addr;
break;
}
+ instr--;
}
l->addr = word_count;
l->ready = 1;
char *reg;
char *constant;
+ DEBUG_PRINTFQ("is multipart.. ");
+
/* eat the plus */
*ep = '\0';
ep++;
*nextwordused += 1;
DEBUG_PRINTFQ("is a dereferenced register (%c) + constant (%hu)\n", *reg, *nextword);
return 0x10 | register_enumerate_(*reg);
- } else if (errno) {
+ } else if (errno == ERANGE) {
+#if 0
+oh, right, labels fall through
DEBUG_PRINTFQ("is out of range\n");
fprintf(stderr, "trouble with operand '%s': %s\n", operand_orig, strerror(errno));
return -1;
+#endif
}
/* what? still here? assume it's a label, I guess */
int r;
if (with_label)
- r = printf("%-16s %3s", i->label ? i->label : "", i->opcode);
- else
- r = printf("%3s", i->opcode);
+ r = printf("%-16s ", i->label ? i->label : "");
+
+ r = printf("%3s", i->opcode ? i->opcode : "");
for (o = i->operands; o; o = o->next)
r += printf(" %s%s", o->operand, o->next ? "," : "");
* Parses a zero-terminated line of input into a newly-allocated struct instruction_.
* [label] instruction [operand[,operand[,...]]]
* Does no validation of contents of any of these tokens, as of yet.
+ * does not clean up after itself if a malloc fails
*/
static
int tokenize_line_(char *line, struct instruction_ **next_instr) {
/* if we have an opcode, we'll need at least one word to compile instruction */
instr_words_needed++;
+ /* build a list of operands to hang off this instruction */
while ( (x = strqtok_r(NULL, ",", '\\', quotes, &qt, &st)) ) {
struct operand_ *new_operand;
char *y;
if (opt_.verbose > 2) {
printf("%s: assembling %p ", __func__, i);
instruction_print_(i, 1);
- printf("(line :%zu)\n", i->src_line);
+ printf("(line %zu)\n", i->src_line);
}
+#if 0
+while debugging, always reassemble
if (i->ready) {
/* already assembled, nothing to do */
return 0;
}
+#endif
+
+ if (i->opcode == NULL) {
+ assert(i->label);
+ assert(i->operands == NULL);
+ /* just a label, move along */
+ i->length = 0;
+ i->ready = 1;
+ return 0;
+ }
/* special case DAT */
if (strncasecmp(i->opcode, "DAT", 3) == 0) {
DEBUG_PRINTF("DAT operand:'%s' next:%p\n", o->operand, o->next);
/* is this a string? */
+ /* does it start with a quote, and end with the same quote? */
if ( (x = strchr("\"'`", o->operand[0])) ) {
dat_len = strlen(o->operand) - 1;
if (o->operand[dat_len] == *x) {
/* otherwise assume it's a label, even if we don't know what it is */
if (label_addr_(labels, o->operand, &i->instr_words[i->length])) {
- DEBUG_PRINTF("(deferred label resolution)\n");
+ DEBUG_PRINTF("(deferred label '%s' resolution)\n", o->operand);
incomplete = 1;
}
i->length++;