int assemble(uint32_t *out_buf, char *asm_buf) { char asm_line[COL_MAX]; char term0[COL_MAX]; output_alias = out_buf; while (mygets(asm_line, asm_buf, COL_MAX) != NULL) { if (set_term0(asm_line, term0) == 1) { if (is_comment(asm_line, term0)) { // blank(comment) } else if (is_directive(asm_line, term0)) { exec_directive(asm_line, term0); } else if (is_label(asm_line, term0)) { register_label(asm_line, term0); } else { encode_and_output(asm_line, term0); } } else { // blank(empty line) } input_line_cnt++; } resolve_label(); return output_cnt; }
int ana_pseudo(const byte *s) { if ( ((OutHdr*)s)->version != 0x11) { msg("%x: pseudo netnode version mismatch\n", cmd.ea); netnode(cmd.ea).supdel(PSEUDO_NETNODE_SUPVAL); return 0; } const byte *e = s + ((OutHdr*)s)->len; int nbytes = 1; if (((OutHdr*)s)->flags & 2) nbytes = ((OutHdr*)s)->ea; else if ( ((OutHdr*)s)->flags & 1 ) { OutHdr t; if (netnode(cmd.ea+1).supval(PSEUDO_NETNODE_SUPVAL, &t, sizeof(t) != -1) && t.len == sizeof(OutHdr)) nbytes = 2; } cmd.itype = ARM_pseudo; s += sizeof(OutHdr); int n = 0; for(;;) { const byte *t = s; s = scantoken(s,e); if (s == e) break; switch(*s++) { case 1: // register s++; break; case 2: { // integer uint32 num = *(uint32*)(s+2); uint flags = *(uint16*)s; s += 6; switch( (flags & TF_MASK) ) { case TF_CALL: case TF_DEREF_STORE: case TF_DEREF_LOAD: case TF_ADDRESS_NOREF: break; case TF_NUM: if (isEnabled(num) || n>= 6) { break; } else { mkimm(n++, num); } break; default: if (n < 6) { mkimm(n++, num); } break; } break; } case 3: // label if (n < 6) { ea_t ea= resolve_label(cmd.ea, *(uint16*)s); mkjmp(n++, ea); } s += 3; break; case 4: { // reg displacement memory access if (n < 6) { mkdispl(n++, *(byte*)s >> 4, *(byte*)s & 0xF, *(int16*)(s+1)); } s += 3; break; } case 5: // struct offset thingy s += 9; // skip 1+4+4 bytes break; case 6: // end of nesting break; // no params default: msg("ANA ERROR!!\n"); return nbytes; // ERROR } }
gboolean mcus_compiler_compile (MCUSCompiler *self, MCUSSimulation *simulation, MCUSInstructionOffset **offset_map, guchar *lookup_table_length, GError **error) { guint i; guchar *memory, *lookup_table; self->priv->dirty = TRUE; memory = mcus_simulation_get_memory (simulation); lookup_table = mcus_simulation_get_lookup_table (simulation); /* Empty the current contents of memory and the lookup table before starting */ memset (memory, 0, MEMORY_SIZE); memset (lookup_table, 0, LOOKUP_TABLE_SIZE); /* Allocate the line number map's memory */ g_free (*offset_map); *offset_map = g_malloc (sizeof (MCUSInstructionOffset) * (self->priv->compiled_size + 1)); g_debug ("Allocating line number map of %lu bytes.", (gulong) (sizeof (guint) * self->priv->compiled_size)); /* Compile it to memory */ self->priv->compiled_size = PROGRAM_START_ADDRESS; for (i = 0; i < self->priv->instruction_count; i++) { guint f, projected_size; const MCUSInstructionData *instruction_data; MCUSInstruction *instruction; instruction = &(self->priv->instructions[i]); instruction_data = &(mcus_instruction_data[instruction->opcode]); /* In case of error, ensure the correct part of the code will be highlighted */ self->priv->i = self->priv->code + instruction->offset; /* Check we're not overflowing memory */ projected_size = self->priv->compiled_size + instruction_data->size; if (projected_size >= MEMORY_SIZE) { self->priv->error_length = strlen (instruction_data->mnemonic); g_set_error (error, MCUS_COMPILER_ERROR, MCUS_COMPILER_ERROR_MEMORY_OVERFLOW, _("Instruction %u overflows the microcontroller memory."), i); return FALSE; } /* Store the line number mapping for the instruction */ (*offset_map)[self->priv->compiled_size].offset = instruction->offset; (*offset_map)[self->priv->compiled_size].length = instruction->length; /* Store the opcode first, as that's easy */ memory[self->priv->compiled_size++] = instruction->opcode; self->priv->i += strlen (instruction_data->mnemonic) + 1; /* Store the operands, although we have to special-case IN and OUT instructions */ switch (instruction->opcode) { case OPCODE_IN: memory[self->priv->compiled_size++] = instruction->operands[0].number; break; case OPCODE_OUT: memory[self->priv->compiled_size++] = instruction->operands[1].number; break; case OPCODE_HALT: case OPCODE_MOVI: case OPCODE_MOV: case OPCODE_ADD: case OPCODE_SUB: case OPCODE_AND: case OPCODE_EOR: case OPCODE_INC: case OPCODE_DEC: case OPCODE_JP: case OPCODE_JZ: case OPCODE_JNZ: case OPCODE_RCALL: case OPCODE_RET: case OPCODE_SHL: case OPCODE_SHR: for (f = 0; f < instruction_data->arity; f++) { if (instruction_data->operand_types[f] == OPERAND_LABEL && instruction->operands[f].type == OPERAND_LABEL) { GError *child_error = NULL; /* We need to resolve the label first */ memory[self->priv->compiled_size++] = resolve_label (self, i, instruction->operands[f].label, &child_error); g_free (instruction->operands[f].label); if (child_error != NULL) { g_propagate_error (error, child_error); return FALSE; } } else { /* Just store the operand */ memory[self->priv->compiled_size++] = instruction->operands[f].number; } } break; default: g_assert_not_reached (); } } /* Set the last element in the line number map to -1 for safety */ (*offset_map)[self->priv->compiled_size].offset = -1; (*offset_map)[self->priv->compiled_size].length = 0; /* Copy across the lookup table */ g_memmove (lookup_table, self->priv->lookup_table.table, sizeof (guchar) * self->priv->lookup_table.length); if (lookup_table_length != NULL) *lookup_table_length = self->priv->lookup_table.length; /* Notify the simulation of the changes to memory and the lookup table */ mcus_simulation_notify_memory (simulation); mcus_simulation_notify_lookup_table (simulation); reset_state (self); return TRUE; }