~jpl8/lorthc3

4138444b559bab16f4281ed24e30517c227a4ed6 — jpl 1 year, 26 days ago 8553342
Add user defined words
2 files changed, 120 insertions(+), 6 deletions(-)

M src/assembler.rs
M src/compiler.rs
M src/assembler.rs => src/assembler.rs +4 -0
@@ 202,6 202,10 @@ impl LC3Assembler {
        self.instr(AND(dest, src, arg))
    }

    pub fn zero(&mut self, r: Register) -> &mut Self {
        self.and(r, r, AndMode::Immediate(0))
    }

    pub fn not(&mut self, dest: Register, src: Register) -> &mut Self {
        self.instr(NOT(dest, src))
    }

M src/compiler.rs => src/compiler.rs +116 -6
@@ 31,6 31,8 @@ impl ForthCompiler {
    const STATE: Word = 0x4102;
    const HERE: Word = 0x4103;

    const FLAG_IMMEDIATE: Word = 0x10;

    pub const SP_ADDR: Word = 0x5000;
    pub const RP_ADDR: Word = 0x6000;



@@ 52,12 54,15 @@ impl ForthCompiler {
            .flat_map(|w| w.to_be_bytes())
    }
    fn load_intermediate_cells(&mut self) -> &mut Self {
        let pc = self.asm.pc() + 1;
        let cells = vec![
            ("latest", pc + 1),
            ("latest_val", self.link),
            ("here", pc + 3),
            ("here_val", 0x7000),
            ("tib", Self::TIB),
            ("toin", Self::TOIN),
            ("latest", self.link),
            ("state", Self::STATE),
            ("here", Self::HERE),
            ("sp_addr", Self::SP_ADDR),
            ("rp_addr", Self::RP_ADDR),
            ("space", ' ' as Word),


@@ 69,7 74,7 @@ impl ForthCompiler {

        for (label, val) in cells {
            self.asm.label(label);
            eprintln!("{} ADDRESS: {:#X?}", label, self.asm.pc());
            eprintln!("{} ADDRESS: {:#X?}; VAL: {:#X?}", label, self.asm.pc(), val);
            self.asm.fill(AsmAddr::Word(val));
        }
        self


@@ 201,6 206,7 @@ impl ForthCompiler {

    fn word(&mut self, name: String, flags: Word) -> &mut Self {
        let pc = self.asm.pc();
        eprintln!("WORD: {} has address: {:#X?}", name, pc);
        self.asm.fill(AsmAddr::Word(self.link));
        self.link = pc;
        self.asm.fill(AsmAddr::Word(name.len() as Word + flags));


@@ 256,11 262,114 @@ impl ForthCompiler {
        let next = self.asm.reference_label("next");
        self.asm.branch_unconditionally(next);

        // halt
        // Key
        self.word(String::from("key"), 0)
            .get_char()
            .asm
            .add(Self::SP, Self::SP, AddMode::Immediate(1))
            .store(R0, Self::SP, 0);
        let next = self.asm.reference_label("next");
        self.asm.branch_unconditionally(next);

        // Emit
        self.word(String::from("emit"), 0)
            .asm
            .load_register(R0, Self::SP, 0)
            .add(Self::SP, Self::SP, AddMode::Immediate(-1i16 as Word));
        self.out_char();
        let next = self.asm.reference_label("next");
        self.asm.branch_unconditionally(next);

        // Halt
        self.word(String::from("bye"), 0).asm.halt();
        let next = self.asm.reference_label("next");
        self.asm.branch_unconditionally(next);

        // Exit
        self.word(String::from("exit"), 0)
            .asm
            .label("exit")
            .load_register(Self::IP, Self::RP, 0)
            .add(Self::RP, Self::RP, AddMode::Immediate(-1i16 as Word));
        let next = self.asm.reference_label("next");
        self.asm.branch_unconditionally(next);

        // ;
        self.word(String::from(";"), Self::FLAG_IMMEDIATE)
            .asm
            .and(R1, R1, AndMode::Immediate(0));
        let state = self.asm.reference_label("state"); // Set state to interpret
        self.asm.store_indirect(R1, state);

        let exit = self.asm.reference_label("exit"); // compile exit
        self.asm.load_effective_address(R0, exit);
        // branch to compile instead of falling through or calling next
        let compile = self.asm.reference_label("compile");
        self.asm.branch_unconditionally(compile);

        // :
        self.word(String::from(":"), 0);
        let token = self.asm.reference_label("token");
        self.asm.subroutine(AsmJsrMode::Addr(token));

        let latest = self.asm.reference_label("latest");
        self.asm.load_indirect(R0, latest);

        let here = self.asm.reference_label("here");
        self.asm.load_indirect(R1, here).store(R0, R1, 0);

        eprintln!("DEBUG LINE : {:#X?}", self.asm.pc);

        let latest = self.asm.reference_label("latest");
        self.asm
            .store_indirect(R1, latest)
            .store(R3, R1, 1)
            .add(R1, R1, AddMode::Immediate(2))
            .label("copy")
            .load_register(R0, R2, 0)
            .store(R0, R1, 0)
            .add(R2, R2, AddMode::Immediate(1))
            .add(R1, R1, AddMode::Immediate(1))
            .add(R3, R3, AddMode::Immediate(-1i16 as Word));
        let copy = self.asm.reference_label("copy");
        self.asm.branch(ConditionCode::POS as Word, copy);
        let load_op = self.asm.reference_label("load_op");
        self.asm.load(R0, load_op).store(R0, R1, 0);
        let jmp_op = self.asm.reference_label("jmp_op");
        self.asm.load(R0, jmp_op).store(R0, R1, 1);
        let docol_op = self.asm.reference_label("docol_op");
        self.asm
            .load(R0, docol_op)
            .store(R0, R1, 2)
            .add(R1, R1, AddMode::Immediate(3));
        let here = self.asm.reference_label("here");
        self.asm
            .store_indirect(R1, here)
            .zero(R2)
            .add(R2, R2, AddMode::Immediate(1));
        let state = self.asm.reference_label("state");
        self.asm.store_indirect(R2, state);
        let next = self.asm.reference_label("next");
        self.asm.branch_unconditionally(next);

        self.asm
            .label("load_op")
            .fill(AsmAddr::Word(0x2201))
            .label("jmp_op")
            .fill(AsmAddr::Word(0xc040))
            .label("docol_op");
        let docol = self.asm.reference_label("docol");
        self.asm.fill(docol);

        // Docol
        self.asm
            .label("docol")
            .store(Self::IP, Self::RP, 1)
            .add(Self::RP, Self::RP, AddMode::Immediate(1))
            .add(Self::IP, R0, AddMode::Immediate(3));
        let next = self.asm.reference_label("next");
        self.asm.branch_unconditionally(next);

        self
    }



@@ 300,7 409,7 @@ impl ForthCompiler {
            .store(R3, Self::SP, 3);

        let latest = self.asm.reference_label("latest");
        self.asm.load(R0, latest);
        self.asm.load_indirect(R0, latest);
        self.asm.label("is_match");

        let error = self.asm.reference_label("error");


@@ 350,6 459,7 @@ impl ForthCompiler {
        let is_match = self.asm.reference_label("is_match");
        self.asm.branch_unconditionally(is_match);

        eprintln!("LABEL: FOUND; {:#X?}", self.asm.pc);
        self.asm.label("found").add(R0, R0, AddMode::Immediate(2));
        let loop_label = self.asm.reference_label("loop");



@@ 434,7 544,7 @@ impl ForthCompiler {
            .halt()
            .assemble()?;

        eprintln!("{:?}", self.asm.instructions);
        // eprintln!("{:?}", self.asm.instructions);
        // eprintln!("{:?}", self.assembled_instructions);

        Ok(self)