diff --git a/src/asm_mn1610.cpp b/src/asm_mn1610.cpp index 674923ea..1a3f1700 100644 --- a/src/asm_mn1610.cpp +++ b/src/asm_mn1610.cpp @@ -15,7 +15,7 @@ */ #include "asm_mn1610.h" - +#include "ibm_float.h" #include "table_mn1610.h" #include "text_common.h" @@ -32,7 +32,6 @@ namespace { constexpr char TEXT_LOC[] PROGMEM = "loc"; constexpr Pseudo PSEUDOS[] PROGMEM = { - {TEXT_DC, &Assembler::defineDataConstant, Assembler::DATA_WORD}, {TEXT_DS, &Assembler::allocateSpaces, Assembler::DATA_WORD}, {TEXT_LOC, &Assembler::defineOrigin}, }; @@ -341,6 +340,63 @@ Error AsmMn1610::parseOperand(StrScanner &scan, Operand &op) const { return op.setError(UNKNOWN_OPERAND); } +Error AsmMn1610::defineDataConstant(StrScanner &scan, AsmInsn &insn, ErrorAt &_error) const { + ErrorAt error; + do { + scan.skipSpaces(); + ErrorAt strErr; + auto end = scan; + const auto err = isString(end, strErr); + if (err == OK) { + generateString(scan, end, insn.insnBase(), DATA_WORD, strErr); + if (error.setErrorIf(strErr) == NO_MEMORY) + break; + continue; + } + ErrorAt exprErr; + auto p = scan; + const auto val = parseExpr(p, exprErr); + if (!endOfLine(p) && *p != ',') { + if (strErr.getError()) { + error.setErrorIf(strErr); + } else { + error.setErrorIf(scan, ILLEGAL_CONSTANT); + } + break; + } + if (exprErr.hasError()) { + error.setErrorIf(strErr.getError() ? strErr : exprErr); + break; + } + if (val.isInteger()) { + if (val.overflowUint16()) + exprErr.setErrorIf(scan, OVERFLOW_RANGE); + exprErr.setErrorIf(scan, insn.emitUint16(val.getUnsigned())); + } else { +#if defined(LIBASM_ASM_NOFLOAT) + (void)val; + exprErr.setErrorIf(scan, FLOAT_NOT_SUPPORTED); + insn.emitUint32(0); +#else + ibm_float32_t f32; + exprErr.setErrorIf(scan, f32.set(val.getFloat())); + exprErr.setErrorIf(scan, insn.emitUint32(f32.bits())); +#endif + } + scan = p; + if (error.setErrorIf(exprErr) == NO_MEMORY) + break; + } while (scan.skipSpaces().expect(',')); + return _error.setError(error); +} + +Error AsmMn1610::processPseudo(StrScanner &scan, Insn &_insn) { + AsmInsn insn(_insn); + if (strcasecmp_P(insn.name(), TEXT_DC) == 0) + return defineDataConstant(scan, insn, _insn); + return Assembler::processPseudo(scan, _insn); +} + Error AsmMn1610::encodeImpl(StrScanner &scan, Insn &_insn) const { AsmInsn insn(_insn); if (TABLE.hasOperand(cpuType(), insn)) { diff --git a/src/asm_mn1610.h b/src/asm_mn1610.h index 68890582..660905d5 100644 --- a/src/asm_mn1610.h +++ b/src/asm_mn1610.h @@ -34,6 +34,8 @@ struct AsmMn1610 final : Assembler, Config { void encodeGenericAddress(AsmInsn &insn, const Operand &op) const; void encodeOperand(AsmInsn &insn, const Operand &op, AddrMode mode) const; + Error defineDataConstant(StrScanner &scan, AsmInsn &insn, ErrorAt &_error) const; + Error processPseudo(StrScanner &scan, Insn &_insn) override; Error encodeImpl(StrScanner &scan, Insn &insn) const override; const ConfigBase &config() const override { return *this; } ConfigSetter &configSetter() override { return *this; } diff --git a/src/asm_tms9900.cpp b/src/asm_tms9900.cpp index 48563a43..592a73a8 100644 --- a/src/asm_tms9900.cpp +++ b/src/asm_tms9900.cpp @@ -15,9 +15,9 @@ */ #include "asm_tms9900.h" - +#include "ibm_float.h" #include "table_tms9900.h" -#include "text_common.h" +#include "text_tms9900.h" namespace libasm { namespace tms9900 { @@ -25,6 +25,7 @@ namespace tms9900 { using namespace pseudo; using namespace reg; using namespace text::common; +using namespace text::tms9900; namespace { @@ -240,6 +241,44 @@ Error AsmTms9900::parseOperand(StrScanner &scan, Operand &op) const { return OK; } +Error AsmTms9900::defineFloatConstant(StrScanner &scan, AsmInsn &insn, ErrorAt &_error) const { + ErrorAt error; + do { + scan.skipSpaces(); + ErrorAt exprErr; + auto p = scan; + const auto val = parseExpr(p, exprErr); + if (!endOfLine(p) && *p != ',') { + error.setErrorIf(scan, ILLEGAL_CONSTANT); + break; + } + if (exprErr.hasError()) { + error.setErrorIf(exprErr); + break; + } +#if defined(LIBASM_ASM_NOFLOAT) + (void)val; + exprErr.setErrorIf(scan, FLOAT_NOT_SUPPORTED); + insn.emitUint32(0); +#else + ibm_float32_t f32; + exprErr.setErrorIf(scan, f32.set(val.getFloat())); + exprErr.setErrorIf(scan, insn.emitUint32(f32.bits())); +#endif + scan = p; + if (error.setErrorIf(exprErr) == NO_MEMORY) + break; + } while (scan.skipSpaces().expect(',')); + return _error.setError(error); +} + +Error AsmTms9900::processPseudo(StrScanner &scan, Insn &_insn) { + AsmInsn insn(_insn); + if (strcasecmp_P(insn.name(), TEXT_SINGLE) == 0) + return defineFloatConstant(scan, insn, _insn); + return Assembler::processPseudo(scan, _insn); +} + Error AsmTms9900::encodeImpl(StrScanner &scan, Insn &_insn) const { AsmInsn insn(_insn); if (TABLE.hasOperand(cpuType(), insn)) { diff --git a/src/asm_tms9900.h b/src/asm_tms9900.h index e8563f19..38c662b1 100644 --- a/src/asm_tms9900.h +++ b/src/asm_tms9900.h @@ -35,6 +35,8 @@ struct AsmTms9900 final : Assembler, Config { void encodeModeReg(AsmInsn &insn, const Operand &op, AddrMode mode) const; void encodeOperand(AsmInsn &insn, const Operand &op, AddrMode mode) const; + Error defineFloatConstant(StrScanner &scan, AsmInsn &insn, ErrorAt &_error) const; + Error processPseudo(StrScanner &scan, Insn &_insn) override; Error encodeImpl(StrScanner &scan, Insn &insn) const override; const ConfigBase &config() const override { return *this; } ConfigSetter &configSetter() override { return *this; } diff --git a/src/text_tms9900.cpp b/src/text_tms9900.cpp index 9ea2f966..99f0da07 100644 --- a/src/text_tms9900.cpp +++ b/src/text_tms9900.cpp @@ -134,6 +134,8 @@ constexpr char TEXT_NEGR[] PROGMEM = "NEGR"; // constexpr char TEXT_SR[] PROGMEM = "SR"; // constexpr char TEXT_STR[] PROGMEM = "STR"; +constexpr char TEXT_SINGLE[] PROGMEM = "SINGLE"; + // clang-format on } // namespace tms9900 } // namespace text diff --git a/src/text_tms9900.h b/src/text_tms9900.h index 58ce0a03..851ac657 100644 --- a/src/text_tms9900.h +++ b/src/text_tms9900.h @@ -137,6 +137,8 @@ extern const char TEXT_NEGR[] PROGMEM; using common::TEXT_SR; using common::TEXT_STR; +extern const char TEXT_SINGLE[] PROGMEM; + // clang-format on } // namespace tms9900 } // namespace text diff --git a/test/driver/test_formatter_mn1610.cpp b/test/driver/test_formatter_mn1610.cpp index d3aacb80..62b04ea1 100644 --- a/test/driver/test_formatter_mn1610.cpp +++ b/test/driver/test_formatter_mn1610.cpp @@ -56,13 +56,17 @@ void test_asm_mn1613() { ASM("mn1613", R"( cpu mn1613 * comment line - org x'34567' + loc x'34567' mvwi str, x'5678', skp + fa dr0, (r2) +f1: dc 7.8125e-03 )", R"( 0 : cpu mn1613 0 : * comment line - 34567 : org x'34567' + 34567 : loc x'34567' 34567 : 7e1f 5678 mvwi str, x'5678', skp + 34569 : 6f0d fa dr0, (r2) + 3456a : 3f20 0000 f1: dc 7.8125e-03 )"); } diff --git a/test/driver/test_formatter_tms9900.cpp b/test/driver/test_formatter_tms9900.cpp index 9bb10d9e..11d51a85 100644 --- a/test/driver/test_formatter_tms9900.cpp +++ b/test/driver/test_formatter_tms9900.cpp @@ -26,13 +26,13 @@ void set_up() {} void tear_down() {} -void test_asm_tms9900() { +void test_asm_tms99110() { PREP_ASM(tms9900::AsmTms9900, IntelDirective); driver.setUpperHex(false); - ASM("tms99105", - R"( cpu tms99105 + ASM("tms99110", + R"( cpu tms99110 * comment line aorg >9abc set location am @>4a4b(r1), @>4c4d(r1) @@ -44,8 +44,10 @@ label1: byte 4, 5, 6, 7 8 is comment even align label2: ab @label1, @label2 jmp label2; loop + mr @f1 +f1: single 7.8125e-03 )", - R"( 0 : cpu tms99105 + R"( 0 : cpu tms99110 0 : * comment line 9abc : aorg >9abc set location 9abc : 002a 4861 4a4b am @>4a4b(r1), @>4c4d(r1) @@ -58,34 +60,38 @@ label2: ab @label1, @label2 9ad0 : even align 9ad0 : b820 9ac7 9ad0 label2: ab @label1, @label2 9ad6 : 10fc jmp label2; loop + 9ad8 : 0d20 9adc mr @f1 + 9adc : 3f20 0000 f1: single 7.8125e-03 )"); } -void test_dis_tms9900() { +void test_dis_tms99110() { PREP_DIS(tms9900::DisTms9900); driver.setUpperHex(false); - DIS16("tms99105", 0x9abc, - R"( cpu 99105 + DIS16("tms99110", 0x9abc, + R"( cpu 99110 org >9abc am @>4a4b(r1), @>4c4d(r1) * test.bin: error: Unknown instruction * 9ac4 : 0383 + ar @>9ac8 )", - R"( 0 : cpu 99105 + R"( 0 : cpu 99110 9abc : org >9abc 9abc : 002a 4861 4a4b am @>4a4b(r1), @>4c4d(r1) 9ac2 : 4c4d test.bin: error: Unknown instruction 9ac4 : 0383 + 9ac6 : 0c60 9ac8 ar @>9ac8 )", - 0x002a, 0x4861, 0x4a4b, 0x4c4d, 0x0383); + 0x002a, 0x4861, 0x4a4b, 0x4c4d, 0x0383, 0x0c60, 0x9ac8); } void run_tests() { - RUN_TEST(test_asm_tms9900); - RUN_TEST(test_dis_tms9900); + RUN_TEST(test_asm_tms99110); + RUN_TEST(test_dis_tms99110); } } // namespace test diff --git a/test/test_asm_mn1610.cpp b/test/test_asm_mn1610.cpp index 15da925b..5fc23696 100644 --- a/test/test_asm_mn1610.cpp +++ b/test/test_asm_mn1610.cpp @@ -771,6 +771,17 @@ static void test_data_constant() { ERRT("DC C'TEXT", MISSING_CLOSING_QUOTE, "C'TEXT"); ERRT("DC 'TEXT", MISSING_CLOSING_QUOTE, "'TEXT"); ERUS("DC 1, UNDEF, 2", "UNDEF, 2", 0x0001, 0x0000, 0x0002); +#if defined(LIBASM_ASM_NOFLOAT) + ERRT("DC -1.0, 42.0, 7.8125e-03", FLOAT_NOT_SUPPORTED, "-1.0, 42.0, 7.8125e-03", + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000); + ERRT("DC 1.0, UNDEF + 0.0, 2.0", FLOAT_NOT_SUPPORTED, "1.0, UNDEF + 0.0, 2.0", + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000); +#else + TEST("DC -1.0, 42.0, 7.8125e-03", + 0xC110, 0x0000, 0x422A, 0x0000, 0x3F20, 0x0000); + ERUS("DC 1.0, UNDEF + 0.0, 2.0", "UNDEF + 0.0, 2.0", + 0x4110, 0x0000, 0x0000, 0x0000, 0x4120, 0x0000); +#endif ERRT("DC C'" "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" diff --git a/test/test_asm_tms9900.cpp b/test/test_asm_tms9900.cpp index 00f44a5d..08fbd76a 100644 --- a/test/test_asm_tms9900.cpp +++ b/test/test_asm_tms9900.cpp @@ -493,6 +493,17 @@ static void test_data_constant() { BERRT("BYTE 1, UNDEF, 2", UNDEFINED_SYMBOL, "UNDEF, 2", 0x01, 0x00, 0x02); BERRT("DATA 1, UNDEF, 2", UNDEFINED_SYMBOL, "UNDEF, 2", 0x00, 0x01, 0x00, 0x00, 0x00, 0x02); BERRT("TEXT 1, UNDEF, 2", UNDEFINED_SYMBOL, "UNDEF, 2", 0x01, 0x00, 0x02); +#if defined(LIBASM_ASM_NOFLOAT) + ERRT("SINGLE -1.0, 42.0, 7.8125e-03", FLOAT_NOT_SUPPORTED, "-1.0, 42.0, 7.8125e-03", + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000); + ERRT("SINGLE 1.0, UNDEF + 0.0, 2.0", FLOAT_NOT_SUPPORTED, "1.0, UNDEF + 0.0, 2.0", + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000); +#else + TEST("SINGLE -1.0, 42.0, 7.8125e-03", + 0xC110, 0x0000, 0x422A, 0x0000, 0x3F20, 0x0000); + ERUS("SINGLE 1.0, UNDEF + 0.0, 2.0", "UNDEF + 0.0, 2.0", + 0x4110, 0x0000, 0x0000, 0x0000, 0x4120, 0x0000); +#endif BERRT("TEXT '" "1234567890" "1234567890" "1234567890" "1234567890" "1234567890" "1234567890"