Skip to content

Commit

Permalink
[TMS32010] Add TMS3202x variants
Browse files Browse the repository at this point in the history
  • Loading branch information
tgtakaoka committed Jan 31, 2025
1 parent d0d91b6 commit d316581
Show file tree
Hide file tree
Showing 36 changed files with 5,413 additions and 183 deletions.
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,10 @@ It can generate Intel HEX or Motorola S-Record output.
MC68HC08 MC6809 HD6309 MOS6502 R65C02 G65SC02 W65C02S W65C816S i8039
i8048 i80C39 i80C48 MSM80C39 MSM80C48 i8051 i8080 i8085 V30EMU Z80 Z8
Z86C Z88 TLCS90 INS8060 INS8070 CDP1802 CDP1804 CDP1804A SCN2650
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 i8086 i80186 V30 i8096
MC68000 MC68010 TMS9900 TMS9980 TMS9995 TMS99105 TMS99110 Z8001 Z8002
NS32032 MN1610 MN1613 MN1613A J11 T11
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 TMS32020 TMS320C25
TMS320C26 i8086 i80186 V30 i8096 MC68000 MC68010 TMS9900 TMS9980
TMS9995 TMS99105 TMS99110 Z8001 Z8002 NS32032 MN1610 MN1613 MN1613A
J11 T11
-o <output> : output file
-l <list> : list file
-S[<bytes>] : output Motorola S-Record format
Expand Down Expand Up @@ -116,9 +117,10 @@ It can read Intel HEX or Motorola S-Record input.
MC68HC08 MC6809 HD6309 MOS6502 R65C02 G65SC02 W65C02S W65C816S i8039
i8048 i80C39 i80C48 MSM80C39 MSM80C48 i8051 i8080 i8085 V30EMU Z80 Z8
Z86C Z88 TLCS90 INS8060 INS8070 CDP1802 CDP1804 CDP1804A SCN2650
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 i8086 i80186 V30 i8096
MC68000 MC68010 TMS9900 TMS9980 TMS9995 TMS99105 TMS99110 Z8001 Z8002
NS32032 MN1610 MN1613 MN1613A J11 T11
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 TMS32020 TMS320C25
TMS320C26 i8086 i80186 V30 i8096 MC68000 MC68010 TMS9900 TMS9980
TMS9995 TMS99105 TMS99110 Z8001 Z8002 NS32032 MN1610 MN1613 MN1613A
J11 T11
-o <output> : output file
-l <list> : list file
<input> : file can be Motorola S-Record or Intel HEX format
Expand Down Expand Up @@ -146,6 +148,8 @@ It can read Intel HEX or Motorola S-Record input.
--short-direct : use |addr| for short direct notation (bool: Z8001)
--string-insn : string instruction as repeat operand (bool: 8086)
--use-absolute : zero register indexing as absolute addressing (bool: 8096)
--use-aux-name : use aux register name ARn (bool: 32010)
--use-port-name : use port name PAn (bool: 32010)
--use-register : use register name Rn (bool: 1802)
--use-sharp : use # (default =) for immediate (bool: 8070)
--work-register : prefer work register name than alias address (bool: Z8)
Expand Down
16 changes: 10 additions & 6 deletions README_.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,10 @@ usage: asm [-o <output>] [-l <list>] <input>
MC68HC08 MC6809 HD6309 MOS6502 R65C02 G65SC02 W65C02S W65C816S i8039
i8048 i80C39 i80C48 MSM80C39 MSM80C48 i8051 i8080 i8085 V30EMU Z80 Z8
Z86C Z88 TLCS90 INS8060 INS8070 CDP1802 CDP1804 CDP1804A SCN2650
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 i8086 i80186 V30 i8096
MC68000 MC68010 TMS9900 TMS9980 TMS9995 TMS99105 TMS99110 Z8001 Z8002
NS32032 MN1610 MN1613 MN1613A J11 T11
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 TMS32020 TMS320C25
TMS320C26 i8086 i80186 V30 i8096 MC68000 MC68010 TMS9900 TMS9980
TMS9995 TMS99105 TMS99110 Z8001 Z8002 NS32032 MN1610 MN1613 MN1613A
J11 T11
-o <output> : output file
-l <list> : list file
-S[<bytes>] : output Motorola S-Record format
Expand Down Expand Up @@ -122,9 +123,10 @@ usage: dis -C <CPU> [-o <output>] [-l <list>] <input>
MC68HC08 MC6809 HD6309 MOS6502 R65C02 G65SC02 W65C02S W65C816S i8039
i8048 i80C39 i80C48 MSM80C39 MSM80C48 i8051 i8080 i8085 V30EMU Z80 Z8
Z86C Z88 TLCS90 INS8060 INS8070 CDP1802 CDP1804 CDP1804A SCN2650
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 i8086 i80186 V30 i8096
MC68000 MC68010 TMS9900 TMS9980 TMS9995 TMS99105 TMS99110 Z8001 Z8002
NS32032 MN1610 MN1613 MN1613A J11 T11
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 TMS32020 TMS320C25
TMS320C26 i8086 i80186 V30 i8096 MC68000 MC68010 TMS9900 TMS9980
TMS9995 TMS99105 TMS99110 Z8001 Z8002 NS32032 MN1610 MN1613 MN1613A
J11 T11
-o <output> : output file
-l <list> : list file
<input> : file can be Motorola S-Record or Intel HEX format
Expand Down Expand Up @@ -152,6 +154,8 @@ usage: dis -C <CPU> [-o <output>] [-l <list>] <input>
--short-direct : use |addr| for short direct notation (bool: Z8001)
--string-insn : string instruction as repeat operand (bool: 8086)
--use-absolute : zero register indexing as absolute addressing (bool: 8096)
--use-aux-name : use aux register name ARn (bool: 32010)
--use-port-name : use port name PAn (bool: 32010)
--use-register : use register name Rn (bool: 1802)
--use-sharp : use # (default =) for immediate (bool: 8070)
--work-register : prefer work register name than alias address (bool: Z8)
Expand Down
4 changes: 3 additions & 1 deletion src/Makefile.arch
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ TGT_pdp11 = j11 t11
TGT_pdp8 = im6100 hd6120
TGT_scn2650 = scn2650
TGT_tlcs90 = tlcs90
TGT_tms32010 = tms32010
TGT_tms32010 = tms32010 tms320c25 tms320c26
TGT_tms7000 = tms7000
TGT_tms9900 = tms9900 tms9980 tms9995 tms99105 tms99110
TGT_z8000 = z8001 z8002 z8k1 z8k2
Expand Down Expand Up @@ -124,6 +124,8 @@ CPU_scn2650 = 2650
CPU_t11 = T11
CPU_tlcs90 = TLCS90
CPU_tms32010 = 32010
CPU_tms320c25 = 320C25
CPU_tms320c26 = 320C26
CPU_tms7000 = TMS7000
CPU_tms9900 = TMS9900
CPU_tms99105 = TMS99105
Expand Down
137 changes: 93 additions & 44 deletions src/asm_tms32010.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,34 +57,67 @@ AsmTms32010::AsmTms32010(const ValueParser::Plugins &plugins)
reset();
}

void AsmTms32010::encodeIndirect(AsmInsn &insn, const Operand &op) const {
static constexpr uint8_t MAR[] PROGMEM = {
0x80, // M_ARP: *
0xA0, // M_INC: *+
0x90, // M_DEC: *-
0xE0, // M_INC0: *0+
0xD0, // M_DEC0: *0-
0xF0, // M_IBR0: *BR0+
0xC0, // M_DBR0: *BR0-
};
if (op.mode >= M_ARP)
insn.embed(pgm_read_byte(&MAR[op.mode - M_ARP]));
}

void AsmTms32010::encodeDirect(AsmInsn &insn, const Operand &op) const {
const auto dma = op.val.getUnsigned();
if (op.val.isNegative() || !validDmAddr(insn.opCode(), dma))
insn.setErrorIf(op, OVERFLOW_RANGE);
insn.embed(dma & 0x7F);
}

void AsmTms32010::encodeNextAR(AsmInsn &insn, const Operand &op) const {
if ((insn.opCode() & 0x80) == 0)
return;
if (op.mode == M_NONE) {
if (is3201x())
insn.embed(8);
return;
}
auto val = op.val.getUnsigned();
if (!isAR(decodeAR(val))) {
val &= maxAR();
insn.setErrorIf(op, UNKNOWN_REGISTER);
}
if (is3202x())
insn.embed(8);
insn.embed(val);
}

void AsmTms32010::encodeOperand(AsmInsn &insn, const Operand &op, AddrMode mode) const {
insn.setErrorIf(op);
auto val = op.val.getUnsigned();
auto max = UINT16_MAX;
switch (mode) {
case M_MAM:
switch (op.mode) {
case M_ARP:
insn.embed(0x88);
break;
case M_INC:
insn.embed(0xA8);
break;
case M_DEC:
insn.embed(0x98);
break;
default:
if (!validDmAddr(insn.opCode(), val))
insn.setErrorIf(op, OVERFLOW_RANGE);
insn.embed(val & 0x7F);
break;
if (op.mode == M_CNST) {
encodeDirect(insn, op);
} else {
encodeIndirect(insn, op);
}
break;
case M_IND:
case M_MAR:
encodeIndirect(insn, op);
break;
case M_LS0:
if (val)
insn.setErrorIf(op, ILLEGAL_CONSTANT);
break;
case M_LS3:
if (!(val == 0 || val == 1 || val == 4))
if (!is320C2x() && !(val == 0 || val == 1 || val == 4))
insn.setErrorIf(op, ILLEGAL_CONSTANT);
// Fall-through
case M_PA:
Expand All @@ -98,55 +131,62 @@ void AsmTms32010::encodeOperand(AsmInsn &insn, const Operand &op, AddrMode mode)
val &= 15;
insn.setErrorIf(op, OVERFLOW_RANGE);
}
embed_hi8:
insn.embed(val << 8);
break;
case M_NARP:
if (op.mode != M_NONE) {
if (!isAR(decodeAR(val))) {
val &= maxAR();
insn.setErrorIf(op, UNKNOWN_REGISTER);
}
insn.setOpCode(insn.opCode() & ~8);
insn.embed(val);
}
encodeNextAR(insn, op);
break;
case M_AR:
if (!isAR(decodeAR(val))) {
val &= maxAR();
insn.setErrorIf(op, UNKNOWN_REGISTER);
}
insn.embed(val << 8);
break;
case M_ARK:
if (!isAR(decodeAR(val))) {
val &= maxAR();
insn.setErrorIf(op, UNKNOWN_REGISTER);
}
insn.embed(val);
break;
if (mode == M_AR)
goto embed_hi8;
goto embed_const;
case M_IM1:
if (op.val.overflow(1)) {
val &= 1;
max = 1;
check_const:
if (op.val.overflow(max)) {
val &= max;
insn.setErrorIf(op, OVERFLOW_RANGE);
}
embed_const:
insn.embed(val);
break;
case M_IM2:
max = 3;
goto check_const;
case M_BIT:
max = 15;
goto embed_hi8;
case M_IM8:
if (op.val.overflow(UINT8_MAX)) {
val &= UINT8_MAX;
insn.setErrorIf(op, OVERFLOW_RANGE);
}
insn.embed(val);
break;
max = UINT8_MAX;
goto check_const;
case M_IM9:
max = 0x1FF;
goto check_const;
case M_IM13:
if (op.val.overflow(0x0FFF, -0x1000))
insn.setErrorIf(op, OVERFLOW_RANGE);
insn.embed(val & 0x1FFF);
break;
case M_PM12:
if (op.val.overflow(0x0FFF))
if (op.val.overflow(0x0FFF)) {
val &= 0x0FFF;
insn.setErrorIf(op, OVERFLOW_RANGE);
}
// Fall-through
case M_PM16:
if (op.val.overflow(UINT16_MAX))
insn.setErrorIf(op, OVERFLOW_RANGE);
// Fall-through
case M_IM16:
if (op.val.overflowUint16())
insn.setErrorIf(op, OVERFLOW_RANGE);
insn.emitOperand16(val & 0x0FFF);
insn.emitOperand16(val);
break;
default:
break;
Expand All @@ -160,11 +200,20 @@ Error AsmTms32010::parseOperand(StrScanner &scan, Operand &op) const {
return OK;

if (p.expect('*')) {
auto s = p;
const auto br = p.iexpect('B') && p.iexpect('R');
if (!br)
p = s;
const auto ar0 = p.expect('0');
if (br && !ar0)
return op.setErrorIf(UNKNOWN_OPERAND);
if (p.expect('+')) {
op.mode = M_INC;
op.mode = ar0 ? (br ? M_IBR0 : M_INC0) : M_INC;
} else if (p.expect('-')) {
op.mode = M_DEC;
op.mode = ar0 ? (br ? M_DBR0 : M_DEC0) : M_DEC;
} else {
if (br || ar0)
return op.setErrorIf(UNKNOWN_OPERAND);
op.mode = M_ARP;
}
scan = p;
Expand Down
3 changes: 3 additions & 0 deletions src/asm_tms32010.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ struct AsmTms32010 final : Assembler, Config {
private:
Error parseOperand(StrScanner &scan, Operand &op) const;

void encodeIndirect(AsmInsn &insn, const Operand &op) const;
void encodeDirect(AsmInsn &insn, const Operand &op) const;
void encodeNextAR(AsmInsn &insn, const Operand &op) const;
void encodeOperand(AsmInsn &insn, const Operand &op, AddrMode mode) const;

Error encodeImpl(StrScanner &scan, Insn &insn) const override;
Expand Down
39 changes: 32 additions & 7 deletions src/config_tms32010.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,33 +26,55 @@ namespace tms32010 {
enum CpuType : uint8_t {
TMS32010,
TMS32015,
TMS32020,
TMS320C25,
TMS320C26,
};

struct Config
: ConfigImpl<CpuType, ADDRESS_12BIT, ADDRESS_WORD, OPCODE_16BIT, ENDIAN_LITTLE, 4, 4> {
Config(const InsnTable<CpuType> &table) : ConfigImpl(table, TMS32010) {}

AddressWidth addressWidth() const override { return is3201x() ? ADDRESS_12BIT : ADDRESS_16BIT; }

protected:
uint16_t dataMemoryMax() const { return cpuType() == TMS32010 ? UINT16_C(0x8F) : PAGE1_MAX; }
bool is3201x() const { return cpuType() == TMS32010 || cpuType() == TMS32015; }
bool is3202x() const { return !is3201x(); }
bool is320C2x() const { return cpuType() == TMS320C25 || cpuType() == TMS320C26; }

uint_fast8_t maxAR() const { return 1; }
uint_fast8_t maxPA() const { return 7; }
uint16_t dataMemoryMax() const {
if (is3201x()) {
return cpuType() == TMS32010 ? UINT16_C(0x8F) : PAGE1_MAX;
} else {
return cpuType() == TMS320C26 ? 0x7FF : 0x3FF;
}
}

uint_fast8_t maxAR() const { return is3201x() ? 1 : 7; }
uint_fast8_t maxPA() const { return is3201x() ? 7 : 15; }
bool isAR(RegName name) const { return name >= REG_AR0 && name <= REG_AR0 + maxAR(); }
bool isPA(RegName name) const { return name >= REG_PA0 && name <= REG_PA0 + maxPA(); }
RegName decodeAR(uint32_t r) const { return r <= maxAR() ? RegName(r + REG_AR0) : REG_UNDEF; }
RegName decodePA(uint32_t r) const { return r <= maxPA() ? RegName(r + REG_PA0) : REG_UNDEF; }

bool isSST(opcode_t opc) const {
opc >>= 8;
return opc == 0x7C; // SST
return is3201x() ? opc == 0x7C // SST
: (opc & 0xFE) == 0x78; // SST and SST1
}

bool validDmAddr(opcode_t opc, uint32_t dma) const {
uint16_t min = UINT16_C(0);
uint16_t max = dataMemoryMax();
if (isSST(opc)) {
// TMS3201x: SST destination must be in page 1.
min = PAGE1_MIN;
if (is3201x()) {
// TMS3201x: SST destination must be in page 1.
min = PAGE1_MIN;
} else {
// TMS3202x: SST/SST1 destination must be in page 0.
min = PAGE0_MIN;
max = PAGE0_MAX;
}
}
return dma >= min && dma <= max;
}
Expand All @@ -61,11 +83,14 @@ struct Config
auto dma = opc & 0x7F;
if (isSST(opc)) {
// TMS3201x: SST destination must be in page 1.
return PAGE1_MIN + dma;
// TMS3202x: SST/SST1 destination must be in page 0.
return (is3201x() ? PAGE1_MIN : PAGE0_MIN) + dma;
}
return dma;
}

static constexpr auto PAGE0_MIN = UINT16_C(0x0000);
static constexpr auto PAGE0_MAX = UINT16_C(0x007F);
static constexpr auto PAGE1_MIN = UINT16_C(0x0080);
static constexpr auto PAGE1_MAX = UINT16_C(0x00FF);
};
Expand Down
Loading

0 comments on commit d316581

Please sign in to comment.