Skip to content

Commit

Permalink
[ASM] Refactor Value and assembler
Browse files Browse the repository at this point in the history
When not supporting floating point number (defined ASM_NOFLOAT in
config_libasm.h), it uses uint32_t to represent values.

When supporting floating point number (comment out ASM_NOFLOAT in
config_libasm.h), it uses uint64_t and double to represent
values. Although it keep external integer API as 32-bit integer for
compatibilty and optimization.
  • Loading branch information
tgtakaoka committed Sep 9, 2024
1 parent 1d8b79a commit 7238248
Show file tree
Hide file tree
Showing 98 changed files with 1,863 additions and 1,233 deletions.
2 changes: 1 addition & 1 deletion cli/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ OBJS_asm = \
$(foreach a,$(ARCHS),$(if $(wildcard ../src/asm_$(a).cpp),asm_$(a).o))
OBJS_dis = \
dis.o dis_commander.o dis_driver.o dis_formatter.o dis_base.o \
config_base.o reg_base.o \
config_base.o reg_base.o value.o \
$(foreach a,$(ARCHS),$(if $(wildcard ../src/dis_$(a).cpp),dis_$(a).o))
OBJS_bin = $(BINS:=.o)
$(eval $(foreach a,$(ARCHS),$(call objs-arch,$(a))))
Expand Down
2 changes: 1 addition & 1 deletion cli/build.ninja
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ build dis: link $
intel_hex.o moto_srec.o $
dis_base.o config_base.o error_reporter.o formatters.o option_base.o $
insn_base.o reg_base.o str_buffer.o str_scanner.o text_common.o $
value_formatter.o $
value_formatter.o value.o $
dis_cdp1802.o reg_cdp1802.o table_cdp1802.o text_cdp1802.o $
dis_f3850.o reg_f3850.o table_f3850.o text_f3850.o $
dis_i8048.o reg_i8048.o table_i8048.o text_i8048.o $
Expand Down
6 changes: 4 additions & 2 deletions driver/asm_directive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@ Error AsmDirective::encode(StrScanner &scan, Insn &insn, Context &context) {
if (context.reportDuplicate && context.symbols.hasSymbol(context.label)) {
setErrorIf(context.label, DUPLICATE_LABEL);
} else {
context.symbols.internSymbol(insn.address(), context.label);
Value addr;
addr.setUnsigned(insn.address());
context.symbols.internSymbol(addr, context.label);
}
}
if (error != UNKNOWN_DIRECTIVE)
Expand Down Expand Up @@ -200,7 +202,7 @@ Error AsmDirective::defineSymbol(
if (context.reportUndefined && error.getError() == UNDEFINED_SYMBOL)
return setError(error);

setErrorIf(symbol, context.symbols.internSymbol(context.value.getUnsigned(), symbol, variable));
setErrorIf(symbol, context.symbols.internSymbol(context.value, symbol, variable));
return getError();
}

Expand Down
4 changes: 2 additions & 2 deletions driver/function_store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ bool FunctionStore::Binding::hasSymbol(const StrScanner &symbol) const {
parent->hasSymbol(symbol);
}

uint32_t FunctionStore::Binding::lookupSymbol(const StrScanner &symbol) const {
SymbolTable::symval_t FunctionStore::Binding::lookupSymbol(const StrScanner &symbol) const {
const auto it = paramsAt.find(std::string(symbol.str(), symbol.size()));
if (it == paramsAt.end())
return parent->lookupSymbol(symbol);
return stack.at(it->second).getUnsigned();
return stack.at(it->second).getSigned();
}

const void *FunctionStore::Binding::lookupFunction(const StrScanner &symbol) const {
Expand Down
2 changes: 1 addition & 1 deletion driver/function_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ struct FunctionStore final {
Binding(const ParametersAt &paramsAt_, const ValueStack &stack_, const SymbolTable *parent_)
: paramsAt(paramsAt_), stack(stack_), parent(parent_) {}
bool hasSymbol(const StrScanner &symbol) const override;
uint32_t lookupSymbol(const StrScanner &symbol) const override;
symval_t lookupSymbol(const StrScanner &symbol) const override;
const void *lookupFunction(const StrScanner &symbol) const override;

private:
Expand Down
10 changes: 6 additions & 4 deletions driver/symbol_store.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ bool SymbolStoreImpl::hasSymbol(const StrScanner &symbol) const {
return hasValue(symbol, false) || hasValue(symbol, true);
}

uint32_t SymbolStoreImpl::lookupSymbol(const StrScanner &symbol) const {
SymbolTable::symval_t SymbolStoreImpl::lookupSymbol(const StrScanner &symbol) const {
const auto key = std::string(symbol.str(), symbol.size());
const auto s = _symbols.find(key);
if (s != _symbols.end())
Expand All @@ -66,17 +66,19 @@ bool SymbolStoreImpl::hasValue(const StrScanner &symbol, bool variable) const {
return map.find(key) != map.end();
}

Error SymbolStoreImpl::internSymbol(uint32_t value, const StrScanner &symbol, bool variable) {
Error SymbolStoreImpl::internSymbol(const Value &value, const StrScanner &symbol, bool variable) {
if (hasValue(symbol, !variable))
return DUPLICATE_LABEL;
if (value.overflowUint32())
return OVERFLOW_RANGE;

const auto key = std::string(symbol.str(), symbol.size());
auto &map = variable ? _variables : _symbols;
auto it = map.find(key);
if (it == map.end()) {
map.emplace(key, value);
map.emplace(key, value.getInteger());
} else {
it->second = value;
it->second = value.getInteger();
}
return OK;
}
Expand Down
14 changes: 8 additions & 6 deletions driver/symbol_store.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ namespace driver {

struct SymbolStore : SymbolTable {
virtual bool hasValue(const StrScanner &symbol, bool variable) const = 0;
virtual Error internSymbol(uint32_t value, const StrScanner &symbol, bool variable = false) = 0;
virtual Error internSymbol(
const Value &value, const StrScanner &symbol, bool variable = false) = 0;
virtual bool hasFunction(const StrScanner &name) const = 0;
virtual Error internFunction(const StrScanner &name, const FunctionStore::Parameters &params,
const StrScanner &body, const ValueParser &parser) = 0;
Expand All @@ -47,21 +48,22 @@ struct SymbolStoreImpl final : SymbolStore {
void clearFunctions();

// SymbolTable
const char *lookupValue(uint32_t) const override { return nullptr; }
const char *lookupValue(symval_t) const override { return nullptr; }
bool hasSymbol(const StrScanner &name) const override;
uint32_t lookupSymbol(const StrScanner &symbol) const override;
symval_t lookupSymbol(const StrScanner &symbol) const override;
const void *lookupFunction(const StrScanner &name) const override;

bool hasValue(const StrScanner &symbol, bool variable) const override;
Error internSymbol(uint32_t value, const StrScanner &symbol, bool variable = false) override;
Error internSymbol(
const Value &value, const StrScanner &symbol, bool variable = false) override;

bool hasFunction(const StrScanner &name) const override;
Error internFunction(const StrScanner &name, const FunctionStore::Parameters &params,
const StrScanner &body, const ValueParser &parser) override;

private:
std::map<std::string, uint32_t, std::less<>> _symbols;
std::map<std::string, uint32_t, std::less<>> _variables;
std::map<std::string, symval_t, std::less<>> _symbols;
std::map<std::string, symval_t, std::less<>> _variables;
FunctionStore _functions;
};

Expand Down
37 changes: 13 additions & 24 deletions src/asm_base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,26 +111,13 @@ Error Assembler::processPseudo(StrScanner &scan, Insn &insn) {
return p ? p->invoke(this, scan, insn) : UNKNOWN_DIRECTIVE;
}

uint16_t Assembler::parseExpr16(StrScanner &expr, ErrorAt &error, char delim) const {
Value Assembler::parseInteger(StrScanner &expr, ErrorAt &error, char delim) const {
auto p = expr;
const auto value = _parser.eval(p, error, _symtab, delim);
#ifndef LIBASM_ASM_NOFLOAT
if (value.isFloat())
error.setErrorIf(expr, INTEGER_REQUIRED);
#endif
if (value.overflowUint16())
error.setErrorIf(expr, OVERFLOW_RANGE);
expr = p;
return value.getUnsigned();
}

uint32_t Assembler::parseExpr32(StrScanner &expr, ErrorAt &error, char delim) const {
const auto value = _parser.eval(expr, error, _symtab, delim);
#ifndef LIBASM_ASM_NOFLOAT
if (value.isFloat())
error.setErrorIf(expr, INTEGER_REQUIRED);
#endif
return value.getUnsigned();
return value;
}

Value Assembler::parseExpr(StrScanner &expr, ErrorAt &error, char delim) const {
Expand Down Expand Up @@ -409,7 +396,7 @@ Error Assembler::defineDataConstant(StrScanner &scan, Insn &insn, uint8_t dataTy
big ? insn.emitUint32Be(v) : insn.emitUint32Le(v);
break;
case DATA_FLOAT32_LONG:
if (val.isInt32()) {
if (val.isInteger()) {
const auto v = val.getUnsigned();
big ? insn.emitUint32Be(v) : insn.emitUint32Le(v);
break;
Expand All @@ -420,8 +407,8 @@ Error Assembler::defineDataConstant(StrScanner &scan, Insn &insn, uint8_t dataTy
big ? insn.emitFloat32Be(val.getFloat()) : insn.emitFloat32Le(val.getFloat());
break;
case DATA_FLOAT64_QUAD:
if (val.isInt64()) {
const auto v = val.getInt64();
if (val.isInteger()) {
const auto v = val.getInteger();
big ? insn.emitUint64Be(v) : insn.emitUint64Le(v);
break;
}
Expand All @@ -430,14 +417,16 @@ Error Assembler::defineDataConstant(StrScanner &scan, Insn &insn, uint8_t dataTy
big ? insn.emitFloat64Be(val.getFloat()) : insn.emitFloat64Le(val.getFloat());
break;
case DATA_FLOAT80_BCD:
if (val.isInt64()) {
const auto value = val.getInt64();
constexpr auto MAX_PBCD80 = 999'999'999'999'999'999L;
constexpr auto MIN_PBCD80 = -MAX_PBCD80;
if (value >= MIN_PBCD80 && value <= MAX_PBCD80) {
insn.emitPackedBcd80Le(value);
if (val.isInteger()) {
constexpr auto PBCD80_MAX = INT64_C(999'999'999'999'999'999);
constexpr auto PBCD80_MIN = -INT64_C(999'999'999'999'999'999);
const auto v = val.getInteger();
if (v >= PBCD80_MIN && v <= PBCD80_MAX) {
insn.emitPackedBcd80Le(v);
break;
}
insn.setError(OVERFLOW_RANGE);
break;
}
if (!big) // i8087
insn.emitFloat80Le(val.getFloat());
Expand Down
9 changes: 3 additions & 6 deletions src/asm_base.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ struct Assembler : private ValueParser::Locator {

const ValueParser &parser() const { return _parser; }
bool endOfLine(StrScanner &scan) const { return _parser.endOfLine(scan); }
/** Parse |expr| text and get value. */
/** Parse |expr| text as an integer expression and get value. */
Value parseInteger(StrScanner &expr, ErrorAt &error, char delim = 0) const;
/** Parse |expr| text as an expression and get value. */
Value parseExpr(StrScanner &expr, ErrorAt &error, char delim = 0) const;

bool setCpu(const char *name);
Expand Down Expand Up @@ -108,11 +110,6 @@ struct Assembler : private ValueParser::Locator {

int32_t branchDelta(uint32_t base, uint32_t target, ErrorAt &error, const ErrorAt &at) const;

/** Parse |expr| text and get value as unsigned 16 bit. */
uint16_t parseExpr16(StrScanner &expr, ErrorAt &error, char delim = 0) const;
/** Parse |expr| text and get value as unsigned 32 bit. */
uint32_t parseExpr32(StrScanner &expr, ErrorAt &error, char delim = 0) const;

void generateString(StrScanner &scan, const StrScanner &end, Insn &insn, DataType type,
ErrorAt &error) const;

Expand Down
51 changes: 27 additions & 24 deletions src/asm_cdp1802.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ struct RcaNumberParser final : NumberParser {
Error parseNumber(StrScanner &scan, Value &val) const override {
auto p = scan;
if (*p == '#' && isxdigit(p[1])) {
const auto error = val.parseNumber(++p, RADIX_16);
const auto error = val.read(++p, RADIX_16);
if (error == OK)
scan = p;
return error;
Expand Down Expand Up @@ -135,23 +135,23 @@ const struct : Functor {
int8_t nargs() const override { return 1; }
Error eval(ValueStack &stack, uint8_t) const override {
// Mark that this is 2 bytes value.
stack.pushUnsigned((stack.pop().getUnsigned() & 0xFFFF) | 0x10000);
stack.pushUnsigned((stack.pop().getUnsigned() & UINT16_MAX) | UINT32_C(0x1000'0000));
return OK;
}
} FN_A;

const struct : Functor {
int8_t nargs() const override { return 1; }
Error eval(ValueStack &stack, uint8_t) const override {
stack.pushUnsigned(stack.pop().getUnsigned() & 0xFF);
stack.pushUnsigned(stack.pop().getUnsigned() & UINT8_MAX);
return OK;
}
} FN_A0;

const struct : Functor {
int8_t nargs() const override { return 1; }
Error eval(ValueStack &stack, uint8_t) const override {
stack.pushUnsigned((stack.pop().getUnsigned() >> 8) & 0xFF);
stack.pushUnsigned((stack.pop().getUnsigned() >> 8) & UINT8_MAX);
return OK;
}
} FN_A1;
Expand Down Expand Up @@ -183,7 +183,7 @@ void interBranch(AsmInsn &insn) {

void AsmCdp1802::encodePage(AsmInsn &insn, AddrMode mode, const Operand &op) const {
const auto base = insn.address() + 2;
const auto target = op.getError() ? base : op.val16;
const auto target = op.getError() ? base : op.val.getUnsigned();
if (mode == M_PAGE || (mode == M_SHRT && !_smartBranch)) {
insn.setErrorIf(op, checkAddr(target, base, 8));
intra_page:
Expand All @@ -193,8 +193,10 @@ void AsmCdp1802::encodePage(AsmInsn &insn, AddrMode mode, const Operand &op) con
}
if (mode == M_ADDR || (mode == M_LONG && !_smartBranch)) {
inter_page:
const auto target = op.val.getUnsigned();
insn.setErrorIf(op, checkAddr(target));
insn.emitInsn();
insn.emitUint16(op.val16);
insn.emitUint16(target);
return;
}
if (op.getError() || checkAddr(target, base, 8)) {
Expand All @@ -207,31 +209,31 @@ void AsmCdp1802::encodePage(AsmInsn &insn, AddrMode mode, const Operand &op) con

void AsmCdp1802::emitOperand(AsmInsn &insn, AddrMode mode, const Operand &op) const {
insn.setErrorIf(op);
auto val16 = op.val16;
auto val = op.val;
switch (mode) {
case M_REG1:
if (op.getError())
val16 = 7; // default work register.
if (val16 == 0) {
val.setUnsigned(7); // default work register.
if (val.isZero()) {
insn.setErrorIf(op, REGISTER_NOT_ALLOWED);
val16 = 7;
val.setUnsigned(7);
}
/* Fall-through */
case M_REGN:
if (op.getError())
val16 = 7; // default work register.
if (val16 >= 16) {
val.setUnsigned(7); // default work register.
if (val.overflow(15)) {
insn.setErrorIf(op, ILLEGAL_REGISTER);
val16 = 7;
val.setUnsigned(7);
}
insn.embed(val16);
insn.embed(val.getUnsigned());
insn.emitInsn();
break;
case M_IMM8:
if (overflowUint8(val16))
if (val.overflowUint8())
insn.setErrorIf(op, OVERFLOW_RANGE);
insn.emitInsn();
insn.emitByte(val16);
insn.emitByte(val.getUnsigned());
break;
case M_PAGE:
case M_ADDR:
Expand All @@ -241,12 +243,12 @@ void AsmCdp1802::emitOperand(AsmInsn &insn, AddrMode mode, const Operand &op) co
break;
case M_IOAD:
if (op.getError())
val16 = 1; // default IO address
if (val16 == 0 || val16 >= 8) {
val.setUnsigned(1); // default IO address
if (val.isZero() || val.overflow(7)) {
insn.setErrorIf(op, OPERAND_NOT_ALLOWED);
val16 = 1;
val.setUnsigned(1);
}
insn.embed(val16);
insn.embed(val.getUnsigned());
insn.emitInsn();
break;
default:
Expand All @@ -264,13 +266,13 @@ Error AsmCdp1802::parseOperand(StrScanner &scan, Operand &op) const {
if (_useReg) {
const auto reg = parseRegName(p);
if (reg != REG_UNDEF) {
op.val16 = int8_t(reg);
op.val.setUnsigned(static_cast<uint8_t>(reg));
op.mode = M_REGN;
scan = p;
return OK;
}
}
op.val16 = parseExpr(p, op).getUnsigned();
op.val = parseInteger(p, op);
if (!op.hasError()) {
op.mode = M_ADDR;
scan = p;
Expand All @@ -293,8 +295,9 @@ Error AsmCdp1802::encodeImpl(StrScanner &scan, Insn &_insn) const {

emitOperand(insn, insn.mode1(), insn.op1);
if (insn.mode2() == M_ADDR) {
insn.setErrorIf(insn.op2);
insn.emitUint16(insn.op2.val16);
const auto &op = insn.op2;
insn.setErrorIf(op);
insn.emitUint16(op.val.getUnsigned());
}
return _insn.setError(insn);
}
Expand Down
Loading

0 comments on commit 7238248

Please sign in to comment.