diff options
| -rw-r--r-- | newasm/Makefile | 28 | ||||
| -rw-r--r-- | newasm/errors.s | 30 | ||||
| -rw-r--r-- | newasm/imm.s | 27 | ||||
| -rw-r--r-- | newasm/main.s | 45 | ||||
| -rw-r--r-- | newasm/optable.s | 9 | ||||
| -rw-r--r-- | newasm/parsers/decimal.s | 4 | ||||
| -rw-r--r-- | newasm/parsers/immediate.s | 13 | ||||
| -rw-r--r-- | newasm/parsers/label.s | 5 | ||||
| -rw-r--r-- | newasm/parsers/register.s | 13 | ||||
| -rw-r--r-- | newasm/regimm.s | 37 | ||||
| -rw-r--r-- | newasm/regreg.s | 29 | ||||
| -rw-r--r-- | newasm/regregimm.s | 47 | ||||
| -rw-r--r-- | newasm/regregreg.s | 44 | ||||
| -rw-r--r-- | newasm/statement.s | 65 | 
14 files changed, 309 insertions, 87 deletions
| diff --git a/newasm/Makefile b/newasm/Makefile index fd057fe..78a0828 100644 --- a/newasm/Makefile +++ b/newasm/Makefile @@ -2,40 +2,42 @@ PICO = /dev/disk/by-label/RPI-RP2  DEVICE = /dev/ttyUSB0  .PHONY: build -build: parse.he +build: assemble.he -parse.he: parse.bin -	od -An -tx2 -v parse.bin | sed "s/^ //" | tr " " "\n" | tr [:lower:] [:upper:] | sed "s/^/0x/" > parse.he +assemble.he: assemble.bin +	od -An -tx2 -v assemble.bin | sed "s/^ //" | tr " " "\n" | tr [:lower:] [:upper:] | sed "s/^/0x/" > assemble.he -parse.bin: parse.elf -	arm-none-eabi-objcopy -O binary parse.elf parse.bin +assemble.bin: assemble.elf +	arm-none-eabi-objcopy -O binary assemble.elf assemble.bin  objects = main.o uart.o data.o string.o input.o \  					statement.o optable.o \ +					regreg.o regregimm.o regimm.o regregreg.o imm.o \  					parsers/whitespace.o \  					parsers/label.o \  					parsers/symbol.o \  					parsers/opcode.o \  					parsers/register.o \ -					parsers/decimal.o +					parsers/decimal.o \ +					parsers/immediate.o -parse.elf: pico_bin.ld $(objects) -	arm-none-eabi-ld -T pico_bin.ld -o parse.elf $(objects) +assemble.elf: pico_bin.ld $(objects) +	arm-none-eabi-ld -T pico_bin.ld -o assemble.elf $(objects)  $(objects): %.o: %.s  	arm-none-eabi-as -o $@ $<  .PHONY: clean  clean: -	rm -f parse.elf parse.bin parse.he slowcat $(objects) +	rm -f assemble.elf assemble.bin assemble.he slowcat $(objects)  .PHONY: dump -dump: parse.bin -	@od -Ax -tx2 -v parse.bin +dump: assemble.bin +	@od -Ax -tx2 -v assemble.bin  .PHONY: serial -serial: $(DEVICE) parse.he slowcat -	cat parse.he | tr "\n" "\r" | ./slowcat | picocom -b 115200 -q $(DEVICE) +serial: $(DEVICE) assemble.he slowcat +	cat assemble.he | tr "\n" "\r" | ./slowcat | picocom -b 115200 -q $(DEVICE)  	@echo  	echo -n "G" | picocom -b 115200 -q $(DEVICE)  	@echo diff --git a/newasm/errors.s b/newasm/errors.s new file mode 100644 index 0000000..3822851 --- /dev/null +++ b/newasm/errors.s @@ -0,0 +1,30 @@ +.syntax unified +.cpu cortex-m0plus +.thumb + +// .type print_error, %function +// .global print_error + +// 00 success +// 01 expected an opcode (or unexpected character) +// 02 expected label or opcode +// 03 expected colon at end of label +// 04 opcode not found + +// 05 expected digit + +// 06 expected register +// 07 invalid general-purpose register number +// 08 invalid register for this register position +// 09 invalid register combo for this instruction + +// 0A immediate value too large + +// 0B extra input at end of statement + +            .align  4 +no_colon:   .asciz  "Error: Expected colon at end of label" +            .align  4 +no_opcode:  .asciz  "Error: Expected an opcode" +            .align  4 +not_found:  .asciz  "Error: Opcode not found" diff --git a/newasm/imm.s b/newasm/imm.s new file mode 100644 index 0000000..f6c7266 --- /dev/null +++ b/newasm/imm.s @@ -0,0 +1,27 @@ +.syntax unified +.cpu cortex-m0plus +.thumb + +.type imm, %function +.global imm + +// R1 instruction under construction +// R3 immediate width +// R4 input buffer + +imm:      PUSH    {LR} +          PUSH    {R3} +          BL      immediate +          POP     {R3} +          BNE     exit +          MOVS    R0, 1 +          LSLS    R0, R3 +          CMP     R2, R0 +          BLO     fine +          MOVS    R0, 0x0A    // return code 0A (immediate value too large) +          POP     {PC} +fine:     ORRS    R1, R2      // fill in imm +          MOVS    R0, 0       // return code 0 (success) +exit:     POP     {PC} +bad_reg:  MOVS    R0, 8       // return code 8 (invalid register for this register position) +          POP     {PC} diff --git a/newasm/main.s b/newasm/main.s index a27fec9..f1d3c0d 100644 --- a/newasm/main.s +++ b/newasm/main.s @@ -6,38 +6,31 @@  .global main, strbuf  main:     LDR     R5, =0x20002000 -          BL      uart_recv -loop:     BL      prompt -          LDR     R0, inpbuf +          BL      uart_recv           // wait for keypress +loop:     BL      prompt              // display address and data +          LDR     R0, inpbuf          // get a line of input            BL      getline -          LDR     R0, inpbuf -          BL      putstrln -          LDR     R4, inpbuf -          LDR     R2, strbuf -          MOVS    R0, 0 +          LDR     R4, inpbuf          // prepare input buffer +          LDR     R2, strbuf          // prepare output buffer +          MOVS    R0, 0               // clear output buffer            STRB    R0, [R2] -          BL      statement -          BNE     bad - -good:     ADR     R0, success -          PUSH    {R1} -          BL      putstrln -          MOVS    R0, R4 -          BL      putstrln -          POP     {R0} +          BL      statement           // call statement parser +          BNE     bad                 // print message if failure +          MOVS    R0, R1              // show assembled instruction            BL      send_hex            LDR     R0, =crlf            BL      putstr -          B       loop - -bad:      ADR     R0, fail -          BL      putstrln -          MOVS    R0, R4 +          B       loop                // repeat +bad:      PUSH    {R0} +          ADR     R0, fail +          BL      putstr +          POP    {R0} +          BL      send_hex +          LDR     R0, =crlf +          BL      putstr +          MOVS     R0, R4            BL      putstrln            B       loop -never:    BL      uart_recv -          LDR     R0, =0x20000001 -          BX      R0  prompt:   PUSH    {LR}            MOVS    R0, R5 @@ -57,4 +50,4 @@ strbuf:   .word   0x20001F80            .align  4  success:  .asciz  "The parser suceeded"            .align  4 -fail:     .asciz  "The parser failed" +fail:     .asciz  "The parser failed: " diff --git a/newasm/optable.s b/newasm/optable.s index a063f02..fb80ab4 100644 --- a/newasm/optable.s +++ b/newasm/optable.s @@ -5,9 +5,6 @@  .type lookup, %function  .global lookup -// 1 unexpected char -// 2 unexpected end of input -  // input:  // R0 input string (unboxed) @@ -25,7 +22,7 @@ loop:     CMP     R5, R6      // if begin == end then range = 0            BEQ     error            ADDS    R2, R5, R6  // get sum            LSRS    R2, 1       // divide by two -no_jiggle:LSLS    R3, R2, 3   // times 8 (index to offset) +          LSLS    R3, R2, 3   // times 8 (index to offset)            LDR     R1, [R4, R3]// read opcode from optable            CMP     R0, R1      // compare opcode to input            BLO     lower       // if lower @@ -42,7 +39,7 @@ lower:    MOVS    R6, R2      // update end pointer            B       loop  higher:   ADDS    R5, R2, 1   // update begin pointer            B     loop -error:    MOVS    R0, 1       // return code 1 (not found) +error:    MOVS    R0, 4       // return code 4 (opcode not found)            POP     {R4, R5, R6}            BX      LR @@ -53,5 +50,5 @@ op_table:            .ascii  "ASPI"; .hword 0xB000;  .byte 0x04, 0x07  // instr type 4, special code 7            .ascii  "ASRI"; .hword 0x1000;  .byte 0x01, 0x05  // instr type 1, special code 5 (imm width)            .ascii  "ADCS"; .hword 0x4140;  .byte 0x00, 0x00  // instr type 0, special code 0 -          .ascii  "ADDS"; .hword 0x1400;  .byte 0x03, 0x00  // instr type 3, special code 0 +          .ascii  "ADDS"; .hword 0x1800;  .byte 0x03, 0x00  // instr type 3, special code 0            .ascii  "BKPT"; .hword 0xBE00;  .byte 0x04, 0x08  // instr type 4, special code 8 diff --git a/newasm/parsers/decimal.s b/newasm/parsers/decimal.s index a1516d2..cc9dff4 100644 --- a/newasm/parsers/decimal.s +++ b/newasm/parsers/decimal.s @@ -5,8 +5,6 @@  .type decimal, %function  .global decimal -// 1 not a digit -  // R4 input stream  // R2 output value @@ -35,5 +33,5 @@ loop:     LDRB    R0, [R4]    // get another char            MULS    R2, R3      // shift result by one decimal place            ADDS    R2, R0      // accumulate into R2            B       loop        // keep getting digits -bad:      MOVS    R0, #1      // return code 1 (not a digit) +bad:      MOVS    R0, #5      // return code 5 (not a digit)            BX      LR diff --git a/newasm/parsers/immediate.s b/newasm/parsers/immediate.s new file mode 100644 index 0000000..ac3e578 --- /dev/null +++ b/newasm/parsers/immediate.s @@ -0,0 +1,13 @@ +.syntax unified +.cpu cortex-m0plus +.thumb + +.type immediate, %function +.global immediate + +// R4 input buffer +// R2 output buffer + +immediate:PUSH    {LR} +          BL      decimal +          POP     {PC} diff --git a/newasm/parsers/label.s b/newasm/parsers/label.s index 4770e6c..45d39e5 100644 --- a/newasm/parsers/label.s +++ b/newasm/parsers/label.s @@ -5,9 +5,6 @@  .type label, %function  .global label -// 1 unexpected begin char -// 2 doesn't end with colon -  // R4 input buffer  // R2 output buffer @@ -23,7 +20,7 @@ label:    PUSH    {LR}            LDRB    R0, [R4]    // get a char            CMP     R0, ':      // colon            BEQ     3f -          MOVS    R0, #2      // return code 2 (expected colon) +          MOVS    R0, #3      // return code 3 (expected colon)            POP     {PC}  3:        ADDS    R4, 1       // consume the colon            MOVS    R0, #0      // return code 0 (success) diff --git a/newasm/parsers/register.s b/newasm/parsers/register.s index 48ebf7a..9334aa3 100644 --- a/newasm/parsers/register.s +++ b/newasm/parsers/register.s @@ -5,9 +5,6 @@  .type register, %function  .global register -// 1 unexpected char -// 2 invalid general-purpose register number -  // R4 input buffer  // R2 output buffer @@ -21,9 +18,12 @@ r_test:   CMP     R0, 'R            POP     {PC}        // error code already in R0  validate: CMP     R2, #12     // general purpose registers 0-12            BLS     success -          MOVS    R0, #2      // invalid register number error code +          MOVS    R0, #7      // invalid register number error code            POP     {PC} -special:  LDRH    R0, [R4]      // get two bytes from input stream +special:  LDRB    R0, [R4]      // get two bytes from input stream +          LDRB    R1, [R4, 1] +          LSLS    R1, 8 +          ORRS    R0, R1            ADR     R2, table     // get address of table            MOVS    R3, 0         // set table offset to 0  loop:     LDRH    R1, [R2, R3]  // get two bytes from table at current offset @@ -32,7 +32,7 @@ loop:     LDRH    R1, [R2, R3]  // get two bytes from table at current offset            ADDS    R3, 2         // increment table offset            CMP     R3, 6         // compare offset to table size            BLO     loop          // loop until end of table -          MOVS    R0, #1        // return code 1 (unexpected char) +          MOVS    R0, #6        // return code 6 (expected register)            POP     {PC}  done:     ADDS    R4, 2         // consume two chars            LSRS    R3, 1         // divide table offset by two to row @@ -41,6 +41,7 @@ done:     ADDS    R4, 2         // consume two chars  success:  MOVS    R0, #0        // return code 0 (success)            POP     {PC} +          .align  4  table:    .ascii  "SP"            .ascii  "LR"            .ascii  "PC" diff --git a/newasm/regimm.s b/newasm/regimm.s new file mode 100644 index 0000000..3e294c8 --- /dev/null +++ b/newasm/regimm.s @@ -0,0 +1,37 @@ +.syntax unified +.cpu cortex-m0plus +.thumb + +.type regimm, %function +.global regimm + +// R1 instruction under construction +// R3 immediate width +// R4 input buffer + +regimm:   PUSH    {LR} +          PUSH    {R3} +          BL      register    // parse a register +          POP     {R3} +          BNE     exit        // exit if failure +          CMP     R2, 7       // check that it's R0-R7 +          BHI     bad_reg +          LSLS    R2, 8       // shift by 8 +          ORRS    R1, R2      // fill in Rdn +          BL      whitespace  // mandatory whitespace +          BNE     exit        // exit if failure +          PUSH    {R3} +          BL      immediate +          POP     {R3} +          BNE     exit +          MOVS    R0, 1 +          LSLS    R0, R3 +          CMP     R2, R0 +          BLO     fine +          MOVS    R0, 0x0A    // returun code 0A (immediate value too large) +          POP     {PC} +fine:     ORRS    R1, R2      // fill in imm +          MOVS    R0, 0       // return code 0 (success) +exit:     POP     {PC} +bad_reg:  MOVS    R0, 8       // return code 8 (invalid register for this register position) +          POP     {PC} diff --git a/newasm/regreg.s b/newasm/regreg.s new file mode 100644 index 0000000..6893dee --- /dev/null +++ b/newasm/regreg.s @@ -0,0 +1,29 @@ +.syntax unified +.cpu cortex-m0plus +.thumb + +.type regreg, %function +.global regreg + +// R1 instruction under construction +// R2 output buffer +// R4 input buffer + +regreg:   PUSH    {LR} +          BL      register    // parse a register +          BNE     exit        // exit if failure +          CMP     R2, 7       // check that it's R0-R7 +          BHI     bad_reg +          ORRS    R1, R2      // fill in Rdn +          BL      whitespace  // mandatory whitespace +          BNE     exit        // exit if failure +          BL      register    // parse a register +          BNE     exit +          CMP     R2, 7       // check that it's R0-R7 +          BHI     bad_reg +          LSLS    R2, 3       // shift by 3 +          ORRS    R1, R2      // fill in Rm +          MOVS    R0, 0       // return code 0 (success) +exit:     POP     {PC} +bad_reg:  MOVS    R0, 8       // return code 8 (invalid register for this register position) +          POP     {PC} diff --git a/newasm/regregimm.s b/newasm/regregimm.s new file mode 100644 index 0000000..6c649e2 --- /dev/null +++ b/newasm/regregimm.s @@ -0,0 +1,47 @@ +.syntax unified +.cpu cortex-m0plus +.thumb + +.type regregimm, %function +.global regregimm + +// R1 instruction under construction +// R3 immediate width +// R4 input buffer + +regregimm:PUSH    {LR} +          PUSH    {R3} +          BL      register    // parse a register +          POP    {R3} +          BNE     exit        // exit if failure +          CMP     R2, 7       // check that it's R0-R7 +          BHI     bad_reg +          ORRS    R1, R2      // fill in Rd +          BL      whitespace  // mandatory whitespace +          BNE     exit        // exit if failure +          PUSH    {R3} +          BL      register    // parse a register +          POP     {R3} +          BNE     exit +          CMP     R2, 7       // check that it's R0-R7 +          BHI     bad_reg +          LSLS    R2, 3       // shift by 3 +          ORRS    R1, R2      // fill in Rn +          BL      whitespace  // mandatory whitespace +          BNE     exit        // exit if failure +          PUSH    {R3} +          BL      immediate +          POP     {R3} +          BNE     exit +          MOVS    R0, 1 +          LSLS    R0, R3 +          CMP     R2, R0 +          BLO     fine +          MOVS    R0, 0x0A    // returun code 0A (immediate value too large) +          POP     {PC} +fine:     LSLS    R2, 6       // shift by 6 +          ORRS    R1, R2      // fill in imm +          MOVS    R0, 0       // return code 0 (success) +exit:     POP     {PC} +bad_reg:  MOVS    R0, 8       // return code 8 (invalid register for this register position) +          POP     {PC} diff --git a/newasm/regregreg.s b/newasm/regregreg.s new file mode 100644 index 0000000..a8be6ee --- /dev/null +++ b/newasm/regregreg.s @@ -0,0 +1,44 @@ +.syntax unified +.cpu cortex-m0plus +.thumb + +.type regregreg, %function +.global regregreg + +// R1 instruction under construction +// R2 output buffer +// R4 input buffer + +regregreg:PUSH    {LR} + +          // TODO loop it +          BL      register    // parse a register +          BNE     exit        // exit if failure +          CMP     R2, 7       // check that it's R0-R7 +          BHI     bad_reg +          ORRS    R1, R2      // fill in Rd + +          BL      whitespace  // mandatory whitespace +          BNE     exit        // exit if failure + +          BL      register    // parse a register +          BNE     exit +          CMP     R2, 7       // check that it's R0-R7 +          BHI     bad_reg +          LSLS    R2, 3       // shift by 3 +          ORRS    R1, R2      // fill in Rn + +          BL      whitespace  // mandatory whitespace +          BNE     exit        // exit if failure + +          BL      register    // parse a register +          BNE     exit +          CMP     R2, 7       // check that it's R0-R7 +          BHI     bad_reg +          LSLS    R2, 6       // shift by 6 +          ORRS    R1, R2      // fill in Rm + +          MOVS    R0, 0       // return code 0 (success) +exit:     POP     {PC} +bad_reg:  MOVS    R0, 8       // return code 8 (invalid register for this register position) +          POP     {PC} diff --git a/newasm/statement.s b/newasm/statement.s index 4a199a6..436ae03 100644 --- a/newasm/statement.s +++ b/newasm/statement.s @@ -5,40 +5,47 @@  .type statement, %function  .global statement -// 1 reported an error -  // R4 input buffer  // R2 output buffer  statement:PUSH    {LR} -          BL      whitespace -          PUSH    {R2} +          MOVS    R3, R2        // save output buffer +          BL      whitespace    // skip leading whitespace            BL      label -          POP     {R2} -          CMP     R0, #2        // check for error code 2 (no colon) -          BNE     1f -          ADR     R0, no_colon -          B       err_exit +          CMP     R0, 3         // only exit for code 3 (no colon at end of label) +          BEQ     exit +          MOVS    R1, R0  1:        BL      whitespace -          PUSH    {R2} -          BL      opcode -          POP     {R2} -          BEQ     2f -          ADR     R0, no_opcode -          B       err_exit -2:        LDR     R0, [R2] +          MOVS    R2, 0         // reset output buffer +          STRB    R2, [R3] +          MOVS    R2, R3 +          BL      opcode        // TODO opcodes longer than 4 +          ADD     R0, R1 +          BNE     exit +2:        MOVS    R0, R3 +          PUSH    {R3} +          BL      putstrln +          POP     {R3} +          LDR     R0, [R3]            BL      lookup -          BEQ     3f -          ADR     R0, not_found -          B       err_exit -3:        POP     {PC}          // success code already in R0 -err_exit: BL      putstrln -          MOVS    R0, #1        // return code 1 (there was an error) -          POP     {PC} +          BNE     exit +          BL      whitespace    // TODO new return code for expected whitespace +          BNE     exit +          ADR     R0, parsers +          LSLS    R2, 2         // multiply by 4 to get byte offset +          LDR     R2, [R0, R2]  // get address of parser +          BLX     R2 +          BNE     exit +          BL      whitespace +          LDRB    R0, [R4]      // get a byte from the input stream +          TST     R0, R0        // check if zero +          BEQ     exit          // if it's zero then success +          MOVS    R0, 0x0B      // return code 0B (extra input at end) +exit:     POP     {PC} -            .align  4 -no_colon:   .asciz  "Error: Expected colon at end of label" -            .align  4 -no_opcode:  .asciz  "Error: Expected an opcode" -            .align  4 -not_found:  .asciz  "Error: Opcode not found" +          .align  4 +parsers:  .word   regreg +          .word   regregimm +          .word   regimm +          .word   regregreg +          .word   imm | 
