Skip to content

Commit f344084

Browse files
committed
[TMS32010] Add TMS3202x variants
1 parent d0d91b6 commit f344084

36 files changed

+5413
-183
lines changed

README.md

+10-6
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,10 @@ It can generate Intel HEX or Motorola S-Record output.
7979
MC68HC08 MC6809 HD6309 MOS6502 R65C02 G65SC02 W65C02S W65C816S i8039
8080
i8048 i80C39 i80C48 MSM80C39 MSM80C48 i8051 i8080 i8085 V30EMU Z80 Z8
8181
Z86C Z88 TLCS90 INS8060 INS8070 CDP1802 CDP1804 CDP1804A SCN2650
82-
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 i8086 i80186 V30 i8096
83-
MC68000 MC68010 TMS9900 TMS9980 TMS9995 TMS99105 TMS99110 Z8001 Z8002
84-
NS32032 MN1610 MN1613 MN1613A J11 T11
82+
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 TMS32020 TMS320C25
83+
TMS320C26 i8086 i80186 V30 i8096 MC68000 MC68010 TMS9900 TMS9980
84+
TMS9995 TMS99105 TMS99110 Z8001 Z8002 NS32032 MN1610 MN1613 MN1613A
85+
J11 T11
8586
-o <output> : output file
8687
-l <list> : list file
8788
-S[<bytes>] : output Motorola S-Record format
@@ -116,9 +117,10 @@ It can read Intel HEX or Motorola S-Record input.
116117
MC68HC08 MC6809 HD6309 MOS6502 R65C02 G65SC02 W65C02S W65C816S i8039
117118
i8048 i80C39 i80C48 MSM80C39 MSM80C48 i8051 i8080 i8085 V30EMU Z80 Z8
118119
Z86C Z88 TLCS90 INS8060 INS8070 CDP1802 CDP1804 CDP1804A SCN2650
119-
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 i8086 i80186 V30 i8096
120-
MC68000 MC68010 TMS9900 TMS9980 TMS9995 TMS99105 TMS99110 Z8001 Z8002
121-
NS32032 MN1610 MN1613 MN1613A J11 T11
120+
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 TMS32020 TMS320C25
121+
TMS320C26 i8086 i80186 V30 i8096 MC68000 MC68010 TMS9900 TMS9980
122+
TMS9995 TMS99105 TMS99110 Z8001 Z8002 NS32032 MN1610 MN1613 MN1613A
123+
J11 T11
122124
-o <output> : output file
123125
-l <list> : list file
124126
<input> : file can be Motorola S-Record or Intel HEX format
@@ -146,6 +148,8 @@ It can read Intel HEX or Motorola S-Record input.
146148
--short-direct : use |addr| for short direct notation (bool: Z8001)
147149
--string-insn : string instruction as repeat operand (bool: 8086)
148150
--use-absolute : zero register indexing as absolute addressing (bool: 8096)
151+
--use-aux-name : use aux register name ARn (bool: 32010)
152+
--use-port-name : use port name PAn (bool: 32010)
149153
--use-register : use register name Rn (bool: 1802)
150154
--use-sharp : use # (default =) for immediate (bool: 8070)
151155
--work-register : prefer work register name than alias address (bool: Z8)

README_.adoc

+10-6
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,10 @@ usage: asm [-o <output>] [-l <list>] <input>
8383
MC68HC08 MC6809 HD6309 MOS6502 R65C02 G65SC02 W65C02S W65C816S i8039
8484
i8048 i80C39 i80C48 MSM80C39 MSM80C48 i8051 i8080 i8085 V30EMU Z80 Z8
8585
Z86C Z88 TLCS90 INS8060 INS8070 CDP1802 CDP1804 CDP1804A SCN2650
86-
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 i8086 i80186 V30 i8096
87-
MC68000 MC68010 TMS9900 TMS9980 TMS9995 TMS99105 TMS99110 Z8001 Z8002
88-
NS32032 MN1610 MN1613 MN1613A J11 T11
86+
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 TMS32020 TMS320C25
87+
TMS320C26 i8086 i80186 V30 i8096 MC68000 MC68010 TMS9900 TMS9980
88+
TMS9995 TMS99105 TMS99110 Z8001 Z8002 NS32032 MN1610 MN1613 MN1613A
89+
J11 T11
8990
-o <output> : output file
9091
-l <list> : list file
9192
-S[<bytes>] : output Motorola S-Record format
@@ -122,9 +123,10 @@ usage: dis -C <CPU> [-o <output>] [-l <list>] <input>
122123
MC68HC08 MC6809 HD6309 MOS6502 R65C02 G65SC02 W65C02S W65C816S i8039
123124
i8048 i80C39 i80C48 MSM80C39 MSM80C48 i8051 i8080 i8085 V30EMU Z80 Z8
124125
Z86C Z88 TLCS90 INS8060 INS8070 CDP1802 CDP1804 CDP1804A SCN2650
125-
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 i8086 i80186 V30 i8096
126-
MC68000 MC68010 TMS9900 TMS9980 TMS9995 TMS99105 TMS99110 Z8001 Z8002
127-
NS32032 MN1610 MN1613 MN1613A J11 T11
126+
F3850 IM6100 HD6120 TMS7000 TMS32010 TMS32015 TMS32020 TMS320C25
127+
TMS320C26 i8086 i80186 V30 i8096 MC68000 MC68010 TMS9900 TMS9980
128+
TMS9995 TMS99105 TMS99110 Z8001 Z8002 NS32032 MN1610 MN1613 MN1613A
129+
J11 T11
128130
-o <output> : output file
129131
-l <list> : list file
130132
<input> : file can be Motorola S-Record or Intel HEX format
@@ -152,6 +154,8 @@ usage: dis -C <CPU> [-o <output>] [-l <list>] <input>
152154
--short-direct : use |addr| for short direct notation (bool: Z8001)
153155
--string-insn : string instruction as repeat operand (bool: 8086)
154156
--use-absolute : zero register indexing as absolute addressing (bool: 8096)
157+
--use-aux-name : use aux register name ARn (bool: 32010)
158+
--use-port-name : use port name PAn (bool: 32010)
155159
--use-register : use register name Rn (bool: 1802)
156160
--use-sharp : use # (default =) for immediate (bool: 8070)
157161
--work-register : prefer work register name than alias address (bool: Z8)

src/Makefile.arch

+3-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ TGT_pdp11 = j11 t11
6969
TGT_pdp8 = im6100 hd6120
7070
TGT_scn2650 = scn2650
7171
TGT_tlcs90 = tlcs90
72-
TGT_tms32010 = tms32010
72+
TGT_tms32010 = tms32010 tms320c25 tms320c26
7373
TGT_tms7000 = tms7000
7474
TGT_tms9900 = tms9900 tms9980 tms9995 tms99105 tms99110
7575
TGT_z8000 = z8001 z8002 z8k1 z8k2
@@ -124,6 +124,8 @@ CPU_scn2650 = 2650
124124
CPU_t11 = T11
125125
CPU_tlcs90 = TLCS90
126126
CPU_tms32010 = 32010
127+
CPU_tms320c25 = 320C25
128+
CPU_tms320c26 = 320C26
127129
CPU_tms7000 = TMS7000
128130
CPU_tms9900 = TMS9900
129131
CPU_tms99105 = TMS99105

src/asm_tms32010.cpp

+93-44
Original file line numberDiff line numberDiff line change
@@ -57,34 +57,67 @@ AsmTms32010::AsmTms32010(const ValueParser::Plugins &plugins)
5757
reset();
5858
}
5959

60+
void AsmTms32010::encodeIndirect(AsmInsn &insn, const Operand &op) const {
61+
static constexpr uint8_t MAR[] PROGMEM = {
62+
0x80, // M_ARP: *
63+
0xA0, // M_INC: *+
64+
0x90, // M_DEC: *-
65+
0xE0, // M_INC0: *0+
66+
0xD0, // M_DEC0: *0-
67+
0xF0, // M_IBR0: *BR0+
68+
0xC0, // M_DBR0: *BR0-
69+
};
70+
if (op.mode >= M_ARP)
71+
insn.embed(pgm_read_byte(&MAR[op.mode - M_ARP]));
72+
}
73+
74+
void AsmTms32010::encodeDirect(AsmInsn &insn, const Operand &op) const {
75+
const auto dma = op.val.getUnsigned();
76+
if (op.val.isNegative() || !validDmAddr(insn.opCode(), dma))
77+
insn.setErrorIf(op, OVERFLOW_RANGE);
78+
insn.embed(dma & 0x7F);
79+
}
80+
81+
void AsmTms32010::encodeNextAR(AsmInsn &insn, const Operand &op) const {
82+
if ((insn.opCode() & 0x80) == 0)
83+
return;
84+
if (op.mode == M_NONE) {
85+
if (is3201x())
86+
insn.embed(8);
87+
return;
88+
}
89+
auto val = op.val.getUnsigned();
90+
if (!isAR(decodeAR(val))) {
91+
val &= maxAR();
92+
insn.setErrorIf(op, UNKNOWN_REGISTER);
93+
}
94+
if (is3202x())
95+
insn.embed(8);
96+
insn.embed(val);
97+
}
98+
6099
void AsmTms32010::encodeOperand(AsmInsn &insn, const Operand &op, AddrMode mode) const {
61100
insn.setErrorIf(op);
62101
auto val = op.val.getUnsigned();
102+
auto max = UINT16_MAX;
63103
switch (mode) {
64104
case M_MAM:
65-
switch (op.mode) {
66-
case M_ARP:
67-
insn.embed(0x88);
68-
break;
69-
case M_INC:
70-
insn.embed(0xA8);
71-
break;
72-
case M_DEC:
73-
insn.embed(0x98);
74-
break;
75-
default:
76-
if (!validDmAddr(insn.opCode(), val))
77-
insn.setErrorIf(op, OVERFLOW_RANGE);
78-
insn.embed(val & 0x7F);
79-
break;
105+
if (op.mode == M_CNST) {
106+
encodeDirect(insn, op);
107+
} else {
108+
encodeIndirect(insn, op);
80109
}
81110
break;
111+
case M_IND:
112+
case M_MAR:
113+
encodeIndirect(insn, op);
114+
break;
82115
case M_LS0:
83116
if (val)
84117
insn.setErrorIf(op, ILLEGAL_CONSTANT);
85118
break;
86119
case M_LS3:
87-
if (!(val == 0 || val == 1 || val == 4))
120+
if (!is320C2x() && !(val == 0 || val == 1 || val == 4))
88121
insn.setErrorIf(op, ILLEGAL_CONSTANT);
89122
// Fall-through
90123
case M_PA:
@@ -98,55 +131,62 @@ void AsmTms32010::encodeOperand(AsmInsn &insn, const Operand &op, AddrMode mode)
98131
val &= 15;
99132
insn.setErrorIf(op, OVERFLOW_RANGE);
100133
}
134+
embed_hi8:
101135
insn.embed(val << 8);
102136
break;
103137
case M_NARP:
104-
if (op.mode != M_NONE) {
105-
if (!isAR(decodeAR(val))) {
106-
val &= maxAR();
107-
insn.setErrorIf(op, UNKNOWN_REGISTER);
108-
}
109-
insn.setOpCode(insn.opCode() & ~8);
110-
insn.embed(val);
111-
}
138+
encodeNextAR(insn, op);
112139
break;
113140
case M_AR:
114-
if (!isAR(decodeAR(val))) {
115-
val &= maxAR();
116-
insn.setErrorIf(op, UNKNOWN_REGISTER);
117-
}
118-
insn.embed(val << 8);
119-
break;
120141
case M_ARK:
121142
if (!isAR(decodeAR(val))) {
122143
val &= maxAR();
123144
insn.setErrorIf(op, UNKNOWN_REGISTER);
124145
}
125-
insn.embed(val);
126-
break;
146+
if (mode == M_AR)
147+
goto embed_hi8;
148+
goto embed_const;
127149
case M_IM1:
128-
if (op.val.overflow(1)) {
129-
val &= 1;
150+
max = 1;
151+
check_const:
152+
if (op.val.overflow(max)) {
153+
val &= max;
130154
insn.setErrorIf(op, OVERFLOW_RANGE);
131155
}
156+
embed_const:
132157
insn.embed(val);
133158
break;
159+
case M_IM2:
160+
max = 3;
161+
goto check_const;
162+
case M_BIT:
163+
max = 15;
164+
goto embed_hi8;
134165
case M_IM8:
135-
if (op.val.overflow(UINT8_MAX)) {
136-
val &= UINT8_MAX;
137-
insn.setErrorIf(op, OVERFLOW_RANGE);
138-
}
139-
insn.embed(val);
140-
break;
166+
max = UINT8_MAX;
167+
goto check_const;
168+
case M_IM9:
169+
max = 0x1FF;
170+
goto check_const;
141171
case M_IM13:
142172
if (op.val.overflow(0x0FFF, -0x1000))
143173
insn.setErrorIf(op, OVERFLOW_RANGE);
144174
insn.embed(val & 0x1FFF);
145175
break;
146176
case M_PM12:
147-
if (op.val.overflow(0x0FFF))
177+
if (op.val.overflow(0x0FFF)) {
178+
val &= 0x0FFF;
179+
insn.setErrorIf(op, OVERFLOW_RANGE);
180+
}
181+
// Fall-through
182+
case M_PM16:
183+
if (op.val.overflow(UINT16_MAX))
184+
insn.setErrorIf(op, OVERFLOW_RANGE);
185+
// Fall-through
186+
case M_IM16:
187+
if (op.val.overflowUint16())
148188
insn.setErrorIf(op, OVERFLOW_RANGE);
149-
insn.emitOperand16(val & 0x0FFF);
189+
insn.emitOperand16(val);
150190
break;
151191
default:
152192
break;
@@ -160,11 +200,20 @@ Error AsmTms32010::parseOperand(StrScanner &scan, Operand &op) const {
160200
return OK;
161201

162202
if (p.expect('*')) {
203+
auto s = p;
204+
const auto br = p.iexpect('B') && p.iexpect('R');
205+
if (!br)
206+
p = s;
207+
const auto ar0 = p.expect('0');
208+
if (br && !ar0)
209+
return op.setErrorIf(UNKNOWN_OPERAND);
163210
if (p.expect('+')) {
164-
op.mode = M_INC;
211+
op.mode = ar0 ? (br ? M_IBR0 : M_INC0) : M_INC;
165212
} else if (p.expect('-')) {
166-
op.mode = M_DEC;
213+
op.mode = ar0 ? (br ? M_DBR0 : M_DEC0) : M_DEC;
167214
} else {
215+
if (br || ar0)
216+
return op.setErrorIf(UNKNOWN_OPERAND);
168217
op.mode = M_ARP;
169218
}
170219
scan = p;

src/asm_tms32010.h

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ struct AsmTms32010 final : Assembler, Config {
3030
private:
3131
Error parseOperand(StrScanner &scan, Operand &op) const;
3232

33+
void encodeIndirect(AsmInsn &insn, const Operand &op) const;
34+
void encodeDirect(AsmInsn &insn, const Operand &op) const;
35+
void encodeNextAR(AsmInsn &insn, const Operand &op) const;
3336
void encodeOperand(AsmInsn &insn, const Operand &op, AddrMode mode) const;
3437

3538
Error encodeImpl(StrScanner &scan, Insn &insn) const override;

src/config_tms32010.h

+32-7
Original file line numberDiff line numberDiff line change
@@ -26,33 +26,55 @@ namespace tms32010 {
2626
enum CpuType : uint8_t {
2727
TMS32010,
2828
TMS32015,
29+
TMS32020,
30+
TMS320C25,
31+
TMS320C26,
2932
};
3033

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

38+
AddressWidth addressWidth() const override { return is3201x() ? ADDRESS_12BIT : ADDRESS_16BIT; }
39+
3540
protected:
36-
uint16_t dataMemoryMax() const { return cpuType() == TMS32010 ? UINT16_C(0x8F) : PAGE1_MAX; }
41+
bool is3201x() const { return cpuType() == TMS32010 || cpuType() == TMS32015; }
42+
bool is3202x() const { return !is3201x(); }
43+
bool is320C2x() const { return cpuType() == TMS320C25 || cpuType() == TMS320C26; }
3744

38-
uint_fast8_t maxAR() const { return 1; }
39-
uint_fast8_t maxPA() const { return 7; }
45+
uint16_t dataMemoryMax() const {
46+
if (is3201x()) {
47+
return cpuType() == TMS32010 ? UINT16_C(0x8F) : PAGE1_MAX;
48+
} else {
49+
return cpuType() == TMS320C26 ? 0x7FF : 0x3FF;
50+
}
51+
}
52+
53+
uint_fast8_t maxAR() const { return is3201x() ? 1 : 7; }
54+
uint_fast8_t maxPA() const { return is3201x() ? 7 : 15; }
4055
bool isAR(RegName name) const { return name >= REG_AR0 && name <= REG_AR0 + maxAR(); }
4156
bool isPA(RegName name) const { return name >= REG_PA0 && name <= REG_PA0 + maxPA(); }
4257
RegName decodeAR(uint32_t r) const { return r <= maxAR() ? RegName(r + REG_AR0) : REG_UNDEF; }
4358
RegName decodePA(uint32_t r) const { return r <= maxPA() ? RegName(r + REG_PA0) : REG_UNDEF; }
4459

4560
bool isSST(opcode_t opc) const {
4661
opc >>= 8;
47-
return opc == 0x7C; // SST
62+
return is3201x() ? opc == 0x7C // SST
63+
: (opc & 0xFE) == 0x78; // SST and SST1
4864
}
4965

5066
bool validDmAddr(opcode_t opc, uint32_t dma) const {
5167
uint16_t min = UINT16_C(0);
5268
uint16_t max = dataMemoryMax();
5369
if (isSST(opc)) {
54-
// TMS3201x: SST destination must be in page 1.
55-
min = PAGE1_MIN;
70+
if (is3201x()) {
71+
// TMS3201x: SST destination must be in page 1.
72+
min = PAGE1_MIN;
73+
} else {
74+
// TMS3202x: SST/SST1 destination must be in page 0.
75+
min = PAGE0_MIN;
76+
max = PAGE0_MAX;
77+
}
5678
}
5779
return dma >= min && dma <= max;
5880
}
@@ -61,11 +83,14 @@ struct Config
6183
auto dma = opc & 0x7F;
6284
if (isSST(opc)) {
6385
// TMS3201x: SST destination must be in page 1.
64-
return PAGE1_MIN + dma;
86+
// TMS3202x: SST/SST1 destination must be in page 0.
87+
return (is3201x() ? PAGE1_MIN : PAGE0_MIN) + dma;
6588
}
6689
return dma;
6790
}
6891

92+
static constexpr auto PAGE0_MIN = UINT16_C(0x0000);
93+
static constexpr auto PAGE0_MAX = UINT16_C(0x007F);
6994
static constexpr auto PAGE1_MIN = UINT16_C(0x0080);
7095
static constexpr auto PAGE1_MAX = UINT16_C(0x00FF);
7196
};

0 commit comments

Comments
 (0)