## Copyright (C) 2016 Jeremiah Orians ## This file is part of M2-Planet. ## ## M2-Planet is free software: you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation, either version 3 of the License, or ## (at your option) any later version. ## ## M2-Planet is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with M2-Planet. If not, see . :_start '0' SP BP NO_SHIFT MOVE_ALWAYS ; Setup Base Pointer ;; Prepare argv !4 R0 ADD BP ARITH_ALWAYS ; ARGV_address = BP + 4 {R0} PUSH_ALWAYS ; Put argv on the stack ;; Prepare envp '0' BP R0 NO_SHIFT MOVE_ALWAYS ; Address we need to load from !0 R0 LOAD32 R0 MEMORY ; Get ARGC !2 R0 ADD R0 ARITH_ALWAYS ; OFFSET = ARGC + 2 '0' R0 R0 '1' MOVE_ALWAYS ; OFFSET = OFFSET * WORDSIZE '0' R0 R0 ADD BP ARITH2_ALWAYS ; ENVP_address = BP + OFFSET {R0} PUSH_ALWAYS ; Put envp on the stack ;; Stack offset !4 BP ADD BP ARITH_ALWAYS ; Fix BP ^~FUNCTION_main CALL_ALWAYS ; Jump right into main !1 R7 LOADI8_ALWAYS ; Setup for final exit SYSCALL_ALWAYS ; Exit # Unsigned Divide :divide {R4} PUSH_ALWAYS ; Protect R4 {R3} PUSH_ALWAYS ; Protect R3 {R2} PUSH_ALWAYS ; Protect R2 '0' R0 R3 NO_SHIFT MOVE_ALWAYS ; MOV R3,R0 '0' R1 R2 NO_SHIFT MOVE_ALWAYS ; MOV R2,R1 !0 R0 LOADI8_ALWAYS ; MOV R0,#0 !0 CMPI8 R2 IMM_ALWAYS ; CMP R2,#0 !1 R0 SUB R0 ARITH_LT ; SUBLT R0,R0,#1 !0 CMPI8 R3 IMM_ALWAYS ; CMP R3,#0 !0 R3 RSUB R3 ARITH_LT ; RSBLT R3,R3,#0 '0' R0 R0 MVN_LT ; MVNLT R0,R0 '0' R0 R4 NO_SHIFT MOVE_ALWAYS ; MOV R4,R0 !32 R0 LOADI8_ALWAYS ; MOV R0,#32. !0 R1 LOADI8_ALWAYS ; MOV R1,#0 :divide_loop '0' R2 R2 ADDS R2 ARITH2_ALWAYS ; ADDS R2,R2,R2 '0' R1 R1 ADCS R1 ARITH2_ALWAYS ; ADCS R1,R1,R1 '0' R3 CMP R1 AUX_ALWAYS ; CMP R1,R3 '0' R3 R1 SUB R1 ARITH2_GE ; SUBGE R1,R1,R3 !1 R2 ADD R2 ARITH_GE ; ADDGE R2,R2,#1 !1 R0 SUB R0 ARITH_ALWAYS ; SUB R0,R0,#1 !0 CMPI8 R0 IMM_ALWAYS ; CMP R0,#0 ^~divide_loop JUMP_NE ; BNE loop '0' R2 R0 NO_SHIFT MOVE_ALWAYS ; MOV R0,R2 {R2} POP_ALWAYS ; Restore R2 {R3} POP_ALWAYS ; Restore R3 {R4} POP_ALWAYS ; Restore R4 '1' LR RETURN # Signed Divide :divides {R4} PUSH_ALWAYS ; Protect R4 {R3} PUSH_ALWAYS ; Protect R3 {R2} PUSH_ALWAYS ; Protect R2 '0' R0 R3 NO_SHIFT MOVE_ALWAYS ; MOV R3,R0 '0' R1 R2 NO_SHIFT MOVE_ALWAYS ; MOV R2,R1 !0 R0 LOADI8_ALWAYS ; MOV R0,#0 !0 CMPI8 R2 IMM_ALWAYS ; CMP R2,#0 !0 R2 RSUB R2 ARITH_LT ; RSBLT R2,R2,#0 !1 R0 SUB R0 ARITH_LT ; SUBLT R0,R0,#1 !0 CMPI8 R3 IMM_ALWAYS ; CMP R3,#0 !0 R3 RSUB R3 ARITH_LT ; RSBLT R3,R3,#0 '0' R0 R0 MVN_LT ; MVNLT R0,R0 '0' R0 R4 NO_SHIFT MOVE_ALWAYS ; MOV R4,R0 !32 R0 LOADI8_ALWAYS ; MOV R0,#32. !0 R1 LOADI8_ALWAYS ; MOV R1,#0 :divides_loop '0' R2 R2 ADDS R2 ARITH2_ALWAYS ; ADDS R2,R2,R2 '0' R1 R1 ADCS R1 ARITH2_ALWAYS ; ADCS R1,R1,R1 '0' R3 CMP R1 AUX_ALWAYS ; CMP R1,R3 '0' R3 R1 SUB R1 ARITH2_GE ; SUBGE R1,R1,R3 !1 R2 ADD R2 ARITH_GE ; ADDGE R2,R2,#1 !1 R0 SUB R0 ARITH_ALWAYS ; SUB R0,R0,#1 !0 CMPI8 R0 IMM_ALWAYS ; CMP R0,#0 ^~divides_loop JUMP_NE ; BNE loop !0 CMPI8 R4 IMM_ALWAYS ; CMP R4,#0 !0 R2 RSUB R2 ARITH_NE ; RSBNE R2,R2,#0 '0' R2 R0 NO_SHIFT MOVE_ALWAYS ; MOV R0,R2 {R2} POP_ALWAYS ; Restore R2 {R3} POP_ALWAYS ; Restore R3 {R4} POP_ALWAYS ; Restore R4 '1' LR RETURN # Unsigned Modulus :modulus {LR} PUSH_ALWAYS ; Prepare to leverage divide ^~divide CALL_ALWAYS ; Use divide '0' R1 R0 NO_SHIFT MOVE_ALWAYS ; MOV R0,R1 {LR} POP_ALWAYS ; Prepare for return '1' LR RETURN # Signed Modulus :moduluss {LR} PUSH_ALWAYS ; Prepare to leverage divide ^~divides CALL_ALWAYS ; Use divides '0' R1 R0 NO_SHIFT MOVE_ALWAYS ; MOV R0,R1 {LR} POP_ALWAYS ; Prepare for return '1' LR RETURN