1/* $NetBSD: muldi3.S,v 1.2 2020/05/31 12:37:07 rin Exp $ */ 2 3/* 4 * Copyright (c) 2020 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Rin Okuyama. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32#include <machine/asm.h> 33 34RCSID("$NetBSD: muldi3.S,v 1.2 2020/05/31 12:37:07 rin Exp $") 35 36| int64_t __muldi3(int64_t X, int64_t Y); 37| 38| * Return lower 64bit of (X * Y) into %d0:%d1. 39| 40| * Intended for 68060: 41| - GCC does not emit __muldi3() for 68020-40, that have 32 * 32 --> 64 mulul. 42| - mulsl (and moveml) are not implemented for 68010. 43| 44| * Notation: 45| - H32:L32 --> higher:lower 32bit of variable 46| - H:L --> higher:lower 16bit of variable/register 47 48#ifdef __mc68010__ 49#error "not for 68010" 50#endif 51 52#define X_H32 (4 * 4) 53#define X_L32 (X_H32 + 4) 54#define Y_H32 (X_L32 + 4) 55#define Y_L32 (Y_H32 + 4) 56 57ENTRY(__muldi3) 58 moveml %d2-%d4, -(%sp) | push %d2-%d4 59 60| First, calculate (X_L32 * Y_L32) as a 64bit integer. 61 62 movel X_L32(%sp), %a0 | save X_L32 63 movel Y_L32(%sp), %a1 | save Y_L32 64 65 movel %a0, %d2 | prepare for X_L32(H) in L 66 movel %a1, %d3 | prepare for Y_L32(H) in L 67 68 movel %a0, %d4 | X_L32(L) in L 69 movel %a1, %d1 | Y_L32(L) in L 70 movel %a0, %d0 | X_L32(L) in L 71 72 swap %d2 | X_L32(H) in L 73 swap %d3 | Y_L32(H) in L 74 75 muluw %d1, %d4 | A = X_L32(L) * Y_L32(L) 76 muluw %d2, %d1 | B = X_L32(H) * Y_L32(L) 77 muluw %d3, %d2 | C = X_L32(H) * Y_L32(H) 78 muluw %d0, %d3 | D = X_L32(L) * Y_L32(H) 79 80 movel %d4, %d0 | extract A(H) 81 clrw %d0 82 swap %d0 83 84 addl %d0, %d1 | B += A(H) (no carry; max 0xffff0000) 85 86 addl %d3, %d1 | B += D 87 bccs 1f | if (carry) 88 addil #0x10000, %d2 | C += 0x10000 89 901: swap %d1 | B(H) <--> B(L) 91 92| (%d0), (%d1), %d2 = C, %d3 = free, %d4 = A 93 94 clrl %d3 | extract B(H) 95 movew %d1, %d3 96 97 movew %d4, %d1 | %d1 = (B(L) << 16) + A(L) 98 99 addl %d3, %d2 | C += B(H) 100 101| We have (X_L32 * Y_L32) in %d2:%d1. Lower 32bit was completed. 102| Add (X_L32 * Y_H32 + X_H32 * Y_L32) to higher 32bit. 103| 104| (%d0), (%d1), %d2 = C, %d3 = free, %d4 = free 105 106 movel %a0, %d0 | restore X_L32 107 movel %a1, %d3 | restore Y_L32 108 mulsl Y_H32(%sp), %d0 | E = X_L32 * Y_H32 109 mulsl X_H32(%sp), %d3 | F = X_H32 * Y_L32 110 addl %d2, %d0 | E += C 111 addl %d3, %d0 | %d0 = E + F 112 113 moveml (%sp)+, %d2-%d4 | pop %d2-%d4 114 rts 115END(__muldi3) 116