~jpl8/lorthc3

85ea14ca6530111e5c4211534f52ebee9719cdf8 — jpl 1 year, 10 months ago 38373a7
Add reading word by word

I believe it is working as intended, but I
still need to make sure with further testing.
2 files changed, 96 insertions(+), 13 deletions(-)

M src/assembler.rs
M src/compiler.rs
M src/assembler.rs => src/assembler.rs +39 -2
@@ 19,6 19,12 @@ pub enum AsmAddr {
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AsmJsrMode {
    Addr(AsmAddr),
    Register(Register),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum AsmInstruction {
    // Conditional branch
    BR(u16, AsmAddr),


@@ 29,7 35,7 @@ pub enum AsmInstruction {
    /// Store
    ST(Register, AsmAddr),
    /// Jump to subroutine
    JSR(JsrMode),
    JSR(AsmJsrMode),
    /// Bit-wise logical AND
    AND(Register, Register, AndMode),
    /// Load base+offset


@@ 106,7 112,15 @@ impl LC3Assembler {
                    r,
                    self.asm_addr_to_offset(addr)? as Word,
                )),
                JSR(mode) => PseudoInstruction::LC3(Instruction::JSR(mode)),
                JSR(mode) => match mode {
                    AsmJsrMode::Register(r) => {
                        PseudoInstruction::LC3(Instruction::JSR(JsrMode::Register(r)))
                    }

                    AsmJsrMode::Addr(addr) => PseudoInstruction::LC3(Instruction::JSR(
                        JsrMode::Offset(self.asm_addr_to_offset(addr)? as Word),
                    )),
                },
                AND(r1, r2, mode) => PseudoInstruction::LC3(Instruction::AND(r1, r2, mode)),
                LDR(r1, r2, offset) => PseudoInstruction::LC3(Instruction::LDR(r1, r2, offset)),
                STR(r1, r2, offset) => PseudoInstruction::LC3(Instruction::STR(r1, r2, offset)),


@@ 163,6 177,9 @@ impl LC3Assembler {
        self.instr(LEA(r, addr))
    }

    pub fn load_register(&mut self, dest: Register, src: Register, offset: Word) -> &mut Self {
        self.instr(LDR(dest, src, offset))
    }
    pub fn get_char(&mut self) -> &mut Self {
        self.instr(TRAP(GETC))
    }


@@ 206,6 223,10 @@ impl LC3Assembler {
        self.instr(LDI(r, addr))
    }

    pub fn neg(&mut self, dest: Register, src: Register) -> &mut Self {
        self.not(dest, src).add(dest, dest, AddMode::Immediate(1))
    }

    // Optimizations

    fn num_diff_bits(a: Word, b: Word) -> u32 {


@@ 223,10 244,26 @@ impl LC3Assembler {
        self.add(r, r, AddMode::Immediate(rem))
    }

    pub fn mov_reg(&mut self, dest: Register, src: Register) -> &mut Self {
        self.and(dest, src, AndMode::Register(src))
    }

    pub fn store(&mut self, src: Register, base: Register, offset: Word) -> &mut Self {
        self.instr(STR(src, base, offset))
    }

    pub fn store_indirect(&mut self, src: Register, addr: AsmAddr) -> &mut Self {
        self.instr(STI(src, addr))
    }

    pub fn ret(&mut self) -> &mut Self {
        self.instr(JMP(R7))
    }

    pub fn subroutine(&mut self, mode: AsmJsrMode) -> &mut Self {
        self.instr(JSR(mode))
    }

    pub fn fill(&mut self, w: Word) -> &mut Self {
        self.instr(FILL(w))
    }

M src/compiler.rs => src/compiler.rs +57 -11
@@ 10,8 10,8 @@ use std::collections::HashMap;
use std::iter;

use crate::assembler::AsmInstruction::{self, *};
use crate::assembler::LC3Assembler;
use crate::assembler::{AsmAddr, PseudoInstruction};
use crate::assembler::{AsmJsrMode, LC3Assembler};

pub type SignedWord = i16;



@@ 64,48 64,94 @@ impl ForthCompiler {
    }

    pub fn read_input(&mut self) -> Result<&mut Self> {
        self.asm.label("readln");
        let tib_addr = self.asm.reference_label("tib");
        self.asm.load(R1, tib_addr);
        let toin_addr = self.asm.reference_label("toin");
        self.asm.load(R0, toin_addr);
        self.asm.load(R0, toin_addr).store(R1, R0, 0);

        let input_reading_loop_label = "input_reading_loop";
        self.asm
            .label(input_reading_loop_label)
            .label("readlp")
            .get_char()
            // TODO: Remove out_char
            .out_char()
            .store(R0, R1, 0)
            .add(R1, R1, AddMode::Immediate(1 as Word))
            .not(R0, R0)
            .and(R0, R0, AndMode::Immediate('\n' as Word));
        let loop_top = self.asm.reference_label(input_reading_loop_label);
        let readlp = self.asm.reference_label("readlp");
        self.asm
            .branch(
                ConditionCode::NEG as Word | ConditionCode::POS as Word,
                loop_top,
                readlp,
            )
            .add(R1, R1, AddMode::Immediate(-1i16 as Word))
            .store(R0, R1, 0);

        let token = self.asm.reference_label("token");
        self.asm.branch_unconditionally(token);

        Ok(self)
    }

    fn parse_words(&mut self) -> Result<&mut Self> {
        let token = self.asm.reference_label("token");
        self.asm.subroutine(AsmJsrMode::Addr(token));
        self.asm
            .branch_unconditionally(AsmAddr::Word(-1i16 as Word));

        self.asm.label("token");

        let toin = self.asm.reference_label("toin");
        self.asm.load_indirect(R3, toin);
        // self.asm.load_indirect(R3, toin);
        self.asm.load(R3, toin);

        let space = self.asm.reference_label("space");
        self.asm.load(R1, space);
        self.asm.load(R1, space).neg(R1, R1);

        self.asm.label("skipws");
        self.asm.load_register(R0, R3, 0);

        let readln = self.asm.reference_label("readln");
        self.asm
            .branch(ConditionCode::ZER as Word, readln)
            .mov_reg(R2, R3)
            .add(R3, R3, AddMode::Immediate(1))
            .add(R0, R0, AddMode::Register(R1));

        let skipws = self.asm.reference_label("skipws");
        self.asm.branch(ConditionCode::ZER as Word, skipws).add(
            R3,
            R3,
            AddMode::Immediate(-1i16 as Word),
        );

        self.asm
            .label("findws")
            .add(R3, R3, AddMode::Immediate(1))
            .load_register(R0, R3, 0);
        let tokend = self.asm.reference_label("tokend");
        self.asm
            .branch(ConditionCode::ZER as Word, tokend)
            .add(R0, R0, AddMode::Register(R1));
        let findws = self.asm.reference_label("findws");
        self.asm.branch(ConditionCode::ZER as Word, findws);

        self.asm.label("tokend");
        let toin = self.asm.reference_label("toin");
        self.asm
            .store_indirect(R3, toin)
            .neg(R1, R2)
            .add(R3, R3, AddMode::Register(R1))
            .ret();

        // unimplemented!();
        Ok(self)
    }

    pub fn print_tib(&mut self) -> Result<&mut Self> {
        let tib_addr = self.asm.reference_label("tib");
        self.asm.instr(LD(R0, tib_addr));

        self.asm.instr(TRAP(PUTS));
        Ok(self)
    }


@@ 122,9 168,9 @@ impl ForthCompiler {

    pub fn compile(&mut self) -> Result<&mut Self> {
        self.load_intermediate_cells()
            .read_input()?
            .print_tib()?
            .parse_words()?
            .read_input()?
            // .print_tib()?
            .halt()
            .assemble()?;