; SPDX-FileCopyrightText: 2025 Leo Marušić <leomarusic7@gmail.com> ; SPDX-License-Identifier: MIT MAIN: MOV SP, #0x10000 ; stack initialization LDR R0, MEM ; pointer to the address of the operands LDR R12, REZ ; pointer for the result address MAINLOOP: ADD R0, R0, #0x8 ; point to the operation in the operand block LDR R1, [R0] ; save the operation code in R1 CMP R1, #0x0 ; check for subtraction BEQ SUBTRACT CMP R1, #0x1 ; check for addition BEQ ADDLOOP CMP R1, #0x2 ; check for multiplication BEQ MULLOOP CMP R1, #0x3 ; check for division BEQ DIVIDEOP MVN R2, #0x0 ; put 0xFFFFFFFF in R2 CMP R1, R2 ; check for the end BEQ FINISH B MAINLOOP ; go back to the loop SUBTRACT: SUB R0, R0, #0x8 ; go back to the beginning of the operand block LDR R1, [R0] ; load the first operand LDR R2, [R0, #0x4] ; load the second operand SUB R3, R1, R2 ; subtract STR R3, [R12] ; save the result ADD R12, R12, #0x4 ; move the result address pointer ADD R0, R0, #0xC ; move the operand address pointer B MAINLOOP ADDLOOP: SUB R0, R0, #0x8 ; go back to the beginning of the operand block LDR R1, [R0] ; load the first operand LDR R2, [R0, #0x4] ; load the second operand ADD R3, R1, R2 ; add STR R3, [R12] ; save the result ADD R12, R12, #0x4 ; move the result address pointer ADD R0, R0, #0xC ; move the operand address pointer B MAINLOOP MULLOOP: SUB R0, R0, #0x8 ; go back to the beginning of the operand block LDR R1, [R0] ; load the first operand LDR R2, [R0, #0x4] ; load the second operand MUL R3, R1, R2 ; multiply STR R3, [R12] ; save the result ADD R12, R12, #0x4 ; move the result address pointer ADD R0, R0, #0xC ; move the operand address pointer B MAINLOOP DIVIDEOP: SUB R0, R0, #0x8 ; go back to the beginning of the operand block LDR R1, [R0] ; load the first operand LDR R2, [R0, #0x4] ; load the second operand SUB SP, SP, #0x4 ; space for the result STMFD SP!, {R1-R2} ; put the operands on the stack BL DIVIDE ADD SP, SP, #0x8 ; stack cleanup LDMFD SP!, {R3} ; retrieve the result STR R3, [R12] ; save the result ADD R12, R12, #0x4 ; move the result address pointer ADD R0, R0, #0xC ; move the operand address pointer B MAINLOOP DIVIDE: STMFD SP!, {R3-R5} ; save the context LDR R3, [SP, #12] ; load the numerator LDR R4, [SP, #16] ; load the denominator MOV R5, #0 ; quotient CMP R4, #0x0 ; check for division by zero BEQ ZERO CMP R3, #0 ; check if the numerator is negative MVNLT R3, R3 ; 1's complement ADDLT R3, R3, #1 ; 2's complement CMP R4, #0 ; check if the denominator is negative MVNLT R4, R4 ; 1's complement ADDLT R4, R4 , #1 ; 2's complement LOOP1: CMP R3, R4 ; compare the numerator and the denominator BLT DONE ; if the numerator is less than the denominator, the division is finished SUB R3, R3, R4 ; subtract the denominator from the numerator ADD R5, R5, #1 ; increment the quotient B LOOP1 DONE: CMP R1, #0 ; check the sign of the original numerator MVNLT R5, R5 ; 1's complement the quotient ADDLT R5, R5, #1 ; 2's complement the quotient CMP R2, #0 ; check the sign of the original denominator MVNLT R5, R5 ; 1's complement the quotient ADDLT R5, R5 , #1 ; 2's complement the quotient STR R5, [SP, #20] ; put the result on the stack LDMFD SP!, {R3-R5} ; restore the context MOV PC, LR ZERO: STR R5, [SP, #20] ; save zero as the result on the stack LDMFD SP!, {R3-R5} ; restore the context MOV PC, LR FINISH: MVN R11, #0x0 ; marker for the end of the output STR R11, [R12] ; save the marker at the end of the output SWI 0x123456 MEM: DW 0x600 ; Memory for the operands ORG 0x600 DW 0xFFFFFEFF DW 0x00000010 DW 0x00000003 DW 0x000001F4 DW 0xFFFFFD44 DW 0x00000000 DW 0x00000003 DW 0xFFFFFFEC DW 0x00000001 DW 0xFFFFFFFE DW 0x0000000A DW 0x00000002 DW 0xFFFFF000 DW 0xFFFFFFC0 DW 0x00000003 DW 0x00000001 DW 0x00000004 DW 0xFFFFFFFF RES: DW 0x2000 ; memory for the result ORG 0x2000 DW 0x0000 DW 0x0000 DW 0x0000 DW 0x0000 DW 0x0000 DW 0x0000 DW 0x0000 DW 0x0000 DW 0x0000 DW 0x0000 DW 0x0000 DW 0x0000 DW 0x0000