Skip to content

Commit

Permalink
Add data constant directive for IBM floating point number
Browse files Browse the repository at this point in the history
- [MN1610] DC directive accepts floating point number and generates
  IBM 32-bit Hexadecimal floating point constants.

- [TMS9900] SINGLE directive accepts floating point number and
  generates IBM 32-bit Hexadecimal floating point constants.
  • Loading branch information
tgtakaoka committed Oct 21, 2024
1 parent 4991814 commit af01160
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 17 deletions.
60 changes: 58 additions & 2 deletions src/asm_mn1610.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/

#include "asm_mn1610.h"

#include "ibm_float.h"
#include "table_mn1610.h"
#include "text_common.h"

Expand All @@ -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},
};
Expand Down Expand Up @@ -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)) {
Expand Down
2 changes: 2 additions & 0 deletions src/asm_mn1610.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
43 changes: 41 additions & 2 deletions src/asm_tms9900.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,17 @@
*/

#include "asm_tms9900.h"

#include "ibm_float.h"
#include "table_tms9900.h"
#include "text_common.h"
#include "text_tms9900.h"

namespace libasm {
namespace tms9900 {

using namespace pseudo;
using namespace reg;
using namespace text::common;
using namespace text::tms9900;

namespace {

Expand Down Expand Up @@ -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)) {
Expand Down
2 changes: 2 additions & 0 deletions src/asm_tms9900.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down
2 changes: 2 additions & 0 deletions src/text_tms9900.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/text_tms9900.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 6 additions & 2 deletions test/driver/test_formatter_mn1610.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
)");
}

Expand Down
28 changes: 17 additions & 11 deletions test/driver/test_formatter_tms9900.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand All @@ -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
Expand Down
11 changes: 11 additions & 0 deletions test/test_asm_mn1610.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
11 changes: 11 additions & 0 deletions test/test_asm_tms9900.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down

0 comments on commit af01160

Please sign in to comment.