Exemplo n.º 1
0
Arquivo: assemble.c Projeto: occho/cpu
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
		}
	}	
Exemplo n.º 3
0
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;
}