.syntax unified .cpu cortex-m0plus .thumb .type assemble, %function .global assemble // TODO: // - implement opcode parser // - test each instruction (do this later -- much easier) // - test 4-bit reg instructions // - test BEQ overlaps // - decide on additional push or pops assemble: // LDR R3, [SP, 20] MOVS R6, 0 LDR R7, =0x00C8E893 // LDR R7, =0xE0E3A588 MOVS R0, ' MOV R8, R0 main_loop: LSRS R0, R7, 8 // just peek BNE skip // if more stuff then skip MOVS R0, '\r MOV R8, R0 //set end char to carriage return skip: // MOVS R0, 0xFF // lsb mask // ANDS R0, R7 // store in R0 UXTB R0, R7 // store lsb in R0 LSRS R1, R0, 4 // upper nibble CMP R1, 0xC // if 0xxxxxxx or 10xxxxxx BLO opcode CMP R1, 0xE // if 110xyyyy BLO handle_imm handle_reg: // if 111xyyyy MOVS R1, (1<<4) // bit 4 mask ANDS R0, R1 // get bit 4 ADDS R0, 3 // add 3 to it (now 3 or 4) BL register // result is put in R4 MOVS R0, 0x0F // lower nibble mask ANDS R0, R7 // store shift amount in R0 LSLS R4, R0 // shift the result by the shift amount ORRS R6, R4 // OR the register code into the word under construction B done_stuff opcode: MOVS R2, 9 // shift amount for 7-bit opcode MOVS R1, (1<<7) // bit 7 mask TST R0, R1 // check bit 7 BEQ fin // if zero done BICS R0, R1 // clear bit 7 MOVS R2, 11 // shift amount for 5-bit opcode high MOVS R1, (1<<5) // bit 5 mask TST R0, R1 // check bit 5 BEQ fin // if zero done BICS R0, R1 // clear bit 5 MOVS R2, 6 // shift amount for 5-bit opcode low fin: LSLS R0, R2 ORRS R6, R0 B here handle_imm: MOVS R1, 0x0F // lower nibble mask ANDS R0, R1 // store immediate width in R0 BL octal // result is put in R4 LSLS R0, R7, 27 LSRS R0, 31 MOVS R2, 6 MULS R0, R2 // R0 has shift amount (0 or 6) LSLS R4, R0 // shift the result by the shift amount ORRS R6, R4 // OR the immediate into the word under construction done_stuff: MOV R0, R8 // copy the end_char into R0 BL uart_send // echo the space (or carriage return) here: LSRS R7, 0x8 // get next parse instruction BNE main_loop // if it's nonzero there are more things to parse done: MOVS R0, '\n // send newline BL uart_send MOVS R0, R6 BL send_hex B assemble .type get_char, %function .global get_char // R8: end_char get_char: PUSH {LR} BL uart_recv CMP R0, 025 // ^U (NAK) BEQ redo_line // CMP R0, 004 // ^D (EOT) // BEQ done_for_real CMP R0, R8 POP {PC} redo_line: POP {R0} B done