Retro68/gcc/libgcc/config/microblaze/muldi3_hard.S
2018-12-28 16:30:48 +01:00

151 lines
3.6 KiB
ArmAsm

###################################-
#
# Copyright (C) 2009-2018 Free Software Foundation, Inc.
#
# Contributed by Michael Eager <eager@eagercon.com>.
#
# This file 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, or (at your option) any
# later version.
#
# GCC 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.
#
# Under Section 7 of GPL version 3, you are granted additional
# permissions described in the GCC Runtime Library Exception, version
# 3.1, as published by the Free Software Foundation.
#
# You should have received a copy of the GNU General Public License and
# a copy of the GCC Runtime Library Exception along with this program;
# see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
# <http://www.gnu.org/licenses/>.
#
# muldi3_hard.S
#
# Multiply operation for 64 bit integers, for devices with hard multiply
# Input : Operand1[H] in Reg r5
# Operand1[L] in Reg r6
# Operand2[H] in Reg r7
# Operand2[L] in Reg r8
# Output: Result[H] in Reg r3
# Result[L] in Reg r4
#
# Explaination:
#
# Both the input numbers are divided into 16 bit number as follows
# op1 = A B C D
# op2 = E F G H
# result = D * H
# + (C * H + D * G) << 16
# + (B * H + C * G + D * F) << 32
# + (A * H + B * G + C * F + D * E) << 48
#
# Only 64 bits of the output are considered
#
#######################################
/* An executable stack is *not* required for these functions. */
#ifdef __linux__
.section .note.GNU-stack,"",%progbits
.previous
#endif
.globl muldi3_hardproc
.ent muldi3_hardproc
muldi3_hardproc:
addi r1,r1,-40
# Save the input operands on the caller's stack
swi r5,r1,44
swi r6,r1,48
swi r7,r1,52
swi r8,r1,56
# Store all the callee saved registers
sw r20,r1,r0
swi r21,r1,4
swi r22,r1,8
swi r23,r1,12
swi r24,r1,16
swi r25,r1,20
swi r26,r1,24
swi r27,r1,28
# Load all the 16 bit values for A through H
lhui r20,r1,44 # A
lhui r21,r1,46 # B
lhui r22,r1,48 # C
lhui r23,r1,50 # D
lhui r24,r1,52 # E
lhui r25,r1,54 # F
lhui r26,r1,56 # G
lhui r27,r1,58 # H
# D * H ==> LSB of the result on stack ==> Store1
mul r9,r23,r27
swi r9,r1,36 # Pos2 and Pos3
# Hi (Store1) + C * H + D * G ==> Store2 ==> Pos1 and Pos2
# Store the carry generated in position 2 for Pos 3
lhui r11,r1,36 # Pos2
mul r9,r22,r27 # C * H
mul r10,r23,r26 # D * G
add r9,r9,r10
addc r12,r0,r0
add r9,r9,r11
addc r12,r12,r0 # Store the Carry
shi r9,r1,36 # Store Pos2
swi r9,r1,32
lhui r11,r1,32
shi r11,r1,34 # Store Pos1
# Hi (Store2) + B * H + C * G + D * F ==> Store3 ==> Pos0 and Pos1
mul r9,r21,r27 # B * H
mul r10,r22,r26 # C * G
mul r7,r23,r25 # D * F
add r9,r9,r11
add r9,r9,r10
add r9,r9,r7
swi r9,r1,32 # Pos0 and Pos1
# Hi (Store3) + A * H + B * G + C * F + D * E ==> Store3 ==> Pos0
lhui r11,r1,32 # Pos0
mul r9,r20,r27 # A * H
mul r10,r21,r26 # B * G
mul r7,r22,r25 # C * F
mul r8,r23,r24 # D * E
add r9,r9,r11
add r9,r9,r10
add r9,r9,r7
add r9,r9,r8
sext16 r9,r9 # Sign extend the MSB
shi r9,r1,32
# Move results to r3 and r4
lhui r3,r1,32
add r3,r3,r12
shi r3,r1,32
lwi r3,r1,32 # Hi Part
lwi r4,r1,36 # Lo Part
# Restore Callee saved registers
lw r20,r1,r0
lwi r21,r1,4
lwi r22,r1,8
lwi r23,r1,12
lwi r24,r1,16
lwi r25,r1,20
lwi r26,r1,24
lwi r27,r1,28
# Restore Frame and return
rtsd r15,8
addi r1,r1,40
.end muldi3_hardproc