diff --git a/debugger/tms7000/compile_flags.txt b/debugger/tms7000/compile_flags.txt new file mode 100644 index 00000000..16aa0ee0 --- /dev/null +++ b/debugger/tms7000/compile_flags.txt @@ -0,0 +1,6 @@ +-O +-Wall +-std=c++14 +-I.. +-I../.pio/libdeps/teensy41/libcli/src +-I../.pio/libdeps/teensy41/libasm/src diff --git a/debugger/tms7000/devs_tms7000.cpp b/debugger/tms7000/devs_tms7000.cpp new file mode 100644 index 00000000..973a5766 --- /dev/null +++ b/debugger/tms7000/devs_tms7000.cpp @@ -0,0 +1,58 @@ +#include "devs_tms7000.h" +#include +#include "debugger.h" +#include "mc6850.h" + +namespace debugger { +namespace tms7000 { + +DevsTms7000 Devs; + +void DevsTms7000::reset() { + ACIA.reset(); + ACIA.setBaseAddr(ACIA_BASE); +} + +void DevsTms7000::begin() { + enableDevice(ACIA); +} + +void DevsTms7000::loop() { + ACIA.loop(); +} + +bool DevsTms7000::isSelected(uint32_t addr) const { + return ACIA.isSelected(addr); +} + +uint16_t DevsTms7000::read(uint32_t addr) const { + return ACIA.read(addr); +} + +void DevsTms7000::write(uint32_t addr, uint16_t data) const { + ACIA.write(addr, data); +} + +Device &DevsTms7000::parseDevice(const char *name) const { + if (strcasecmp(name, ACIA.name()) == 0) + return ACIA; + return Devs::nullDevice(); +} + +void DevsTms7000::enableDevice(Device &dev) { + ACIA.enable(&dev == &ACIA); +} + +void DevsTms7000::printDevices() const { + printDevice(ACIA); +} + +} // namespace tms7000 +} // namespace debugger + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/devs_tms7000.h b/debugger/tms7000/devs_tms7000.h new file mode 100644 index 00000000..54005b63 --- /dev/null +++ b/debugger/tms7000/devs_tms7000.h @@ -0,0 +1,35 @@ +#ifndef __DEVS_TMS7000_H__ +#define __DEVS_TMS7000_H__ + +#include "devs.h" + +#define ACIA_BASE 0x01F0 // P240 + +namespace debugger { +namespace tms7000 { + +struct DevsTms7000 : Devs { + void begin() override; + void reset() override; + void loop() override; + bool isSelected(uint32_t addr) const override; + uint16_t read(uint32_t addr) const override; + void write(uint32_t addr, uint16_t data) const override; + + Device &parseDevice(const char *name) const override; + void enableDevice(Device &dev) override; + void printDevices() const override; +}; + +extern struct DevsTms7000 Devs; + +} // namespace tms7000 +} // namespace debugger +#endif /* __DEVS_TMS7000H__ */ + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/inst_tms7000.awk b/debugger/tms7000/inst_tms7000.awk new file mode 100755 index 00000000..94aee3e7 --- /dev/null +++ b/debugger/tms7000/inst_tms7000.awk @@ -0,0 +1,54 @@ +#!/usr/bin/gawk -f +# -*- mode: awk; -*- + +BEGIN { + PRETTY_PRINT = 0; + GENERATE_TABLE = 1; +} + +BEGIN { + if (PRETTY_PRINT) { + pretty_print("op", "mnemo", "operand", "#", "bus"); + pretty_print("--", "-----", "----------", "-", "-"); + } + if (GENERATE_TABLE) { + printf("constexpr uint8_t INST_TABLE[] = {\n"); + } +} + +function pretty_print(opc, mnemo, operand, len, bus) { + if (PRETTY_PRINT == 0) + return; + printf("%-2s %-5s %-10s %s %s\n", + opc, mnemo, operand, len, bus); +} + +function generate_ENTRY(opc, mnemo, operand, len, bus) { + if (GENERATE_TABLE == 0) + return; + if (bus == "-") + bus = "0"; + if (len == "-") { + printf(" 0, // %s\n", opc); + } else { + printf(" E(%d, %d), // %s: %-5s %s\n", + len, bus, opc, mnemo, operand); + } +} + +END { + if (GENERATE_TABLE) + printf("};\n"); +} + +$1 !~ /[0-9A-F][0-9A-F]/ { next; } +$1 ~ /[0-9A-F][0-9A-F]/ { + opc = $1; + mne = $2; + opr = $3; + len = $4; + bus = $5; + + pretty_print(opc, mne, opr, len, bus); + generate_ENTRY(opc, mne, opr, len, bus); +} diff --git a/debugger/tms7000/inst_tms7000.cpp b/debugger/tms7000/inst_tms7000.cpp new file mode 100644 index 00000000..3444cc91 --- /dev/null +++ b/debugger/tms7000/inst_tms7000.cpp @@ -0,0 +1,297 @@ +#include "inst_tms7000.h" +#include +#include "debugger.h" +#include "mems_tms7000.h" +#include "regs_tms7000.h" + +namespace debugger { +namespace tms7000 { + +namespace { + +constexpr uint8_t E(uint8_t len, uint8_t bus) { + return (len << 4) | bus; +} + +constexpr uint8_t inst_len(uint8_t entry) { + return entry >> 4; +} + +constexpr uint8_t bus_cycles(uint8_t entry) { + return entry & 0xF; +} + +constexpr uint8_t INST_TABLE[] = { + E(1, 0), // 00: NOP - + E(1, 0), // 01: IDLE - + 0, // 02 + 0, // 03 + 0, // 04 + E(1, 0), // 05: EINT - + E(1, 0), // 06: DINT - + E(1, 0), // 07: SETC - + E(1, 0), // 08: POP ST + E(1, 0), // 09: STSP - + E(1, 0), // 0A: RETS - + E(1, 0), // 0B: RETI - + 0, // 0C + E(1, 0), // 0D: LDSP - + E(1, 0), // 0E: PUSH ST + 0, // 0F + 0, // 10 + 0, // 11 + E(2, 0), // 12: MOV Rs,A + E(2, 0), // 13: AND Rs,A + E(2, 0), // 14: OR Rs,A + E(2, 0), // 15: XOR Rs,A + E(3, 0), // 16: BTJO Rn,A,r8 + E(3, 0), // 17: BTJZ Rn,A,r8 + E(2, 0), // 18: ADD Rs,A + E(2, 0), // 19: ADC Rs,A + E(2, 0), // 1A: SUB Rs,A + E(2, 0), // 1B: SBB Rs,A + E(2, 0), // 1C: MPY Rs,A + E(2, 0), // 1D: CMP Rs,A + E(2, 0), // 1E: DAC Rs,A + E(2, 0), // 1F: DSB Rs,A + 0, // 20 + 0, // 21 + E(2, 0), // 22: MOV %n,A + E(2, 0), // 23: AND %n,A + E(2, 0), // 24: OR %n,A + E(2, 0), // 25: XOR %n,A + E(3, 0), // 26: BTJO %n,A,r8 + E(3, 0), // 27: BTJZ %n,A,r8 + E(2, 0), // 28: ADD %n,A + E(2, 0), // 29: ADC %n,A + E(2, 0), // 2A: SUB %n,A + E(2, 0), // 2B: SBB %n,A + E(2, 0), // 2C: MPY %n,A + E(2, 0), // 2D: CMP %n,A + E(2, 0), // 2E: DAC %n,A + E(2, 0), // 2F: DSB %n,A + 0, // 30 + 0, // 31 + E(2, 0), // 32: MOV Rs,B + E(2, 0), // 33: AND Rs,B + E(2, 0), // 34: OR Rs,B + E(2, 0), // 35: XOR Rs,B + E(3, 0), // 36: BTJO Rn,B,r8 + E(3, 0), // 37: BTJZ Rn,B,r8 + E(2, 0), // 38: ADD Rs,B + E(2, 0), // 39: ADC Rs,B + E(2, 0), // 3A: SUB Rs,B + E(2, 0), // 3B: SBB Rs,B + E(2, 0), // 3C: MPY Rs,B + E(2, 0), // 3D: CMP Rs,B + E(2, 0), // 3E: DAC Rs,B + E(2, 0), // 3F: DSB Rs,B + 0, // 40 + 0, // 41 + E(3, 0), // 42: MOV Rs,Rd + E(3, 0), // 43: AND Rs,Rd + E(3, 0), // 44: OR Rs,Rd + E(3, 0), // 45: XOR Rs,Rd + E(4, 0), // 46: BTJO Rn,Rd,r8 + E(4, 0), // 47: BTJZ Rn,Rd,r8 + E(3, 0), // 48: ADD Rs,Rd + E(3, 0), // 49: ADC Rs,Rd + E(3, 0), // 4A: SUB Rs,Rd + E(3, 0), // 4B: SBB Rs,Rd + E(3, 0), // 4C: MPY Rn,Rn + E(3, 0), // 4D: CMP Rs,Rd + E(3, 0), // 4E: DAC Rs,Rd + E(3, 0), // 4F: DSB Rs,Rd + 0, // 50 + 0, // 51 + E(2, 0), // 52: MOV %n,B + E(2, 0), // 53: AND %n,B + E(2, 0), // 54: OR %n,B + E(2, 0), // 55: XOR %n,B + E(3, 0), // 56: BTJO %n,B,r8 + E(3, 0), // 57: BTJZ %n,B,r8 + E(2, 0), // 58: ADD %n,B + E(2, 0), // 59: ADC %n,B + E(2, 0), // 5A: SUB %n,B + E(2, 0), // 5B: SBB %n,B + E(2, 0), // 5C: MPY %n,B + E(2, 0), // 5D: CMP %n,B + E(2, 0), // 5E: DAC %n,B + E(2, 0), // 5F: DSB %n,B + 0, // 60 + 0, // 61 + E(1, 0), // 62: MOV B,A + E(1, 0), // 63: AND B,A + E(1, 0), // 64: OR B,A + E(1, 0), // 65: XOR B,A + E(2, 0), // 66: BTJO B,A,r8 + E(2, 0), // 67: BTJZ B,A,r8 + E(1, 0), // 68: ADD B,A + E(1, 0), // 69: ADC B,A + E(1, 0), // 6A: SUB B,A + E(1, 0), // 6B: SBB B,A + E(1, 0), // 6C: MPY B,A + E(1, 0), // 6D: CMP B,A + E(1, 0), // 6E: DAC B,A + E(1, 0), // 6F: DSB B,A + 0, // 70 + 0, // 71 + E(3, 0), // 72: MOV %n,Rd + E(3, 0), // 73: AND %n,Rd + E(3, 0), // 74: OR %n,Rd + E(3, 0), // 75: XOR %n,Rd + E(4, 0), // 76: BTJO %n,Rn,r8 + E(4, 0), // 77: BTJZ %n,Rn,r8 + E(3, 0), // 78: ADD %n,Rd + E(3, 0), // 79: ADC %n,Rd + E(3, 0), // 7A: SUB Rs,Rd + E(3, 0), // 7B: SBB Rs,Rd + E(3, 0), // 7C: MPY %n,Rn + E(3, 0), // 7D: CMP %n,Rd + E(3, 0), // 7E: DAC %n,Rn + E(3, 0), // 7F: DSB %n,Rd + E(2, 1), // 80: MOVP Ps,A + 0, // 81 + E(2, 2), // 82: MOVP A,Pd + E(2, 2), // 83: ANDP A,Pd + E(2, 2), // 84: ORP A,Pd + E(2, 2), // 85: XORP A,Pd + E(3, 1), // 86: BTJOP A,Pn,r8 + E(3, 1), // 87: BTJZP A,Pn,r8 + E(4, 0), // 88: MOVD %n16,Rp + 0, // 89 + E(3, 1), // 8A: LDA @a16 + E(3, 1), // 8B: STA @a16 + E(3, 0), // 8C: BR @a16 + E(3, 1), // 8D: CMPA @a16 + E(3, 0), // 8E: CALL @a16 + 0, // 8F + 0, // 90 + E(2, 1), // 91: MOVP Ps,B + E(2, 2), // 92: MOVP B,Pd + E(2, 2), // 93: ANDP B,Pd + E(2, 2), // 94: ORP B,Pd + E(2, 2), // 95: XORP B,Pd + E(3, 1), // 96: BTJOP B,Pn,r8 + E(3, 1), // 97: BTJZP B,Pn,r8 + E(3, 0), // 98: MOVD Rp,Rp + 0, // 99 + E(2, 1), // 9A: LDA *Rp + E(2, 1), // 9B: STA *Rp + E(2, 0), // 9C: BR *Rp + E(2, 1), // 9D: CMPA *Rp + E(2, 0), // 9E: CALL *Rp + 0, // 9F + 0, // A0 + 0, // A1 + E(3, 2), // A2: MOVP %n,Pd + E(3, 2), // A3: ANDP %n,Pd + E(3, 2), // A4: ORP %n,Pd + E(3, 2), // A5: XORP %n,Pd + E(4, 1), // A6: BTJOP %n,Pn,r8 + E(4, 1), // A7: BTJZP %n,Pn,r8 + E(4, 0), // A8: MOVD @a16(B),Rp + 0, // A9 + E(3, 1), // AA: LDA @a16(B) + E(3, 1), // AB: STA @a16(B) + E(3, 0), // AC: BR @a16(B) + E(3, 1), // AD: CMPA @a16(B) + E(3, 0), // AE: CALL @a16(B) + 0, // AF + E(1, 0), // B0: TSTA - + 0, // B1 + E(1, 0), // B2: DEC A + E(1, 0), // B3: INC A + E(1, 0), // B4: INV A + E(1, 0), // B5: CLR A + E(1, 0), // B6: XCHB A + E(1, 0), // B7: SWAP A + E(1, 0), // B8: PUSH A + E(1, 0), // B9: POP A + E(2, 0), // BA: DJNZ A,r8 + E(1, 0), // BB: DECD A + E(1, 0), // BC: RR A + E(1, 0), // BD: RRC A + E(1, 0), // BE: RL A + E(1, 0), // BF: RLC A + E(1, 0), // C0: MOV A,B + E(1, 0), // C1: TST B + E(1, 0), // C2: DEC B + E(1, 0), // C3: INC B + E(1, 0), // C4: INV B + E(1, 0), // C5: CLR B + 0, // C6 + E(1, 0), // C7: SWAP B + E(1, 0), // C8: PUSH B + E(1, 0), // C9: POP B + E(2, 0), // CA: DJNZ B,r8 + E(1, 0), // CB: DECD B + E(1, 0), // CC: RR B + E(1, 0), // CD: RRC B + E(1, 0), // CE: RL B + E(1, 0), // CF: RLC B + E(2, 0), // D0: MOV A,Rd + E(2, 0), // D1: MOV B,Rd + E(2, 0), // D2: DEC Rn + E(2, 0), // D3: INC Rn + E(2, 0), // D4: INV Rn + E(2, 0), // D5: CLR Rn + E(2, 0), // D6: XCHB Rn + E(2, 0), // D7: SWAP Rd + E(2, 0), // D8: PUSH Rs + E(2, 0), // D9: POP Rd + E(3, 0), // DA: DJNZ Rn,r8 + E(2, 0), // DB: DECD Rp + E(2, 0), // DC: RR Rd + E(2, 0), // DD: RRC Rd + E(2, 0), // DE: RL Rd + E(2, 0), // DF: RLC Rd + E(2, 0), // E0: JMP r8 + E(2, 0), // E1: JN r8 + E(2, 0), // E2: JZ r8 + E(2, 0), // E3: JC r8 + E(2, 0), // E4: JP r8 + E(2, 0), // E5: JPZ r8 + E(2, 0), // E6: JNZ r8 + E(2, 0), // E7: JNC r8 + E(1, 0), // E8: TRAP 23 + E(1, 0), // E9: TRAP 22 + E(1, 0), // EA: TRAP 21 + E(1, 0), // EB: TRAP 20 + E(1, 0), // EC: TRAP 19 + E(1, 0), // ED: TRAP 18 + E(1, 0), // EE: TRAP 17 + E(1, 0), // EF: TRAP 16 + E(1, 0), // F0: TRAP 15 + E(1, 0), // F1: TRAP 14 + E(1, 0), // F2: TRAP 13 + E(1, 0), // F3: TRAP 12 + E(1, 0), // F4: TRAP 11 + E(1, 0), // F5: TRAP 10 + E(1, 0), // F6: TRAP 9 + E(1, 0), // F7: TRAP 8 + E(1, 0), // F8: TRAP 7 + E(1, 0), // F9: TRAP 6 + E(1, 0), // FA: TRAP 5 + E(1, 0), // FB: TRAP 4 + E(1, 0), // FC: TRAP 3 + E(1, 0), // FD: TRAP 2 + E(1, 0), // FE: TRAP 1 + E(1, 0), // FF: TRAP 0 +}; +} // namespace + +uint8_t InstTms7000::busCycles(uint8_t opc) { + const auto e = INST_TABLE[opc]; + return inst_len(e) + bus_cycles(e); +} + +} // namespace tms7000 +} // namespace debugger + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/inst_tms7000.h b/debugger/tms7000/inst_tms7000.h new file mode 100644 index 00000000..c989368b --- /dev/null +++ b/debugger/tms7000/inst_tms7000.h @@ -0,0 +1,31 @@ +#ifndef __INST_TMS7000_H__ +#define __INST_TMS7000_H__ + +#include + +namespace debugger { +namespace tms7000 { + +struct InstTms7000 { + static constexpr uint8_t NOP = 0x00; + static constexpr uint8_t IDLE = 0x01; + static constexpr uint8_t JMP = 0xE0; + static constexpr uint8_t JMP_HERE = 0xFE; + static constexpr uint16_t VEC_RESET = 0xFFFE; + + static uint8_t busCycles(uint8_t opc); + static bool isBTJxx(uint8_t opc) { + return (opc & 0xE) == 6 && (opc >= 0x10 && opc < 0xB0); + } +}; + +} // namespace tms7000 +} // namespace debugger +#endif + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/mems_tms7000.cpp b/debugger/tms7000/mems_tms7000.cpp new file mode 100644 index 00000000..0a41b530 --- /dev/null +++ b/debugger/tms7000/mems_tms7000.cpp @@ -0,0 +1,65 @@ +#include "mems_tms7000.h" +#include +#include +#include +#include "devs_tms7000.h" +#include "regs_tms7000.h" + +namespace debugger { +namespace tms7000 { + +struct MemsTms7000 Memory; + +uint16_t MemsTms7000::read(uint32_t addr) const { + return Devs.isSelected(addr) ? Devs.read(addr) : raw_read(addr); +} + +void MemsTms7000::write(uint32_t addr, uint16_t data) const { + if (Devs.isSelected(addr)) { + Devs.write(addr, data); + } else { + raw_write(addr, data); + } +} + +uint16_t MemsTms7000::get(uint32_t addr, const char *space) const { + if (Devs.isSelected(addr)) + return Devs.read(addr); + return addr < 0x0200 ? Regs.read_internal(addr) : raw_read(addr); +} + +void MemsTms7000::put(uint32_t addr, uint16_t data, const char *space) const { + if (Devs.isSelected(addr)) { + Devs.write(addr, data); + } else if (addr < 0x0200) { + Regs.write_internal(addr, data); + } else { + raw_write(addr, data); + } +} + +#ifdef WITH_ASSEMBLER +libasm::Assembler *MemsTms7000::assembler() const { + static auto as = new libasm::tms7000::AsmTms7000(); + as->setCpu(Regs.cpu()); + return as; +} +#endif + +#ifdef WITH_DISASSEMBLER +libasm::Disassembler *MemsTms7000::disassembler() const { + static auto dis = new libasm::tms7000::DisTms7000(); + dis->setCpu(Regs.cpu()); + return dis; +} +#endif + +} // namespace tms7000 +} // namespace debugger + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/mems_tms7000.h b/debugger/tms7000/mems_tms7000.h new file mode 100644 index 00000000..4de24a21 --- /dev/null +++ b/debugger/tms7000/mems_tms7000.h @@ -0,0 +1,39 @@ +#ifndef __MEMS_TMS7000_H__ +#define __MEMS_TMS7000_H__ + +#include "mems.h" + +namespace debugger { +namespace tms7000 { + +struct MemsTms7000 final : DmaMemory { + MemsTms7000() : DmaMemory(Endian::ENDIAN_BIG) {} + + uint32_t maxAddr() const override { return UINT16_MAX; } + uint16_t read(uint32_t addr) const override; + void write(uint32_t addr, uint16_t data) const override; + uint16_t get(uint32_t addr, const char *space = nullptr) const override; + void put(uint32_t addr, uint16_t data, + const char *space = nullptr) const override; + +protected: +#ifdef WITH_ASSEMBLER + libasm::Assembler *assembler() const override; +#endif +#ifdef WITH_DISASSEMBLER + libasm::Disassembler *disassembler() const override; +#endif +}; + +extern struct MemsTms7000 Memory; + +} // namespace tms7000 +} // namespace debugger +#endif + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/pins_tms7000.cpp b/debugger/tms7000/pins_tms7000.cpp new file mode 100644 index 00000000..35e81510 --- /dev/null +++ b/debugger/tms7000/pins_tms7000.cpp @@ -0,0 +1,423 @@ +#include "pins_tms7000.h" +#include "debugger.h" +#include "devs_tms7000.h" +#include "digital_bus.h" +#include "inst_tms7000.h" +#include "mems_tms7000.h" +#include "regs_tms7000.h" +#include "signals_tms7000.h" + +namespace debugger { +namespace tms7000 { + +struct PinsTms7000 Pins; + +// clang-format off +/** + * TMS7000 bus cycle. + * __ __ __ __ __ __ __ __ __ __ __ __ __ __ _ + * CLKIN __| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| |__| + * \ _\__\ \ \ ____\ \ _\__\ \ \ ____\ \ ____\ \ ____\ \ ____\ \ _ + * CLKOUT ___| | |__|__| |_____| | |__|__| |_____| |_____| |_____| |_____| + * |_____| | | |_____| | + * ALATCH ______| |__|___________|__| |__|________ + * _______________| |___________| + * #ENABLE |___________| |_____ + * _____________________________________ + * R/#W + * + * AD + * + */ +// clang-format on + +namespace { + +constexpr auto clkin_hi_ns = 500; +constexpr auto clkin_lo_ns = 500; + +inline void clkin_hi() { + digitalWriteFast(PIN_CLKIN, HIGH); +} + +inline void clkin_lo() { + digitalWriteFast(PIN_CLKIN, LOW); +} + +inline auto signal_clkout() { + return digitalReadFast(PIN_CLKOUT); +} + +inline auto signal_enable() { + return digitalReadFast(PIN_ENABLE); +} + +inline auto signal_alatch() { + return digitalReadFast(PIN_ALATCH); +} + +inline auto signal_rw() { + return digitalReadFast(PIN_RW); +} + +void negate_reset() { + digitalWriteFast(PIN_RESET, HIGH); +} + +const uint8_t PINS_LOW[] = { + PIN_RESET, +}; + +const uint8_t PINS_HIGH[] = { + PIN_CLKIN, + PIN_INT1, + PIN_INT3, +}; + +const uint8_t PINS_INPUT[] = { + PIN_AD0, + PIN_AD1, + PIN_AD2, + PIN_AD3, + PIN_AD4, + PIN_AD5, + PIN_AD6, + PIN_AD7, + PIN_ADDR8, + PIN_ADDR9, + PIN_ADDR10, + PIN_ADDR11, + PIN_ADDR12, + PIN_ADDR13, + PIN_ADDR14, + PIN_ADDR15, + PIN_CLKOUT, + PIN_ENABLE, + PIN_RW, + PIN_ALATCH, + PIN_PA0, + PIN_PA1, + PIN_PA2, + PIN_PA3, + PIN_PA4, + PIN_PA5, + PIN_PA6, + PIN_PA7, + PIN_PB0, + PIN_PB1, + PIN_PB2, + PIN_PB3, +}; + +inline void clkin_cycle_lo() { + clkin_hi(); + delayNanoseconds(clkin_hi_ns); + clkin_lo(); +} + +inline void clkin_cycle() { + clkin_cycle_lo(); + delayNanoseconds(clkin_lo_ns); +} + +} // namespace + +void PinsTms7000::reset() { + // Assert reset condition + pinsMode(PINS_LOW, sizeof(PINS_LOW), OUTPUT, LOW); + pinsMode(PINS_HIGH, sizeof(PINS_HIGH), OUTPUT, HIGH); + pinsMode(PINS_INPUT, sizeof(PINS_INPUT), INPUT); + + // The RESET function is initiated when the #RESET line of the + // TMS7000 device is held at a logic zero level for at least five + // clock cycles. + for (auto i = 0; i < 100; i++) + clkin_cycle(); + negate_reset(); + clkin_cycle(); + Signals::resetCycles(); + // Clear IOCNT0 (>0100) to disable interrupts + cycle(); + // Inject dummy reset vector >8000 + inject(0x00); // >FFFF + inject(0x80); // >FFFE + // CLKOUT=H + Regs.save(); + Regs.setIp(Memory.raw_read16(InstTms7000::VEC_RESET)); + checkHardwareType(); +} + +void PinsTms7000::checkHardwareType() { + inject(0x8A); // LDA @>0080 + inject(hi(0x0080)); // TMS7000/TMS7001 executes external read cycle + inject(lo(0x0080)); // TMS7002 executes internal read cycle + const auto reg80 = cycle(); + inject(0x8A); // LDA @>0110 + inject(hi(0x0110)); // TMS7000/TMS7001 executes external read cycle + inject(lo(0x0110)); // TMS7002 executes internal read cycle + const auto port10 = cycle(); + if (reg80->external()) { + _hardType = port10->external() ? HW_TMS7000 : HW_TMS7001; + } else { + _hardType = HW_TMS7002; + } + Regs.restoreA(); +} + +Signals *PinsTms7000::prepareCycle() const { + auto s = Signals::put(); + while (signal_alatch() == LOW) + clkin_cycle(); + // CLKOUT=H, ALATCH=H + clkin_hi(); + delayNanoseconds(clkin_hi_ns); + // CLKOUT=L + clkin_lo(); + // assert_debug(); + s->getAddress(); + // negate_debug(); + delayNanoseconds(clkin_lo_ns); + // CLKOUT=H + clkin_hi(); + delayNanoseconds(clkin_hi_ns); + // assert_debug(); + s->getDirection(); + // negate_debug(); + return s; +} + +Signals *PinsTms7000::completeCycle(Signals *s) const { + if (s->read()) { // External read + clkin_lo(); + if (s->readMemory()) { + s->data = Memory.read(s->addr); + } else { + ; // inject + } + delayNanoseconds(clkin_lo_ns); + // CLKOUT=L + clkin_hi(); + // assert_debug(); + s->outData(); + // negate_debug(); + delayNanoseconds(clkin_hi_ns); + clkin_lo(); + delayNanoseconds(clkin_lo_ns); + // CLKOUT=H + clkin_hi(); + while (signal_enable() == LOW) + ; + // assert_debug(); + s->inputMode(); + // negate_debug(); + delayNanoseconds(clkin_hi_ns); + clkin_lo(); + delayNanoseconds(clkin_lo_ns); + } else if (s->write()) { // External write + clkin_lo(); + delayNanoseconds(clkin_lo_ns); + // CLKOUT=L + clkin_hi(); + // assert_debug(); + s->getData(); + // negate_debug(); + delayNanoseconds(clkin_hi_ns); + clkin_lo(); + if (s->writeMemory()) { + Memory.write(s->addr, s->data); + } else { + ; // capture + } + delayNanoseconds(clkin_lo_ns); + } else { // Internal cycle + clkin_lo(); + delayNanoseconds(clkin_lo_ns); + // assert_debug(); + s->getData(); + // negate_debug(); + } + // assert_debug(); + Signals::nextCycle(); + // negate_debug(); + while (signal_alatch() == LOW) + clkin_cycle(); + return s; +} + +Signals *PinsTms7000::cycle() const { + return completeCycle(prepareCycle()); +} + +Signals *PinsTms7000::inject(uint8_t data) const { + return completeCycle(prepareCycle()->inject(data)); +} + +void PinsTms7000::execInst(const uint8_t *inst, uint8_t len, uint8_t extra) { + execute(inst, len); + for (uint8_t i = 0; i < extra; ++i) + cycle(); +} + +void PinsTms7000::captureWrites(const uint8_t *inst, uint8_t len, uint8_t *buf, + uint8_t max, uint16_t *addr) { + execute(inst, len, buf, max, addr); +} + +void PinsTms7000::execute(const uint8_t *inst, uint8_t len, uint8_t *buf, + uint8_t max, uint16_t *addr) { + uint8_t inj = 0; + uint8_t cap = 0; + while (inj < len || cap < max) { + auto s = prepareCycle(); + if (inj < len) + s->inject(inst[inj]); + if (cap < max) + s->capture(); + completeCycle(s); + if (s->read()) { + if (inj == 0 && addr) + *addr = s->addr; + if (inj < len) + ++inj; + } else if (s->write()) { + if (cap < max && buf) + buf[cap++] = s->data; + } + } +} + +void PinsTms7000::idle() { + auto s = inject(InstTms7000::JMP); + inject(InstTms7000::JMP_HERE); + Signals::discard(s); +} + +void PinsTms7000::loop() { + while (true) { + Devs.loop(); + if (!rawStep() || haltSwitch()) + return; + } +} + +void PinsTms7000::run() { + Regs.restore(); + Signals::resetCycles(); + saveBreakInsts(); + loop(); + restoreBreakInsts(); + disassembleCycles(); + Regs.save(); +} + +bool PinsTms7000::rawStep() { + auto s = prepareCycle(); + if (s->intack()) { // Interrupt + interrupt: + completeCycle(s); + cycle(); // lo(vector) + cycle(); // hi(vector) + s = prepareCycle(); + } + const auto opc = Memory.raw_read(s->addr); + const auto cycles = InstTms7000::busCycles(opc); + if (opc == InstTms7000::IDLE || cycles == 0) { + assert_debug(); + completeCycle(s->inject(InstTms7000::JMP)); + inject(InstTms7000::JMP_HERE); + negate_debug(); + Signals::discard(s); + return false; + } + completeCycle(s)->markFetch(true); + for (uint8_t i = 1; i < cycles; ++i) { + s = prepareCycle(); + if (s->intack()) + goto interrupt; + completeCycle(s); + } + return true; +} + +bool PinsTms7000::step(bool show) { + Signals::resetCycles(); + Regs.restore(); + if (show) + Signals::resetCycles(); + if (rawStep()) { + if (show) + printCycles(); + Regs.save(); + return true; + } + return false; +} + +void PinsTms7000::assertInt(uint8_t name) { + switch (name) { + case INTR_INT1: + digitalWriteFast(PIN_INT1, LOW); + break; + case INTR_INT3: + digitalWriteFast(PIN_INT3, LOW); + break; + case INTR_NONE: + break; + } +} + +void PinsTms7000::negateInt(uint8_t name) { + switch (name) { + case INTR_INT1: + digitalWriteFast(PIN_INT1, HIGH); + break; + case INTR_INT3: + digitalWriteFast(PIN_INT3, HIGH); + break; + case INTR_NONE: + break; + } +} + +void PinsTms7000::setBreakInst(uint32_t addr) const { + Memory.put_inst(addr, InstTms7000::IDLE); +} + +void PinsTms7000::printCycles() { + const auto g = Signals::get(); + const auto cycles = g->diff(Signals::put()); + for (auto i = 0; i < cycles; ++i) { + g->next(i)->print(); + idle(); + } +} + +void PinsTms7000::disassembleCycles() { + const auto g = Signals::get(); + const auto cycles = g->diff(Signals::put()); + for (auto i = 0; i < cycles;) { + const auto s = g->next(i); + if (s->fetch()) { + const auto len = Memory.disassemble(s->addr, 1) - s->addr; + for (uint8_t j = 0; j < len; ++j) + s->next(j)->print(); + i += len; + // if (InstTms7000::isBTJxx(s->data)) + // s->next(len - 1)->print(); + } else { + s->print(); + ++i; + } + idle(); + } +} + +} // namespace tms7000 +} // namespace debugger + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/pins_tms7000.h b/debugger/tms7000/pins_tms7000.h new file mode 100644 index 00000000..a16585c6 --- /dev/null +++ b/debugger/tms7000/pins_tms7000.h @@ -0,0 +1,117 @@ +#ifndef __PINS_TMS7000_H__ +#define __PINS_TMS7000_H__ + +#define PORT_AD 6 /* GPIO6 */ +#define AD_gp 16 /* P6.16-P6.23 */ +#define AD_gm 0xFF /* P6.16-P6.23 */ +#define AD_vp 0 /* AD0-AD7 */ +#define PIN_AD0 19 /* P6.16 */ +#define PIN_AD1 18 /* P6.17 */ +#define PIN_AD2 14 /* P6.18 */ +#define PIN_AD3 15 /* P6.19 */ +#define PIN_AD4 40 /* P6.20 */ +#define PIN_AD5 41 /* P6.21 */ +#define PIN_AD6 17 /* P6.22 */ +#define PIN_AD7 16 /* P6.23 */ +#define PORT_ADDR 6 /* GPIO6 */ +#define ADDR_gp 16 /* P6.16-P6.31 */ +#define ADDR_gm 0xFFFF /* P6.16-P6.31 */ +#define ADDR_vp 0 /* A0-A15 */ +#define PIN_ADDR8 22 /* P6.24 */ +#define PIN_ADDR9 23 /* P6.25 */ +#define PIN_ADDR10 20 /* P6.26 */ +#define PIN_ADDR11 21 /* P6.27 */ +#define PIN_ADDR12 38 /* P6.28 */ +#define PIN_ADDR13 39 /* P6.29 */ +#define PIN_ADDR14 26 /* P6.30 */ +#define PIN_ADDR15 27 /* P6.31 */ +#define PIN_PA0 10 /* P7.00 */ +#define PIN_PA1 12 /* P7.01 */ +#define PIN_PA2 11 /* P7.02 */ +#define PIN_PA3 13 /* P7.03 */ +#define PIN_PA4 8 /* P7.16 */ +#define PIN_PA5 7 /* P7.17 */ +#define PIN_PA6 36 /* P7.18 */ +#define PIN_PA7 37 /* P7.19 */ +#define PORT_CNTL 9 /* GPIO9 */ +#define CNTL_gp 4 /* P9.04-P9.07 */ +#define CNTL_gm 0xF /* P9.04-P9.07 */ +#define CNTL_vp 0 /* CNTL0-CNTL4 */ +#define PIN_ENABLE 2 /* P9.04 */ +#define PIN_RW 3 /* P9.05 */ +#define PIN_ALATCH 33 /* P9.07 */ +#define CNTL_ENABLE 0x1 /* CNTL0 */ +#define CNTL_RW 0x2 /* CNTL1 */ +#define CNTL_ALATCH 0x8 /* CNTL3 */ +#define PIN_PB3 0 /* P6.03 */ +#define PIN_CLKIN 5 /* P9.08 */ +#define PIN_CLKOUT 29 /* P9.31 */ +#define PIN_INT1 6 /* P7.10 */ +#define PIN_INT3 9 /* P7.11 */ +#define PIN_PB0 32 /* P7.12 */ +#define PIN_RESET 28 /* P8.18 */ +#define PIN_PB1 31 /* P8.22 */ +#define PIN_PB2 30 /* P8.23 */ + +#include "pins.h" +#include "signals_tms7000.h" + +namespace debugger { +namespace tms7000 { + +enum HardwareType : uint8_t { + HW_TMS7000 = 0, // TMS7000 + HW_TMS7001 = 1, // TMS7001 + HW_TMS7002 = 2, // TMS7002 +}; + +enum IntrName : uint8_t { + INTR_NONE = 0, + INTR_INT1 = 1, + INTR_INT3 = 3, +}; + +struct PinsTms7000 final : Pins { + void reset() override; + void idle() override; + bool step(bool show) override; + void run() override; + void assertInt(uint8_t name) override; + void negateInt(uint8_t name) override; + void printCycles() override; + + void execInst(const uint8_t *inst, uint8_t len, uint8_t extra = 0); + void captureWrites(const uint8_t *inst, uint8_t len, uint8_t *buf, + uint8_t max, uint16_t *addr = nullptr); + HardwareType hardwareType() const { return _hardType; } + +private: + HardwareType _hardType; + + void setBreakInst(uint32_t addr) const override; + + void checkHardwareType(); + void loop(); + Signals *prepareCycle() const; + Signals *completeCycle(Signals *signals) const; + Signals *cycle() const; + Signals *inject(uint8_t data) const; + bool rawStep(); + void execute(const uint8_t *inst, uint8_t len, uint8_t *buf = nullptr, + uint8_t max = 0, uint16_t *addr = nullptr); + + void disassembleCycles(); +}; + +extern struct PinsTms7000 Pins; + +} // namespace tms7000 +} // namespace debugger +#endif /* __PINS_H__ */ + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/regs_tms7000.cpp b/debugger/tms7000/regs_tms7000.cpp new file mode 100644 index 00000000..eca818ca --- /dev/null +++ b/debugger/tms7000/regs_tms7000.cpp @@ -0,0 +1,170 @@ +#include "regs_tms7000.h" +#include "char_buffer.h" +#include "debugger.h" +#include "digital_bus.h" +#include "inst_tms7000.h" +#include "mems_tms7000.h" +#include "pins_tms7000.h" + +namespace debugger { +namespace tms7000 { + +struct RegsTms7000 Regs; + +namespace { +constexpr const char *const CPU_NAMES[/*HardwareType*/] = { + "TMS7000", + "TMS7001", + "TMS7002", +}; +} + +const char *RegsTms7000::cpu() const { + return CPU_NAMES[HW_TMS7000]; +} + +const char *RegsTms7000::cpuName() const { + const auto type = Pins.hardwareType(); + return CPU_NAMES[type]; +} + +void RegsTms7000::print() const { + // 01234567890123456789012345678901234 + static constexpr char line[] = "PC=xxxx SP=xx A=xx B=xx ST=CNZI1111"; + static auto &buffer = *new CharBuffer(line); + buffer.hex16(3, _pc); + buffer.hex8(11, _sp); + buffer.hex8(16, _a); + buffer.hex8(21, _b); + buffer.bits(27, _st, 0x80, line + 27); + cli.println(buffer); + Pins.idle(); +} + +void RegsTms7000::save() { + static constexpr uint8_t SAVE_ALL[] = { + 0x0E, // PUSH ST + 0x8B, 0x80, 0x00, // STA @>8000 + 0xB9, // POP A + 0x8B, 0x80, 0x00, // STA @>8000 + 0x62, // MOV B, A + 0x8B, 0x80, 0x00, // STA @>8000 + 0x09, // STSP + 0x62, // MOV B, A + 0x8B, 0x80, 0x00, // STA @>8000 + }; + uint8_t buffer[4]; + Pins.captureWrites( + SAVE_ALL, sizeof(SAVE_ALL), buffer, sizeof(buffer), &_pc); + write_internal(A, buffer[0]); + _st = buffer[1]; + write_internal(B, buffer[2]); + _sp = buffer[3]; +} + +void RegsTms7000::restore() { + uint8_t LOAD_ALL[] = { + 0x52, _sp, // MOV %_sp, B + 0x0D, // LDSP + 0x52, _b, // MOV %_b, B + 0x22, _st, // MOV %_st, A + 0xB8, // PUSH A + 0x22, _a, // MOV %_a, A + 0x08, // POP ST + 0x8C, hi(_pc), lo(_pc), // BR @_pc + }; + Pins.execInst(LOAD_ALL, sizeof(LOAD_ALL)); +} + +void RegsTms7000::restoreA() { + write_internal(A, _a); +} + +uint8_t RegsTms7000::read_internal(uint16_t addr) { + uint8_t READ[] = { + 0x8A, hi(addr), lo(addr), // LDA @addr + }; + Pins.execInst(READ, sizeof(READ), 1); + uint8_t CAPTURE[] = { + 0x8B, 0x80, 0x00, // STA @>8000 + }; + uint8_t data; + Pins.captureWrites(CAPTURE, sizeof(CAPTURE), &data, sizeof(data)); + restoreA(); + return data; +} + +void RegsTms7000::write_internal(uint16_t addr, uint8_t data) { + if (addr == A) { + uint8_t MOV_A[] = { + 0x22, _a = data, // MOV %data, A + }; + Pins.execInst(MOV_A, sizeof(MOV_A)); + return; + } + if (addr == B) { + uint8_t MOV_B[] = { + 0x52, _b = data, // MOV %data, B + }; + Pins.execInst(MOV_B, sizeof(MOV_B)); + return; + } + uint8_t WRITE[] = { + 0x22, data, // MOV %data, A + 0x8B, hi(addr), lo(addr), // STA @addr + }; + Pins.execInst(WRITE, sizeof(WRITE), 1); + restoreA(); +} + +void RegsTms7000::helpRegisters() const { + cli.println(F("?Reg: PC SP A B ST")); +} + +constexpr const char *REGS8[] = { + "ST", // 1 + "A", // 2 + "B", // 3 + "SP", // 4 +}; +constexpr const char *REGS16[] = { + "PC", // 5 +}; + +const Regs::RegList *RegsTms7000::listRegisters(uint8_t n) const { + static constexpr RegList REG_LIST[] = { + {REGS8, 4, 1, UINT8_MAX}, + {REGS16, 1, 5, UINT16_MAX}, + }; + return n < 2 ? ®_LIST[n] : nullptr; +} + +void RegsTms7000::setRegister(uint8_t reg, uint32_t value) { + switch (reg) { + case 5: + _pc = value; + break; + case 4: + _sp = value; + break; + case 2: + write_internal(A, value); + break; + case 3: + write_internal(B, value); + break; + case 1: + _st = value; + break; + } +} + +} // namespace tms7000 +} // namespace debugger + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/regs_tms7000.h b/debugger/tms7000/regs_tms7000.h new file mode 100644 index 00000000..17384e04 --- /dev/null +++ b/debugger/tms7000/regs_tms7000.h @@ -0,0 +1,50 @@ +#ifndef __REGS_TMS7000_H__ +#define __REGS_TMS7000_H__ + +#include "regs.h" + +namespace debugger { +namespace tms7000 { + +struct RegsTms7000 final : Regs { + const char *cpu() const override; + const char *cpuName() const override; + + void print() const override; + void reset(); + void save() override; + void restore() override; + + uint32_t nextIp() const override { return _pc; } + void restoreA(); + void setIp(uint16_t addr) { _pc = addr; } + void helpRegisters() const override; + const RegList *listRegisters(uint8_t n) const override; + void setRegister(uint8_t reg, uint32_t value) override; + + uint8_t read_internal(uint16_t add); + void write_internal(uint16_t add, uint8_t data); + +private: + uint8_t _a; + uint8_t _b; + uint8_t _sp; + uint8_t _st; + uint16_t _pc; + + static constexpr uint16_t A = 0x0000; + static constexpr uint16_t B = 0x0001; +}; + +extern struct RegsTms7000 Regs; + +} // namespace tms7000 +} // namespace debugger +#endif + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/signals_tms7000.cpp b/debugger/tms7000/signals_tms7000.cpp new file mode 100644 index 00000000..05b9e15b --- /dev/null +++ b/debugger/tms7000/signals_tms7000.cpp @@ -0,0 +1,73 @@ +#include "signals_tms7000.h" +#include "char_buffer.h" +#include "debugger.h" +#include "digital_bus.h" +#include "pins_tms7000.h" + +namespace debugger { +namespace tms7000 { + +void Signals::getAddress() { + addr = busRead(ADDR); +} + +void Signals::getDirection() { + cntl() = busRead(CNTL); + markFetch(false); +} + +bool Signals::external() const { + return (cntl() & CNTL_ENABLE) == 0; +} + +bool Signals::read() const { + return (cntl() & (CNTL_ENABLE | CNTL_RW)) == CNTL_RW; +} + +bool Signals::write() const { + return (cntl() & (CNTL_ENABLE | CNTL_RW)) == 0; +} + +bool Signals::intack() const { + return addr == 0 && (cntl() & (CNTL_ENABLE | CNTL_RW)) == (CNTL_ENABLE | CNTL_RW); +} + +void Signals::getData() { + data = busRead(AD); +} + +void Signals::outData() { + busMode(AD, OUTPUT); + busWrite(AD, data); +} + +void Signals::inputMode() const { + busMode(AD, INPUT); +} + +void Signals::print() const { + cli.printDec(pos(), -4); + // 0123456789012 + static constexpr char line[] = "R A=xxxx D=xx"; + static auto &buffer = *new CharBuffer(line); + if (fetch()) { + buffer[0] = 'F'; + } else if (external()) { + buffer[0] = write() ? 'W' : 'R'; + } else { + buffer[0] = intack() ? 'I' : (cntl() & CNTL_RW) ? 'r' : 'w'; + } + buffer.hex16(4, addr); + buffer.hex8(11, data); + cli.println(buffer); +} + +} // namespace tms7000 +} // namespace debugger + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/signals_tms7000.h b/debugger/tms7000/signals_tms7000.h new file mode 100644 index 00000000..ad50cddf --- /dev/null +++ b/debugger/tms7000/signals_tms7000.h @@ -0,0 +1,38 @@ +#ifndef __SIGNALS_TMS7000_H__ +#define __SIGNALS_TMS7000_H__ + +#include "signals.h" + +namespace debugger { +namespace tms7000 { + +struct Signals final : SignalsBase { + void getAddress(); + void getDirection(); + void getData(); + void outData(); + void inputMode() const; + void print() const; + + bool external() const; + bool read() const; + bool write() const; + bool fetch() const { return _signals[1]; } + void markFetch(bool fetch) { _signals[1] = fetch; } + bool intack() const; + +private: + uint8_t cntl() const { return _signals[0]; } + uint8_t &cntl() { return _signals[0]; } +}; + +} // namespace tms7000 +} // namespace debugger +#endif /* __SIGNALS_H__ */ + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/target_tms7000.cpp b/debugger/tms7000/target_tms7000.cpp new file mode 100644 index 00000000..46c9ced7 --- /dev/null +++ b/debugger/tms7000/target_tms7000.cpp @@ -0,0 +1,23 @@ +#include "target.h" + +#include "devs_tms7000.h" +#include "mems_tms7000.h" +#include "pins_tms7000.h" +#include "regs_tms7000.h" + +namespace debugger { +namespace tms7000 { + +struct Target TargetTms7000 { + "TMS7000", Pins, Regs, Memory, Devs +}; + +} // namespace tms7000 +} // namespace debugger + +// Local Variables: +// mode: c++ +// c-basic-offset: 4 +// tab-width: 4 +// End: +// vim: set ft=cpp et ts=4 sw=4: diff --git a/debugger/tms7000/tms7000.txt b/debugger/tms7000/tms7000.txt new file mode 100644 index 00000000..ef0be017 --- /dev/null +++ b/debugger/tms7000/tms7000.txt @@ -0,0 +1,258 @@ +op mnemo operand # bus +-- ----- ---------- - - +00 NOP - 1 - +01 IDLE - 1 - +02 - - - - +03 - - - - +04 - - - - +05 EINT - 1 - +06 DINT - 1 - +07 SETC - 1 - +08 POP ST 1 - +09 STSP - 1 - +0A RETS - 1 - +0B RETI - 1 - +0C - - - - +0D LDSP - 1 - +0E PUSH ST 1 - +0F - - - - +10 - - - - +11 - - - - +12 MOV Rs,A 2 - +13 AND Rs,A 2 - +14 OR Rs,A 2 - +15 XOR Rs,A 2 - +16 BTJO Rn,A,r8 3 - +17 BTJZ Rn,A,r8 3 - +18 ADD Rs,A 2 - +19 ADC Rs,A 2 - +1A SUB Rs,A 2 - +1B SBB Rs,A 2 - +1C MPY Rs,A 2 - +1D CMP Rs,A 2 - +1E DAC Rs,A 2 - +1F DSB Rs,A 2 - +20 - - - - +21 - - - - +22 MOV %n,A 2 - +23 AND %n,A 2 - +24 OR %n,A 2 - +25 XOR %n,A 2 - +26 BTJO %n,A,r8 3 - +27 BTJZ %n,A,r8 3 - +28 ADD %n,A 2 - +29 ADC %n,A 2 - +2A SUB %n,A 2 - +2B SBB %n,A 2 - +2C MPY %n,A 2 - +2D CMP %n,A 2 - +2E DAC %n,A 2 - +2F DSB %n,A 2 - +30 - - - - +31 - - - - +32 MOV Rs,B 2 - +33 AND Rs,B 2 - +34 OR Rs,B 2 - +35 XOR Rs,B 2 - +36 BTJO Rn,B,r8 3 - +37 BTJZ Rn,B,r8 3 - +38 ADD Rs,B 2 - +39 ADC Rs,B 2 - +3A SUB Rs,B 2 - +3B SBB Rs,B 2 - +3C MPY Rs,B 2 - +3D CMP Rs,B 2 - +3E DAC Rs,B 2 - +3F DSB Rs,B 2 - +40 - - - - +41 - - - - +42 MOV Rs,Rd 3 - +43 AND Rs,Rd 3 - +44 OR Rs,Rd 3 - +45 XOR Rs,Rd 3 - +46 BTJO Rn,Rd,r8 4 - +47 BTJZ Rn,Rd,r8 4 - +48 ADD Rs,Rd 3 - +49 ADC Rs,Rd 3 - +4A SUB Rs,Rd 3 - +4B SBB Rs,Rd 3 - +4C MPY Rn,Rn 3 - +4D CMP Rs,Rd 3 - +4E DAC Rs,Rd 3 - +4F DSB Rs,Rd 3 - +50 - - - - +51 - - - - +52 MOV %n,B 2 - +53 AND %n,B 2 - +54 OR %n,B 2 - +55 XOR %n,B 2 - +56 BTJO %n,B,r8 3 - +57 BTJZ %n,B,r8 3 - +58 ADD %n,B 2 - +59 ADC %n,B 2 - +5A SUB %n,B 2 - +5B SBB %n,B 2 - +5C MPY %n,B 2 - +5D CMP %n,B 2 - +5E DAC %n,B 2 - +5F DSB %n,B 2 - +60 - - - - +61 - - - - +62 MOV B,A 1 - +63 AND B,A 1 - +64 OR B,A 1 - +65 XOR B,A 1 - +66 BTJO B,A,r8 2 - +67 BTJZ B,A,r8 2 - +68 ADD B,A 1 - +69 ADC B,A 1 - +6A SUB B,A 1 - +6B SBB B,A 1 - +6C MPY B,A 1 - +6D CMP B,A 1 - +6E DAC B,A 1 - +6F DSB B,A 1 - +70 - - - - +71 - - - - +72 MOV %n,Rd 3 - +73 AND %n,Rd 3 - +74 OR %n,Rd 3 - +75 XOR %n,Rd 3 - +76 BTJO %n,Rn,r8 4 - +77 BTJZ %n,Rn,r8 4 - +78 ADD %n,Rd 3 - +79 ADC %n,Rd 3 - +7A SUB Rs,Rd 3 - +7B SBB Rs,Rd 3 - +7C MPY %n,Rn 3 - +7D CMP %n,Rd 3 - +7E DAC %n,Rn 3 - +7F DSB %n,Rd 3 - +80 MOVP Ps,A 2 1 +81 - - - - +82 MOVP A,Pd 2 2 +83 ANDP A,Pd 2 2 +84 ORP A,Pd 2 2 +85 XORP A,Pd 2 2 +86 BTJOP A,Pn,r8 3 1 +87 BTJZP A,Pn,r8 3 1 +88 MOVD %n16,Rp 4 - +89 - - - - +8A LDA @a16 3 1 +8B STA @a16 3 1 +8C BR @a16 3 - +8D CMPA @a16 3 1 +8E CALL @a16 3 - +8F - - - - +90 - - - - +91 MOVP Ps,B 2 1 +92 MOVP B,Pd 2 2 +93 ANDP B,Pd 2 2 +94 ORP B,Pd 2 2 +95 XORP B,Pd 2 2 +96 BTJOP B,Pn,r8 3 1 +97 BTJZP B,Pn,r8 3 1 +98 MOVD Rp,Rp 3 - +99 - - - - +9A LDA *Rp 2 1 +9B STA *Rp 2 1 +9C BR *Rp 2 - +9D CMPA *Rp 2 1 +9E CALL *Rp 2 - +9F - - - - +A0 - - - - +A1 - - - - +A2 MOVP %n,Pd 3 2 +A3 ANDP %n,Pd 3 2 +A4 ORP %n,Pd 3 2 +A5 XORP %n,Pd 3 2 +A6 BTJOP %n,Pn,r8 4 1 +A7 BTJZP %n,Pn,r8 4 1 +A8 MOVD @a16(B),Rp 4 - +A9 - - - - +AA LDA @a16(B) 3 1 +AB STA @a16(B) 3 1 +AC BR @a16(B) 3 - +AD CMPA @a16(B) 3 1 +AE CALL @a16(B) 3 - +AF - - - - +B0 TSTA - 1 - +B1 - - - - +B2 DEC A 1 - +B3 INC A 1 - +B4 INV A 1 - +B5 CLR A 1 - +B6 XCHB A 1 - +B7 SWAP A 1 - +B8 PUSH A 1 - +B9 POP A 1 - +BA DJNZ A,r8 2 - +BB DECD A 1 - +BC RR A 1 - +BD RRC A 1 - +BE RL A 1 - +BF RLC A 1 - +C0 MOV A,B 1 - +C1 TST B 1 - +C2 DEC B 1 - +C3 INC B 1 - +C4 INV B 1 - +C5 CLR B 1 - +C6 - - - - +C7 SWAP B 1 - +C8 PUSH B 1 - +C9 POP B 1 - +CA DJNZ B,r8 2 - +CB DECD B 1 - +CC RR B 1 - +CD RRC B 1 - +CE RL B 1 - +CF RLC B 1 - +D0 MOV A,Rd 2 - +D1 MOV B,Rd 2 - +D2 DEC Rn 2 - +D3 INC Rn 2 - +D4 INV Rn 2 - +D5 CLR Rn 2 - +D6 XCHB Rn 2 - +D7 SWAP Rd 2 - +D8 PUSH Rs 2 - +D9 POP Rd 2 - +DA DJNZ Rn,r8 3 - +DB DECD Rp 2 - +DC RR Rd 2 - +DD RRC Rd 2 - +DE RL Rd 2 - +DF RLC Rd 2 - +E0 JMP r8 2 - +E1 JN r8 2 - +E2 JZ r8 2 - +E3 JC r8 2 - +E4 JP r8 2 - +E5 JPZ r8 2 - +E6 JNZ r8 2 - +E7 JNC r8 2 - +E8 TRAP 23 1 - +E9 TRAP 22 1 - +EA TRAP 21 1 - +EB TRAP 20 1 - +EC TRAP 19 1 - +ED TRAP 18 1 - +EE TRAP 17 1 - +EF TRAP 16 1 - +F0 TRAP 15 1 - +F1 TRAP 14 1 - +F2 TRAP 13 1 - +F3 TRAP 12 1 - +F4 TRAP 11 1 - +F5 TRAP 10 1 - +F6 TRAP 9 1 - +F7 TRAP 8 1 - +F8 TRAP 7 1 - +F9 TRAP 6 1 - +FA TRAP 5 1 - +FB TRAP 4 1 - +FC TRAP 3 1 - +FD TRAP 2 1 - +FE TRAP 1 1 - +FF TRAP 0 1 - diff --git a/samples/tms7000/Makefile b/samples/tms7000/Makefile new file mode 100644 index 00000000..ce6d26eb --- /dev/null +++ b/samples/tms7000/Makefile @@ -0,0 +1,11 @@ +ASM=asm + +.PHONY: clean + +all: echo.hex echoir.hex echoitr.hex arith.hex mandelbrot.hex + +%.hex: %.asm + $(ASM) -l $*.lst -o $@ $^ + +clean: + -rm -f *.lst *.hex diff --git a/samples/tms7000/arith.asm b/samples/tms7000/arith.asm new file mode 100644 index 00000000..2d6c2da8 --- /dev/null +++ b/samples/tms7000/arith.asm @@ -0,0 +1,271 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + cpu tms7000 + include "tms7000.inc" + + *** MC6850 Asynchronous Communication Interface Adapter +ACIA: equ >01F0 + include "mc6850.inc" + + *** Internal register file +Rd: equ 5 R4:R5 +Rs: equ 7 R6:R7 +vA: equ 9 R8:R9 +vB: equ 11 R10:R11 + + org >60 + * TMS7000's SP is pre-increment/post-decrement +stack: + + org VEC_RESET + data initialize + + org >1000 +initialize: + mov %stack, B + ldsp + movp %CDS_RESET_gc, ACIA_control Master reset + movp %WSB_8N1_gc, ACIA_control 8 bits + No Parity + 1 Stop Bits + * Transmit, Receive interrupts disabled + + call @arith + idle + + *** Print out char + *** @param A char + *** @clobber A +putspace: + mov %' ', A + jmp putchar +newline: + mov %>0D, A + call @putchar + mov %>0A, A +putchar: + btjzp %TDRE_bm, ACIA_status, putchar + movp A, ACIA_data + rets + + *** Print "v1 op v2" + *** @param vA v1 + *** @param vB v2 + *** @param A op letter + *** @clobber Rd Rs +expr: + push A + movd vA, Rd + call @print_int16 print v1 + call @putspace + pop A + call @putchar print op + call @putspace + movd vB, Rd + call @print_int16 print v2 + movd vA, Rd + movd vB, Rs + rets + + *** Print " = v\n" + *** @param Rd v + *** @clobber Rd Rs +answer: + call @putspace + mov %'=', A + call @putchar + call @putspace + call @print_int16 print v + jmp newline + + *** Print "v1 rel v2" + *** @param R8:vA v1 + *** @param R10:vB v2 + *** @clobber Rd Rs +comp: + movd vA, Rd + movd vB, Rs + call @cmp16 + tsta + jeq comp_eq + jlt comp_lt + jgt comp_gt + mov %'?', A + jmp comp_out +comp_gt: + mov %'>', A + jmp comp_out +comp_eq: + mov %'=', A + jmp comp_out +comp_lt: + mov %'<', A +comp_out: + call @expr + jmp newline + +arith: + movd %18000, vA + movd %28000, vB + mov %'+', A + call @expr + call @add16 ; Rd=Rd+Rs + call @answer ; -19536 + + movd %18000, vA + movd %-18000, vB + mov %'+', A + call @expr + call @add16 ; Rd=Rd+Rs + call @answer ; 0 + + movd %-18000, vA + movd %-18000, vB + mov %'+', A + call @expr + call @add16 ; Rd=Rd+Rs + call @answer ; 29536 + + movd %-18000, vA + movd %-28000, vB + mov %'-', A + call @expr + call @sub16 ; Rd=Rd-Rs + call @answer ; 10000 + + movd %18000, vA + movd %-18000, vB + mov %'-', A + call @expr + call @sub16 ; Rd=Rd-Rs + call @answer ; 29536 + + movd %-28000, vA + movd %-18000, vB + mov %'-', A + call @expr + call @sub16 ; Rd=Rd-Rs + call @answer ; -10000 + + movd %100, vA + movd %300, vB + mov %'*', A + call @expr + call @mul16 ; Rd=Rd*Rs + call @answer ; 30000 + + movd %200, vA + movd %100, vB + mov %'*', A + call @expr + call @mul16 ; Rd=Rd*Rs + call @answer ; 20000 + + movd %300, vA + movd %-200, vB + mov %'*', A + call @expr + call @mul16 ; Rd=Rd*Rs + call @answer ; 5536 + + movd %100, vA + movd %-300, vB + mov %'*', A + call @expr + call @mul16 ; Rd=Rd*Rs + call @answer ; -30000 + + movd %-200, vA + movd %-100, vB + mov %'*', A + call @expr + call @mul16 ; Rd=Rd*Rs + call @answer ; 20000 + + movd %30000, vA + movd %100, vB + mov %'/', A + call @expr + call @div16 ; Rd=Rd/Rs + call @answer ; 300 + + movd %-200, vA + movd %100, vB + mov %'/', A + call @expr + call @div16 ; Rd=Rd/Rs + call @answer ; -2 + + movd %-30000, vA + movd %-200, vB + mov %'/', A + call @expr + call @div16 ; Rd=Rd/Rs + call @answer ; 150 + + movd %-30000, vA + movd %78, vB + mov %'/', A + call @expr + call @div16 ; Rd=Rd/Rs + call @answer ; -384 + + movd %5000, vA + movd %4000, vB + call @comp + + movd %5000, vA + movd %5000, vB + call @comp + + movd %4000, vA + movd %5000, vB + call @comp + + movd %-5000, vA + movd %-4000, vB + call @comp + + movd %-5000, vA + movd %-5000, vB + call @comp + + movd %-4000, vA + movd %-5000, vB + call @comp + + movd %32700, vA + movd %32600, vB + call @comp + + movd %32700, vA + movd %32700, vB + call @comp + + movd %32600, vA + movd %32700, vB + call @comp + + movd %-32700, vA + movd %-32600, vB + call @comp + + movd %-32700, vA + movd %-32700, vB + call @comp + + movd %-32600, vA + movd %-32700, vB + call @comp + + movd %18000, vA + movd %-28000, vB + call @comp + + movd %-28000, vA + movd %-28000, vB + call @comp + + movd %-28000, vA + movd %18000, vB + call @comp + rets + + include "arith.inc" diff --git a/samples/tms7000/arith.hex b/samples/tms7000/arith.hex new file mode 100644 index 00000000..48b39dce --- /dev/null +++ b/samples/tms7000/arith.hex @@ -0,0 +1,30 @@ +:2010000052600DA203F0A214F08E1070012220E007220D8E1018220AA702F0FC82F10AB8C3 +:201020009809058E12338E100DB98E10188E100D980B058E1233980905980B070A8E100DF2 +:20104000223D8E10188E100D8E1233E0C4980905980B078E1273B0E20CE10EE404223FE040 +:201060000A223EE006223DE002223C8E101FE0A188465009886D600B222B8E101F8E1265AD +:201080008E103D8846500988B9B00B222B8E101F8E12658E103D88B9B00988B9B00B222B25 +:2010A0008E101F8E12658E103D88B9B0098892A00B222D8E101F8E126C8E103D88465009BA +:2010C00088B9B00B222D8E101F8E126C8E103D8892A00988B9B00B222D8E101F8E126C8EBC +:2010E000103D8800640988012C0B222A8E101F8E12CC8E103D8800C8098800640B222A8E74 +:20110000101F8E12CC8E103D88012C0988FF380B222A8E101F8E12CC8E103D880064098804 +:20112000FED40B222A8E101F8E12CC8E103D88FF380988FF9C0B222A8E101F8E12CC8E1079 +:201140003D887530098800640B222F8E101F8E134C8E103D88FF38098800640B222F8E10A1 +:201160001F8E134C8E103D888AD00988FF380B222F8E101F8E134C8E103D888AD00988008A +:201180004E0B222F8E101F8E134C8E103D88138809880FA00B8E104D881388098813880B6D +:2011A0008E104D880FA0098813880B8E104D88EC780988F0600B8E104D88EC780988EC7847 +:2011C0000B8E104D88F0600988EC780B8E104D887FBC09887F580B8E104D887FBC09887F62 +:2011E000BC0B8E104D887F5809887FBC0B8E104D888044098880A80B8E104D888044098844 +:2012000080440B8E104D8880A8098880440B8E104D884650098892A00B8E104D8892A0097F +:201220008892A00B8E104D8892A0098846500B8E104D0A7780040F222D8E1018D404D4055D +:20124000D305E702D30412041405E21312041405E21288000A078E12FED8078E124CB924D0 +:20126000308C10180A4807054906040A4A07054B06040AD803D8029805034A07034B06021E +:2012800012021403E21612021504D0031204150613031502E1042201E00222FFD902D9030B +:2012A000B00AD803D80298050388000005E012B0DD06DD07E706480305490204B0DF03DF2C +:2012C0000212061407E6E8D902D9030A12041506B87780060AD406D407D307E702D3067792 +:2012E00080040AD404D405D305E702D3048E12A2B9E50AD404D405D305E702D3040A1206C2 +:201300001407E247D808720108E007B0DF07DF06D308778006F5D803D80288000003E00AD5 +:20132000B0DD06DD07B0DF03DF024A07054B0604E704D303E006480705490604DA08E1986F +:201340000507980305D902D903D9080A12041506B87780060AD406D407D307E702D3067787 +:1E13600080040AD404D405D305E702D3048E12FEB9E50AD404D405D305E702D3040AFF +:02FFFE001000F1 +:00000001FF diff --git a/samples/tms7000/arith.inc b/samples/tms7000/arith.inc new file mode 100644 index 00000000..71c66670 --- /dev/null +++ b/samples/tms7000/arith.inc @@ -0,0 +1,233 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + cpu tms7000 + + *** Print signed 16-bit integer as decimal + *** @param R4:R5 value + *** @clobber A R4:R5 R6:R7 +print_int16: + btjz %>80, R4, print_uint16 + mov %'-', A + call @putchar + inv R4 + inv R5 + inc R5 + jnc print_uint16 + inc R4 ; negate R4:R5 + *** Print unsigned 16-bit integer as decimal + *** @param R4:R5 value + *** @clobber A R4:R5 R6:R7 +print_uint16: + mov R4, A + or R5, A + jz print_uint16_zero +print_uint16_loop: + mov R4, A + or R5, A + jz print_uint16_end ; branch if value == 0 + movd %10, R7 ; R6:R7=10 + call @udiv16 ; R4:R5=value/10 + push R7 ; push reminder + call @print_uint16_loop + pop A +print_uint16_zero: + or %'0', A + br @putchar +print_uint16_end: + rets + + *** Addition: R4:R5 += R6:R7 +add16: + add R7, R5 + adc R6, R4 + rets + + *** Subtraction: R4:R5 -= R6:R7 +sub16: + sub R7, R5 + sbb R6, R4 + rets + + *** Signed compare A=sign(minuend-subtrahend) + *** @param R4:R5 minuend + *** @param R6:R7 subtrahend + *** @return A=0 JEQ (minuend == subtrahend) + *** A=1 JGT (minuend > subtrahend) + *** A=-1 JLT (minuend < subtrahend) + *** @clobber A +cmp16: + push R3 + push R2 + movd R5, R3 ; R2:R3=minuend + sub R7, R3 + sbb R6, R2 ; R2:R3=minuend-subtrahend + mov R2, A + or R3, A + jeq cmp16_end ; return with A=0 + mov R2, A ; A=hi(minuend-subtrahend) + xor R4, A ; A=hi((minuend-subtrahend)^minuend) + mov A, R3 ; R3=hi((minuend-subtrahend)^minuend) + mov R4, A ; A=hi(minuend) + xor R6, A ; A=hi(minuend^subtrahend) + and R3, A ; A=overflow flag + xor R2, A ; A=V^N + jn cmp16_lt ; branch if minuend < subtrahend +cmp16_gt: + mov %1, A + jmp cmp16_end +cmp16_lt: + mov %-1, A +cmp16_end: + pop R2 + pop R3 + tsta + rets + + *** Unsigned multiplication: result = multiplicand * multiplier + *** @param R4:R5 multiplicand + *** @param R6:R7 multiplier + *** @return R4:R5 result + *** @clobber A R4:R5 R6:R7 +umul16: + push R3 + push R2 + movd R5, R3 ; R2:R3=multiplicand + movd %0, R5 ; R4:R5=result=0 + jmp umul16_check +umul16_loop: + clrc + rrc R6 + rrc R7 ; multiplier >>= 1 + jnc umul16_next ; if lsb(multiplier) == 0 + add R3, R5 + adc R2, R4 ; result += multiplicand +umul16_next: + clrc + rlc R3 + rlc R2 ; multiplicand <<= 1 +umul16_check: + mov R6, A + or R7, A + jnz umul16_loop ; while multiplier != 0 +umul16_end: + pop R2 + pop R3 + rets + + *** Multiply: result = multiplicand * multiplier + *** @param R4:R5 multiplicand + *** @param R6:R7 multiplier + *** @return R4:R5 result + *** @clobber A R6:R7 +mul16: + mov R4, A + xor R6, A + push A ; save hi(multiplicand^multiplier) + btjz %>80, R6, mul16_multiplicand + inv R6 + inv R7 + inc R7 + jnc mul16_multiplicand + inc R6 ; negate multiplier +mul16_multiplicand: + btjz %>80, R4, mul16_multiply + inv R4 + inv R5 + inc R5 + jnc mul16_multiply + inc R4 ; negate multiplicand +mul16_multiply: + call @umul16 ; R4:R5=result + pop A ; A=(multiplicand^multiplier) + jpz mul16_end + inv R4 + inv R5 + inc R5 + jnc mul16_end + inc R4 ; negate result +mul16_end: + rets + + *** Unsigned division: dividend / divisor = quotient ... reminder + *** @praram R4:R5 dividend + *** @praram R6:R7 divisor + *** @return R4:R5 quotient + *** @return R6:R7 reminder + *** @clobber A +udiv16: + mov R6, A + or R7, A + jz udiv16_end ; branch if divisor==0 + push R8 + mov %1, R8 ; R8=bits + jmp udiv16_prep +udiv16_prep_loop: + clrc + rlc R7 + rlc R6 ; divisor <<= 1 + inc R8 ; ++bits +udiv16_prep: + btjz %>80, R6, udiv16_prep_loop ; while msb(divisor) == 0 + push R3 + push R2 + movd %0, R3 ; R2:R3=quotient=0 + jmp udiv16_enter_loop +udiv16_loop: + clrc + rrc R6 + rrc R7 ; divisor >>= 1 + clrc + rlc R3 + rlc R2 ; quotient <<= 1 +udiv16_enter_loop: + sub R7, R5 + sbb R6, R4 ; dividend -= divisor + jl udiv16_readd + inc R3 ; quotient |= 1 + jmp udiv16_next +udiv16_readd: + add R7, R5 + adc R6, R4 ; dividend += divisor +udiv16_next: + djnz R8, udiv16_loop ; while bits-- != 0 + movd R5, R7 ; R6:R7=reminder + movd R3, R5 ; R4:R5=quotient + pop R2 + pop R3 + pop R8 +udiv16_end: + rets + + *** Division: dividend / divisor = quotient ... reminder + *** @param R4:R5 dividend + *** @param R6:R7 divisor + *** @return R4:R5 quotient + *** @return R6:R7 reminder + *** @clobber A +div16: + mov R4, A + xor R6, A + push A ; save hi(dividend^divisor) + btjz %>80, R6, div16_dividend + inv R6 + inv R7 + inc R7 + jnc div16_dividend + inc R6 ; negate divisor +div16_dividend: + btjz %>80, R4, div16_divide + inv R4 + inv R5 + inc R5 + jnc div16_divide + inc R4 +div16_divide: + call @udiv16 ; R4:R5=quotient + pop A ; A=(dividend^divisor) + jpz div16_end + inv R4 + inv R5 + inc R5 + jnc div16_end + inc R4 ; negate quotient +div16_end: + rets diff --git a/samples/tms7000/arith.lst b/samples/tms7000/arith.lst new file mode 100644 index 00000000..98556b61 --- /dev/null +++ b/samples/tms7000/arith.lst @@ -0,0 +1,601 @@ + 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- + 0 : cpu tms7000 + 0 : include "tms7000.inc" +(1) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : *** TMS7000 +(1) 0 : *** Status Register +(1) 0 : =80 ST_CARRY: equ ?10000000 set to 1 if carry occurred +(1) 0 : =40 ST_NEGATIVE: equ ?01000000 set to 1 if result is negative +(1) 0 : =20 ST_ZERO: equ ?00100000 set to 1 if result is zero +(1) 0 : =10 ST_INT: equ ?00010000 if 1, interrupt is enabled +(1) 0 : *** Vector +(1) 0 : =FFF8 VEC_INT3: equ >FFF8 #INT3 interrupt +(1) 0 : =FFFA VEC_INT2: equ >FFFA Timer 1 +(1) 0 : =FFFC VEC_INT1: equ >FFFC #INT1 interrupt +(1) 0 : =FFFE VEC_RESET: equ >FFFE #RESET vector +(1) 0 : *** Trap Vector +(1) 0 : =FFFE VEC_TRAP0: equ VEC_RESET +(1) 0 : =FFFC VEC_TRAP1: equ VEC_INT1 +(1) 0 : =FFFA VEC_TRAP2: equ VEC_INT2 +(1) 0 : =FFF8 VEC_TRAP3: equ VEC_INT3 +(1) 0 : =FFF6 VEC_TRAP4: equ >FFF6 +(1) 0 : =FFF4 VEC_TRAP5: equ >FFF4 +(1) 0 : =FFF2 VEC_TRAP6: equ >FFF2 +(1) 0 : =FFF0 VEC_TRAP7: equ >FFF0 +(1) 0 : =FFEE VEC_TRAP8: equ >FFEE +(1) 0 : =FFEC VEC_TRAP9: equ >FFEC +(1) 0 : =FFEA VEC_TRAP10: equ >FFEA +(1) 0 : =FFE8 VEC_TRAP11: equ >FFE8 +(1) 0 : =FFE6 VEC_TRAP12: equ >FFE6 +(1) 0 : =FFE4 VEC_TRAP13: equ >FFE4 +(1) 0 : =FFE2 VEC_TRAP14: equ >FFE2 +(1) 0 : =FFE0 VEC_TRAP15: equ >FFE0 +(1) 0 : =FFDE VEC_TRAP16: equ >FFDE +(1) 0 : =FFDC VEC_TRAP17: equ >FFDC +(1) 0 : =FFDA VEC_TRAP18: equ >FFDA +(1) 0 : =FFD8 VEC_TRAP19: equ >FFD8 +(1) 0 : =FFD6 VEC_TRAP20: equ >FFD6 +(1) 0 : =FFD4 VEC_TRAP21: equ >FFD4 +(1) 0 : =FFD2 VEC_TRAP22: equ >FFD2 +(1) 0 : =FFD0 VEC_TRAP23: equ >FFD0 +(1) 0 : +(1) 0 : *** Internal Peripherals +(1) 0 : =100 IOCNT0: equ >0100 I/O Control register +(1) 0 : =20 INT3_F: equ ?100000 #INT3 flag +(1) 0 : =10 INT3_E: equ ?010000 #INT3 enable +(1) 0 : =8 INT2_F: equ ?001000 INT2 flag +(1) 0 : =4 INT2_E: equ ?000100 INT2 enable +(1) 0 : =2 INT1_F: equ ?000010 #INT1 flag +(1) 0 : =1 INT1_E: equ ?000001 #INT1 enable +(1) 0 : =102 T1DATA: equ >0102 Timer 1 data +(1) 0 : =103 T1CTL: equ >0103 Timer 1 control +(1) 0 : =104 APORT: equ >0104 Port A data +(1) 0 : =106 BPORT: equ >0106 Port B data +(1) 0 : =108 CPORT: equ >0108 Port C data +(1) 0 : =109 CDDR: equ >0109 Port C data direction register +(1) 0 : =10A DPORT: equ >010A Port D data +(1) 0 : =10B DDDR: equ >010B Port D data direction register +(1) 0 : +(1) 0 : *** Local Variables: +(1) 0 : *** comment-start: "*" +(1) 0 : *** End: + 0 : + 0 : *** MC6850 Asynchronous Communication Interface Adapter + 0 : =1F0 ACIA: equ >01F0 + 0 : include "mc6850.inc" +(1) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : *** MC6850 +(1) 0 : *** Asynchronous Communication Interface Adapter +(1) 0 : =1F0 ACIA_control: equ ACIA+0 +(1) 0 : =1F0 ACIA_status: equ ACIA+0 +(1) 0 : =1F1 ACIA_data: equ ACIA+1 +(1) 0 : ** Counter Divider Select Bits +(1) 0 : =3 CDS_gm: equ ?11 Group mask +(1) 0 : =0 CDS_DIV1_gc: equ ?00000000 /1 +(1) 0 : =0 CDS_DIV16_gc: equ ?00000001 /16 +(1) 0 : =0 CDS_DIV64_gc: equ ?00000010 /64 +(1) 0 : =3 CDS_RESET_gc: equ ?00000011 Master Reset +(1) 0 : ** Word Select Bits +(1) 0 : =1C WSB_gm: equ ?00011100 Group mask +(1) 0 : =0 WSB_7E2_gc: equ ?00000000 7 Bits + Even Parity + 2 Stop Bits +(1) 0 : =4 WSB_7O2_gc: equ ?00000100 7 bits + Odd Parity + 2 Stop Bits +(1) 0 : =8 WSB_7E1_gc: equ ?00001000 7 bits + Even Parity + 1 Stop Bits +(1) 0 : =C WSB_7O1_gc: equ ?00001100 7 bits + Odd Parity + 1 Stop Bits +(1) 0 : =10 WSB_8N2_gc: equ ?00010000 8 bits + No Parity + 2 Stop Bits +(1) 0 : =14 WSB_8N1_gc: equ ?00010100 8 bits + No Parity + 1 Stop Bits +(1) 0 : =18 WSB_8E1_gc: equ ?00011000 8 bits + Even Parity + 1 Stop Bits +(1) 0 : =1C WSB_8O1_gc: equ ?00011100 8 bits + Odd Parity + 1 Stop Bits +(1) 0 : ** Transmit Control Bits +(1) 0 : =60 TCB_gm: equ ?01100000 Group mask +(1) 0 : =0 TCB_DI_gc: equ ?00000000 RTS=Low, Tx Interrupt Disabled +(1) 0 : =20 TCB_EI_gc: equ ?00100000 RTS=Low, Tx Interrupt Enabled +(1) 0 : =40 TCB_RTS_gc: equ ?01000000 RTS=High, Tx Interrupt Disabled +(1) 0 : =60 TCB_BREAK_gc: equ ?01100000 RTS=Low, Tx Interrupt Disabled +(1) 0 : * Transmit Break Level +(1) 0 : =80 RIEB_bm: equ ?10000000 Receive Interrupt Enable Bit mask +(1) 0 : *** Status register +(1) 0 : =1 RDRF_bm: equ ?00000001 Receive Data Register Full +(1) 0 : =2 TDRE_bm: equ ?00000010 Transmit Data Register Empty +(1) 0 : =4 DCDF_bm: equ ?00000100 Data Carrier Detect Flag +(1) 0 : =8 CTSF_bm: equ ?00001000 Clear To Send Flag +(1) 0 : =10 FERR_bm: equ ?00010000 Frame Error Flag +(1) 0 : =20 OVRN_bm: equ ?00100000 Receiver Overrun Flag +(1) 0 : =40 PERR_bm: equ ?01000000 Parity Error Flag +(1) 0 : =80 IRQF_bm: equ ?10000000 Interrupt Request Flag + 0 : + 0 : *** Internal register file + 0 : =5 Rd: equ 5 R4:R5 + 0 : =7 Rs: equ 7 R6:R7 + 0 : =9 vA: equ 9 R8:R9 + 0 : =B vB: equ 11 R10:R11 + 0 : + 60 : org >60 + 60 : * TMS7000's SP is pre-increment/post-decrement + 60 : stack: + 60 : + FFFE : org VEC_RESET + FFFE : 10 00 data initialize + 10000 : + 1000 : org >1000 + 1000 : initialize: + 1000 : 52 60 mov %stack, B + 1002 : 0D ldsp + 1003 : A2 03 F0 movp %CDS_RESET_gc, ACIA_control Master reset + 1006 : A2 14 F0 movp %WSB_8N1_gc, ACIA_control 8 bits + No Parity + 1 Stop Bits + 1009 : * Transmit, Receive interrupts disabled + 1009 : + 1009 : 8E 10 70 call @arith + 100C : 01 idle + 100D : + 100D : *** Print out char + 100D : *** @param A char + 100D : *** @clobber A + 100D : putspace: + 100D : 22 20 mov %' ', A + 100F : E0 07 jmp putchar + 1011 : newline: + 1011 : 22 0D mov %>0D, A + 1013 : 8E 10 18 call @putchar + 1016 : 22 0A mov %>0A, A + 1018 : putchar: + 1018 : A7 02 F0 FC btjzp %TDRE_bm, ACIA_status, putchar + 101C : 82 F1 movp A, ACIA_data + 101E : 0A rets + 101F : + 101F : *** Print "v1 op v2" + 101F : *** @param vA v1 + 101F : *** @param vB v2 + 101F : *** @param A op letter + 101F : *** @clobber Rd Rs + 101F : expr: + 101F : B8 push A + 1020 : 98 09 05 movd vA, Rd + 1023 : 8E 12 33 call @print_int16 print v1 + 1026 : 8E 10 0D call @putspace + 1029 : B9 pop A + 102A : 8E 10 18 call @putchar print op + 102D : 8E 10 0D call @putspace + 1030 : 98 0B 05 movd vB, Rd + 1033 : 8E 12 33 call @print_int16 print v2 + 1036 : 98 09 05 movd vA, Rd + 1039 : 98 0B 07 movd vB, Rs + 103C : 0A rets + 103D : + 103D : *** Print " = v\n" + 103D : *** @param Rd v + 103D : *** @clobber Rd Rs + 103D : answer: + 103D : 8E 10 0D call @putspace + 1040 : 22 3D mov %'=', A + 1042 : 8E 10 18 call @putchar + 1045 : 8E 10 0D call @putspace + 1048 : 8E 12 33 call @print_int16 print v + 104B : E0 C4 jmp newline + 104D : + 104D : *** Print "v1 rel v2" + 104D : *** @param R8:vA v1 + 104D : *** @param R10:vB v2 + 104D : *** @clobber Rd Rs + 104D : comp: + 104D : 98 09 05 movd vA, Rd + 1050 : 98 0B 07 movd vB, Rs + 1053 : 8E 12 73 call @cmp16 + 1056 : B0 tsta + 1057 : E2 0C jeq comp_eq + 1059 : E1 0E jlt comp_lt + 105B : E4 04 jgt comp_gt + 105D : 22 3F mov %'?', A + 105F : E0 0A jmp comp_out + 1061 : comp_gt: + 1061 : 22 3E mov %'>', A + 1063 : E0 06 jmp comp_out + 1065 : comp_eq: + 1065 : 22 3D mov %'=', A + 1067 : E0 02 jmp comp_out + 1069 : comp_lt: + 1069 : 22 3C mov %'<', A + 106B : comp_out: + 106B : 8E 10 1F call @expr + 106E : E0 A1 jmp newline + 1070 : + 1070 : arith: + 1070 : 88 46 50 09 movd %18000, vA + 1074 : 88 6D 60 0B movd %28000, vB + 1078 : 22 2B mov %'+', A + 107A : 8E 10 1F call @expr + 107D : 8E 12 65 call @add16 ; Rd=Rd+Rs + 1080 : 8E 10 3D call @answer ; -19536 + 1083 : + 1083 : 88 46 50 09 movd %18000, vA + 1087 : 88 B9 B0 0B movd %-18000, vB + 108B : 22 2B mov %'+', A + 108D : 8E 10 1F call @expr + 1090 : 8E 12 65 call @add16 ; Rd=Rd+Rs + 1093 : 8E 10 3D call @answer ; 0 + 1096 : + 1096 : 88 B9 B0 09 movd %-18000, vA + 109A : 88 B9 B0 0B movd %-18000, vB + 109E : 22 2B mov %'+', A + 10A0 : 8E 10 1F call @expr + 10A3 : 8E 12 65 call @add16 ; Rd=Rd+Rs + 10A6 : 8E 10 3D call @answer ; 29536 + 10A9 : + 10A9 : 88 B9 B0 09 movd %-18000, vA + 10AD : 88 92 A0 0B movd %-28000, vB + 10B1 : 22 2D mov %'-', A + 10B3 : 8E 10 1F call @expr + 10B6 : 8E 12 6C call @sub16 ; Rd=Rd-Rs + 10B9 : 8E 10 3D call @answer ; 10000 + 10BC : + 10BC : 88 46 50 09 movd %18000, vA + 10C0 : 88 B9 B0 0B movd %-18000, vB + 10C4 : 22 2D mov %'-', A + 10C6 : 8E 10 1F call @expr + 10C9 : 8E 12 6C call @sub16 ; Rd=Rd-Rs + 10CC : 8E 10 3D call @answer ; 29536 + 10CF : + 10CF : 88 92 A0 09 movd %-28000, vA + 10D3 : 88 B9 B0 0B movd %-18000, vB + 10D7 : 22 2D mov %'-', A + 10D9 : 8E 10 1F call @expr + 10DC : 8E 12 6C call @sub16 ; Rd=Rd-Rs + 10DF : 8E 10 3D call @answer ; -10000 + 10E2 : + 10E2 : 88 00 64 09 movd %100, vA + 10E6 : 88 01 2C 0B movd %300, vB + 10EA : 22 2A mov %'*', A + 10EC : 8E 10 1F call @expr + 10EF : 8E 12 CC call @mul16 ; Rd=Rd*Rs + 10F2 : 8E 10 3D call @answer ; 30000 + 10F5 : + 10F5 : 88 00 C8 09 movd %200, vA + 10F9 : 88 00 64 0B movd %100, vB + 10FD : 22 2A mov %'*', A + 10FF : 8E 10 1F call @expr + 1102 : 8E 12 CC call @mul16 ; Rd=Rd*Rs + 1105 : 8E 10 3D call @answer ; 20000 + 1108 : + 1108 : 88 01 2C 09 movd %300, vA + 110C : 88 FF 38 0B movd %-200, vB + 1110 : 22 2A mov %'*', A + 1112 : 8E 10 1F call @expr + 1115 : 8E 12 CC call @mul16 ; Rd=Rd*Rs + 1118 : 8E 10 3D call @answer ; 5536 + 111B : + 111B : 88 00 64 09 movd %100, vA + 111F : 88 FE D4 0B movd %-300, vB + 1123 : 22 2A mov %'*', A + 1125 : 8E 10 1F call @expr + 1128 : 8E 12 CC call @mul16 ; Rd=Rd*Rs + 112B : 8E 10 3D call @answer ; -30000 + 112E : + 112E : 88 FF 38 09 movd %-200, vA + 1132 : 88 FF 9C 0B movd %-100, vB + 1136 : 22 2A mov %'*', A + 1138 : 8E 10 1F call @expr + 113B : 8E 12 CC call @mul16 ; Rd=Rd*Rs + 113E : 8E 10 3D call @answer ; 20000 + 1141 : + 1141 : 88 75 30 09 movd %30000, vA + 1145 : 88 00 64 0B movd %100, vB + 1149 : 22 2F mov %'/', A + 114B : 8E 10 1F call @expr + 114E : 8E 13 4C call @div16 ; Rd=Rd/Rs + 1151 : 8E 10 3D call @answer ; 300 + 1154 : + 1154 : 88 FF 38 09 movd %-200, vA + 1158 : 88 00 64 0B movd %100, vB + 115C : 22 2F mov %'/', A + 115E : 8E 10 1F call @expr + 1161 : 8E 13 4C call @div16 ; Rd=Rd/Rs + 1164 : 8E 10 3D call @answer ; -2 + 1167 : + 1167 : 88 8A D0 09 movd %-30000, vA + 116B : 88 FF 38 0B movd %-200, vB + 116F : 22 2F mov %'/', A + 1171 : 8E 10 1F call @expr + 1174 : 8E 13 4C call @div16 ; Rd=Rd/Rs + 1177 : 8E 10 3D call @answer ; 150 + 117A : + 117A : 88 8A D0 09 movd %-30000, vA + 117E : 88 00 4E 0B movd %78, vB + 1182 : 22 2F mov %'/', A + 1184 : 8E 10 1F call @expr + 1187 : 8E 13 4C call @div16 ; Rd=Rd/Rs + 118A : 8E 10 3D call @answer ; -384 + 118D : + 118D : 88 13 88 09 movd %5000, vA + 1191 : 88 0F A0 0B movd %4000, vB + 1195 : 8E 10 4D call @comp + 1198 : + 1198 : 88 13 88 09 movd %5000, vA + 119C : 88 13 88 0B movd %5000, vB + 11A0 : 8E 10 4D call @comp + 11A3 : + 11A3 : 88 0F A0 09 movd %4000, vA + 11A7 : 88 13 88 0B movd %5000, vB + 11AB : 8E 10 4D call @comp + 11AE : + 11AE : 88 EC 78 09 movd %-5000, vA + 11B2 : 88 F0 60 0B movd %-4000, vB + 11B6 : 8E 10 4D call @comp + 11B9 : + 11B9 : 88 EC 78 09 movd %-5000, vA + 11BD : 88 EC 78 0B movd %-5000, vB + 11C1 : 8E 10 4D call @comp + 11C4 : + 11C4 : 88 F0 60 09 movd %-4000, vA + 11C8 : 88 EC 78 0B movd %-5000, vB + 11CC : 8E 10 4D call @comp + 11CF : + 11CF : 88 7F BC 09 movd %32700, vA + 11D3 : 88 7F 58 0B movd %32600, vB + 11D7 : 8E 10 4D call @comp + 11DA : + 11DA : 88 7F BC 09 movd %32700, vA + 11DE : 88 7F BC 0B movd %32700, vB + 11E2 : 8E 10 4D call @comp + 11E5 : + 11E5 : 88 7F 58 09 movd %32600, vA + 11E9 : 88 7F BC 0B movd %32700, vB + 11ED : 8E 10 4D call @comp + 11F0 : + 11F0 : 88 80 44 09 movd %-32700, vA + 11F4 : 88 80 A8 0B movd %-32600, vB + 11F8 : 8E 10 4D call @comp + 11FB : + 11FB : 88 80 44 09 movd %-32700, vA + 11FF : 88 80 44 0B movd %-32700, vB + 1203 : 8E 10 4D call @comp + 1206 : + 1206 : 88 80 A8 09 movd %-32600, vA + 120A : 88 80 44 0B movd %-32700, vB + 120E : 8E 10 4D call @comp + 1211 : + 1211 : 88 46 50 09 movd %18000, vA + 1215 : 88 92 A0 0B movd %-28000, vB + 1219 : 8E 10 4D call @comp + 121C : + 121C : 88 92 A0 09 movd %-28000, vA + 1220 : 88 92 A0 0B movd %-28000, vB + 1224 : 8E 10 4D call @comp + 1227 : + 1227 : 88 92 A0 09 movd %-28000, vA + 122B : 88 46 50 0B movd %18000, vB + 122F : 8E 10 4D call @comp + 1232 : 0A rets + 1233 : + 1233 : include "arith.inc" +(1) 1233 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 1233 : cpu tms7000 +(1) 1233 : +(1) 1233 : *** Print signed 16-bit integer as decimal +(1) 1233 : *** @param R4:R5 value +(1) 1233 : *** @clobber A R4:R5 R6:R7 +(1) 1233 : print_int16: +(1) 1233 : 77 80 04 0F btjz %>80, R4, print_uint16 +(1) 1237 : 22 2D mov %'-', A +(1) 1239 : 8E 10 18 call @putchar +(1) 123C : D4 04 inv R4 +(1) 123E : D4 05 inv R5 +(1) 1240 : D3 05 inc R5 +(1) 1242 : E7 02 jnc print_uint16 +(1) 1244 : D3 04 inc R4 ; negate R4:R5 +(1) 1246 : *** Print unsigned 16-bit integer as decimal +(1) 1246 : *** @param R4:R5 value +(1) 1246 : *** @clobber A R4:R5 R6:R7 +(1) 1246 : print_uint16: +(1) 1246 : 12 04 mov R4, A +(1) 1248 : 14 05 or R5, A +(1) 124A : E2 13 jz print_uint16_zero +(1) 124C : print_uint16_loop: +(1) 124C : 12 04 mov R4, A +(1) 124E : 14 05 or R5, A +(1) 1250 : E2 12 jz print_uint16_end ; branch if value == 0 +(1) 1252 : 88 00 0A 07 movd %10, R7 ; R6:R7=10 +(1) 1256 : 8E 12 FE call @udiv16 ; R4:R5=value/10 +(1) 1259 : D8 07 push R7 ; push reminder +(1) 125B : 8E 12 4C call @print_uint16_loop +(1) 125E : B9 pop A +(1) 125F : print_uint16_zero: +(1) 125F : 24 30 or %'0', A +(1) 1261 : 8C 10 18 br @putchar +(1) 1264 : print_uint16_end: +(1) 1264 : 0A rets +(1) 1265 : +(1) 1265 : *** Addition: R4:R5 += R6:R7 +(1) 1265 : add16: +(1) 1265 : 48 07 05 add R7, R5 +(1) 1268 : 49 06 04 adc R6, R4 +(1) 126B : 0A rets +(1) 126C : +(1) 126C : *** Subtraction: R4:R5 -= R6:R7 +(1) 126C : sub16: +(1) 126C : 4A 07 05 sub R7, R5 +(1) 126F : 4B 06 04 sbb R6, R4 +(1) 1272 : 0A rets +(1) 1273 : +(1) 1273 : *** Signed compare A=sign(minuend-subtrahend) +(1) 1273 : *** @param R4:R5 minuend +(1) 1273 : *** @param R6:R7 subtrahend +(1) 1273 : *** @return A=0 JEQ (minuend == subtrahend) +(1) 1273 : *** A=1 JGT (minuend > subtrahend) +(1) 1273 : *** A=-1 JLT (minuend < subtrahend) +(1) 1273 : *** @clobber A +(1) 1273 : cmp16: +(1) 1273 : D8 03 push R3 +(1) 1275 : D8 02 push R2 +(1) 1277 : 98 05 03 movd R5, R3 ; R2:R3=minuend +(1) 127A : 4A 07 03 sub R7, R3 +(1) 127D : 4B 06 02 sbb R6, R2 ; R2:R3=minuend-subtrahend +(1) 1280 : 12 02 mov R2, A +(1) 1282 : 14 03 or R3, A +(1) 1284 : E2 16 jeq cmp16_end ; return with A=0 +(1) 1286 : 12 02 mov R2, A ; A=hi(minuend-subtrahend) +(1) 1288 : 15 04 xor R4, A ; A=hi((minuend-subtrahend)^minuend) +(1) 128A : D0 03 mov A, R3 ; R3=hi((minuend-subtrahend)^minuend) +(1) 128C : 12 04 mov R4, A ; A=hi(minuend) +(1) 128E : 15 06 xor R6, A ; A=hi(minuend^subtrahend) +(1) 1290 : 13 03 and R3, A ; A=overflow flag +(1) 1292 : 15 02 xor R2, A ; A=V^N +(1) 1294 : E1 04 jn cmp16_lt ; branch if minuend < subtrahend +(1) 1296 : cmp16_gt: +(1) 1296 : 22 01 mov %1, A +(1) 1298 : E0 02 jmp cmp16_end +(1) 129A : cmp16_lt: +(1) 129A : 22 FF mov %-1, A +(1) 129C : cmp16_end: +(1) 129C : D9 02 pop R2 +(1) 129E : D9 03 pop R3 +(1) 12A0 : B0 tsta +(1) 12A1 : 0A rets +(1) 12A2 : +(1) 12A2 : *** Unsigned multiplication: result = multiplicand * multiplier +(1) 12A2 : *** @param R4:R5 multiplicand +(1) 12A2 : *** @param R6:R7 multiplier +(1) 12A2 : *** @return R4:R5 result +(1) 12A2 : *** @clobber A R4:R5 R6:R7 +(1) 12A2 : umul16: +(1) 12A2 : D8 03 push R3 +(1) 12A4 : D8 02 push R2 +(1) 12A6 : 98 05 03 movd R5, R3 ; R2:R3=multiplicand +(1) 12A9 : 88 00 00 05 movd %0, R5 ; R4:R5=result=0 +(1) 12AD : E0 12 jmp umul16_check +(1) 12AF : umul16_loop: +(1) 12AF : B0 clrc +(1) 12B0 : DD 06 rrc R6 +(1) 12B2 : DD 07 rrc R7 ; multiplier >>= 1 +(1) 12B4 : E7 06 jnc umul16_next ; if lsb(multiplier) == 0 +(1) 12B6 : 48 03 05 add R3, R5 +(1) 12B9 : 49 02 04 adc R2, R4 ; result += multiplicand +(1) 12BC : umul16_next: +(1) 12BC : B0 clrc +(1) 12BD : DF 03 rlc R3 +(1) 12BF : DF 02 rlc R2 ; multiplicand <<= 1 +(1) 12C1 : umul16_check: +(1) 12C1 : 12 06 mov R6, A +(1) 12C3 : 14 07 or R7, A +(1) 12C5 : E6 E8 jnz umul16_loop ; while multiplier != 0 +(1) 12C7 : umul16_end: +(1) 12C7 : D9 02 pop R2 +(1) 12C9 : D9 03 pop R3 +(1) 12CB : 0A rets +(1) 12CC : +(1) 12CC : *** Multiply: result = multiplicand * multiplier +(1) 12CC : *** @param R4:R5 multiplicand +(1) 12CC : *** @param R6:R7 multiplier +(1) 12CC : *** @return R4:R5 result +(1) 12CC : *** @clobber A R6:R7 +(1) 12CC : mul16: +(1) 12CC : 12 04 mov R4, A +(1) 12CE : 15 06 xor R6, A +(1) 12D0 : B8 push A ; save hi(multiplicand^multiplier) +(1) 12D1 : 77 80 06 0A btjz %>80, R6, mul16_multiplicand +(1) 12D5 : D4 06 inv R6 +(1) 12D7 : D4 07 inv R7 +(1) 12D9 : D3 07 inc R7 +(1) 12DB : E7 02 jnc mul16_multiplicand +(1) 12DD : D3 06 inc R6 ; negate multiplier +(1) 12DF : mul16_multiplicand: +(1) 12DF : 77 80 04 0A btjz %>80, R4, mul16_multiply +(1) 12E3 : D4 04 inv R4 +(1) 12E5 : D4 05 inv R5 +(1) 12E7 : D3 05 inc R5 +(1) 12E9 : E7 02 jnc mul16_multiply +(1) 12EB : D3 04 inc R4 ; negate multiplicand +(1) 12ED : mul16_multiply: +(1) 12ED : 8E 12 A2 call @umul16 ; R4:R5=result +(1) 12F0 : B9 pop A ; A=(multiplicand^multiplier) +(1) 12F1 : E5 0A jpz mul16_end +(1) 12F3 : D4 04 inv R4 +(1) 12F5 : D4 05 inv R5 +(1) 12F7 : D3 05 inc R5 +(1) 12F9 : E7 02 jnc mul16_end +(1) 12FB : D3 04 inc R4 ; negate result +(1) 12FD : mul16_end: +(1) 12FD : 0A rets +(1) 12FE : +(1) 12FE : *** Unsigned division: dividend / divisor = quotient ... reminder +(1) 12FE : *** @praram R4:R5 dividend +(1) 12FE : *** @praram R6:R7 divisor +(1) 12FE : *** @return R4:R5 quotient +(1) 12FE : *** @return R6:R7 reminder +(1) 12FE : *** @clobber A +(1) 12FE : udiv16: +(1) 12FE : 12 06 mov R6, A +(1) 1300 : 14 07 or R7, A +(1) 1302 : E2 47 jz udiv16_end ; branch if divisor==0 +(1) 1304 : D8 08 push R8 +(1) 1306 : 72 01 08 mov %1, R8 ; R8=bits +(1) 1309 : E0 07 jmp udiv16_prep +(1) 130B : udiv16_prep_loop: +(1) 130B : B0 clrc +(1) 130C : DF 07 rlc R7 +(1) 130E : DF 06 rlc R6 ; divisor <<= 1 +(1) 1310 : D3 08 inc R8 ; ++bits +(1) 1312 : udiv16_prep: +(1) 1312 : 77 80 06 F5 btjz %>80, R6, udiv16_prep_loop ; while msb(divisor) == 0 +(1) 1316 : D8 03 push R3 +(1) 1318 : D8 02 push R2 +(1) 131A : 88 00 00 03 movd %0, R3 ; R2:R3=quotient=0 +(1) 131E : E0 0A jmp udiv16_enter_loop +(1) 1320 : udiv16_loop: +(1) 1320 : B0 clrc +(1) 1321 : DD 06 rrc R6 +(1) 1323 : DD 07 rrc R7 ; divisor >>= 1 +(1) 1325 : B0 clrc +(1) 1326 : DF 03 rlc R3 +(1) 1328 : DF 02 rlc R2 ; quotient <<= 1 +(1) 132A : udiv16_enter_loop: +(1) 132A : 4A 07 05 sub R7, R5 +(1) 132D : 4B 06 04 sbb R6, R4 ; dividend -= divisor +(1) 1330 : E7 04 jl udiv16_readd +(1) 1332 : D3 03 inc R3 ; quotient |= 1 +(1) 1334 : E0 06 jmp udiv16_next +(1) 1336 : udiv16_readd: +(1) 1336 : 48 07 05 add R7, R5 +(1) 1339 : 49 06 04 adc R6, R4 ; dividend += divisor +(1) 133C : udiv16_next: +(1) 133C : DA 08 E1 djnz R8, udiv16_loop ; while bits-- != 0 +(1) 133F : 98 05 07 movd R5, R7 ; R6:R7=reminder +(1) 1342 : 98 03 05 movd R3, R5 ; R4:R5=quotient +(1) 1345 : D9 02 pop R2 +(1) 1347 : D9 03 pop R3 +(1) 1349 : D9 08 pop R8 +(1) 134B : udiv16_end: +(1) 134B : 0A rets +(1) 134C : +(1) 134C : *** Division: dividend / divisor = quotient ... reminder +(1) 134C : *** @param R4:R5 dividend +(1) 134C : *** @param R6:R7 divisor +(1) 134C : *** @return R4:R5 quotient +(1) 134C : *** @return R6:R7 reminder +(1) 134C : *** @clobber A +(1) 134C : div16: +(1) 134C : 12 04 mov R4, A +(1) 134E : 15 06 xor R6, A +(1) 1350 : B8 push A ; save hi(dividend^divisor) +(1) 1351 : 77 80 06 0A btjz %>80, R6, div16_dividend +(1) 1355 : D4 06 inv R6 +(1) 1357 : D4 07 inv R7 +(1) 1359 : D3 07 inc R7 +(1) 135B : E7 02 jnc div16_dividend +(1) 135D : D3 06 inc R6 ; negate divisor +(1) 135F : div16_dividend: +(1) 135F : 77 80 04 0A btjz %>80, R4, div16_divide +(1) 1363 : D4 04 inv R4 +(1) 1365 : D4 05 inv R5 +(1) 1367 : D3 05 inc R5 +(1) 1369 : E7 02 jnc div16_divide +(1) 136B : D3 04 inc R4 +(1) 136D : div16_divide: +(1) 136D : 8E 12 FE call @udiv16 ; R4:R5=quotient +(1) 1370 : B9 pop A ; A=(dividend^divisor) +(1) 1371 : E5 0A jpz div16_end +(1) 1373 : D4 04 inv R4 +(1) 1375 : D4 05 inv R5 +(1) 1377 : D3 05 inc R5 +(1) 1379 : E7 02 jnc div16_end +(1) 137B : D3 04 inc R4 ; negate quotient +(1) 137D : div16_end: +(1) 137D : 0A rets diff --git a/samples/tms7000/echo.asm b/samples/tms7000/echo.asm new file mode 100644 index 00000000..9421c1c9 --- /dev/null +++ b/samples/tms7000/echo.asm @@ -0,0 +1,42 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + cpu tms7000 + include "tms7000.inc" + + *** MC6850 Asynchronous Communication Interface Adapter +ACIA: equ >01F0 + include "mc6850.inc" + + org VEC_RESET + data initialize + + org >1000 +initialize: + movp %CDS_RESET_gc, ACIA_control Master reset + movp %WSB_8N1_gc, ACIA_control 8 bits + No Parity + 1 Stop Bits + * Transmit, Receive interrupts disabled +loop: call @getchar + tsta + jeq halt_to_system +echo: call @putchar + cmp %>0D, A + jne loop + mov %>0A, A + jmp echo +halt_to_system: + idle + +getchar: + btjzp %RDRF_bm, ACIA_status, getchar + movp ACIA_data, A + rets + +putchar: + btjzp %TDRE_bm, ACIA_status, putchar + movp A, ACIA_data + rets + + *** Local Variables: + *** mode: asm + *** mode: flyspell-prog + *** comment-start: "*" + *** End: diff --git a/samples/tms7000/echo.hex b/samples/tms7000/echo.hex new file mode 100644 index 00000000..87c2bbc0 --- /dev/null +++ b/samples/tms7000/echo.hex @@ -0,0 +1,4 @@ +:20100000A203F0A214F08E1018B0E20B8E101F2D0DE6F3220AE0F501A701F0FC80F10AA7BA +:0610200002F0FC82F10A5F +:02FFFE001000F1 +:00000001FF diff --git a/samples/tms7000/echo.lst b/samples/tms7000/echo.lst new file mode 100644 index 00000000..27d7c9a3 --- /dev/null +++ b/samples/tms7000/echo.lst @@ -0,0 +1,139 @@ + 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- + 0 : cpu tms7000 + 0 : include "tms7000.inc" +(1) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : *** TMS7000 +(1) 0 : *** Status Register +(1) 0 : =80 ST_CARRY: equ ?10000000 set to 1 if carry occurred +(1) 0 : =40 ST_NEGATIVE: equ ?01000000 set to 1 if result is negative +(1) 0 : =20 ST_ZERO: equ ?00100000 set to 1 if result is zero +(1) 0 : =10 ST_INT: equ ?00010000 if 1, interrupt is enabled +(1) 0 : *** Vector +(1) 0 : =FFF8 VEC_INT3: equ >FFF8 #INT3 interrupt +(1) 0 : =FFFA VEC_INT2: equ >FFFA Timer 1 +(1) 0 : =FFFC VEC_INT1: equ >FFFC #INT1 interrupt +(1) 0 : =FFFE VEC_RESET: equ >FFFE #RESET vector +(1) 0 : *** Trap Vector +(1) 0 : =FFFE VEC_TRAP0: equ VEC_RESET +(1) 0 : =FFFC VEC_TRAP1: equ VEC_INT1 +(1) 0 : =FFFA VEC_TRAP2: equ VEC_INT2 +(1) 0 : =FFF8 VEC_TRAP3: equ VEC_INT3 +(1) 0 : =FFF6 VEC_TRAP4: equ >FFF6 +(1) 0 : =FFF4 VEC_TRAP5: equ >FFF4 +(1) 0 : =FFF2 VEC_TRAP6: equ >FFF2 +(1) 0 : =FFF0 VEC_TRAP7: equ >FFF0 +(1) 0 : =FFEE VEC_TRAP8: equ >FFEE +(1) 0 : =FFEC VEC_TRAP9: equ >FFEC +(1) 0 : =FFEA VEC_TRAP10: equ >FFEA +(1) 0 : =FFE8 VEC_TRAP11: equ >FFE8 +(1) 0 : =FFE6 VEC_TRAP12: equ >FFE6 +(1) 0 : =FFE4 VEC_TRAP13: equ >FFE4 +(1) 0 : =FFE2 VEC_TRAP14: equ >FFE2 +(1) 0 : =FFE0 VEC_TRAP15: equ >FFE0 +(1) 0 : =FFDE VEC_TRAP16: equ >FFDE +(1) 0 : =FFDC VEC_TRAP17: equ >FFDC +(1) 0 : =FFDA VEC_TRAP18: equ >FFDA +(1) 0 : =FFD8 VEC_TRAP19: equ >FFD8 +(1) 0 : =FFD6 VEC_TRAP20: equ >FFD6 +(1) 0 : =FFD4 VEC_TRAP21: equ >FFD4 +(1) 0 : =FFD2 VEC_TRAP22: equ >FFD2 +(1) 0 : =FFD0 VEC_TRAP23: equ >FFD0 +(1) 0 : +(1) 0 : *** Internal Peripherals +(1) 0 : =100 IOCNT0: equ >0100 I/O Control register +(1) 0 : =20 INT3_F: equ ?100000 #INT3 flag +(1) 0 : =10 INT3_E: equ ?010000 #INT3 enable +(1) 0 : =8 INT2_F: equ ?001000 INT2 flag +(1) 0 : =4 INT2_E: equ ?000100 INT2 enable +(1) 0 : =2 INT1_F: equ ?000010 #INT1 flag +(1) 0 : =1 INT1_E: equ ?000001 #INT1 enable +(1) 0 : =102 T1DATA: equ >0102 Timer 1 data +(1) 0 : =103 T1CTL: equ >0103 Timer 1 control +(1) 0 : =104 APORT: equ >0104 Port A data +(1) 0 : =106 BPORT: equ >0106 Port B data +(1) 0 : =108 CPORT: equ >0108 Port C data +(1) 0 : =109 CDDR: equ >0109 Port C data direction register +(1) 0 : =10A DPORT: equ >010A Port D data +(1) 0 : =10B DDDR: equ >010B Port D data direction register +(1) 0 : +(1) 0 : *** Local Variables: +(1) 0 : *** comment-start: "*" +(1) 0 : *** End: + 0 : + 0 : *** MC6850 Asynchronous Communication Interface Adapter + 0 : =1F0 ACIA: equ >01F0 + 0 : include "mc6850.inc" +(1) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : *** MC6850 +(1) 0 : *** Asynchronous Communication Interface Adapter +(1) 0 : =1F0 ACIA_control: equ ACIA+0 +(1) 0 : =1F0 ACIA_status: equ ACIA+0 +(1) 0 : =1F1 ACIA_data: equ ACIA+1 +(1) 0 : ** Counter Divider Select Bits +(1) 0 : =3 CDS_gm: equ ?11 Group mask +(1) 0 : =0 CDS_DIV1_gc: equ ?00000000 /1 +(1) 0 : =0 CDS_DIV16_gc: equ ?00000001 /16 +(1) 0 : =0 CDS_DIV64_gc: equ ?00000010 /64 +(1) 0 : =3 CDS_RESET_gc: equ ?00000011 Master Reset +(1) 0 : ** Word Select Bits +(1) 0 : =1C WSB_gm: equ ?00011100 Group mask +(1) 0 : =0 WSB_7E2_gc: equ ?00000000 7 Bits + Even Parity + 2 Stop Bits +(1) 0 : =4 WSB_7O2_gc: equ ?00000100 7 bits + Odd Parity + 2 Stop Bits +(1) 0 : =8 WSB_7E1_gc: equ ?00001000 7 bits + Even Parity + 1 Stop Bits +(1) 0 : =C WSB_7O1_gc: equ ?00001100 7 bits + Odd Parity + 1 Stop Bits +(1) 0 : =10 WSB_8N2_gc: equ ?00010000 8 bits + No Parity + 2 Stop Bits +(1) 0 : =14 WSB_8N1_gc: equ ?00010100 8 bits + No Parity + 1 Stop Bits +(1) 0 : =18 WSB_8E1_gc: equ ?00011000 8 bits + Even Parity + 1 Stop Bits +(1) 0 : =1C WSB_8O1_gc: equ ?00011100 8 bits + Odd Parity + 1 Stop Bits +(1) 0 : ** Transmit Control Bits +(1) 0 : =60 TCB_gm: equ ?01100000 Group mask +(1) 0 : =0 TCB_DI_gc: equ ?00000000 RTS=Low, Tx Interrupt Disabled +(1) 0 : =20 TCB_EI_gc: equ ?00100000 RTS=Low, Tx Interrupt Enabled +(1) 0 : =40 TCB_RTS_gc: equ ?01000000 RTS=High, Tx Interrupt Disabled +(1) 0 : =60 TCB_BREAK_gc: equ ?01100000 RTS=Low, Tx Interrupt Disabled +(1) 0 : * Transmit Break Level +(1) 0 : =80 RIEB_bm: equ ?10000000 Receive Interrupt Enable Bit mask +(1) 0 : *** Status register +(1) 0 : =1 RDRF_bm: equ ?00000001 Receive Data Register Full +(1) 0 : =2 TDRE_bm: equ ?00000010 Transmit Data Register Empty +(1) 0 : =4 DCDF_bm: equ ?00000100 Data Carrier Detect Flag +(1) 0 : =8 CTSF_bm: equ ?00001000 Clear To Send Flag +(1) 0 : =10 FERR_bm: equ ?00010000 Frame Error Flag +(1) 0 : =20 OVRN_bm: equ ?00100000 Receiver Overrun Flag +(1) 0 : =40 PERR_bm: equ ?01000000 Parity Error Flag +(1) 0 : =80 IRQF_bm: equ ?10000000 Interrupt Request Flag + 0 : + FFFE : org VEC_RESET + FFFE : 10 00 data initialize + 10000 : + 1000 : org >1000 + 1000 : initialize: + 1000 : A2 03 F0 movp %CDS_RESET_gc, ACIA_control Master reset + 1003 : A2 14 F0 movp %WSB_8N1_gc, ACIA_control 8 bits + No Parity + 1 Stop Bits + 1006 : * Transmit, Receive interrupts disabled + 1006 : 8E 10 18 loop: call @getchar + 1009 : B0 tsta + 100A : E2 0B jeq halt_to_system + 100C : 8E 10 1F echo: call @putchar + 100F : 2D 0D cmp %>0D, A + 1011 : E6 F3 jne loop + 1013 : 22 0A mov %>0A, A + 1015 : E0 F5 jmp echo + 1017 : halt_to_system: + 1017 : 01 idle + 1018 : + 1018 : getchar: + 1018 : A7 01 F0 FC btjzp %RDRF_bm, ACIA_status, getchar + 101C : 80 F1 movp ACIA_data, A + 101E : 0A rets + 101F : + 101F : putchar: + 101F : A7 02 F0 FC btjzp %TDRE_bm, ACIA_status, putchar + 1023 : 82 F1 movp A, ACIA_data + 1025 : 0A rets + 1026 : + 1026 : *** Local Variables: + 1026 : *** mode: asm + 1026 : *** mode: flyspell-prog + 1026 : *** comment-start: "*" + 1026 : *** End: diff --git a/samples/tms7000/echoir.asm b/samples/tms7000/echoir.asm new file mode 100644 index 00000000..b2165b3a --- /dev/null +++ b/samples/tms7000/echoir.asm @@ -0,0 +1,76 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + cpu tms7000 + include "tms7000.inc" + + *** MC6850 Asynchronous Communication Interface Adapter +ACIA: equ >01F0 + include "mc6850.inc" +RX_INT_TX_NO: equ WSB_8N1_gc|RIEB_bm + + org >2000 +rx_queue_size: equ 128 +rx_queue: bss rx_queue_size + + * Internal registers + org >60 + * TMS7000's SP is pre-increment/post-decrement +stack: + + org VEC_INT1 + data isr_int1 + + org VEC_RESET + data initialize + + org >1000 +initialize: + mov %stack, B + ldsp + movd %rx_queue, R3 + mov %rx_queue_size, B + call @queue_init + ** initialize ACIA + movp %CDS_RESET_gc, ACIA_control Master reset + movp %RX_INT_TX_NO, ACIA_control + movp %1, ACIA+2 #INT1 for Rx + movp %INT3_F|INT1_F|INT1_E, IOCNT0 enable #INT1 + +loop: + eint + movd %rx_queue, R3 + dint (clear all ST bits) + call @queue_remove + jnc loop + eint + tsta + jz halt_to_system + call @putchar + cmp %>0D, A + jne loop + mov %>0A, A + call @putchar + jmp loop +halt_to_system: + idle + +putchar: + btjzp %TDRE_bm, ACIA_status, putchar + movp A, ACIA_data + rets + + include "queue.inc" + +isr_int1: + btjzp %IRQF_bm, ACIA_status, isr_int1_return + btjzp %RDRF_bm, ACIA_status, isr_int1_return + push A + movp ACIA_data, A + push R2 + push R3 + movd %rx_queue, R3 + call @queue_add + pop R3 + pop R2 + pop A +isr_int1_return: + reti diff --git a/samples/tms7000/echoir.hex b/samples/tms7000/echoir.hex new file mode 100644 index 00000000..a244803d --- /dev/null +++ b/samples/tms7000/echoir.hex @@ -0,0 +1,9 @@ +:2010000052600D8820000352808E103DA203F0A294F0A201F2A223000588200003068E1050 +:2010200088E7F505B0E20E8E10362D0DE6EA220A8E1036E0E301A702F0FC82F10AB59B03A0 +:20104000622A04D3039B035A02D303B59B03D303CAFA0AB89A03D3039D03E702B90AB3D267 +:20106000039B03B9780203D803B89A032802480003B99B03D903B89A03B3D2039D03E7015C +:20108000B5D3039B03B9070A9A03E602B00AB29B03780303D8039A0328014800039A03D9EE +:2010A00003B89A03B37A02039D03E701B57802039B03B9070AA780F017A701F013B880F182 +:1110C000D802D803882000038E1053D903D902B90B53 +:04FFFC0010B510002C +:00000001FF diff --git a/samples/tms7000/echoir.lst b/samples/tms7000/echoir.lst new file mode 100644 index 00000000..7f7b8959 --- /dev/null +++ b/samples/tms7000/echoir.lst @@ -0,0 +1,274 @@ + 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- + 0 : cpu tms7000 + 0 : include "tms7000.inc" +(1) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : *** TMS7000 +(1) 0 : *** Status Register +(1) 0 : =80 ST_CARRY: equ ?10000000 set to 1 if carry occurred +(1) 0 : =40 ST_NEGATIVE: equ ?01000000 set to 1 if result is negative +(1) 0 : =20 ST_ZERO: equ ?00100000 set to 1 if result is zero +(1) 0 : =10 ST_INT: equ ?00010000 if 1, interrupt is enabled +(1) 0 : *** Vector +(1) 0 : =FFF8 VEC_INT3: equ >FFF8 #INT3 interrupt +(1) 0 : =FFFA VEC_INT2: equ >FFFA Timer 1 +(1) 0 : =FFFC VEC_INT1: equ >FFFC #INT1 interrupt +(1) 0 : =FFFE VEC_RESET: equ >FFFE #RESET vector +(1) 0 : *** Trap Vector +(1) 0 : =FFFE VEC_TRAP0: equ VEC_RESET +(1) 0 : =FFFC VEC_TRAP1: equ VEC_INT1 +(1) 0 : =FFFA VEC_TRAP2: equ VEC_INT2 +(1) 0 : =FFF8 VEC_TRAP3: equ VEC_INT3 +(1) 0 : =FFF6 VEC_TRAP4: equ >FFF6 +(1) 0 : =FFF4 VEC_TRAP5: equ >FFF4 +(1) 0 : =FFF2 VEC_TRAP6: equ >FFF2 +(1) 0 : =FFF0 VEC_TRAP7: equ >FFF0 +(1) 0 : =FFEE VEC_TRAP8: equ >FFEE +(1) 0 : =FFEC VEC_TRAP9: equ >FFEC +(1) 0 : =FFEA VEC_TRAP10: equ >FFEA +(1) 0 : =FFE8 VEC_TRAP11: equ >FFE8 +(1) 0 : =FFE6 VEC_TRAP12: equ >FFE6 +(1) 0 : =FFE4 VEC_TRAP13: equ >FFE4 +(1) 0 : =FFE2 VEC_TRAP14: equ >FFE2 +(1) 0 : =FFE0 VEC_TRAP15: equ >FFE0 +(1) 0 : =FFDE VEC_TRAP16: equ >FFDE +(1) 0 : =FFDC VEC_TRAP17: equ >FFDC +(1) 0 : =FFDA VEC_TRAP18: equ >FFDA +(1) 0 : =FFD8 VEC_TRAP19: equ >FFD8 +(1) 0 : =FFD6 VEC_TRAP20: equ >FFD6 +(1) 0 : =FFD4 VEC_TRAP21: equ >FFD4 +(1) 0 : =FFD2 VEC_TRAP22: equ >FFD2 +(1) 0 : =FFD0 VEC_TRAP23: equ >FFD0 +(1) 0 : +(1) 0 : *** Internal Peripherals +(1) 0 : =100 IOCNT0: equ >0100 I/O Control register +(1) 0 : =20 INT3_F: equ ?100000 #INT3 flag +(1) 0 : =10 INT3_E: equ ?010000 #INT3 enable +(1) 0 : =8 INT2_F: equ ?001000 INT2 flag +(1) 0 : =4 INT2_E: equ ?000100 INT2 enable +(1) 0 : =2 INT1_F: equ ?000010 #INT1 flag +(1) 0 : =1 INT1_E: equ ?000001 #INT1 enable +(1) 0 : =102 T1DATA: equ >0102 Timer 1 data +(1) 0 : =103 T1CTL: equ >0103 Timer 1 control +(1) 0 : =104 APORT: equ >0104 Port A data +(1) 0 : =106 BPORT: equ >0106 Port B data +(1) 0 : =108 CPORT: equ >0108 Port C data +(1) 0 : =109 CDDR: equ >0109 Port C data direction register +(1) 0 : =10A DPORT: equ >010A Port D data +(1) 0 : =10B DDDR: equ >010B Port D data direction register +(1) 0 : +(1) 0 : *** Local Variables: +(1) 0 : *** comment-start: "*" +(1) 0 : *** End: + 0 : + 0 : *** MC6850 Asynchronous Communication Interface Adapter + 0 : =1F0 ACIA: equ >01F0 + 0 : include "mc6850.inc" +(1) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : *** MC6850 +(1) 0 : *** Asynchronous Communication Interface Adapter +(1) 0 : =1F0 ACIA_control: equ ACIA+0 +(1) 0 : =1F0 ACIA_status: equ ACIA+0 +(1) 0 : =1F1 ACIA_data: equ ACIA+1 +(1) 0 : ** Counter Divider Select Bits +(1) 0 : =3 CDS_gm: equ ?11 Group mask +(1) 0 : =0 CDS_DIV1_gc: equ ?00000000 /1 +(1) 0 : =0 CDS_DIV16_gc: equ ?00000001 /16 +(1) 0 : =0 CDS_DIV64_gc: equ ?00000010 /64 +(1) 0 : =3 CDS_RESET_gc: equ ?00000011 Master Reset +(1) 0 : ** Word Select Bits +(1) 0 : =1C WSB_gm: equ ?00011100 Group mask +(1) 0 : =0 WSB_7E2_gc: equ ?00000000 7 Bits + Even Parity + 2 Stop Bits +(1) 0 : =4 WSB_7O2_gc: equ ?00000100 7 bits + Odd Parity + 2 Stop Bits +(1) 0 : =8 WSB_7E1_gc: equ ?00001000 7 bits + Even Parity + 1 Stop Bits +(1) 0 : =C WSB_7O1_gc: equ ?00001100 7 bits + Odd Parity + 1 Stop Bits +(1) 0 : =10 WSB_8N2_gc: equ ?00010000 8 bits + No Parity + 2 Stop Bits +(1) 0 : =14 WSB_8N1_gc: equ ?00010100 8 bits + No Parity + 1 Stop Bits +(1) 0 : =18 WSB_8E1_gc: equ ?00011000 8 bits + Even Parity + 1 Stop Bits +(1) 0 : =1C WSB_8O1_gc: equ ?00011100 8 bits + Odd Parity + 1 Stop Bits +(1) 0 : ** Transmit Control Bits +(1) 0 : =60 TCB_gm: equ ?01100000 Group mask +(1) 0 : =0 TCB_DI_gc: equ ?00000000 RTS=Low, Tx Interrupt Disabled +(1) 0 : =20 TCB_EI_gc: equ ?00100000 RTS=Low, Tx Interrupt Enabled +(1) 0 : =40 TCB_RTS_gc: equ ?01000000 RTS=High, Tx Interrupt Disabled +(1) 0 : =60 TCB_BREAK_gc: equ ?01100000 RTS=Low, Tx Interrupt Disabled +(1) 0 : * Transmit Break Level +(1) 0 : =80 RIEB_bm: equ ?10000000 Receive Interrupt Enable Bit mask +(1) 0 : *** Status register +(1) 0 : =1 RDRF_bm: equ ?00000001 Receive Data Register Full +(1) 0 : =2 TDRE_bm: equ ?00000010 Transmit Data Register Empty +(1) 0 : =4 DCDF_bm: equ ?00000100 Data Carrier Detect Flag +(1) 0 : =8 CTSF_bm: equ ?00001000 Clear To Send Flag +(1) 0 : =10 FERR_bm: equ ?00010000 Frame Error Flag +(1) 0 : =20 OVRN_bm: equ ?00100000 Receiver Overrun Flag +(1) 0 : =40 PERR_bm: equ ?01000000 Parity Error Flag +(1) 0 : =80 IRQF_bm: equ ?10000000 Interrupt Request Flag + 0 : =94 RX_INT_TX_NO: equ WSB_8N1_gc|RIEB_bm + 0 : + 2000 : org >2000 + 2000 : =80 rx_queue_size: equ 128 + 2000 : rx_queue: bss rx_queue_size + 2080 : + 2080 : * Internal registers + 60 : org >60 + 60 : * TMS7000's SP is pre-increment/post-decrement + 60 : stack: + 60 : + FFFC : org VEC_INT1 + FFFC : 10 B5 data isr_int1 + FFFE : + FFFE : org VEC_RESET + FFFE : 10 00 data initialize + 10000 : + 1000 : org >1000 + 1000 : initialize: + 1000 : 52 60 mov %stack, B + 1002 : 0D ldsp + 1003 : 88 20 00 03 movd %rx_queue, R3 + 1007 : 52 80 mov %rx_queue_size, B + 1009 : 8E 10 3D call @queue_init + 100C : ** initialize ACIA + 100C : A2 03 F0 movp %CDS_RESET_gc, ACIA_control Master reset + 100F : A2 94 F0 movp %RX_INT_TX_NO, ACIA_control + 1012 : A2 01 F2 movp %1, ACIA+2 #INT1 for Rx + 1015 : A2 23 00 movp %INT3_F|INT1_F|INT1_E, IOCNT0 enable #INT1 + 1018 : + 1018 : loop: + 1018 : 05 eint + 1019 : 88 20 00 03 movd %rx_queue, R3 + 101D : 06 dint (clear all ST bits) + 101E : 8E 10 88 call @queue_remove + 1021 : E7 F5 jnc loop + 1023 : 05 eint + 1024 : B0 tsta + 1025 : E2 0E jz halt_to_system + 1027 : 8E 10 36 call @putchar + 102A : 2D 0D cmp %>0D, A + 102C : E6 EA jne loop + 102E : 22 0A mov %>0A, A + 1030 : 8E 10 36 call @putchar + 1033 : E0 E3 jmp loop + 1035 : halt_to_system: + 1035 : 01 idle + 1036 : + 1036 : putchar: + 1036 : A7 02 F0 FC btjzp %TDRE_bm, ACIA_status, putchar + 103A : 82 F1 movp A, ACIA_data + 103C : 0A rets + 103D : + 103D : include "queue.inc" +(1) 103D : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 103D : *** [queue] queue structure +(1) 103D : =0 queue_len: equ 0 queue length +(1) 103D : =1 queue_size: equ 1 buffer size +(1) 103D : =2 queue_put: equ 2 queue put index +(1) 103D : =3 queue_get: equ 3 queue get index +(1) 103D : =4 queue_buf: equ 4 buffer start offset +(1) 103D : +(1) 103D : *** [queue] Initialize queue +(1) 103D : *** @param R2:R3 queue work space pointer +(1) 103D : *** @param B queue work space size +(1) 103D : *** @clobber A B R2:R3 +(1) 103D : queue_init: +(1) 103D : B5 clr A +(1) 103E : 9B 03 sta *R3 queue_len +(1) 1040 : 62 mov B, A +(1) 1041 : 2A 04 sub %queue_buf, A +(1) 1043 : D3 03 inc R3 +(1) 1045 : 9B 03 sta *R3 queue_size +(1) 1047 : 5A 02 sub %queue_put, B offset queue_len and queue_size +(1) 1049 : D3 03 inc R3 R2:R3=&queue_put +(1) 104B : B5 clr A +(1) 104C : queue_init_loop: +(1) 104C : 9B 03 sta *R3 +(1) 104E : D3 03 inc R3 +(1) 1050 : CA FA djnz B, queue_init_loop +(1) 1052 : 0A rets +(1) 1053 : +(1) 1053 : *** [queue] Add an element to queue +(1) 1053 : *** @param R2:R3 queue work space pointer +(1) 1053 : *** @param A an element +(1) 1053 : *** @return ST.C 0 if queue is full +(1) 1053 : *** @clobber R2:R3 +(1) 1053 : queue_add: +(1) 1053 : B8 push A +(1) 1054 : 9A 03 lda *R3 A=queue_len +(1) 1056 : D3 03 inc R3 R2:R3=&queue_size +(1) 1058 : 9D 03 cmpa *R3 +(1) 105A : E7 02 jl queue_add_element +(1) 105C : B9 pop A ST.C=0 +(1) 105D : 0A rets +(1) 105E : queue_add_element: +(1) 105E : B3 inc A +(1) 105F : D2 03 dec R3 +(1) 1061 : 9B 03 sta *R3 queue_len++ +(1) 1063 : B9 pop A +(1) 1064 : 78 02 03 add %queue_put-queue_len, R3 R2:R3=&queue_put +(1) 1067 : D8 03 push R3 +(1) 1069 : B8 push A +(1) 106A : 9A 03 lda *R3 A=queue_put +(1) 106C : 28 02 add %queue_buf-queue_put, A +(1) 106E : 48 00 03 add A, R3 R2:R3=&queue[queue_put] +(1) 1071 : B9 pop A +(1) 1072 : 9B 03 sta *R3 store element +(1) 1074 : D9 03 pop R3 R2:R3=&queue_put +(1) 1076 : B8 push A +(1) 1077 : 9A 03 lda *R3 +(1) 1079 : B3 inc A +(1) 107A : D2 03 dec R3 R2:R3=&queue_size +(1) 107C : 9D 03 cmpa *R3 +(1) 107E : E7 01 jl queue_add_return +(1) 1080 : B5 clr A wraparound +(1) 1081 : queue_add_return: +(1) 1081 : D3 03 inc R3 R2:R3=&queue_put +(1) 1083 : 9B 03 sta *R3 update queue_put +(1) 1085 : B9 pop A +(1) 1086 : 07 setc ST.C=1 +(1) 1087 : 0A rets +(1) 1088 : +(1) 1088 : *** [queue] Remove an element from queue +(1) 1088 : *** @param R2:R3 queue work space pointer +(1) 1088 : *** @return A an element +(1) 1088 : *** @return ST.C 0 if queue is empty +(1) 1088 : queue_remove: +(1) 1088 : 9A 03 lda *R3 A=queue_len +(1) 108A : E6 02 jnz queue_remove_elem +(1) 108C : B0 clrc +(1) 108D : 0A rets +(1) 108E : queue_remove_elem: +(1) 108E : B2 dec A +(1) 108F : 9B 03 sta *R3 queue_len-- +(1) 1091 : 78 03 03 add %queue_get-queue_len, R3 R2:R3=&queue_get +(1) 1094 : D8 03 push R3 +(1) 1096 : 9A 03 lda *R3 A=queue_get +(1) 1098 : 28 01 add %queue_buf-queue_get, A +(1) 109A : 48 00 03 add A, R3 R2:R3=&queue_buf[queue_get] +(1) 109D : 9A 03 lda *R3 remove element +(1) 109F : D9 03 pop R3 R2:R3=&queue_get +(1) 10A1 : B8 push A +(1) 10A2 : 9A 03 lda *R3 +(1) 10A4 : B3 inc A +(1) 10A5 : 7A 02 03 sub %queue_get-queue_size, R3 +(1) 10A8 : 9D 03 cmpa *R3 +(1) 10AA : E7 01 jl queue_remove_return +(1) 10AC : B5 clr A wraparound +(1) 10AD : queue_remove_return: +(1) 10AD : 78 02 03 add %queue_get-queue_size, R3 +(1) 10B0 : 9B 03 sta *R3 update queue_get +(1) 10B2 : B9 pop A +(1) 10B3 : 07 setc +(1) 10B4 : 0A rets + 10B5 : + 10B5 : isr_int1: + 10B5 : A7 80 F0 17 btjzp %IRQF_bm, ACIA_status, isr_int1_return + 10B9 : A7 01 F0 13 btjzp %RDRF_bm, ACIA_status, isr_int1_return + 10BD : B8 push A + 10BE : 80 F1 movp ACIA_data, A + 10C0 : D8 02 push R2 + 10C2 : D8 03 push R3 + 10C4 : 88 20 00 03 movd %rx_queue, R3 + 10C8 : 8E 10 53 call @queue_add + 10CB : D9 03 pop R3 + 10CD : D9 02 pop R2 + 10CF : B9 pop A + 10D0 : isr_int1_return: + 10D0 : 0B reti diff --git a/samples/tms7000/echoitr.asm b/samples/tms7000/echoitr.asm new file mode 100644 index 00000000..465b68ae --- /dev/null +++ b/samples/tms7000/echoitr.asm @@ -0,0 +1,170 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + cpu tms7000 + include "tms7000.inc" + + *** MC6850 Asynchronous Communication Interface Adapter +ACIA: equ >01F0 + include "mc6850.inc" +RX_INT_TX_NO: equ WSB_8N1_gc|RIEB_bm +RX_INT_TX_INT: equ WSB_8N1_gc|RIEB_bm|TCB_EI_gc + + org >2000 +rx_queue_size: equ 128 +rx_queue: bss rx_queue_size +tx_queue_size: equ 128 +tx_queue: bss tx_queue_size + + * Internal registers + org >60 + * TMS7000's SP is pre-increment/post-decrement +stack: + + org VEC_INT3 + data isr_int3 + + org VEC_RESET + data initialize + + org >1000 +initialize: + mov %stack, B + ldsp + movd %rx_queue, R3 + mov %rx_queue_size, B + call @queue_init + movd %tx_queue, R3 + mov %tx_queue_size, B + call @queue_init + ** initialize ACIA + movp %CDS_RESET_gc, ACIA_control Master reset + movp %RX_INT_TX_NO, ACIA_control + movp %3, ACIA+2 #INT3 for Rx/Tx + movp %INT3_F|INT3_E|INT1_F, IOCNT0 enable #INT1 and #INT3 + +loop: + call @getchar + jnc loop + tsta + jz halt_to_system + mov A, B + call @putchar echo + call @putspace + call @put_hex8 print in hex + call @putspace + call @put_bin8 print in binary + call @newline + jmp loop +halt_to_system: + idle + + *** Put sapce + *** @clobber A +putspace: + mov %' ', A + jmp putchar + + *** Put newline + *** @clobber A +newline: + mov %>0D, A + call @putchar + mov %>0A, A + jmp putchar + + *** Print uint8_t in hex + *** @param B uint8_t value to be printed in hex. + *** @clobber A +put_hex8: + mov %'0', A + call @putchar + mov %'x', A + call @putchar + mov B, A + swap A + call @put_hex4 + mov B, A +put_hex4: + and %>0F, A + cmp %10, A + jl put_hex8_dec + add %'A'-10-'0', A +put_hex8_dec: + add %'0', A + jmp putchar + + *** Print uint8_t in binary + *** @param B uint8_t value to be printed in binary. + *** @clobber A B +put_bin8: + mov %'0', A + call @putchar + mov %'b', A + call @putchar + call @put_bin4 +put_bin4: + call @put_bin2 +put_bin2: + call @put_bin1 +put_bin1: + mov %'0', A + rlc B + jnc putchar ; MSB=0 + inc A ; MSB=1 + jmp putchar + + *** Get character + *** @return A + *** @return ST.C 0 if no character + *** @clobber R2:R3 +getchar: + movd %rx_queue, R3 + dint + call @queue_remove + jnc getchar_empty + eint ST.C=1 + rets +getchar_empty: + eint ST.C=1 + clrc + rets + + *** Put character + *** @param A + *** @clobber R2:R3 +putchar: + eint + movd %tx_queue, R3 + dint + call @queue_add + jnc putchar + eint + movp %RX_INT_TX_INT, ACIA_control enable Tx interrupt + rets + + include "queue.inc" + +isr_int3: + btjzp %IRQF_bm, ACIA_status, isr_int3_return + push A + push R2 + push R3 + btjzp %RDRF_bm, ACIA_status, isr_tx + movp ACIA_data, A + movd %rx_queue, R3 + call @queue_add +isr_int3_exit: + pop R3 + pop R2 + pop A +isr_int3_return: + reti +isr_tx: + btjzp %TDRE_bm, ACIA_status, isr_int3_exit + movd %tx_queue, R3 + call @queue_remove + jnc isr_tx_empty + movp A, ACIA_data send character + jmp isr_int3_exit +isr_tx_empty: + movp %RX_INT_TX_NO, ACIA_control disable Tx interrupt + jmp isr_int3_exit diff --git a/samples/tms7000/echoitr.hex b/samples/tms7000/echoitr.hex new file mode 100644 index 00000000..af01a1bf --- /dev/null +++ b/samples/tms7000/echoitr.hex @@ -0,0 +1,14 @@ +:2010000052600D8820000352808E10A28820800352808E10A2A203F0A294F0A203F2A232F1 +:20102000008E1083E7FBB0E215C08E10928E103F8E104C8E103F8E10688E1043E0E30122A5 +:2010400020E04F220D8E1092220AE04622308E109222788E109262B78E105C62230F2D0A66 +:20106000E70228072830E02A22308E109222628E10928E10758E10788E107B2230CFE71264 +:20108000B3E00F88200003068E10EDE702050A05B00A0588208003068E10B8E7F505A2B4F8 +:2010A000F00AB59B03622A04D3039B035A02D303B59B03D303CAFA0AB89A03D3039D03E704 +:2010C00002B90AB3D2039B03B9780203D803B89A032802480003B99B03D903B89A03B3D23D +:2010E000039D03E701B5D3039B03B9070A9A03E602B00AB29B03780303D8039A032801487C +:2011000000039A03D903B89A03B37A02039D03E701B57802039B03B9070AA780F017B8D8EC +:2011200002D803A701F00F80F1882000038E10B8D903D902B90BA702F0F6882080038E10E6 +:0C114000EDE70482F1E0E9A294F0E0E4A5 +:02FFF800111ADC +:02FFFE001000F1 +:00000001FF diff --git a/samples/tms7000/echoitr.lst b/samples/tms7000/echoitr.lst new file mode 100644 index 00000000..797afb50 --- /dev/null +++ b/samples/tms7000/echoitr.lst @@ -0,0 +1,368 @@ + 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- + 0 : cpu tms7000 + 0 : include "tms7000.inc" +(1) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : *** TMS7000 +(1) 0 : *** Status Register +(1) 0 : =80 ST_CARRY: equ ?10000000 set to 1 if carry occurred +(1) 0 : =40 ST_NEGATIVE: equ ?01000000 set to 1 if result is negative +(1) 0 : =20 ST_ZERO: equ ?00100000 set to 1 if result is zero +(1) 0 : =10 ST_INT: equ ?00010000 if 1, interrupt is enabled +(1) 0 : *** Vector +(1) 0 : =FFF8 VEC_INT3: equ >FFF8 #INT3 interrupt +(1) 0 : =FFFA VEC_INT2: equ >FFFA Timer 1 +(1) 0 : =FFFC VEC_INT1: equ >FFFC #INT1 interrupt +(1) 0 : =FFFE VEC_RESET: equ >FFFE #RESET vector +(1) 0 : *** Trap Vector +(1) 0 : =FFFE VEC_TRAP0: equ VEC_RESET +(1) 0 : =FFFC VEC_TRAP1: equ VEC_INT1 +(1) 0 : =FFFA VEC_TRAP2: equ VEC_INT2 +(1) 0 : =FFF8 VEC_TRAP3: equ VEC_INT3 +(1) 0 : =FFF6 VEC_TRAP4: equ >FFF6 +(1) 0 : =FFF4 VEC_TRAP5: equ >FFF4 +(1) 0 : =FFF2 VEC_TRAP6: equ >FFF2 +(1) 0 : =FFF0 VEC_TRAP7: equ >FFF0 +(1) 0 : =FFEE VEC_TRAP8: equ >FFEE +(1) 0 : =FFEC VEC_TRAP9: equ >FFEC +(1) 0 : =FFEA VEC_TRAP10: equ >FFEA +(1) 0 : =FFE8 VEC_TRAP11: equ >FFE8 +(1) 0 : =FFE6 VEC_TRAP12: equ >FFE6 +(1) 0 : =FFE4 VEC_TRAP13: equ >FFE4 +(1) 0 : =FFE2 VEC_TRAP14: equ >FFE2 +(1) 0 : =FFE0 VEC_TRAP15: equ >FFE0 +(1) 0 : =FFDE VEC_TRAP16: equ >FFDE +(1) 0 : =FFDC VEC_TRAP17: equ >FFDC +(1) 0 : =FFDA VEC_TRAP18: equ >FFDA +(1) 0 : =FFD8 VEC_TRAP19: equ >FFD8 +(1) 0 : =FFD6 VEC_TRAP20: equ >FFD6 +(1) 0 : =FFD4 VEC_TRAP21: equ >FFD4 +(1) 0 : =FFD2 VEC_TRAP22: equ >FFD2 +(1) 0 : =FFD0 VEC_TRAP23: equ >FFD0 +(1) 0 : +(1) 0 : *** Internal Peripherals +(1) 0 : =100 IOCNT0: equ >0100 I/O Control register +(1) 0 : =20 INT3_F: equ ?100000 #INT3 flag +(1) 0 : =10 INT3_E: equ ?010000 #INT3 enable +(1) 0 : =8 INT2_F: equ ?001000 INT2 flag +(1) 0 : =4 INT2_E: equ ?000100 INT2 enable +(1) 0 : =2 INT1_F: equ ?000010 #INT1 flag +(1) 0 : =1 INT1_E: equ ?000001 #INT1 enable +(1) 0 : =102 T1DATA: equ >0102 Timer 1 data +(1) 0 : =103 T1CTL: equ >0103 Timer 1 control +(1) 0 : =104 APORT: equ >0104 Port A data +(1) 0 : =106 BPORT: equ >0106 Port B data +(1) 0 : =108 CPORT: equ >0108 Port C data +(1) 0 : =109 CDDR: equ >0109 Port C data direction register +(1) 0 : =10A DPORT: equ >010A Port D data +(1) 0 : =10B DDDR: equ >010B Port D data direction register +(1) 0 : +(1) 0 : *** Local Variables: +(1) 0 : *** comment-start: "*" +(1) 0 : *** End: + 0 : + 0 : *** MC6850 Asynchronous Communication Interface Adapter + 0 : =1F0 ACIA: equ >01F0 + 0 : include "mc6850.inc" +(1) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : *** MC6850 +(1) 0 : *** Asynchronous Communication Interface Adapter +(1) 0 : =1F0 ACIA_control: equ ACIA+0 +(1) 0 : =1F0 ACIA_status: equ ACIA+0 +(1) 0 : =1F1 ACIA_data: equ ACIA+1 +(1) 0 : ** Counter Divider Select Bits +(1) 0 : =3 CDS_gm: equ ?11 Group mask +(1) 0 : =0 CDS_DIV1_gc: equ ?00000000 /1 +(1) 0 : =0 CDS_DIV16_gc: equ ?00000001 /16 +(1) 0 : =0 CDS_DIV64_gc: equ ?00000010 /64 +(1) 0 : =3 CDS_RESET_gc: equ ?00000011 Master Reset +(1) 0 : ** Word Select Bits +(1) 0 : =1C WSB_gm: equ ?00011100 Group mask +(1) 0 : =0 WSB_7E2_gc: equ ?00000000 7 Bits + Even Parity + 2 Stop Bits +(1) 0 : =4 WSB_7O2_gc: equ ?00000100 7 bits + Odd Parity + 2 Stop Bits +(1) 0 : =8 WSB_7E1_gc: equ ?00001000 7 bits + Even Parity + 1 Stop Bits +(1) 0 : =C WSB_7O1_gc: equ ?00001100 7 bits + Odd Parity + 1 Stop Bits +(1) 0 : =10 WSB_8N2_gc: equ ?00010000 8 bits + No Parity + 2 Stop Bits +(1) 0 : =14 WSB_8N1_gc: equ ?00010100 8 bits + No Parity + 1 Stop Bits +(1) 0 : =18 WSB_8E1_gc: equ ?00011000 8 bits + Even Parity + 1 Stop Bits +(1) 0 : =1C WSB_8O1_gc: equ ?00011100 8 bits + Odd Parity + 1 Stop Bits +(1) 0 : ** Transmit Control Bits +(1) 0 : =60 TCB_gm: equ ?01100000 Group mask +(1) 0 : =0 TCB_DI_gc: equ ?00000000 RTS=Low, Tx Interrupt Disabled +(1) 0 : =20 TCB_EI_gc: equ ?00100000 RTS=Low, Tx Interrupt Enabled +(1) 0 : =40 TCB_RTS_gc: equ ?01000000 RTS=High, Tx Interrupt Disabled +(1) 0 : =60 TCB_BREAK_gc: equ ?01100000 RTS=Low, Tx Interrupt Disabled +(1) 0 : * Transmit Break Level +(1) 0 : =80 RIEB_bm: equ ?10000000 Receive Interrupt Enable Bit mask +(1) 0 : *** Status register +(1) 0 : =1 RDRF_bm: equ ?00000001 Receive Data Register Full +(1) 0 : =2 TDRE_bm: equ ?00000010 Transmit Data Register Empty +(1) 0 : =4 DCDF_bm: equ ?00000100 Data Carrier Detect Flag +(1) 0 : =8 CTSF_bm: equ ?00001000 Clear To Send Flag +(1) 0 : =10 FERR_bm: equ ?00010000 Frame Error Flag +(1) 0 : =20 OVRN_bm: equ ?00100000 Receiver Overrun Flag +(1) 0 : =40 PERR_bm: equ ?01000000 Parity Error Flag +(1) 0 : =80 IRQF_bm: equ ?10000000 Interrupt Request Flag + 0 : =94 RX_INT_TX_NO: equ WSB_8N1_gc|RIEB_bm + 0 : =B4 RX_INT_TX_INT: equ WSB_8N1_gc|RIEB_bm|TCB_EI_gc + 0 : + 2000 : org >2000 + 2000 : =80 rx_queue_size: equ 128 + 2000 : rx_queue: bss rx_queue_size + 2080 : =80 tx_queue_size: equ 128 + 2080 : tx_queue: bss tx_queue_size + 2100 : + 2100 : * Internal registers + 60 : org >60 + 60 : * TMS7000's SP is pre-increment/post-decrement + 60 : stack: + 60 : + FFF8 : org VEC_INT3 + FFF8 : 11 1A data isr_int3 + FFFA : + FFFE : org VEC_RESET + FFFE : 10 00 data initialize + 10000 : + 1000 : org >1000 + 1000 : initialize: + 1000 : 52 60 mov %stack, B + 1002 : 0D ldsp + 1003 : 88 20 00 03 movd %rx_queue, R3 + 1007 : 52 80 mov %rx_queue_size, B + 1009 : 8E 10 A2 call @queue_init + 100C : 88 20 80 03 movd %tx_queue, R3 + 1010 : 52 80 mov %tx_queue_size, B + 1012 : 8E 10 A2 call @queue_init + 1015 : ** initialize ACIA + 1015 : A2 03 F0 movp %CDS_RESET_gc, ACIA_control Master reset + 1018 : A2 94 F0 movp %RX_INT_TX_NO, ACIA_control + 101B : A2 03 F2 movp %3, ACIA+2 #INT3 for Rx/Tx + 101E : A2 32 00 movp %INT3_F|INT3_E|INT1_F, IOCNT0 enable #INT1 and #INT3 + 1021 : + 1021 : loop: + 1021 : 8E 10 83 call @getchar + 1024 : E7 FB jnc loop + 1026 : B0 tsta + 1027 : E2 15 jz halt_to_system + 1029 : C0 mov A, B + 102A : 8E 10 92 call @putchar echo + 102D : 8E 10 3F call @putspace + 1030 : 8E 10 4C call @put_hex8 print in hex + 1033 : 8E 10 3F call @putspace + 1036 : 8E 10 68 call @put_bin8 print in binary + 1039 : 8E 10 43 call @newline + 103C : E0 E3 jmp loop + 103E : halt_to_system: + 103E : 01 idle + 103F : + 103F : *** Put sapce + 103F : *** @clobber A + 103F : putspace: + 103F : 22 20 mov %' ', A + 1041 : E0 4F jmp putchar + 1043 : + 1043 : *** Put newline + 1043 : *** @clobber A + 1043 : newline: + 1043 : 22 0D mov %>0D, A + 1045 : 8E 10 92 call @putchar + 1048 : 22 0A mov %>0A, A + 104A : E0 46 jmp putchar + 104C : + 104C : *** Print uint8_t in hex + 104C : *** @param B uint8_t value to be printed in hex. + 104C : *** @clobber A + 104C : put_hex8: + 104C : 22 30 mov %'0', A + 104E : 8E 10 92 call @putchar + 1051 : 22 78 mov %'x', A + 1053 : 8E 10 92 call @putchar + 1056 : 62 mov B, A + 1057 : B7 swap A + 1058 : 8E 10 5C call @put_hex4 + 105B : 62 mov B, A + 105C : put_hex4: + 105C : 23 0F and %>0F, A + 105E : 2D 0A cmp %10, A + 1060 : E7 02 jl put_hex8_dec + 1062 : 28 07 add %'A'-10-'0', A + 1064 : put_hex8_dec: + 1064 : 28 30 add %'0', A + 1066 : E0 2A jmp putchar + 1068 : + 1068 : *** Print uint8_t in binary + 1068 : *** @param B uint8_t value to be printed in binary. + 1068 : *** @clobber A B + 1068 : put_bin8: + 1068 : 22 30 mov %'0', A + 106A : 8E 10 92 call @putchar + 106D : 22 62 mov %'b', A + 106F : 8E 10 92 call @putchar + 1072 : 8E 10 75 call @put_bin4 + 1075 : put_bin4: + 1075 : 8E 10 78 call @put_bin2 + 1078 : put_bin2: + 1078 : 8E 10 7B call @put_bin1 + 107B : put_bin1: + 107B : 22 30 mov %'0', A + 107D : CF rlc B + 107E : E7 12 jnc putchar ; MSB=0 + 1080 : B3 inc A ; MSB=1 + 1081 : E0 0F jmp putchar + 1083 : + 1083 : *** Get character + 1083 : *** @return A + 1083 : *** @return ST.C 0 if no character + 1083 : *** @clobber R2:R3 + 1083 : getchar: + 1083 : 88 20 00 03 movd %rx_queue, R3 + 1087 : 06 dint + 1088 : 8E 10 ED call @queue_remove + 108B : E7 02 jnc getchar_empty + 108D : 05 eint ST.C=1 + 108E : 0A rets + 108F : getchar_empty: + 108F : 05 eint ST.C=1 + 1090 : B0 clrc + 1091 : 0A rets + 1092 : + 1092 : *** Put character + 1092 : *** @param A + 1092 : *** @clobber R2:R3 + 1092 : putchar: + 1092 : 05 eint + 1093 : 88 20 80 03 movd %tx_queue, R3 + 1097 : 06 dint + 1098 : 8E 10 B8 call @queue_add + 109B : E7 F5 jnc putchar + 109D : 05 eint + 109E : A2 B4 F0 movp %RX_INT_TX_INT, ACIA_control enable Tx interrupt + 10A1 : 0A rets + 10A2 : + 10A2 : include "queue.inc" +(1) 10A2 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 10A2 : *** [queue] queue structure +(1) 10A2 : =0 queue_len: equ 0 queue length +(1) 10A2 : =1 queue_size: equ 1 buffer size +(1) 10A2 : =2 queue_put: equ 2 queue put index +(1) 10A2 : =3 queue_get: equ 3 queue get index +(1) 10A2 : =4 queue_buf: equ 4 buffer start offset +(1) 10A2 : +(1) 10A2 : *** [queue] Initialize queue +(1) 10A2 : *** @param R2:R3 queue work space pointer +(1) 10A2 : *** @param B queue work space size +(1) 10A2 : *** @clobber A B R2:R3 +(1) 10A2 : queue_init: +(1) 10A2 : B5 clr A +(1) 10A3 : 9B 03 sta *R3 queue_len +(1) 10A5 : 62 mov B, A +(1) 10A6 : 2A 04 sub %queue_buf, A +(1) 10A8 : D3 03 inc R3 +(1) 10AA : 9B 03 sta *R3 queue_size +(1) 10AC : 5A 02 sub %queue_put, B offset queue_len and queue_size +(1) 10AE : D3 03 inc R3 R2:R3=&queue_put +(1) 10B0 : B5 clr A +(1) 10B1 : queue_init_loop: +(1) 10B1 : 9B 03 sta *R3 +(1) 10B3 : D3 03 inc R3 +(1) 10B5 : CA FA djnz B, queue_init_loop +(1) 10B7 : 0A rets +(1) 10B8 : +(1) 10B8 : *** [queue] Add an element to queue +(1) 10B8 : *** @param R2:R3 queue work space pointer +(1) 10B8 : *** @param A an element +(1) 10B8 : *** @return ST.C 0 if queue is full +(1) 10B8 : *** @clobber R2:R3 +(1) 10B8 : queue_add: +(1) 10B8 : B8 push A +(1) 10B9 : 9A 03 lda *R3 A=queue_len +(1) 10BB : D3 03 inc R3 R2:R3=&queue_size +(1) 10BD : 9D 03 cmpa *R3 +(1) 10BF : E7 02 jl queue_add_element +(1) 10C1 : B9 pop A ST.C=0 +(1) 10C2 : 0A rets +(1) 10C3 : queue_add_element: +(1) 10C3 : B3 inc A +(1) 10C4 : D2 03 dec R3 +(1) 10C6 : 9B 03 sta *R3 queue_len++ +(1) 10C8 : B9 pop A +(1) 10C9 : 78 02 03 add %queue_put-queue_len, R3 R2:R3=&queue_put +(1) 10CC : D8 03 push R3 +(1) 10CE : B8 push A +(1) 10CF : 9A 03 lda *R3 A=queue_put +(1) 10D1 : 28 02 add %queue_buf-queue_put, A +(1) 10D3 : 48 00 03 add A, R3 R2:R3=&queue[queue_put] +(1) 10D6 : B9 pop A +(1) 10D7 : 9B 03 sta *R3 store element +(1) 10D9 : D9 03 pop R3 R2:R3=&queue_put +(1) 10DB : B8 push A +(1) 10DC : 9A 03 lda *R3 +(1) 10DE : B3 inc A +(1) 10DF : D2 03 dec R3 R2:R3=&queue_size +(1) 10E1 : 9D 03 cmpa *R3 +(1) 10E3 : E7 01 jl queue_add_return +(1) 10E5 : B5 clr A wraparound +(1) 10E6 : queue_add_return: +(1) 10E6 : D3 03 inc R3 R2:R3=&queue_put +(1) 10E8 : 9B 03 sta *R3 update queue_put +(1) 10EA : B9 pop A +(1) 10EB : 07 setc ST.C=1 +(1) 10EC : 0A rets +(1) 10ED : +(1) 10ED : *** [queue] Remove an element from queue +(1) 10ED : *** @param R2:R3 queue work space pointer +(1) 10ED : *** @return A an element +(1) 10ED : *** @return ST.C 0 if queue is empty +(1) 10ED : queue_remove: +(1) 10ED : 9A 03 lda *R3 A=queue_len +(1) 10EF : E6 02 jnz queue_remove_elem +(1) 10F1 : B0 clrc +(1) 10F2 : 0A rets +(1) 10F3 : queue_remove_elem: +(1) 10F3 : B2 dec A +(1) 10F4 : 9B 03 sta *R3 queue_len-- +(1) 10F6 : 78 03 03 add %queue_get-queue_len, R3 R2:R3=&queue_get +(1) 10F9 : D8 03 push R3 +(1) 10FB : 9A 03 lda *R3 A=queue_get +(1) 10FD : 28 01 add %queue_buf-queue_get, A +(1) 10FF : 48 00 03 add A, R3 R2:R3=&queue_buf[queue_get] +(1) 1102 : 9A 03 lda *R3 remove element +(1) 1104 : D9 03 pop R3 R2:R3=&queue_get +(1) 1106 : B8 push A +(1) 1107 : 9A 03 lda *R3 +(1) 1109 : B3 inc A +(1) 110A : 7A 02 03 sub %queue_get-queue_size, R3 +(1) 110D : 9D 03 cmpa *R3 +(1) 110F : E7 01 jl queue_remove_return +(1) 1111 : B5 clr A wraparound +(1) 1112 : queue_remove_return: +(1) 1112 : 78 02 03 add %queue_get-queue_size, R3 +(1) 1115 : 9B 03 sta *R3 update queue_get +(1) 1117 : B9 pop A +(1) 1118 : 07 setc +(1) 1119 : 0A rets + 111A : + 111A : isr_int3: + 111A : A7 80 F0 17 btjzp %IRQF_bm, ACIA_status, isr_int3_return + 111E : B8 push A + 111F : D8 02 push R2 + 1121 : D8 03 push R3 + 1123 : A7 01 F0 0F btjzp %RDRF_bm, ACIA_status, isr_tx + 1127 : 80 F1 movp ACIA_data, A + 1129 : 88 20 00 03 movd %rx_queue, R3 + 112D : 8E 10 B8 call @queue_add + 1130 : isr_int3_exit: + 1130 : D9 03 pop R3 + 1132 : D9 02 pop R2 + 1134 : B9 pop A + 1135 : isr_int3_return: + 1135 : 0B reti + 1136 : isr_tx: + 1136 : A7 02 F0 F6 btjzp %TDRE_bm, ACIA_status, isr_int3_exit + 113A : 88 20 80 03 movd %tx_queue, R3 + 113E : 8E 10 ED call @queue_remove + 1141 : E7 04 jnc isr_tx_empty + 1143 : 82 F1 movp A, ACIA_data send character + 1145 : E0 E9 jmp isr_int3_exit + 1147 : isr_tx_empty: + 1147 : A2 94 F0 movp %RX_INT_TX_NO, ACIA_control disable Tx interrupt + 114A : E0 E4 jmp isr_int3_exit diff --git a/samples/tms7000/mandelbrot.asm b/samples/tms7000/mandelbrot.asm new file mode 100644 index 00000000..cec0f963 --- /dev/null +++ b/samples/tms7000/mandelbrot.asm @@ -0,0 +1,142 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + cpu tms7000 + include "tms7000.inc" + + *** MC6850 Asynchronous Communication Interface Adapter +ACIA: equ >01F0 + include "mc6850.inc" +RX_INT_TX_NO: equ WSB_8N1_gc|RIEB_bm +RX_INT_TX_INT: equ WSB_8N1_gc|RIEB_bm|TCB_EI_gc + + org >2000 +rx_queue_size: equ 128 +rx_queue: bss rx_queue_size +tx_queue_size: equ 128 +tx_queue: bss tx_queue_size + + * Internal registers + org >0004 +RdH: bss 1 +RdL: bss 1 +Rd: equ RdL ; R4:R5 +RsH: bss 1 +RsL: bss 1 +Rs: equ RsL ; R6:R7 + bss 1 +tmp: bss 1 + bss 1 +vC: bss 1 + bss 1 +vD: bss 1 + bss 1 +vA: bss 1 + bss 1 +vB: bss 1 + bss 1 +vP: bss 1 + bss 1 +vQ: bss 1 + bss 1 +vS: bss 1 +vTH bss 1 +vTL: bss 1 +vT: equ vTL +cF: equ 50 +vY: bss 1 +vX: bss 1 +vI: bss 1 + * TMS7000's SP is pre-increment/post-decrement +stack: + + org VEC_INT1 + data isr_int1 + + org VEC_RESET + data initialize + + org >1000 +initialize: + mov %stack, B + ldsp + movd %rx_queue, R3 + mov %rx_queue_size, B + call @queue_init + movd %tx_queue, R3 + mov %tx_queue_size, B + call @queue_init + ** initialize ACIA + movp %CDS_RESET_gc, ACIA_control Master reset + movp %RX_INT_TX_NO, ACIA_control + movp %1, ACIA+2 #INT1 for Rx/Tx + movp %INT3_F|INT1_E|INT1_F, IOCNT0 enable #INT1 and #INT1 + +loop: + call @mandelbrot + call @newline + jmp loop + + *** Get character + *** @return A + *** @return ST.C 0 if no character + *** @clobber R2:R3 +getchar: + movd %rx_queue, R3 + dint + call @queue_remove + jnc getchar_empty + eint ST.C=1 + rets +getchar_empty: + eint ST.C=1 + clrc + rets + + *** Put character + *** @param A + *** @clobber R2:R3 +putspace: + mov %' ', A + jmp putchar +newline: + mov %>0D, A + call @putchar + mov %>0A, A +putchar: + eint + movd %tx_queue, R3 + dint + call @queue_add + jnc putchar + eint + movp %RX_INT_TX_INT, ACIA_control enable Tx interrupt + rets + + include "mandelbrot.inc" + include "arith.inc" + include "queue.inc" + +isr_int1: + btjzp %IRQF_bm, ACIA_status, isr_int1_return + push A + push R2 + push R3 + btjzp %RDRF_bm, ACIA_status, isr_tx + movp ACIA_data, A + movd %rx_queue, R3 + call @queue_add +isr_int1_exit: + pop R3 + pop R2 + pop A +isr_int1_return: + reti +isr_tx: + btjzp %TDRE_bm, ACIA_status, isr_int1_exit + movd %tx_queue, R3 + call @queue_remove + jnc isr_tx_empty + movp A, ACIA_data send character + jmp isr_int1_exit +isr_tx_empty: + movp %RX_INT_TX_NO, ACIA_control disable Tx interrupt + jmp isr_int1_exit diff --git a/samples/tms7000/mandelbrot.bas b/samples/tms7000/mandelbrot.bas new file mode 100644 index 00000000..f7e1954b --- /dev/null +++ b/samples/tms7000/mandelbrot.bas @@ -0,0 +1,22 @@ +10 REM **************************** +20 REM * ASCII art Mandelbrot set * +30 REM **************************** +40 FOR Y=-12 TO 12 +50 FOR X=-49 TO 29 +60 CA=X*0.0458 +70 CB=Y*0.08333 +80 A=CA +90 B=CB +100 FOR I=0 TO 15 +110 T=A*A-B*B+CA +120 B=2*A*B+CB +130 A=T +140 IF (A*A+B*B)>4 THEN GOTO 180 +150 NEXT I +160 PRINT " "; +170 GOTO 200 +180 IF I>9 THEN I=I+7 +190 PRINT CHR$(48+I); +200 NEXT X +210 PRINT +220 NEXT Y diff --git a/samples/tms7000/mandelbrot.hex b/samples/tms7000/mandelbrot.hex new file mode 100644 index 00000000..0604d21b --- /dev/null +++ b/samples/tms7000/mandelbrot.hex @@ -0,0 +1,31 @@ +:20100000521D0D8820000352808E12F28820800352808E12F2A203F0A294F0A201F2A223A1 +:20102000008E106A8E103CE0F888200003068E133DE702050A05B00A2220E007220D8E10BA +:2010400043220A0588208003068E1308E7F505A2B4F00A8E1043223D8E10438E11A78C100E +:2010600038D504D005E502D4040A72F41A72CF1B121B8E10618800E5078E12408800640772 +:201080008E12C098050B980B0F121A8E10618801A0078E1240880064078E12C098050D98C6 +:2010A0000D11D51C981105880032078E12C0980515880032078E12409811174A05174B048A +:2010C000169811059811078E1240D804D805980F05980F078E1240D907D9064A07054B0663 +:2010E00004880032078E12C0480B05490A04D804D805980F059815078E1240D804D80598D2 +:201100000F059817078E1240880032078E12C0D907D906480705490604B0DF05DF04480DD2 +:2011200005490C04980511D905D90498050F880032078E12C09805139805078E1240D8040B +:20114000D805981105880032078E12C09805159805078E1240D907D90648070549060498AF +:2011600005191218E6137D0419E40ED31C7D101CE5038C10A42220E00A121C2D0AE1022846 +:201180000728308E10438E1029E704B0E60101D31B7D1E1BE5038C10708E103CD31A7D0DDC +:2011A0001AE5038C106D0A7780040F222D8E1043D404D405D305E702D30412041405E21373 +:2011C00012041405E21288000A078E1272D8078E11C0B924308C10430A4807054906040A5C +:2011E0004A07054B06040AD803D8029805034A07034B060212021403E21612021504D0031B +:201200001204150613031502E1042201E00222FFD902D903B00AD803D80298050388000017 +:2012200005E012B0DD06DD07E706480305490204B0DF03DF0212061407E6E8D902D9030A7F +:2012400012041506B87780060AD406D407D307E702D3067780040AD404D405D305E702D303 +:20126000048E1216B9E50AD404D405D305E702D3040A12061407E247D808720108E007B06B +:20128000DF07DF06D308778006F5D803D80288000003E00AB0DD06DD07B0DF03DF024A0751 +:2012A000054B0604E704D303E006480705490604DA08E1980507980305D902D903D9080ADD +:2012C00012041506B87780060AD406D407D307E702D3067780040AD404D405D305E702D383 +:2012E000048E1272B9E50AD404D405D305E702D3040AB59B03622A04D3039B035A02D30354 +:20130000B59B03D303CAFA0AB89A03D3039D03E702B90AB3D2039B03B9780203D803B89AD6 +:20132000032802480003B99B03D903B89A03B3D2039D03E701B5D3039B03B9070A9A03E627 +:2013400002B00AB29B03780303D8039A0328014800039A03D903B89A03B37A02039D03E790 +:2013600001B57802039B03B9070AA780F017B8D802D803A701F00F80F1882000038E1308CB +:1C138000D903D902B90BA702F0F6882080038E133DE70482F1E0E9A294F0E0E42D +:04FFFC00136A100074 +:00000001FF diff --git a/samples/tms7000/mandelbrot.inc b/samples/tms7000/mandelbrot.inc new file mode 100644 index 00000000..77a5548e --- /dev/null +++ b/samples/tms7000/mandelbrot.inc @@ -0,0 +1,203 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + cpu tms7000 + + *** Print variable: "A=variable " + *** @param Rd variable + *** @param A variable letter + *** @clobber A Rd Rs +print: + call @putchar print variable letter + mov %'=', A + call @putchar + call @print_int16 + br @putspace + + *** Sign extend + *** @param A 8-bit value + *** @return Rd signed extended 16-bit value +sex: + clr RdH + mov A, RdL + jpz sex_end + inv RdH +sex_end: + rets + +mandelbrot: + mov %-12, vY ; Y=-12 +loop_y: + mov %-49, vX ; X=-49 +loop_x: + mov vX, A + call @sex ; Rd=extend(X) + movd %229, Rs + call @mul16 ; Rd=X*229 + movd %100, Rs + call @div16 ; Rd=X*229/100 + movd Rd, vC ; C=X*229/100 + movd vC, vA ; A=C + mov vY, A + call @sex ; Rd=extend(Y) + movd %416, Rs + call @mul16 ; Rd=Y*416 + movd %100, Rs + call @div16 ; Rd=Y*416/100 + movd Rd, vD ; D=Y*416/100 + movd vD, vB ; B=D + clr vI ; I=0 + + ;; mov vY, A + ;; call @sex ; Rd=Y + ;; mov %'Y', A + ;; call @print + ;; mov vX, A + ;; call @sex ; Rd=X + ;; mov %'X', A + ;; call @print + ;; movd vC, Rd ; C + ;; mov %'C', A + ;; call @print + ;; movd vD, Rd ; D + ;; mov %'D', A + ;; call @print + ;; call @newline + +loop_i: + movd vB, Rd ; Rd=B + movd %cF, Rs + call @div16 ; Rd=B/F + movd Rd, vQ ; Q=B/F + movd %cF, Rs + call @mul16 ; Rd=Q*F + movd vB, vS ; S=B + sub RdL, vS + sbb RdH, vS-1 ; S=B-Q*F + movd vB, Rd + movd vB, Rs + call @mul16 ; Rd=B*B + push RdH + push RdL ; push B*B + movd vA, Rd + movd vA, Rs + call @mul16 ; Rd=A*A + pop RsL + pop RsH ; Rs=B*B + sub RsL, RdL + sbb RsH, RdH ; Rd=A*A-B*B + movd %cF, Rs + call @div16 ; Rd=(A*A-B*B)/F + add vC, RdL + adc vC-1, RdH ; Rd=(A*A-B*B)/F+C + push RdH + push RdL ; push (A*A-B*B)/F+C + movd vA, Rd + movd vQ, Rs + call @mul16 ; Rd=A*Q + push RdH + push RdL ; push A*Q + movd vA, Rd + movd vS, Rs + call @mul16 ; Rd=A*S + movd %cF, Rs + call @div16 ; Rd=A*S/F + pop RsL + pop RsH ; pop A*Q + add RsL, RdL + adc RsH, RdH ; Rd=A*Q+A*S/F + clrc + rlc RdL + rlc RdH ; Rd=2*(A*Q+A*S/F) + add vD, RdL + adc vD-1, RdH ; Rd=2*(A*Q+A*S/F)+D + movd Rd, vB ; B=2*(A*Q+A*S/F)+D + pop RdL + pop RdH ; pop (A*A-B*B)/F+C + movd Rd, vA ; A=(A*A-B*B)/F+C + movd %cF, Rs + call @div16 ; Rd=A/F + movd Rd, vP ; P=A/F + movd Rd, Rs + call @mul16 ; P*P + push RdH + push RdL ; push P*P + movd vB, Rd + movd %cF, Rs + call @div16 ; Rd=B/F + movd Rd, vQ ; Q=B/F + movd Rd, Rs + call @mul16 ; Q*Q + pop RsL + pop RsH ; pop P*P + add RsL, RdL + adc RsH, RdH ; Rd=Q*Q+P*P + movd Rd, vT ; T=Q*Q+P*P + + ;; call @putspace + ;; mov vI, A + ;; call @sex ; Rd=I + ;; mov %'I', A + ;; call @print + ;; movd vA, Rd ; A + ;; mov %'A', A + ;; call @print + ;; movd vB, Rd ; B + ;; mov %'B', A + ;; call @print + ;; movd vP, Rd ; P + ;; mov %'P', A + ;; call @print + ;; movd vQ, Rd ; Q + ;; mov %'Q', A + ;; call @print + ;; movd vT, Rd ; T + ;; mov %'T', A + ;; call @print + ;; call @newline + + mov vT-1, A + jnz print_i ; if hi(T)>0 + cmp %4, vT + jgt print_i ; if T>4 + inc vI ; I+=1 + cmp %16, vI + jpz print_space ; if I>=16 + br @loop_i ; if I<16 +print_space: + mov %' ', A + jmp print_char +print_i: + mov vI, A + cmp %10, A + jlt print_i2 ; if I<10 + add %'A'-'0'-10, A +print_i2: + add %'0', A +print_char: + ;; push A + ;; mov %'@', A + ;; call @putchar + ;; mov %'=', A + ;; call @putchar + ;; pop A + ;; call @putchar + ;; call @newline + + call @putchar + call @getchar + jnc next_x + tsta + jnz next_x + idle ; halt to system +next_x: + inc vX ; X+=1 + cmp %30, vX + jge next_y ; if X>=30 + br @loop_x ; if X<30 +next_y: + call @newline + inc vY ; Y+=1 + cmp %13, vY + jge mandelbrot_end ; if Y>=13 + br @loop_y ; if Y<13 +mandelbrot_end: + rets diff --git a/samples/tms7000/mandelbrot.lst b/samples/tms7000/mandelbrot.lst new file mode 100644 index 00000000..036d4b00 --- /dev/null +++ b/samples/tms7000/mandelbrot.lst @@ -0,0 +1,776 @@ + 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- + 0 : cpu tms7000 + 0 : include "tms7000.inc" +(1) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : *** TMS7000 +(1) 0 : *** Status Register +(1) 0 : =80 ST_CARRY: equ ?10000000 set to 1 if carry occurred +(1) 0 : =40 ST_NEGATIVE: equ ?01000000 set to 1 if result is negative +(1) 0 : =20 ST_ZERO: equ ?00100000 set to 1 if result is zero +(1) 0 : =10 ST_INT: equ ?00010000 if 1, interrupt is enabled +(1) 0 : *** Vector +(1) 0 : =FFF8 VEC_INT3: equ >FFF8 #INT3 interrupt +(1) 0 : =FFFA VEC_INT2: equ >FFFA Timer 1 +(1) 0 : =FFFC VEC_INT1: equ >FFFC #INT1 interrupt +(1) 0 : =FFFE VEC_RESET: equ >FFFE #RESET vector +(1) 0 : *** Trap Vector +(1) 0 : =FFFE VEC_TRAP0: equ VEC_RESET +(1) 0 : =FFFC VEC_TRAP1: equ VEC_INT1 +(1) 0 : =FFFA VEC_TRAP2: equ VEC_INT2 +(1) 0 : =FFF8 VEC_TRAP3: equ VEC_INT3 +(1) 0 : =FFF6 VEC_TRAP4: equ >FFF6 +(1) 0 : =FFF4 VEC_TRAP5: equ >FFF4 +(1) 0 : =FFF2 VEC_TRAP6: equ >FFF2 +(1) 0 : =FFF0 VEC_TRAP7: equ >FFF0 +(1) 0 : =FFEE VEC_TRAP8: equ >FFEE +(1) 0 : =FFEC VEC_TRAP9: equ >FFEC +(1) 0 : =FFEA VEC_TRAP10: equ >FFEA +(1) 0 : =FFE8 VEC_TRAP11: equ >FFE8 +(1) 0 : =FFE6 VEC_TRAP12: equ >FFE6 +(1) 0 : =FFE4 VEC_TRAP13: equ >FFE4 +(1) 0 : =FFE2 VEC_TRAP14: equ >FFE2 +(1) 0 : =FFE0 VEC_TRAP15: equ >FFE0 +(1) 0 : =FFDE VEC_TRAP16: equ >FFDE +(1) 0 : =FFDC VEC_TRAP17: equ >FFDC +(1) 0 : =FFDA VEC_TRAP18: equ >FFDA +(1) 0 : =FFD8 VEC_TRAP19: equ >FFD8 +(1) 0 : =FFD6 VEC_TRAP20: equ >FFD6 +(1) 0 : =FFD4 VEC_TRAP21: equ >FFD4 +(1) 0 : =FFD2 VEC_TRAP22: equ >FFD2 +(1) 0 : =FFD0 VEC_TRAP23: equ >FFD0 +(1) 0 : +(1) 0 : *** Internal Peripherals +(1) 0 : =100 IOCNT0: equ >0100 I/O Control register +(1) 0 : =20 INT3_F: equ ?100000 #INT3 flag +(1) 0 : =10 INT3_E: equ ?010000 #INT3 enable +(1) 0 : =8 INT2_F: equ ?001000 INT2 flag +(1) 0 : =4 INT2_E: equ ?000100 INT2 enable +(1) 0 : =2 INT1_F: equ ?000010 #INT1 flag +(1) 0 : =1 INT1_E: equ ?000001 #INT1 enable +(1) 0 : =102 T1DATA: equ >0102 Timer 1 data +(1) 0 : =103 T1CTL: equ >0103 Timer 1 control +(1) 0 : =104 APORT: equ >0104 Port A data +(1) 0 : =106 BPORT: equ >0106 Port B data +(1) 0 : =108 CPORT: equ >0108 Port C data +(1) 0 : =109 CDDR: equ >0109 Port C data direction register +(1) 0 : =10A DPORT: equ >010A Port D data +(1) 0 : =10B DDDR: equ >010B Port D data direction register +(1) 0 : +(1) 0 : *** Local Variables: +(1) 0 : *** comment-start: "*" +(1) 0 : *** End: + 0 : + 0 : *** MC6850 Asynchronous Communication Interface Adapter + 0 : =1F0 ACIA: equ >01F0 + 0 : include "mc6850.inc" +(1) 0 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 0 : *** MC6850 +(1) 0 : *** Asynchronous Communication Interface Adapter +(1) 0 : =1F0 ACIA_control: equ ACIA+0 +(1) 0 : =1F0 ACIA_status: equ ACIA+0 +(1) 0 : =1F1 ACIA_data: equ ACIA+1 +(1) 0 : ** Counter Divider Select Bits +(1) 0 : =3 CDS_gm: equ ?11 Group mask +(1) 0 : =0 CDS_DIV1_gc: equ ?00000000 /1 +(1) 0 : =0 CDS_DIV16_gc: equ ?00000001 /16 +(1) 0 : =0 CDS_DIV64_gc: equ ?00000010 /64 +(1) 0 : =3 CDS_RESET_gc: equ ?00000011 Master Reset +(1) 0 : ** Word Select Bits +(1) 0 : =1C WSB_gm: equ ?00011100 Group mask +(1) 0 : =0 WSB_7E2_gc: equ ?00000000 7 Bits + Even Parity + 2 Stop Bits +(1) 0 : =4 WSB_7O2_gc: equ ?00000100 7 bits + Odd Parity + 2 Stop Bits +(1) 0 : =8 WSB_7E1_gc: equ ?00001000 7 bits + Even Parity + 1 Stop Bits +(1) 0 : =C WSB_7O1_gc: equ ?00001100 7 bits + Odd Parity + 1 Stop Bits +(1) 0 : =10 WSB_8N2_gc: equ ?00010000 8 bits + No Parity + 2 Stop Bits +(1) 0 : =14 WSB_8N1_gc: equ ?00010100 8 bits + No Parity + 1 Stop Bits +(1) 0 : =18 WSB_8E1_gc: equ ?00011000 8 bits + Even Parity + 1 Stop Bits +(1) 0 : =1C WSB_8O1_gc: equ ?00011100 8 bits + Odd Parity + 1 Stop Bits +(1) 0 : ** Transmit Control Bits +(1) 0 : =60 TCB_gm: equ ?01100000 Group mask +(1) 0 : =0 TCB_DI_gc: equ ?00000000 RTS=Low, Tx Interrupt Disabled +(1) 0 : =20 TCB_EI_gc: equ ?00100000 RTS=Low, Tx Interrupt Enabled +(1) 0 : =40 TCB_RTS_gc: equ ?01000000 RTS=High, Tx Interrupt Disabled +(1) 0 : =60 TCB_BREAK_gc: equ ?01100000 RTS=Low, Tx Interrupt Disabled +(1) 0 : * Transmit Break Level +(1) 0 : =80 RIEB_bm: equ ?10000000 Receive Interrupt Enable Bit mask +(1) 0 : *** Status register +(1) 0 : =1 RDRF_bm: equ ?00000001 Receive Data Register Full +(1) 0 : =2 TDRE_bm: equ ?00000010 Transmit Data Register Empty +(1) 0 : =4 DCDF_bm: equ ?00000100 Data Carrier Detect Flag +(1) 0 : =8 CTSF_bm: equ ?00001000 Clear To Send Flag +(1) 0 : =10 FERR_bm: equ ?00010000 Frame Error Flag +(1) 0 : =20 OVRN_bm: equ ?00100000 Receiver Overrun Flag +(1) 0 : =40 PERR_bm: equ ?01000000 Parity Error Flag +(1) 0 : =80 IRQF_bm: equ ?10000000 Interrupt Request Flag + 0 : =94 RX_INT_TX_NO: equ WSB_8N1_gc|RIEB_bm + 0 : =B4 RX_INT_TX_INT: equ WSB_8N1_gc|RIEB_bm|TCB_EI_gc + 0 : + 2000 : org >2000 + 2000 : =80 rx_queue_size: equ 128 + 2000 : rx_queue: bss rx_queue_size + 2080 : =80 tx_queue_size: equ 128 + 2080 : tx_queue: bss tx_queue_size + 2100 : + 2100 : * Internal registers + 4 : org >0004 + 4 : RdH: bss 1 + 5 : RdL: bss 1 + 6 : =5 Rd: equ RdL ; R4:R5 + 6 : RsH: bss 1 + 7 : RsL: bss 1 + 8 : =7 Rs: equ RsL ; R6:R7 + 8 : bss 1 + 9 : tmp: bss 1 + A : bss 1 + B : vC: bss 1 + C : bss 1 + D : vD: bss 1 + E : bss 1 + F : vA: bss 1 + 10 : bss 1 + 11 : vB: bss 1 + 12 : bss 1 + 13 : vP: bss 1 + 14 : bss 1 + 15 : vQ: bss 1 + 16 : bss 1 + 17 : vS: bss 1 + 18 : vTH bss 1 + 19 : vTL: bss 1 + 1A : =19 vT: equ vTL + 1A : =32 cF: equ 50 + 1A : vY: bss 1 + 1B : vX: bss 1 + 1C : vI: bss 1 + 1D : * TMS7000's SP is pre-increment/post-decrement + 1D : stack: + 1D : + FFFC : org VEC_INT1 + FFFC : 13 6A data isr_int1 + FFFE : + FFFE : org VEC_RESET + FFFE : 10 00 data initialize + 10000 : + 1000 : org >1000 + 1000 : initialize: + 1000 : 52 1D mov %stack, B + 1002 : 0D ldsp + 1003 : 88 20 00 03 movd %rx_queue, R3 + 1007 : 52 80 mov %rx_queue_size, B + 1009 : 8E 12 F2 call @queue_init + 100C : 88 20 80 03 movd %tx_queue, R3 + 1010 : 52 80 mov %tx_queue_size, B + 1012 : 8E 12 F2 call @queue_init + 1015 : ** initialize ACIA + 1015 : A2 03 F0 movp %CDS_RESET_gc, ACIA_control Master reset + 1018 : A2 94 F0 movp %RX_INT_TX_NO, ACIA_control + 101B : A2 01 F2 movp %1, ACIA+2 #INT1 for Rx/Tx + 101E : A2 23 00 movp %INT3_F|INT1_E|INT1_F, IOCNT0 enable #INT1 and #INT1 + 1021 : + 1021 : loop: + 1021 : 8E 10 6A call @mandelbrot + 1024 : 8E 10 3C call @newline + 1027 : E0 F8 jmp loop + 1029 : + 1029 : *** Get character + 1029 : *** @return A + 1029 : *** @return ST.C 0 if no character + 1029 : *** @clobber R2:R3 + 1029 : getchar: + 1029 : 88 20 00 03 movd %rx_queue, R3 + 102D : 06 dint + 102E : 8E 13 3D call @queue_remove + 1031 : E7 02 jnc getchar_empty + 1033 : 05 eint ST.C=1 + 1034 : 0A rets + 1035 : getchar_empty: + 1035 : 05 eint ST.C=1 + 1036 : B0 clrc + 1037 : 0A rets + 1038 : + 1038 : *** Put character + 1038 : *** @param A + 1038 : *** @clobber R2:R3 + 1038 : putspace: + 1038 : 22 20 mov %' ', A + 103A : E0 07 jmp putchar + 103C : newline: + 103C : 22 0D mov %>0D, A + 103E : 8E 10 43 call @putchar + 1041 : 22 0A mov %>0A, A + 1043 : putchar: + 1043 : 05 eint + 1044 : 88 20 80 03 movd %tx_queue, R3 + 1048 : 06 dint + 1049 : 8E 13 08 call @queue_add + 104C : E7 F5 jnc putchar + 104E : 05 eint + 104F : A2 B4 F0 movp %RX_INT_TX_INT, ACIA_control enable Tx interrupt + 1052 : 0A rets + 1053 : + 1053 : include "mandelbrot.inc" +(1) 1053 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 1053 : cpu tms7000 +(1) 1053 : +(1) 1053 : *** Print variable: "A=variable " +(1) 1053 : *** @param Rd variable +(1) 1053 : *** @param A variable letter +(1) 1053 : *** @clobber A Rd Rs +(1) 1053 : print: +(1) 1053 : 8E 10 43 call @putchar print variable letter +(1) 1056 : 22 3D mov %'=', A +(1) 1058 : 8E 10 43 call @putchar +(1) 105B : 8E 11 A7 call @print_int16 +(1) 105E : 8C 10 38 br @putspace +(1) 1061 : +(1) 1061 : *** Sign extend +(1) 1061 : *** @param A 8-bit value +(1) 1061 : *** @return Rd signed extended 16-bit value +(1) 1061 : sex: +(1) 1061 : D5 04 clr RdH +(1) 1063 : D0 05 mov A, RdL +(1) 1065 : E5 02 jpz sex_end +(1) 1067 : D4 04 inv RdH +(1) 1069 : sex_end: +(1) 1069 : 0A rets +(1) 106A : +(1) 106A : mandelbrot: +(1) 106A : 72 F4 1A mov %-12, vY ; Y=-12 +(1) 106D : loop_y: +(1) 106D : 72 CF 1B mov %-49, vX ; X=-49 +(1) 1070 : loop_x: +(1) 1070 : 12 1B mov vX, A +(1) 1072 : 8E 10 61 call @sex ; Rd=extend(X) +(1) 1075 : 88 00 E5 07 movd %229, Rs +(1) 1079 : 8E 12 40 call @mul16 ; Rd=X*229 +(1) 107C : 88 00 64 07 movd %100, Rs +(1) 1080 : 8E 12 C0 call @div16 ; Rd=X*229/100 +(1) 1083 : 98 05 0B movd Rd, vC ; C=X*229/100 +(1) 1086 : 98 0B 0F movd vC, vA ; A=C +(1) 1089 : 12 1A mov vY, A +(1) 108B : 8E 10 61 call @sex ; Rd=extend(Y) +(1) 108E : 88 01 A0 07 movd %416, Rs +(1) 1092 : 8E 12 40 call @mul16 ; Rd=Y*416 +(1) 1095 : 88 00 64 07 movd %100, Rs +(1) 1099 : 8E 12 C0 call @div16 ; Rd=Y*416/100 +(1) 109C : 98 05 0D movd Rd, vD ; D=Y*416/100 +(1) 109F : 98 0D 11 movd vD, vB ; B=D +(1) 10A2 : D5 1C clr vI ; I=0 +(1) 10A4 : +(1) 10A4 : ;; mov vY, A +(1) 10A4 : ;; call @sex ; Rd=Y +(1) 10A4 : ;; mov %'Y', A +(1) 10A4 : ;; call @print +(1) 10A4 : ;; mov vX, A +(1) 10A4 : ;; call @sex ; Rd=X +(1) 10A4 : ;; mov %'X', A +(1) 10A4 : ;; call @print +(1) 10A4 : ;; movd vC, Rd ; C +(1) 10A4 : ;; mov %'C', A +(1) 10A4 : ;; call @print +(1) 10A4 : ;; movd vD, Rd ; D +(1) 10A4 : ;; mov %'D', A +(1) 10A4 : ;; call @print +(1) 10A4 : ;; call @newline +(1) 10A4 : +(1) 10A4 : loop_i: +(1) 10A4 : 98 11 05 movd vB, Rd ; Rd=B +(1) 10A7 : 88 00 32 07 movd %cF, Rs +(1) 10AB : 8E 12 C0 call @div16 ; Rd=B/F +(1) 10AE : 98 05 15 movd Rd, vQ ; Q=B/F +(1) 10B1 : 88 00 32 07 movd %cF, Rs +(1) 10B5 : 8E 12 40 call @mul16 ; Rd=Q*F +(1) 10B8 : 98 11 17 movd vB, vS ; S=B +(1) 10BB : 4A 05 17 sub RdL, vS +(1) 10BE : 4B 04 16 sbb RdH, vS-1 ; S=B-Q*F +(1) 10C1 : 98 11 05 movd vB, Rd +(1) 10C4 : 98 11 07 movd vB, Rs +(1) 10C7 : 8E 12 40 call @mul16 ; Rd=B*B +(1) 10CA : D8 04 push RdH +(1) 10CC : D8 05 push RdL ; push B*B +(1) 10CE : 98 0F 05 movd vA, Rd +(1) 10D1 : 98 0F 07 movd vA, Rs +(1) 10D4 : 8E 12 40 call @mul16 ; Rd=A*A +(1) 10D7 : D9 07 pop RsL +(1) 10D9 : D9 06 pop RsH ; Rs=B*B +(1) 10DB : 4A 07 05 sub RsL, RdL +(1) 10DE : 4B 06 04 sbb RsH, RdH ; Rd=A*A-B*B +(1) 10E1 : 88 00 32 07 movd %cF, Rs +(1) 10E5 : 8E 12 C0 call @div16 ; Rd=(A*A-B*B)/F +(1) 10E8 : 48 0B 05 add vC, RdL +(1) 10EB : 49 0A 04 adc vC-1, RdH ; Rd=(A*A-B*B)/F+C +(1) 10EE : D8 04 push RdH +(1) 10F0 : D8 05 push RdL ; push (A*A-B*B)/F+C +(1) 10F2 : 98 0F 05 movd vA, Rd +(1) 10F5 : 98 15 07 movd vQ, Rs +(1) 10F8 : 8E 12 40 call @mul16 ; Rd=A*Q +(1) 10FB : D8 04 push RdH +(1) 10FD : D8 05 push RdL ; push A*Q +(1) 10FF : 98 0F 05 movd vA, Rd +(1) 1102 : 98 17 07 movd vS, Rs +(1) 1105 : 8E 12 40 call @mul16 ; Rd=A*S +(1) 1108 : 88 00 32 07 movd %cF, Rs +(1) 110C : 8E 12 C0 call @div16 ; Rd=A*S/F +(1) 110F : D9 07 pop RsL +(1) 1111 : D9 06 pop RsH ; pop A*Q +(1) 1113 : 48 07 05 add RsL, RdL +(1) 1116 : 49 06 04 adc RsH, RdH ; Rd=A*Q+A*S/F +(1) 1119 : B0 clrc +(1) 111A : DF 05 rlc RdL +(1) 111C : DF 04 rlc RdH ; Rd=2*(A*Q+A*S/F) +(1) 111E : 48 0D 05 add vD, RdL +(1) 1121 : 49 0C 04 adc vD-1, RdH ; Rd=2*(A*Q+A*S/F)+D +(1) 1124 : 98 05 11 movd Rd, vB ; B=2*(A*Q+A*S/F)+D +(1) 1127 : D9 05 pop RdL +(1) 1129 : D9 04 pop RdH ; pop (A*A-B*B)/F+C +(1) 112B : 98 05 0F movd Rd, vA ; A=(A*A-B*B)/F+C +(1) 112E : 88 00 32 07 movd %cF, Rs +(1) 1132 : 8E 12 C0 call @div16 ; Rd=A/F +(1) 1135 : 98 05 13 movd Rd, vP ; P=A/F +(1) 1138 : 98 05 07 movd Rd, Rs +(1) 113B : 8E 12 40 call @mul16 ; P*P +(1) 113E : D8 04 push RdH +(1) 1140 : D8 05 push RdL ; push P*P +(1) 1142 : 98 11 05 movd vB, Rd +(1) 1145 : 88 00 32 07 movd %cF, Rs +(1) 1149 : 8E 12 C0 call @div16 ; Rd=B/F +(1) 114C : 98 05 15 movd Rd, vQ ; Q=B/F +(1) 114F : 98 05 07 movd Rd, Rs +(1) 1152 : 8E 12 40 call @mul16 ; Q*Q +(1) 1155 : D9 07 pop RsL +(1) 1157 : D9 06 pop RsH ; pop P*P +(1) 1159 : 48 07 05 add RsL, RdL +(1) 115C : 49 06 04 adc RsH, RdH ; Rd=Q*Q+P*P +(1) 115F : 98 05 19 movd Rd, vT ; T=Q*Q+P*P +(1) 1162 : +(1) 1162 : ;; call @putspace +(1) 1162 : ;; mov vI, A +(1) 1162 : ;; call @sex ; Rd=I +(1) 1162 : ;; mov %'I', A +(1) 1162 : ;; call @print +(1) 1162 : ;; movd vA, Rd ; A +(1) 1162 : ;; mov %'A', A +(1) 1162 : ;; call @print +(1) 1162 : ;; movd vB, Rd ; B +(1) 1162 : ;; mov %'B', A +(1) 1162 : ;; call @print +(1) 1162 : ;; movd vP, Rd ; P +(1) 1162 : ;; mov %'P', A +(1) 1162 : ;; call @print +(1) 1162 : ;; movd vQ, Rd ; Q +(1) 1162 : ;; mov %'Q', A +(1) 1162 : ;; call @print +(1) 1162 : ;; movd vT, Rd ; T +(1) 1162 : ;; mov %'T', A +(1) 1162 : ;; call @print +(1) 1162 : ;; call @newline +(1) 1162 : +(1) 1162 : 12 18 mov vT-1, A +(1) 1164 : E6 13 jnz print_i ; if hi(T)>0 +(1) 1166 : 7D 04 19 cmp %4, vT +(1) 1169 : E4 0E jgt print_i ; if T>4 +(1) 116B : D3 1C inc vI ; I+=1 +(1) 116D : 7D 10 1C cmp %16, vI +(1) 1170 : E5 03 jpz print_space ; if I>=16 +(1) 1172 : 8C 10 A4 br @loop_i ; if I<16 +(1) 1175 : print_space: +(1) 1175 : 22 20 mov %' ', A +(1) 1177 : E0 0A jmp print_char +(1) 1179 : print_i: +(1) 1179 : 12 1C mov vI, A +(1) 117B : 2D 0A cmp %10, A +(1) 117D : E1 02 jlt print_i2 ; if I<10 +(1) 117F : 28 07 add %'A'-'0'-10, A +(1) 1181 : print_i2: +(1) 1181 : 28 30 add %'0', A +(1) 1183 : print_char: +(1) 1183 : ;; push A +(1) 1183 : ;; mov %'@', A +(1) 1183 : ;; call @putchar +(1) 1183 : ;; mov %'=', A +(1) 1183 : ;; call @putchar +(1) 1183 : ;; pop A +(1) 1183 : ;; call @putchar +(1) 1183 : ;; call @newline +(1) 1183 : +(1) 1183 : 8E 10 43 call @putchar +(1) 1186 : 8E 10 29 call @getchar +(1) 1189 : E7 04 jnc next_x +(1) 118B : B0 tsta +(1) 118C : E6 01 jnz next_x +(1) 118E : 01 idle ; halt to system +(1) 118F : next_x: +(1) 118F : D3 1B inc vX ; X+=1 +(1) 1191 : 7D 1E 1B cmp %30, vX +(1) 1194 : E5 03 jge next_y ; if X>=30 +(1) 1196 : 8C 10 70 br @loop_x ; if X<30 +(1) 1199 : next_y: +(1) 1199 : 8E 10 3C call @newline +(1) 119C : D3 1A inc vY ; Y+=1 +(1) 119E : 7D 0D 1A cmp %13, vY +(1) 11A1 : E5 03 jge mandelbrot_end ; if Y>=13 +(1) 11A3 : 8C 10 6D br @loop_y ; if Y<13 +(1) 11A6 : mandelbrot_end: +(1) 11A6 : 0A rets + 11A7 : include "arith.inc" +(1) 11A7 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 11A7 : cpu tms7000 +(1) 11A7 : +(1) 11A7 : *** Print signed 16-bit integer as decimal +(1) 11A7 : *** @param R4:R5 value +(1) 11A7 : *** @clobber A R4:R5 R6:R7 +(1) 11A7 : print_int16: +(1) 11A7 : 77 80 04 0F btjz %>80, R4, print_uint16 +(1) 11AB : 22 2D mov %'-', A +(1) 11AD : 8E 10 43 call @putchar +(1) 11B0 : D4 04 inv R4 +(1) 11B2 : D4 05 inv R5 +(1) 11B4 : D3 05 inc R5 +(1) 11B6 : E7 02 jnc print_uint16 +(1) 11B8 : D3 04 inc R4 ; negate R4:R5 +(1) 11BA : *** Print unsigned 16-bit integer as decimal +(1) 11BA : *** @param R4:R5 value +(1) 11BA : *** @clobber A R4:R5 R6:R7 +(1) 11BA : print_uint16: +(1) 11BA : 12 04 mov R4, A +(1) 11BC : 14 05 or R5, A +(1) 11BE : E2 13 jz print_uint16_zero +(1) 11C0 : print_uint16_loop: +(1) 11C0 : 12 04 mov R4, A +(1) 11C2 : 14 05 or R5, A +(1) 11C4 : E2 12 jz print_uint16_end ; branch if value == 0 +(1) 11C6 : 88 00 0A 07 movd %10, R7 ; R6:R7=10 +(1) 11CA : 8E 12 72 call @udiv16 ; R4:R5=value/10 +(1) 11CD : D8 07 push R7 ; push reminder +(1) 11CF : 8E 11 C0 call @print_uint16_loop +(1) 11D2 : B9 pop A +(1) 11D3 : print_uint16_zero: +(1) 11D3 : 24 30 or %'0', A +(1) 11D5 : 8C 10 43 br @putchar +(1) 11D8 : print_uint16_end: +(1) 11D8 : 0A rets +(1) 11D9 : +(1) 11D9 : *** Addition: R4:R5 += R6:R7 +(1) 11D9 : add16: +(1) 11D9 : 48 07 05 add R7, R5 +(1) 11DC : 49 06 04 adc R6, R4 +(1) 11DF : 0A rets +(1) 11E0 : +(1) 11E0 : *** Subtraction: R4:R5 -= R6:R7 +(1) 11E0 : sub16: +(1) 11E0 : 4A 07 05 sub R7, R5 +(1) 11E3 : 4B 06 04 sbb R6, R4 +(1) 11E6 : 0A rets +(1) 11E7 : +(1) 11E7 : *** Signed compare A=sign(minuend-subtrahend) +(1) 11E7 : *** @param R4:R5 minuend +(1) 11E7 : *** @param R6:R7 subtrahend +(1) 11E7 : *** @return A=0 JEQ (minuend == subtrahend) +(1) 11E7 : *** A=1 JGT (minuend > subtrahend) +(1) 11E7 : *** A=-1 JLT (minuend < subtrahend) +(1) 11E7 : *** @clobber A +(1) 11E7 : cmp16: +(1) 11E7 : D8 03 push R3 +(1) 11E9 : D8 02 push R2 +(1) 11EB : 98 05 03 movd R5, R3 ; R2:R3=minuend +(1) 11EE : 4A 07 03 sub R7, R3 +(1) 11F1 : 4B 06 02 sbb R6, R2 ; R2:R3=minuend-subtrahend +(1) 11F4 : 12 02 mov R2, A +(1) 11F6 : 14 03 or R3, A +(1) 11F8 : E2 16 jeq cmp16_end ; return with A=0 +(1) 11FA : 12 02 mov R2, A ; A=hi(minuend-subtrahend) +(1) 11FC : 15 04 xor R4, A ; A=hi((minuend-subtrahend)^minuend) +(1) 11FE : D0 03 mov A, R3 ; R3=hi((minuend-subtrahend)^minuend) +(1) 1200 : 12 04 mov R4, A ; A=hi(minuend) +(1) 1202 : 15 06 xor R6, A ; A=hi(minuend^subtrahend) +(1) 1204 : 13 03 and R3, A ; A=overflow flag +(1) 1206 : 15 02 xor R2, A ; A=V^N +(1) 1208 : E1 04 jn cmp16_lt ; branch if minuend < subtrahend +(1) 120A : cmp16_gt: +(1) 120A : 22 01 mov %1, A +(1) 120C : E0 02 jmp cmp16_end +(1) 120E : cmp16_lt: +(1) 120E : 22 FF mov %-1, A +(1) 1210 : cmp16_end: +(1) 1210 : D9 02 pop R2 +(1) 1212 : D9 03 pop R3 +(1) 1214 : B0 tsta +(1) 1215 : 0A rets +(1) 1216 : +(1) 1216 : *** Unsigned multiplication: result = multiplicand * multiplier +(1) 1216 : *** @param R4:R5 multiplicand +(1) 1216 : *** @param R6:R7 multiplier +(1) 1216 : *** @return R4:R5 result +(1) 1216 : *** @clobber A R4:R5 R6:R7 +(1) 1216 : umul16: +(1) 1216 : D8 03 push R3 +(1) 1218 : D8 02 push R2 +(1) 121A : 98 05 03 movd R5, R3 ; R2:R3=multiplicand +(1) 121D : 88 00 00 05 movd %0, R5 ; R4:R5=result=0 +(1) 1221 : E0 12 jmp umul16_check +(1) 1223 : umul16_loop: +(1) 1223 : B0 clrc +(1) 1224 : DD 06 rrc R6 +(1) 1226 : DD 07 rrc R7 ; multiplier >>= 1 +(1) 1228 : E7 06 jnc umul16_next ; if lsb(multiplier) == 0 +(1) 122A : 48 03 05 add R3, R5 +(1) 122D : 49 02 04 adc R2, R4 ; result += multiplicand +(1) 1230 : umul16_next: +(1) 1230 : B0 clrc +(1) 1231 : DF 03 rlc R3 +(1) 1233 : DF 02 rlc R2 ; multiplicand <<= 1 +(1) 1235 : umul16_check: +(1) 1235 : 12 06 mov R6, A +(1) 1237 : 14 07 or R7, A +(1) 1239 : E6 E8 jnz umul16_loop ; while multiplier != 0 +(1) 123B : umul16_end: +(1) 123B : D9 02 pop R2 +(1) 123D : D9 03 pop R3 +(1) 123F : 0A rets +(1) 1240 : +(1) 1240 : *** Multiply: result = multiplicand * multiplier +(1) 1240 : *** @param R4:R5 multiplicand +(1) 1240 : *** @param R6:R7 multiplier +(1) 1240 : *** @return R4:R5 result +(1) 1240 : *** @clobber A R6:R7 +(1) 1240 : mul16: +(1) 1240 : 12 04 mov R4, A +(1) 1242 : 15 06 xor R6, A +(1) 1244 : B8 push A ; save hi(multiplicand^multiplier) +(1) 1245 : 77 80 06 0A btjz %>80, R6, mul16_multiplicand +(1) 1249 : D4 06 inv R6 +(1) 124B : D4 07 inv R7 +(1) 124D : D3 07 inc R7 +(1) 124F : E7 02 jnc mul16_multiplicand +(1) 1251 : D3 06 inc R6 ; negate multiplier +(1) 1253 : mul16_multiplicand: +(1) 1253 : 77 80 04 0A btjz %>80, R4, mul16_multiply +(1) 1257 : D4 04 inv R4 +(1) 1259 : D4 05 inv R5 +(1) 125B : D3 05 inc R5 +(1) 125D : E7 02 jnc mul16_multiply +(1) 125F : D3 04 inc R4 ; negate multiplicand +(1) 1261 : mul16_multiply: +(1) 1261 : 8E 12 16 call @umul16 ; R4:R5=result +(1) 1264 : B9 pop A ; A=(multiplicand^multiplier) +(1) 1265 : E5 0A jpz mul16_end +(1) 1267 : D4 04 inv R4 +(1) 1269 : D4 05 inv R5 +(1) 126B : D3 05 inc R5 +(1) 126D : E7 02 jnc mul16_end +(1) 126F : D3 04 inc R4 ; negate result +(1) 1271 : mul16_end: +(1) 1271 : 0A rets +(1) 1272 : +(1) 1272 : *** Unsigned division: dividend / divisor = quotient ... reminder +(1) 1272 : *** @praram R4:R5 dividend +(1) 1272 : *** @praram R6:R7 divisor +(1) 1272 : *** @return R4:R5 quotient +(1) 1272 : *** @return R6:R7 reminder +(1) 1272 : *** @clobber A +(1) 1272 : udiv16: +(1) 1272 : 12 06 mov R6, A +(1) 1274 : 14 07 or R7, A +(1) 1276 : E2 47 jz udiv16_end ; branch if divisor==0 +(1) 1278 : D8 08 push R8 +(1) 127A : 72 01 08 mov %1, R8 ; R8=bits +(1) 127D : E0 07 jmp udiv16_prep +(1) 127F : udiv16_prep_loop: +(1) 127F : B0 clrc +(1) 1280 : DF 07 rlc R7 +(1) 1282 : DF 06 rlc R6 ; divisor <<= 1 +(1) 1284 : D3 08 inc R8 ; ++bits +(1) 1286 : udiv16_prep: +(1) 1286 : 77 80 06 F5 btjz %>80, R6, udiv16_prep_loop ; while msb(divisor) == 0 +(1) 128A : D8 03 push R3 +(1) 128C : D8 02 push R2 +(1) 128E : 88 00 00 03 movd %0, R3 ; R2:R3=quotient=0 +(1) 1292 : E0 0A jmp udiv16_enter_loop +(1) 1294 : udiv16_loop: +(1) 1294 : B0 clrc +(1) 1295 : DD 06 rrc R6 +(1) 1297 : DD 07 rrc R7 ; divisor >>= 1 +(1) 1299 : B0 clrc +(1) 129A : DF 03 rlc R3 +(1) 129C : DF 02 rlc R2 ; quotient <<= 1 +(1) 129E : udiv16_enter_loop: +(1) 129E : 4A 07 05 sub R7, R5 +(1) 12A1 : 4B 06 04 sbb R6, R4 ; dividend -= divisor +(1) 12A4 : E7 04 jl udiv16_readd +(1) 12A6 : D3 03 inc R3 ; quotient |= 1 +(1) 12A8 : E0 06 jmp udiv16_next +(1) 12AA : udiv16_readd: +(1) 12AA : 48 07 05 add R7, R5 +(1) 12AD : 49 06 04 adc R6, R4 ; dividend += divisor +(1) 12B0 : udiv16_next: +(1) 12B0 : DA 08 E1 djnz R8, udiv16_loop ; while bits-- != 0 +(1) 12B3 : 98 05 07 movd R5, R7 ; R6:R7=reminder +(1) 12B6 : 98 03 05 movd R3, R5 ; R4:R5=quotient +(1) 12B9 : D9 02 pop R2 +(1) 12BB : D9 03 pop R3 +(1) 12BD : D9 08 pop R8 +(1) 12BF : udiv16_end: +(1) 12BF : 0A rets +(1) 12C0 : +(1) 12C0 : *** Division: dividend / divisor = quotient ... reminder +(1) 12C0 : *** @param R4:R5 dividend +(1) 12C0 : *** @param R6:R7 divisor +(1) 12C0 : *** @return R4:R5 quotient +(1) 12C0 : *** @return R6:R7 reminder +(1) 12C0 : *** @clobber A +(1) 12C0 : div16: +(1) 12C0 : 12 04 mov R4, A +(1) 12C2 : 15 06 xor R6, A +(1) 12C4 : B8 push A ; save hi(dividend^divisor) +(1) 12C5 : 77 80 06 0A btjz %>80, R6, div16_dividend +(1) 12C9 : D4 06 inv R6 +(1) 12CB : D4 07 inv R7 +(1) 12CD : D3 07 inc R7 +(1) 12CF : E7 02 jnc div16_dividend +(1) 12D1 : D3 06 inc R6 ; negate divisor +(1) 12D3 : div16_dividend: +(1) 12D3 : 77 80 04 0A btjz %>80, R4, div16_divide +(1) 12D7 : D4 04 inv R4 +(1) 12D9 : D4 05 inv R5 +(1) 12DB : D3 05 inc R5 +(1) 12DD : E7 02 jnc div16_divide +(1) 12DF : D3 04 inc R4 +(1) 12E1 : div16_divide: +(1) 12E1 : 8E 12 72 call @udiv16 ; R4:R5=quotient +(1) 12E4 : B9 pop A ; A=(dividend^divisor) +(1) 12E5 : E5 0A jpz div16_end +(1) 12E7 : D4 04 inv R4 +(1) 12E9 : D4 05 inv R5 +(1) 12EB : D3 05 inc R5 +(1) 12ED : E7 02 jnc div16_end +(1) 12EF : D3 04 inc R4 ; negate quotient +(1) 12F1 : div16_end: +(1) 12F1 : 0A rets + 12F2 : include "queue.inc" +(1) 12F2 : ;;; -*- mode: asm; mode: flyspell-prog; -*- +(1) 12F2 : *** [queue] queue structure +(1) 12F2 : =0 queue_len: equ 0 queue length +(1) 12F2 : =1 queue_size: equ 1 buffer size +(1) 12F2 : =2 queue_put: equ 2 queue put index +(1) 12F2 : =3 queue_get: equ 3 queue get index +(1) 12F2 : =4 queue_buf: equ 4 buffer start offset +(1) 12F2 : +(1) 12F2 : *** [queue] Initialize queue +(1) 12F2 : *** @param R2:R3 queue work space pointer +(1) 12F2 : *** @param B queue work space size +(1) 12F2 : *** @clobber A B R2:R3 +(1) 12F2 : queue_init: +(1) 12F2 : B5 clr A +(1) 12F3 : 9B 03 sta *R3 queue_len +(1) 12F5 : 62 mov B, A +(1) 12F6 : 2A 04 sub %queue_buf, A +(1) 12F8 : D3 03 inc R3 +(1) 12FA : 9B 03 sta *R3 queue_size +(1) 12FC : 5A 02 sub %queue_put, B offset queue_len and queue_size +(1) 12FE : D3 03 inc R3 R2:R3=&queue_put +(1) 1300 : B5 clr A +(1) 1301 : queue_init_loop: +(1) 1301 : 9B 03 sta *R3 +(1) 1303 : D3 03 inc R3 +(1) 1305 : CA FA djnz B, queue_init_loop +(1) 1307 : 0A rets +(1) 1308 : +(1) 1308 : *** [queue] Add an element to queue +(1) 1308 : *** @param R2:R3 queue work space pointer +(1) 1308 : *** @param A an element +(1) 1308 : *** @return ST.C 0 if queue is full +(1) 1308 : *** @clobber R2:R3 +(1) 1308 : queue_add: +(1) 1308 : B8 push A +(1) 1309 : 9A 03 lda *R3 A=queue_len +(1) 130B : D3 03 inc R3 R2:R3=&queue_size +(1) 130D : 9D 03 cmpa *R3 +(1) 130F : E7 02 jl queue_add_element +(1) 1311 : B9 pop A ST.C=0 +(1) 1312 : 0A rets +(1) 1313 : queue_add_element: +(1) 1313 : B3 inc A +(1) 1314 : D2 03 dec R3 +(1) 1316 : 9B 03 sta *R3 queue_len++ +(1) 1318 : B9 pop A +(1) 1319 : 78 02 03 add %queue_put-queue_len, R3 R2:R3=&queue_put +(1) 131C : D8 03 push R3 +(1) 131E : B8 push A +(1) 131F : 9A 03 lda *R3 A=queue_put +(1) 1321 : 28 02 add %queue_buf-queue_put, A +(1) 1323 : 48 00 03 add A, R3 R2:R3=&queue[queue_put] +(1) 1326 : B9 pop A +(1) 1327 : 9B 03 sta *R3 store element +(1) 1329 : D9 03 pop R3 R2:R3=&queue_put +(1) 132B : B8 push A +(1) 132C : 9A 03 lda *R3 +(1) 132E : B3 inc A +(1) 132F : D2 03 dec R3 R2:R3=&queue_size +(1) 1331 : 9D 03 cmpa *R3 +(1) 1333 : E7 01 jl queue_add_return +(1) 1335 : B5 clr A wraparound +(1) 1336 : queue_add_return: +(1) 1336 : D3 03 inc R3 R2:R3=&queue_put +(1) 1338 : 9B 03 sta *R3 update queue_put +(1) 133A : B9 pop A +(1) 133B : 07 setc ST.C=1 +(1) 133C : 0A rets +(1) 133D : +(1) 133D : *** [queue] Remove an element from queue +(1) 133D : *** @param R2:R3 queue work space pointer +(1) 133D : *** @return A an element +(1) 133D : *** @return ST.C 0 if queue is empty +(1) 133D : queue_remove: +(1) 133D : 9A 03 lda *R3 A=queue_len +(1) 133F : E6 02 jnz queue_remove_elem +(1) 1341 : B0 clrc +(1) 1342 : 0A rets +(1) 1343 : queue_remove_elem: +(1) 1343 : B2 dec A +(1) 1344 : 9B 03 sta *R3 queue_len-- +(1) 1346 : 78 03 03 add %queue_get-queue_len, R3 R2:R3=&queue_get +(1) 1349 : D8 03 push R3 +(1) 134B : 9A 03 lda *R3 A=queue_get +(1) 134D : 28 01 add %queue_buf-queue_get, A +(1) 134F : 48 00 03 add A, R3 R2:R3=&queue_buf[queue_get] +(1) 1352 : 9A 03 lda *R3 remove element +(1) 1354 : D9 03 pop R3 R2:R3=&queue_get +(1) 1356 : B8 push A +(1) 1357 : 9A 03 lda *R3 +(1) 1359 : B3 inc A +(1) 135A : 7A 02 03 sub %queue_get-queue_size, R3 +(1) 135D : 9D 03 cmpa *R3 +(1) 135F : E7 01 jl queue_remove_return +(1) 1361 : B5 clr A wraparound +(1) 1362 : queue_remove_return: +(1) 1362 : 78 02 03 add %queue_get-queue_size, R3 +(1) 1365 : 9B 03 sta *R3 update queue_get +(1) 1367 : B9 pop A +(1) 1368 : 07 setc +(1) 1369 : 0A rets + 136A : + 136A : isr_int1: + 136A : A7 80 F0 17 btjzp %IRQF_bm, ACIA_status, isr_int1_return + 136E : B8 push A + 136F : D8 02 push R2 + 1371 : D8 03 push R3 + 1373 : A7 01 F0 0F btjzp %RDRF_bm, ACIA_status, isr_tx + 1377 : 80 F1 movp ACIA_data, A + 1379 : 88 20 00 03 movd %rx_queue, R3 + 137D : 8E 13 08 call @queue_add + 1380 : isr_int1_exit: + 1380 : D9 03 pop R3 + 1382 : D9 02 pop R2 + 1384 : B9 pop A + 1385 : isr_int1_return: + 1385 : 0B reti + 1386 : isr_tx: + 1386 : A7 02 F0 F6 btjzp %TDRE_bm, ACIA_status, isr_int1_exit + 138A : 88 20 80 03 movd %tx_queue, R3 + 138E : 8E 13 3D call @queue_remove + 1391 : E7 04 jnc isr_tx_empty + 1393 : 82 F1 movp A, ACIA_data send character + 1395 : E0 E9 jmp isr_int1_exit + 1397 : isr_tx_empty: + 1397 : A2 94 F0 movp %RX_INT_TX_NO, ACIA_control disable Tx interrupt + 139A : E0 E4 jmp isr_int1_exit diff --git a/samples/tms7000/mc6850.inc b/samples/tms7000/mc6850.inc new file mode 100644 index 00000000..618f4ef3 --- /dev/null +++ b/samples/tms7000/mc6850.inc @@ -0,0 +1,39 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + *** MC6850 + *** Asynchronous Communication Interface Adapter +ACIA_control: equ ACIA+0 +ACIA_status: equ ACIA+0 +ACIA_data: equ ACIA+1 + ** Counter Divider Select Bits +CDS_gm: equ ?11 Group mask +CDS_DIV1_gc: equ ?00000000 /1 +CDS_DIV16_gc: equ ?00000001 /16 +CDS_DIV64_gc: equ ?00000010 /64 +CDS_RESET_gc: equ ?00000011 Master Reset + ** Word Select Bits +WSB_gm: equ ?00011100 Group mask +WSB_7E2_gc: equ ?00000000 7 Bits + Even Parity + 2 Stop Bits +WSB_7O2_gc: equ ?00000100 7 bits + Odd Parity + 2 Stop Bits +WSB_7E1_gc: equ ?00001000 7 bits + Even Parity + 1 Stop Bits +WSB_7O1_gc: equ ?00001100 7 bits + Odd Parity + 1 Stop Bits +WSB_8N2_gc: equ ?00010000 8 bits + No Parity + 2 Stop Bits +WSB_8N1_gc: equ ?00010100 8 bits + No Parity + 1 Stop Bits +WSB_8E1_gc: equ ?00011000 8 bits + Even Parity + 1 Stop Bits +WSB_8O1_gc: equ ?00011100 8 bits + Odd Parity + 1 Stop Bits + ** Transmit Control Bits +TCB_gm: equ ?01100000 Group mask +TCB_DI_gc: equ ?00000000 RTS=Low, Tx Interrupt Disabled +TCB_EI_gc: equ ?00100000 RTS=Low, Tx Interrupt Enabled +TCB_RTS_gc: equ ?01000000 RTS=High, Tx Interrupt Disabled +TCB_BREAK_gc: equ ?01100000 RTS=Low, Tx Interrupt Disabled + * Transmit Break Level +RIEB_bm: equ ?10000000 Receive Interrupt Enable Bit mask + *** Status register +RDRF_bm: equ ?00000001 Receive Data Register Full +TDRE_bm: equ ?00000010 Transmit Data Register Empty +DCDF_bm: equ ?00000100 Data Carrier Detect Flag +CTSF_bm: equ ?00001000 Clear To Send Flag +FERR_bm: equ ?00010000 Frame Error Flag +OVRN_bm: equ ?00100000 Receiver Overrun Flag +PERR_bm: equ ?01000000 Parity Error Flag +IRQF_bm: equ ?10000000 Interrupt Request Flag diff --git a/samples/tms7000/queue.inc b/samples/tms7000/queue.inc new file mode 100644 index 00000000..5e77b42a --- /dev/null +++ b/samples/tms7000/queue.inc @@ -0,0 +1,101 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + *** [queue] queue structure +queue_len: equ 0 queue length +queue_size: equ 1 buffer size +queue_put: equ 2 queue put index +queue_get: equ 3 queue get index +queue_buf: equ 4 buffer start offset + + *** [queue] Initialize queue + *** @param R2:R3 queue work space pointer + *** @param B queue work space size + *** @clobber A B R2:R3 +queue_init: + clr A + sta *R3 queue_len + mov B, A + sub %queue_buf, A + inc R3 + sta *R3 queue_size + sub %queue_put, B offset queue_len and queue_size + inc R3 R2:R3=&queue_put + clr A +queue_init_loop: + sta *R3 + inc R3 + djnz B, queue_init_loop + rets + + *** [queue] Add an element to queue + *** @param R2:R3 queue work space pointer + *** @param A an element + *** @return ST.C 0 if queue is full + *** @clobber R2:R3 +queue_add: + push A + lda *R3 A=queue_len + inc R3 R2:R3=&queue_size + cmpa *R3 + jl queue_add_element + pop A ST.C=0 + rets +queue_add_element: + inc A + dec R3 + sta *R3 queue_len++ + pop A + add %queue_put-queue_len, R3 R2:R3=&queue_put + push R3 + push A + lda *R3 A=queue_put + add %queue_buf-queue_put, A + add A, R3 R2:R3=&queue[queue_put] + pop A + sta *R3 store element + pop R3 R2:R3=&queue_put + push A + lda *R3 + inc A + dec R3 R2:R3=&queue_size + cmpa *R3 + jl queue_add_return + clr A wraparound +queue_add_return: + inc R3 R2:R3=&queue_put + sta *R3 update queue_put + pop A + setc ST.C=1 + rets + + *** [queue] Remove an element from queue + *** @param R2:R3 queue work space pointer + *** @return A an element + *** @return ST.C 0 if queue is empty +queue_remove: + lda *R3 A=queue_len + jnz queue_remove_elem + clrc + rets +queue_remove_elem: + dec A + sta *R3 queue_len-- + add %queue_get-queue_len, R3 R2:R3=&queue_get + push R3 + lda *R3 A=queue_get + add %queue_buf-queue_get, A + add A, R3 R2:R3=&queue_buf[queue_get] + lda *R3 remove element + pop R3 R2:R3=&queue_get + push A + lda *R3 + inc A + sub %queue_get-queue_size, R3 + cmpa *R3 + jl queue_remove_return + clr A wraparound +queue_remove_return: + add %queue_get-queue_size, R3 + sta *R3 update queue_get + pop A + setc + rets diff --git a/samples/tms7000/tms7000.inc b/samples/tms7000/tms7000.inc new file mode 100644 index 00000000..e4c6a5a3 --- /dev/null +++ b/samples/tms7000/tms7000.inc @@ -0,0 +1,58 @@ +;;; -*- mode: asm; mode: flyspell-prog; -*- + *** TMS7000 + *** Status Register +ST_CARRY: equ ?10000000 set to 1 if carry occurred +ST_NEGATIVE: equ ?01000000 set to 1 if result is negative +ST_ZERO: equ ?00100000 set to 1 if result is zero +ST_INT: equ ?00010000 if 1, interrupt is enabled + *** Vector +VEC_INT3: equ >FFF8 #INT3 interrupt +VEC_INT2: equ >FFFA Timer 1 +VEC_INT1: equ >FFFC #INT1 interrupt +VEC_RESET: equ >FFFE #RESET vector + *** Trap Vector +VEC_TRAP0: equ VEC_RESET +VEC_TRAP1: equ VEC_INT1 +VEC_TRAP2: equ VEC_INT2 +VEC_TRAP3: equ VEC_INT3 +VEC_TRAP4: equ >FFF6 +VEC_TRAP5: equ >FFF4 +VEC_TRAP6: equ >FFF2 +VEC_TRAP7: equ >FFF0 +VEC_TRAP8: equ >FFEE +VEC_TRAP9: equ >FFEC +VEC_TRAP10: equ >FFEA +VEC_TRAP11: equ >FFE8 +VEC_TRAP12: equ >FFE6 +VEC_TRAP13: equ >FFE4 +VEC_TRAP14: equ >FFE2 +VEC_TRAP15: equ >FFE0 +VEC_TRAP16: equ >FFDE +VEC_TRAP17: equ >FFDC +VEC_TRAP18: equ >FFDA +VEC_TRAP19: equ >FFD8 +VEC_TRAP20: equ >FFD6 +VEC_TRAP21: equ >FFD4 +VEC_TRAP22: equ >FFD2 +VEC_TRAP23: equ >FFD0 + + *** Internal Peripherals +IOCNT0: equ >0100 I/O Control register +INT3_F: equ ?100000 #INT3 flag +INT3_E: equ ?010000 #INT3 enable +INT2_F: equ ?001000 INT2 flag +INT2_E: equ ?000100 INT2 enable +INT1_F: equ ?000010 #INT1 flag +INT1_E: equ ?000001 #INT1 enable +T1DATA: equ >0102 Timer 1 data +T1CTL: equ >0103 Timer 1 control +APORT: equ >0104 Port A data +BPORT: equ >0106 Port B data +CPORT: equ >0108 Port C data +CDDR: equ >0109 Port C data direction register +DPORT: equ >010A Port D data +DDDR: equ >010B Port D data direction register + + *** Local Variables: + *** comment-start: "*" + *** End: diff --git a/samples/tms7000/tms7001.inc b/samples/tms7000/tms7001.inc new file mode 100644 index 00000000..914fe407 --- /dev/null +++ b/samples/tms7000/tms7001.inc @@ -0,0 +1,26 @@ + *** -*- mode: asm; mode: flyspell-prog; -*- + include "tms7000.inc" + *** TMS7001 + *** Vector +VEC_INT5: equ >FFF4 Tuner 2 +VEC_INT4: equ >FFF6 Serial port + *** Internal Peripherals +ADDR: equ >0105 Port A data direction register +IOCNT1: equ >0110 I/O control register 1 +INT5_F: equ ?1000 INT5 flag +INT5_E: equ ?0100 INT5 enable +INT4_F: equ ?0010 INT4 flag +INT4_E: equ ?0001 INT4 enable +SMODE: equ >0111 Serial mode (first write) +SCTL0: equ >0111 Serial control 0 (write only) +SSTAT: equ >0111 Serial status register (read only) +T2DATA: equ >0112 Timer 2 data +T2CNTL: equ >0113 Timer 2 control +T3DATA: equ >0114 Timer 3 data +SCTL1: equ >0115 Serial control +RXBUF: equ >0116 Receive buffer +TXBUF: equ >0117 Transmitter buffer + + *** Local Variables: + *** comment-start: "*" + *** End: diff --git a/samples/tms7000/tms70c02.inc b/samples/tms7000/tms70c02.inc new file mode 100644 index 00000000..a949477a --- /dev/null +++ b/samples/tms7000/tms70c02.inc @@ -0,0 +1,17 @@ + *** -*- mode: asm; mode: flyspell-prog; -*- + include "tms7001.inc" + *** TMS7002 + *** Internal Peripherals +IOCNT2: equ >0101 I/O control register 2 +INT3_EDGE: ?100000 #INT3 1=edge sense, 0=level sense +INT3_POL: ?010000 #INT3 polarity 1=high/raising, 0=low/falling +INT1_EDGE: ?000010 #INT1 1=edge sense, 0=level sense +INT1_POL: ?000001 #INT1 polarity 1=high/raising, 0=low/falling + *** - SCTL1 has start/stop bit of Timer 3 + *** - Serial baud-rate is doubled than TMS7001 + *** - #INT1 and #INT3 can be level active + *** - No /4 clock option + + *** Local Variables: + *** comment-start: "*" + *** End: