146 lines
4.9 KiB
Plaintext
146 lines
4.9 KiB
Plaintext
|
### GNU Mes --- Maxwell Equations of Software
|
||
|
### Copyright (C) 2016 Jeremiah Orians
|
||
|
### Copyright © 2022 Jan (janneke) Nieuwenhuizen <janneke@gnu.org>
|
||
|
###
|
||
|
### This file is part of GNU Mes.
|
||
|
###
|
||
|
### GNU Mes 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.
|
||
|
###
|
||
|
### GNU Mes 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 GNU Mes. If not, see <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
:_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
|
||
|
|
||
|
mov____%r0,0x32 &GLOBAL_environ
|
||
|
|
||
|
;; Stack offset
|
||
|
!4 BP ADD BP ARITH_ALWAYS ; Fix BP
|
||
|
|
||
|
;;^~FUNCTION___init_io CALL_ALWAYS ; Setup for FILE*
|
||
|
|
||
|
;; Initialize MesCC lib file descriptors.
|
||
|
!0 mov____$i8,%r0
|
||
|
mov____%r0,0x32 &GLOBAL___stdin
|
||
|
!1 mov____$i8,%r0
|
||
|
mov____%r0,0x32 &GLOBAL___stdout
|
||
|
!2 mov____$i8,%r0
|
||
|
mov____%r0,0x32 &GLOBAL___stderr
|
||
|
|
||
|
^~FUNCTION_main CALL_ALWAYS ; Jump right into main
|
||
|
|
||
|
SYS_exit mov____$i8,%r7
|
||
|
swi____$0
|
||
|
|
||
|
|
||
|
# 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
|