Skip to content

Commit

Permalink
[TEST] Improve ArrayMemory
Browse files Browse the repository at this point in the history
  • Loading branch information
tgtakaoka committed Jan 29, 2025
1 parent c7d84ef commit e30904f
Show file tree
Hide file tree
Showing 10 changed files with 315 additions and 123 deletions.
81 changes: 58 additions & 23 deletions src/array_memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,49 +26,85 @@
namespace libasm {

/**
* Byte addressable memory from array constant
* Byte/Word addressable memory from array constant
*/
struct ArrayMemory {
/** DisMemory interface of ArrayMemory */
struct Iterator : DisMemory {
bool hasNext() const override { return _index < _memory.size(); }

uint16_t readUint16() {
uint16_t word = readByte();
if (_endian == ENDIAN_BIG) {
word = (word << 8) | readByte();
} else {
word |= readByte() << 8;
}
return word;
}

/** rewind to the first byte */
void rewind() {
DisMemory::resetAddress(_memory.origin());
DisMemory::resetAddress(_memory.origin() * _memory.unit());
_index = 0;
}

private:
friend ArrayMemory;
Iterator(const ArrayMemory &memory)
: DisMemory(memory.origin()), _memory(memory), _index(0) {}
uint8_t nextByte() override { return _memory.byteAt(_memory.origin() + _index++); }
Iterator(const ArrayMemory &memory, Endian endian)
: DisMemory(memory.origin() * memory.unit()),
_memory(memory),
_endian(endian),
_index(0) {}

uint8_t nextByte() override {
return _memory.byteAt(_memory.origin() * _memory.unit() + _index++);
}

const ArrayMemory &_memory;
const Endian _endian;
size_t _index;
};

/** Construct byte addressable memory from uint8_t array */
ArrayMemory(
uint32_t origin, const uint8_t *bytes, size_t sizeof_bytes, Endian endian = ENDIAN_BIG)
: _origin(origin), _bytes(bytes), _words(nullptr), _size(sizeof_bytes), _endian(endian) {}
ArrayMemory(uint32_t origin, const uint8_t *bytes, size_t sizeof_bytes,
Endian endian = ENDIAN_BIG, AddressUnit = ADDRESS_BYTE)
: _origin(origin),
_bytes(bytes),
_words(nullptr),
_size(sizeof_bytes),
_endian(endian),
_unit(ADDRESS_BYTE) {}

/** Construct byte/word addressable memory from uint16_t array */
ArrayMemory(uint32_t origin, const uint16_t *words, size_t sizeof_words, Endian endian,
AddressUnit unit)
: _origin(origin * unit),
_bytes(nullptr),
_words(words),
_size(sizeof_words),
_endian(endian),
_unit(unit) {}

/** byte address of the first byte/word */
uint32_t origin() const { return _origin / _unit; }

/** byte address of the last byte/word */
uint32_t end() const { return (_origin + size()) / _unit - 1; }

/** Construct byte addressable memory from uint16_t array with specified endian */
ArrayMemory(uint32_t origin, const uint16_t *words, size_t sizeof_words, Endian endian)
: _origin(origin), _bytes(nullptr), _words(words), _size(sizeof_words), _endian(endian) {}
/** memory size in byte */
size_t size() const { return _size; }

/** byte address of the first byte */
uint32_t origin() const { return _origin; }
bool word() const { return _words != nullptr; }

/** byte address of the last byte */
uint32_t end() const { return _origin + size() - 1; }
/** endianess */
Endian endian() const { return _endian; }

/** memory size in byte */
size_t size() const { return _size; }
AddressUnit unit() const { return _unit; }

/** returns DisMemory interface */
Iterator iterator() const { return Iterator(*this); }
/** returns DisMemory interface with specified endian */
Iterator iterator(Endian endian = ENDIAN_BIG) const { return Iterator(*this, endian); }

/** returns byte at address |addr|, otherwise zero */
uint8_t byteAt(uint32_t addr) const {
Expand All @@ -78,12 +114,10 @@ struct ArrayMemory {
if (_bytes)
return _bytes[offset];
const uint16_t word = _words[offset / 2];
const uint8_t hi = word >> 8;
const uint8_t lo = word;
if (offset % 2 == 0) {
return _endian == ENDIAN_BIG ? hi : lo;
if (_endian == ENDIAN_BIG) {
return (offset % 2) == 0 ? (word >> 8) : word;
} else {
return _endian == ENDIAN_BIG ? lo : hi;
return (offset % 2) == 0 ? word : (word >> 8);
}
}

Expand All @@ -95,6 +129,7 @@ struct ArrayMemory {
/** size in byte */
const size_t _size;
const Endian _endian;
const AddressUnit _unit;
};

} // namespace libasm
Expand Down
8 changes: 8 additions & 0 deletions src/config_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ enum Endian : uint8_t {
ENDIAN_LITTLE,
};

enum Radix : uint8_t {
RADIX_NONE = 0,
RADIX_2 = 2,
RADIX_8 = 8,
RADIX_10 = 10,
RADIX_16 = 16,
};

enum Size : uint8_t {
SZ_NONE = 0,
SZ_BYTE = 1, // 1 byte
Expand Down
9 changes: 1 addition & 8 deletions src/value.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,14 @@
#define __LIBASM_VALUE_H__

#include <stdint.h>
#include "config_base.h"
#include "error_reporter.h"
#include "float80.h"

namespace libasm {

struct StrScanner;

enum Radix : uint8_t {
RADIX_NONE = 0,
RADIX_2 = 2,
RADIX_8 = 8,
RADIX_10 = 10,
RADIX_16 = 16,
};

struct Value {
#if defined(LIBASM_ASM_NOFLOAT)
using signed_t = int32_t;
Expand Down
4 changes: 2 additions & 2 deletions test/test_asm_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ TestSymtab symtab;

void asm_assert(const char *file, int line, const ErrorAt &error, const char *src,
const ArrayMemory &expected) {
Insn insn(expected.origin() / assembler.config().addressUnit());
Insn insn(expected.origin());
assembler.encode(src, insn, &symtab);
asserter.equals(file, line, src, error.errorText_P(), insn.errorText_P());
asserter.equals(file, line, "error at", error.errorAt(), insn.errorAt());
asserter.equals(file, line, src, expected, insn.bytes(), insn.length());
asserter.equals(file, line, src, expected, insn.bytes(), insn.length(), assembler.listRadix());
}

bool test_failed;
Expand Down
22 changes: 10 additions & 12 deletions test/test_asm_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,22 @@ void run_test(void (*test)(), const char *name, void (*set_up)(), void (*tear_do
asserter.equals_P(__FILE__, __LINE__, msg, expected, actual_P)
#define __VASSERT(file, line, err, at, addr, src, ...) \
do { \
const auto unit = assembler.config().addressUnit(); \
const auto endian = assembler.config().endian(); \
const Config::opcode_t expected[] = {__VA_ARGS__}; \
const ArrayMemory memory(addr *unit, expected, sizeof(expected), endian); \
ErrorAt error; \
error.setError(at, err); \
asm_assert(file, line, error, src, memory); \
} while (0)
#define __BVASSERT(file, line, err, at, addr, src, ...) \
do { \
const auto unit = assembler.config().addressUnit(); \
const auto endian = assembler.config().endian(); \
const uint8_t expected[] = {__VA_ARGS__}; \
const ArrayMemory memory(addr *unit, expected, sizeof(expected), endian); \
const auto unit = assembler.config().addressUnit(); \
const ArrayMemory memory(addr, expected, sizeof(expected), endian, unit); \
ErrorAt error; \
error.setError(at, err); \
asm_assert(file, line, error, src, memory); \
} while (0)
#define __BVASSERT(file, line, err, at, addr, src, ...) \
do { \
const uint8_t expected[] = {__VA_ARGS__}; \
const ArrayMemory memory(addr, expected, sizeof(expected)); \
ErrorAt error; \
error.setError(at, err); \
asm_assert(file, line, error, src, memory); \
} while (0)
#define VASSERT(error, at, addr, src, ...) \
__VASSERT(__FILE__, __LINE__, error, at, addr, src, ##__VA_ARGS__)
#define BVASSERT(error, at, addr, src, ...) \
Expand Down
26 changes: 21 additions & 5 deletions test/test_asserter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,10 @@ void TestAsserter::equals(const char *file, const int line, const char *message,
}

void TestAsserter::equals(const char *file, const int line, const char *message,
const ArrayMemory &expected, const uint8_t actual[], size_t actual_len) {
const ArrayMemory &expected, const uint8_t actual[], size_t actual_len, Radix radix) {
const auto endian = expected.endian();
size_t i;
auto it = expected.iterator();
auto it = expected.iterator(endian);
for (i = 0, it.rewind(); i < actual_len && it.hasNext(); i++) {
if (it.readByte() != actual[i])
break;
Expand All @@ -189,18 +190,33 @@ void TestAsserter::equals(const char *file, const int line, const char *message,
return;
}
_fail_count++;
const auto unit = expected.unit();
const auto word = (unit == ADDRESS_WORD) || (expected.word());
const auto fmt8 = (radix == RADIX_8) ? "%03" PRIo8 : "%02" PRIX8;
const auto fmt16 = (radix == RADIX_8) ? "%06" PRIo16 : "%04" PRIX16;

printf("%s:%d: %s: expected [", file, line, message);
for (i = 0, it.rewind(); it.hasNext(); i++) {
if (i)
printf(" ");
printf("%02" PRIX8, it.readByte());
if (word) {
printf(fmt16, it.readUint16());
} else {
printf(fmt8, it.readByte());
}
}
printf("]\n");
const ArrayMemory mem(0, actual, actual_len, endian, unit);
auto m = mem.iterator(endian);
printf("%s:%d: %s: actual [", file, line, message);
for (i = 0; i < actual_len; i++) {
for (i = 0; m.hasNext(); i++) {
if (i)
printf(" ");
printf("%02" PRIX8, actual[i]);
if (word) {
printf(fmt16, m.readUint16());
} else {
printf(fmt8, m.readByte());
}
}
printf("]\n");
}
Expand Down
2 changes: 1 addition & 1 deletion test/test_asserter.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ struct TestAsserter {

/** assert uint8_t[] with ArrayMemory */
void equals(const char *file, const int line, const char *message, const ArrayMemory &expected,
const uint8_t actual[], size_t actual_len);
const uint8_t actual[], size_t actual_len, Radix radix = RADIX_16);

/** assert const char* is not equal */
void not_equals(const char *file, int line, const char *message, const char *expected,
Expand Down
5 changes: 3 additions & 2 deletions test/test_dis_helper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,16 @@ char actual_opr[128];

void dis_assert(const char *file, int line, const ErrorAt &error, const ArrayMemory &memory,
const char *expected_name, const char *expected_opr) {
Insn insn(memory.origin() / disassembler.config().addressUnit());
Insn insn(memory.origin());
auto mem = memory.iterator();
disassembler.decode(mem, insn, actual_opr, sizeof(actual_opr), &symtab);

asserter.equals(file, line, expected_name, error.errorText_P(), insn.errorText_P());
asserter.equals(file, line, "error at", error.errorAt(), insn.errorAt());
asserter.equals(file, line, expected_name, expected_name, insn);
asserter.equals(file, line, expected_name, expected_opr, actual_opr);
asserter.equals(file, line, expected_name, memory, insn.bytes(), insn.length());
asserter.equals(file, line, expected_name, memory, insn.bytes(), insn.length(),
disassembler.listRadix());
}

bool test_failed;
Expand Down
6 changes: 3 additions & 3 deletions test/test_dis_helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ void run_test(void (*test)(), const char *name, void (*set_up)(), void (*tear_do
asserter.not_equals(__FILE__, __LINE__, msg, expected, actual)
#define __VASSERT(file, line, err, at, addr, name, opr, ...) \
do { \
const auto unit = disassembler.config().addressUnit(); \
const auto endian = disassembler.config().endian(); \
const Config::opcode_t codes[] = {__VA_ARGS__}; \
const ArrayMemory memory(addr *unit, codes, sizeof(codes), endian); \
const auto endian = disassembler.config().endian(); \
const auto unit = disassembler.config().addressUnit(); \
const ArrayMemory memory(addr, codes, sizeof(codes), endian, unit); \
ErrorAt error; \
error.setError(at, err); \
dis_assert(file, line, error, memory, name, opr); \
Expand Down
Loading

0 comments on commit e30904f

Please sign in to comment.