Skip to content

Commit

Permalink
[TLCS90] Fix LDA/JP/CALL operand
Browse files Browse the repository at this point in the history
  • Loading branch information
tgtakaoka committed Nov 28, 2023
1 parent 722f5ad commit 405f881
Show file tree
Hide file tree
Showing 8 changed files with 746 additions and 699 deletions.
116 changes: 56 additions & 60 deletions src/asm_tlcs90.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ void AsmTlcs90::encodeOperand(
insn.emitInsn(opc | encodeReg16(op.reg));
return;
case M_IDX:
case M_IXPD:
if (overflowInt8(static_cast<int16_t>(op.val16)))
insn.setErrorIf(op, OVERFLOW_RANGE);
insn.emitInsn(opc | encodeIndexReg(op.reg));
Expand Down Expand Up @@ -184,83 +185,78 @@ Error AsmTlcs90::parseOperand(StrScanner &scan, Operand &op) const {
return OK;
}

auto reg = parseRegName(p);
if (reg != REG_UNDEF) {
switch (reg) {
case REG_IX:
case REG_IY:
op.mode = M_REGIX;
break;
case REG_B:
case REG_D:
case REG_E:
case REG_H:
case REG_L:
op.mode = M_REG8;
break;
default:
op.mode = AddrMode(int8_t(reg) + R_BASE);
break;
const auto paren = p.expect('(') ? ')' : 0;
const auto regAt = p.skipSpaces();
const auto reg = parseRegName(p);
if (reg == REG_UNDEF) {
op.val16 = parseExpr16(p, op, paren);
if (op.hasError())
return op.getError();
if (paren && !p.skipSpaces().expect(')'))
return op.setError(p, MISSING_CLOSING_PAREN);
if (paren) { // (nnnn)
op.mode = op.getError() ? M_SYM : (op.val16 >= 0xFF00 ? M_DIR : M_EXT);
} else { // nnnn
op.mode = M_IMM16;
}
op.reg = reg;
scan = p;
return OK;
}
if (p.expect('(')) {
const auto regp = p.skipSpaces();
reg = parseRegName(p);
if (reg == REG_UNDEF) { // (nnnn)
op.val16 = parseExpr16(p, op, ')');
if (op.hasError())
return op.getError();
if (!p.skipSpaces().expect(')'))
return op.setError(p, MISSING_CLOSING_PAREN);
op.mode = op.getError() ? M_SYM : (op.val16 >= 0xFF00 ? M_DIR : M_EXT);
p.skipSpaces();
op.reg = reg;
if (paren && p.expect(')')) { // (rr)
if (isReg16(reg)) {
op.mode = M_IND;
scan = p;
return OK;
}
op.reg = reg;
if (p.skipSpaces().expect(')')) { // (rr)
if (isReg16(reg)) {
op.mode = M_IND;
scan = p;
return OK;
}
return op.setError(regp, REGISTER_NOT_ALLOWED);
}
auto a = p;
if (reg == REG_HL && a.expect('+')) {
const auto idxp = a.skipSpaces();
const auto idx = parseRegName(a);
return op.setError(regAt, REGISTER_NOT_ALLOWED);
}
const auto dispAt = p;
const auto disp = p.expect([](char c) { return c == '+' || c == '-'; });
if (disp) {
if (reg == REG_HL && disp == '+') {
const auto idxAt = p.skipSpaces();
const auto idx = parseRegName(p);
if (idx != REG_UNDEF) {
if (idx != REG_A)
return op.setError(idxp, REGISTER_NOT_ALLOWED);
if (!a.skipSpaces().expect(')'))
return op.setError(a, MISSING_CLOSING_PAREN);
scan = a;
op.mode = M_BASE; // (HL+A)
return op.setError(idxAt, REGISTER_NOT_ALLOWED);
if (paren && !p.skipSpaces().expect(')'))
return op.setError(p, MISSING_CLOSING_PAREN);
scan = p;
op.mode = paren ? M_BASE : M_HLPA; // (HL+A), HL+A
return OK;
}
}
if (*p == '+' || *p == '-') { // (rr+n)
op.val16 = parseExpr16(p, op, ')');
if (isRegIndex(reg)) {
p = dispAt;
op.val16 = parseExpr16(p, op, paren);
if (op.hasError())
return op.getError();
if (!p.skipSpaces().expect(')'))
if (paren && !p.skipSpaces().expect(')'))
return op.setError(p, MISSING_CLOSING_PAREN);
if (isRegIndex(reg)) {
scan = p;
op.mode = M_IDX;
return OK;
}
return op.setError(regp, REGISTER_NOT_ALLOWED);
scan = p;
op.mode = paren ? M_IDX : M_IXPD; // (ix+d), ix+d
return OK;
}
return op.setError(UNKNOWN_OPERAND);
return op.setError(regAt, REGISTER_NOT_ALLOWED);
}
switch (reg) {
case REG_IX:
case REG_IY:
op.mode = M_REGIX;
break;
case REG_B:
case REG_D:
case REG_E:
case REG_H:
case REG_L:
op.mode = M_REG8;
break;
default:
op.mode = AddrMode(int8_t(reg) + R_BASE);
break;
}
op.val16 = parseExpr16(p, op);
if (op.hasError())
return op.getError();
op.mode = M_IMM16;
scan = p;
return OK;
}
Expand Down
26 changes: 19 additions & 7 deletions src/dis_tlcs90.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,24 @@ void DisTlcs90::decodeOperand(
outRegName(out.letter('('), op.reg).letter(')');
break;
case M_IDX:
outRegName(out.letter('('), op.reg);
case M_IXPD:
if (mode == M_IDX)
out.letter('(');
outRegName(out, op.reg);
if (val8 >= 0)
out.letter('+');
outHex(out, val8, -8).letter(')');
outHex(out, val8, -8);
if (mode == M_IDX)
out.letter(')');
break;
case M_BASE:
outRegName(out.letter('('), REG_HL).letter('+');
outRegName(out, REG_A).letter(')');
case M_HLPA:
if (mode == M_BASE)
out.letter('(');
outRegName(out, REG_HL).letter('+');
outRegName(out, REG_A);
if (mode == M_BASE)
out.letter(')');
break;
case M_CC:
outCcName(out, op.cc);
Expand All @@ -140,7 +150,7 @@ void DisTlcs90::decodeOperand(
case R_AF:
case R_AFP:
case R_A:
outRegName(out, RegName(uint8_t(mode) - 16));
outRegName(out, RegName(uint8_t(mode) - R_BASE));
break;
default:
break;
Expand All @@ -152,7 +162,9 @@ Error DisTlcs90::decodeImpl(DisMemory &memory, Insn &_insn, StrBuffer &out) cons
const auto opc = insn.readByte();
insn.setOpCode(opc);
Operand prefixOp;
insn.setPrefixMode(M_NONE);
if (TABLE.isPrefix(cpuType(), opc, prefixOp.mode)) {
insn.setPrefixMode(prefixOp.mode);
if (insn.readOpCode(prefixOp))
return _insn.setError(insn);
}
Expand All @@ -163,7 +175,7 @@ Error DisTlcs90::decodeImpl(DisMemory &memory, Insn &_insn, StrBuffer &out) cons
if (dst != M_NONE) {
const auto *start = out.mark();
if (dst == M_DST) {
decodeOperand(insn, out, prefixOp.mode, prefixOp);
decodeOperand(insn, out, insn.pre(), prefixOp);
} else {
Operand op;
if (readOperand(insn, dst, op))
Expand All @@ -175,7 +187,7 @@ Error DisTlcs90::decodeImpl(DisMemory &memory, Insn &_insn, StrBuffer &out) cons
if (out.mark() != start) // skip CC_T because it's empty.
out.comma();
if (src == M_SRC) {
decodeOperand(insn, out, prefixOp.mode, prefixOp);
decodeOperand(insn, out, insn.pre(), prefixOp);
} else {
Operand op;
if (readOperand(insn, src, op))
Expand Down
4 changes: 3 additions & 1 deletion src/entry_tlcs90.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ enum AddrMode : uint8_t {
M_REG8 = 13, // Register 8-bit: B/C/D/E/H/L/A
M_REG16 = 14, // Register 16-bit: BC/DE/HL/IX/IY/SP
M_REGIX = 15, // Register index: IX/IY/SP
R_BASE = 16,
M_HLPA = 16, // HL+A
M_IXPD = 17, // ix+disp
R_BASE = 18,
R_BC = R_BASE + REG_BC,
R_DE = R_BASE + REG_DE,
R_HL = R_BASE + REG_HL,
Expand Down
9 changes: 5 additions & 4 deletions src/insn_tlcs90.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ struct EntryInsn : EntryInsnBase<Config, Entry> {
AddrMode dst() const { return flags().dst(); }
AddrMode src() const { return flags().src(); }
void setAddrMode(AddrMode dst, AddrMode src) { setFlags(Entry::Flags::create(dst, src)); }
AddrMode pre() const { return _prefixMode; }
void setPrefixMode(AddrMode mode) { _prefixMode = mode; }

private:
AddrMode _prefixMode;
};

struct Operand final : ErrorAt {
Expand All @@ -44,9 +49,6 @@ struct AsmInsn final : AsmInsnImpl<Config>, EntryInsn {

Operand dstOp, srcOp;

AddrMode pre() const { return _prefixMode; }
void setPrefixMode(AddrMode mode) { _prefixMode = mode; }

void setEmitInsn() { _emitInsn = true; }
void emitInsn(Config::opcode_t opc) {
if (_emitInsn) {
Expand All @@ -56,7 +58,6 @@ struct AsmInsn final : AsmInsnImpl<Config>, EntryInsn {
}

private:
AddrMode _prefixMode;
bool _emitInsn;
};

Expand Down
24 changes: 15 additions & 9 deletions src/table_tlcs90.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ static constexpr Entry TABLE_TLCS90[] PROGMEM = {
E2(0x14, TEXT_ADD, M_REGIX, M_IMM16),
E1(0x18, TEXT_DJNZ, M_REL8),
E2(0x19, TEXT_DJNZ, R_BC, M_REL8),
E1(0x1A, TEXT_JP, M_EXT),
E1(0x1A, TEXT_JP, M_IMM16),
E1(0x1B, TEXT_JRL, M_REL16),
E1(0x1C, TEXT_CALL, M_EXT),
E1(0x1C, TEXT_CALL, M_IMM16),
E1(0x1D, TEXT_CALR, M_REL16),
E0(0x1E, TEXT_RET),
E0(0x1F, TEXT_RETI),
Expand Down Expand Up @@ -499,8 +499,10 @@ struct EntryPage : entry::PrefixTableBase<Entry> {
const auto reg = code & 7;
switch (prefixMode()) {
case M_IND:
case M_REG16:
return (code & ~7) == pre && reg != 3 && reg != 7;
case M_IDX:
case M_IXPD:
return (code & ~3) == pre && reg != 3;
case M_REG8:
return (code & ~7) == pre && reg != 7;
Expand Down Expand Up @@ -532,13 +534,13 @@ static constexpr EntryPage TLCS90_PAGES[] PROGMEM = {
{0xE8, M_IND, ARRAY_RANGE(TABLE_DST), ARRAY_RANGE(INDEX_DST)}, // dst (rr)
{0xF7, M_BASE, ARRAY_RANGE(TABLE_DST), ARRAY_RANGE(INDEX_DST)}, // dst (HL+A)
{0xF4, M_IDX, ARRAY_RANGE(TABLE_DST), ARRAY_RANGE(INDEX_DST)}, // dst (ix+d)
{0xEB, M_EXT, ARRAY_RANGE(TABLE_JMP), ARRAY_RANGE(INDEX_JMP)}, // JP/CALL
{0xE8, M_IND, ARRAY_RANGE(TABLE_JMP), ARRAY_RANGE(INDEX_JMP)}, // JP/CALL
{0xF7, M_BASE, ARRAY_RANGE(TABLE_JMP), ARRAY_RANGE(INDEX_JMP)}, // JP/CALL
{0xF4, M_IDX, ARRAY_RANGE(TABLE_JMP), ARRAY_RANGE(INDEX_JMP)}, // JP/CALL
{0xEB, M_IMM16, ARRAY_RANGE(TABLE_JMP), ARRAY_RANGE(INDEX_JMP)}, // JP/CALL nnnn
{0xE8, M_REG16, ARRAY_RANGE(TABLE_JMP), ARRAY_RANGE(INDEX_JMP)}, // JP/CALL rr
{0xF7, M_HLPA, ARRAY_RANGE(TABLE_JMP), ARRAY_RANGE(INDEX_JMP)}, // JP/CALL HL+A
{0xF4, M_IXPD, ARRAY_RANGE(TABLE_JMP), ARRAY_RANGE(INDEX_JMP)}, // JP/CALL ix+d
{0xF8, M_REG8, ARRAY_RANGE(TABLE_REG), ARRAY_RANGE(INDEX_REG)}, // r/rr
{0xF7, M_BASE, ARRAY_RANGE(TABLE_LDA), ARRAY_RANGE(INDEX_LDA)}, // LDA
{0xF4, M_IDX, ARRAY_RANGE(TABLE_LDA), ARRAY_RANGE(INDEX_LDA)}, // LDA
{0xF7, M_HLPA, ARRAY_RANGE(TABLE_LDA), ARRAY_RANGE(INDEX_LDA)}, // LDA HL+A
{0xF4, M_IXPD, ARRAY_RANGE(TABLE_LDA), ARRAY_RANGE(INDEX_LDA)}, // LDA ix+d
{0xFE, M_NONE, ARRAY_RANGE(TABLE_COND), ARRAY_RANGE(INDEX_COND)},
{0xFE, M_NONE, ARRAY_RANGE(TABLE_BLOCK), ARRAY_RANGE(INDEX_BLOCK)},
};
Expand Down Expand Up @@ -628,7 +630,11 @@ Error TableTlcs90::searchName(CpuType cpuType, AsmInsn &insn) const {
}

static bool prefixMatcher(DisInsn &insn, const EntryPage *page) {
return page->prefixMatcher(insn.prefix());
if (page->prefixMatcher(insn.prefix())) {
insn.setPrefixMode(page->prefixMode());
return true;
}
return false;
}

static bool invalidPrefixCode(Config::opcode_t prefix, AddrMode mode) {
Expand Down
Loading

0 comments on commit 405f881

Please sign in to comment.