Пример #1
0
/**
 * A utility function to avoid duplication when testing pop() implementations.
 *
 * @param push_value TODO
 * @param pop_mode TODO
 * @param storage_location TODO
 * @param source_location TODO
 */
void
pop_test_util(uint32_t push_value, uint8_t pop_mode, uint32_t storage_location,
              int source_location)
{
    allocate();
    push(push_value);

    if (source_location == SOURCE_IMMEDIATE)
    {
        store_dword(ram, NEXT_INSTR, NEXT2_INSTR);

        if (storage_location == NEXT3_INSTR)
            store_dword(ram, NEXT2_INSTR, NEXT3_INSTR);

        exec(create_instruction(INSTR_POP, pop_mode, EMPTY_BYTE,
                                EMPTY_BYTE));
    }
    else
    {
        //  We can point the register to next instruction by default
        r[TEST_REGISTER] = NEXT_INSTR;

        if (storage_location == NEXT2_INSTR)
            store_dword(ram, NEXT_INSTR, NEXT2_INSTR);

        exec(create_instruction(INSTR_POP, pop_mode, EMPTY_BYTE,
                                TEST_REGISTER));
    }

    if (storage_location == REGISTER_LOCATION)
    {
        CU_ASSERT(push_value == r[TEST_REGISTER]);
    }
    else
    {
        switch (push_value)
        {
            case DUMMY_VALUE_32:
            CU_ASSERT(push_value == get_dword(ram, storage_location));
                break;
            case DUMMY_VALUE_16:
            CU_ASSERT(push_value == get_word(ram, storage_location));
                break;
            case DUMMY_VALUE_8:
            CU_ASSERT(push_value == get_byte(ram, storage_location));
                break;
            default:
            CU_FAIL("Invalid push_value");
        }
    }

    deallocate();
}
Пример #2
0
/**
 * Tests 'isntr_exit()'.
 */
void test_instr_exit()
{
    allocate();
    CU_ASSERT(1 == exec(create_instruction(INSTR_EXIT, EMPTY_BYTE, EMPTY_BYTE,
                                           EMPTY_BYTE)));
    deallocate();
}
Пример #3
0
static token_list * zero_reg_op( token_list *t, int op ) {
    RW_Robo_Op new_op;
    /* Create instruction */
    encode_op_regs(new_op, op_zero_reg, 0, 0, op);
    create_instruction(new_op);
    return t->next;
}
Пример #4
0
static token_list * push_op( token_list *t ) {
    token_list *tok = t;
    int dest, reg;
    RW_Robo_Op new_op;
    /* Push can take a register, immediate, or label.
       This makes things a bit hairy, as we don't have an instruction for both
       immediates and registers. Therefor, we have two different instructions,
       and pick which one depending on what we got. */
    tok = t->next;
    if( !tok ) {
        error = err_unexpected_eof;
        return NULL;
    }
    else if( tok->t == token_reg ) {
        reg = tok->value;
        encode_op_regs(new_op, op_one_reg, reg, 0, op_pushr);
    }
    else if( tok->t == token_num ) {
        dest = tok->value;
        encode_op_imme(new_op, op_push, dest);
    }
    else if( tok->t == token_label ) {
        dest = check_label(tok);
        encode_op_imme(new_op, op_push, dest);
    }
    else {
        error_line = tok->line_number;
        error = err_labelnumreg_expected;
        return NULL;
    }
    create_instruction(new_op);
    return tok->next;
}
Пример #5
0
instruction* decode_mnemonic_instruction(char** tokens) {
	instruction* inst;
	inst = create_instruction();

	char** tokens_tmp;
	int count = 0;

	tokens_tmp = tokens;

	inst->mnemonico = (char*)malloc(sizeof(strlen(*tokens_tmp)*sizeof(char)));
	strcpy(inst->mnemonico,*tokens_tmp);

	prepair_instruct_by_minemonic(&inst);

	int i;
	for (i = 1; i <= inst->qtd_op; i++) {
		if (i == 1) {

			inst->op1 = (char*)malloc(sizeof(strlen(*(tokens_tmp + i))*sizeof(char)));
			strcpy(inst->op1,*(tokens_tmp + i));

		} else if (i == 2) {
			inst->op2 = (char*)malloc(sizeof(strlen(*(tokens_tmp + i))*sizeof(char)));
			strcpy(inst->op2,*(tokens_tmp + i));
		} else if (i == 3) {
			inst->op3 = (char*)malloc(sizeof(strlen(*(tokens_tmp + i))*sizeof(char)));
			strcpy(inst->op2,*(tokens_tmp + i));
		}
	}

	inst->type = 1;

	return inst;
}
Пример #6
0
/**
 * Tests 'exec_program()'.
 */
void test_exec_program()
{
    allocate();
    uint32_t test_instructions[2] = {
            create_instruction(INSTR_NOOP, EMPTY_BYTE, EMPTY_BYTE, EMPTY_BYTE),
            create_instruction(INSTR_EXIT, EMPTY_BYTE, EMPTY_BYTE, EMPTY_BYTE)};
    load_program(test_instructions,
                 sizeof(test_instructions) / sizeof(test_instructions[0]),
                 flash);
    exec_program();
    // TODO: Maybe there is a better way to test this
    // This is a very trivial test just to check that the pc was incremented
    // after executing a no op
    CU_ASSERT(0 != pc);
    deallocate();
}
Пример #7
0
/**
 * Tests 'instr_noop'
 */
void test_instr_noop()
{
    allocate();
    exec(create_instruction(INSTR_NOOP, EMPTY_BYTE, EMPTY_BYTE, EMPTY_BYTE));
    // TODO: Not sure what to test here, just checking that the PC
    // was incremented for now
    CU_ASSERT(INSTRUCTION_SIZE == pc);
    deallocate();
}
Пример #8
0
static void __init create_trampoline(unsigned long addr)
{
	/* The maximum range of a single instruction branch, is the current
	 * instruction's address + (32 MB - 4) bytes. For the trampoline we
	 * need to branch to current address + 32 MB. So we insert a nop at
	 * the trampoline address, then the next instruction (+ 4 bytes)
	 * does a branch to (32 MB - 4). The net effect is that when we
	 * branch to "addr" we jump to ("addr" + 32 MB). Although it requires
	 * two instructions it doesn't require any registers.
	 */
	create_instruction(addr, 0x60000000); /* nop */
	create_branch(addr + 4, addr + PHYSICAL_START, 0);
}
Пример #9
0
static token_list * two_reg_op( token_list *t, int op ) {
    int reg1, reg2;
    RW_Robo_Op new_op;
    token_list *tok = t;
    /* Get reg1 */
    tok = tok->next;
    if( !tok ) {
        error = err_unexpected_eof;
        return NULL;
    }
    else if( tok->t != token_reg ) {
        /* Syntax error */
        error_line = tok->line_number;
        error = err_reg1_expected;
        return NULL;
    }
    reg1 = tok->value;
    /* Eat a comma, get reg2 or first immediate */
    tok = tok->next;
    if( !tok ) {
        error = err_unexpected_eof;
        return NULL;
    }
    else if( tok->t != token_comma ) {
        /* Syntax error */
        error_line = tok->line_number;
        error = err_comma_expected;
        return NULL;
    }
    tok = tok->next;
    if( !tok ) {
        error = err_unexpected_eof;
        return NULL;
    }
    else if( tok->t == token_reg ) {
        reg2 = tok->value;
    }
    else if( tok->t == token_num ) {
        reg2 = reg_a;
        create_mova(tok->value);
    }
    else {
        error_line = tok->line_number;
        error = err_regnum2_expected;
        return NULL;
    }
    /* Create instruction */
    encode_op_regs(new_op, op_two_reg, reg1, reg2, op);
    create_instruction(new_op);
    return tok->next;
}
Пример #10
0
/**
 * Tests 'copy_memory()'.
 */
void test_copy_memory()
{
    allocate();

    // We don't need to test a TON of ram...
    int num_instructions = (configured_ram_size / 2 > 1000)
                           ? 1000
                           : configured_ram_size / 2;
    uint32_t instruction_array[num_instructions];

    for (int i = 0; i < num_instructions; i++)
    {
        uint8_t *p_ram = ram + (i * INSTRUCTION_SIZE);
        instruction_array[i] = create_instruction(i, i, i, i);
        *((uint32_t *) p_ram) = instruction_array[i];
    }

    // Find the next available ram
    int used_ram = INSTRUCTION_SIZE * num_instructions;
    uint8_t *p_dest = ram + used_ram;
    CU_ASSERT(0 == copy_memory(ram, p_dest, num_instructions));
    int failed_match = 0;

    // Check the memory where we copied to and verify it is the same as the
    // source data
    for (int i = 0; i < num_instructions; i++)
    {
        if ((((uint32_t *) p_dest)[i] != instruction_array[i]))
        {
            failed_match = 1;
            break;
        }
    }

    CU_ASSERT(0 == failed_match);

    // Check that we can't write past our allocated RAM
    CU_ASSERT(1 == copy_memory(ram, p_dest + configured_ram_size,
                               num_instructions));
    deallocate();
}
Пример #11
0
static token_list * one_reg_op( token_list *t, int op ) {
    int reg1;
    RW_Robo_Op new_op;
    token_list *tok = t;
    /* Get reg1 */
    tok = tok->next;
    if( !tok ) {
        error = err_unexpected_eof;
        return NULL;
    }
    else if( tok->t != token_reg ) {
        /* Syntax error */
        error_line = tok->line_number;
        error = err_reg1_expected;
        return NULL;
    }
    reg1 = tok->value;
    /* Create instruction */
    encode_op_regs(new_op, op_one_reg, reg1, 0, op);
    create_instruction(new_op);
    return tok->next;
}
t_list		*my_append_instruction(t_list *begin, char *str,
				       int *label_nbr, int line_nbr)
{
  t_list	*new_element;
  t_list	*tmp;
  char		**args;

  if ((new_element = malloc(sizeof(t_list))) == NULL)
    exit(0);
  args = create_instruction(str, label_nbr, line_nbr, -1);
  new_element->args = args;
  new_element->argnbr = (args == NULL) ? 0 : my_getnbr(args[1]);
  new_element->line = line_nbr;
  new_element->octet = 0;
  new_element->next = NULL;
  if (begin == NULL)
    return (new_element);
  tmp = begin;
  while (tmp->next != NULL)
    tmp = tmp->next;
  tmp->next = new_element;
  return (begin);
}
Пример #13
0
/**
 * A utility function to avoid duplication when testing push() implementations.
 *
 * @param pop_value TODO
 * @param push_mode TODO
 * @param storage_location TODO
 * @param source_location TODO
 */
void
push_test_util(uint32_t pop_value, uint8_t push_mode, uint32_t storage_location,
               int source_location)
{
    allocate();

    if (storage_location != IMMEDIATE)
    {
        if (storage_location == NEXT2_INSTR)
            store_dword(ram, NEXT_INSTR, NEXT2_INSTR);

        if (source_location == SOURCE_IMMEDIATE &&
            storage_location == NEXT3_INSTR)
        {
            store_dword(ram, NEXT_INSTR, NEXT2_INSTR);
            store_dword(ram, NEXT2_INSTR, NEXT3_INSTR);
        }
        else if (source_location == SOURCE_REGISTER)
            r[TEST_REGISTER] = NEXT_INSTR;
    }

    switch (pop_value)
    {
        case DUMMY_VALUE_8:
            if (source_location == SOURCE_IMMEDIATE)
            {
                store_byte(ram, storage_location, DUMMY_VALUE_8);
                exec(create_instruction(INSTR_PUSH, push_mode, EMPTY_BYTE,
                                        DUMMY_VALUE_8));
            }
            else if (source_location == SOURCE_REGISTER)
            {
                if (storage_location == IMMEDIATE)
                    r[TEST_REGISTER] = DUMMY_VALUE_8;
                else
                    store_byte(ram, storage_location, DUMMY_VALUE_8);
            }
            break;
        case DUMMY_VALUE_16:
            if (source_location == SOURCE_IMMEDIATE)
            {
                store_word(ram, storage_location, DUMMY_VALUE_16);
                exec(create_instruction(INSTR_PUSH, push_mode, DUMMY_VALUE_8,
                                        DUMMY_VALUE_8));
            }
            else if (source_location == SOURCE_REGISTER)
            {
                if (storage_location == IMMEDIATE)
                    r[TEST_REGISTER] = DUMMY_VALUE_16;
                else
                    store_word(ram, storage_location, DUMMY_VALUE_16);
            }
            break;
        case DUMMY_VALUE_32:
            if (source_location == SOURCE_IMMEDIATE)
            {
                store_dword(ram, storage_location, DUMMY_VALUE_32);
                exec(create_instruction(INSTR_PUSH, push_mode, EMPTY_BYTE,
                                        EMPTY_BYTE));
            }
            else if (source_location == SOURCE_REGISTER)
            {
                if (storage_location == IMMEDIATE)
                    r[TEST_REGISTER] = DUMMY_VALUE_32;
                else
                    store_dword(ram, storage_location, DUMMY_VALUE_32);
            }
            break;
        default:
        CU_FAIL("Invalid pop_value");
    }

    if (source_location == SOURCE_REGISTER)
        exec(create_instruction(INSTR_PUSH, push_mode, EMPTY_BYTE,
                                TEST_REGISTER));

    CU_ASSERT(pop_value == pop());
    deallocate();
}
Пример #14
0
static token_list * branch_op( token_list *t ) {
    int reg, dest;
    RW_Robo_Op new_op;
    token_list *tok = t;
    int type = tok->t;
    /* Check if we need a test instruction */
    if( tok->t != token_call && tok->t != token_jump ) {
        /* Get reg1 */
        tok = tok->next;
        if( !tok ) {
            error = err_unexpected_eof;
            return NULL;
        }
        else if( tok->t != token_reg ) {
            /* Syntax error */
            error_line = tok->line_number;
            error = err_reg1_expected;
            return NULL;
        }
        reg = tok->value;
        /* Create test instruction */
        encode_op_regs(new_op, op_one_reg, reg, 0, op_test);
        create_instruction(new_op);
        /* Eat comma */
        tok = tok->next;
        if( !tok ) {
            error = err_unexpected_eof;
            return NULL;
        }
        else if( tok->t != token_comma ) {
            /* Syntax error */
            error_line = tok->line_number;
            error = err_comma_expected;
            return NULL;
        }
    }
    /* Every branch instruction has at least 1 dest */
    tok = tok->next;
    if( !tok ) {
        error = err_unexpected_eof;
        return NULL;
    }
    else if( tok->t != token_label && tok->t != token_num ) {
        /* Syntax error */
        error_line = tok->line_number;
        error = err_labelnum_expected;
        return NULL;
    }
    if( tok->t == token_label ) {
        dest = check_label(tok);
    }
    else { /* tok->t == token_num */
        dest = tok->value;
    }
    /* Create first (and possibly last) branch instruction */
    if( type == token_jump || type == token_ifg || type == token_ifeg ) {
        encode_op_imme(new_op, op_jump, dest);
        create_instruction(new_op);
    }
    else {
        encode_op_imme(new_op, op_call, dest);
        create_instruction(new_op);
    }
    /* Do we have a second branch instruction we need to make? */
    if( type == token_ife || type == token_ifeg ) {
        /* Eat comma */
        tok = tok->next;
        if( !tok ) {
            error = err_unexpected_eof;
            return NULL;
        }
        else if( tok->t != token_comma ) {
            /* Syntax error */
            error_line = tok->line_number;
            error = err_comma_expected;
            return NULL;
        }
        tok = tok->next;
        if( !tok ) {
            error = err_unexpected_eof;
            return NULL;
        }
        else if( tok->t != token_label && tok->t != token_num ) {
            /* Syntax error */
            error_line = tok->line_number;
            error = err_labelnum_expected;
            return NULL;
        }
        if( tok->t == token_label ) {
            dest = check_label(tok);
        }
        else { /* tok->t == token_num */
            dest = tok->value;
        }
        /* Create second branch instruction */
        if( type == token_ifeg ) {
            encode_op_imme(new_op, op_jump, dest);
            create_instruction(new_op);
        }
        else {
            encode_op_imme(new_op, op_call, dest);
            create_instruction(new_op);
        }
    }
    return tok->next;
}
Пример #15
0
static void create_movb( int value ) {
    RW_Robo_Op new_op;
    encode_op_imme(new_op, op_movb, value);
    create_instruction(new_op);
}