/* $NetBSD: cpu_in_cksum.S,v 1.12 2024/02/07 04:20:27 msaitoh Exp $ */ /*- * Copyright (c) 2000 SHIMIZU Ryo * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _LOCORE #define _LOCORE #endif #include #include #include "assym.h" __KERNEL_RCSID(0, "$NetBSD: cpu_in_cksum.S,v 1.12 2024/02/07 04:20:27 msaitoh Exp $") #define reg_byte_swapped r1 #define reg_mlen r2 #define reg_tmp3 r3 #define reg_m r4 #define reg_len r5 #define reg_off r6 #define reg_w r6 /* recycle */ #define reg_sum r7 #define REDUCE \ swap.w reg_sum, r0 ; \ extu.w reg_sum, reg_sum ; \ extu.w r0, r0 ; \ add r0, reg_sum #define ROL \ shll8 reg_sum #if _BYTE_ORDER == BIG_ENDIAN #define ADDB \ mov.b @reg_w+, r0 ; \ ROL ; \ extu.b r0, r0 ; \ add r0, reg_sum ; \ not reg_byte_swapped, reg_byte_swapped #else #define ADDB \ mov.b @reg_w+, r0 ; \ extu.b r0, r0 ; \ add r0, reg_sum ; \ ROL ; \ not reg_byte_swapped, reg_byte_swapped #endif #define ADDS \ mov.w @reg_w+, r0 ; \ extu.w r0, r0 ; \ add r0, reg_sum #define ADDCL \ mov.l @reg_w+, r0 ; \ addc r0, reg_sum #define FORWARD1 \ add #-1, reg_mlen #define FORWARD2 \ add #-2, reg_mlen /* * LINTSTUB: include * LINTSTUB: include * * LINTSTUB: Func: int cpu_in_cksum(struct mbuf *m, int len, int off, uint32_t initial_sum); */ ENTRY(cpu_in_cksum) sts.l pr, @-sp PIC_PROLOGUE(.L_got) tst reg_len, reg_len bt/s mbuf_loop_done mov #0, reg_byte_swapped .L_mbuf_skip: tst reg_m, reg_m bt out_of_mbufs mov.l @(M_LEN, reg_m), reg_mlen cmp/gt reg_off, reg_mlen /* mlen > off ? */ bt .L_mbuf_found !! while (off >= mlen) mov.l @(M_NEXT, reg_m), reg_m ! m = m->m_next bra .L_mbuf_skip sub reg_mlen, reg_off ! off -= mlen .L_mbuf_found: !! if (mlen > off) mov.l @(M_DATA, reg_m), reg_tmp3 sub reg_off, reg_mlen ! mlen -= off bra .L_mbuf_loop_enter add reg_tmp3, reg_off ! w = m->m_data + off #undef reg_off /* it is dead now and we recycle it for reg_w */ mbuf_loop: tst reg_m, reg_m bt out_of_mbufs mov.l @(M_LEN, reg_m), reg_mlen tst reg_mlen, reg_mlen bt/s mbuf_loop_continue mov.l @(M_DATA, reg_m), reg_w !! Entry point for mbuf loop. We jump here after we have !! found the mbuf (reg_m) that contains data at the specified !! offset. reg_mlen and reg_w were adjusted to point at the !! first interesting byte of data. .L_mbuf_loop_enter: cmp/ge reg_mlen, reg_len bt 1f mov reg_len, reg_mlen 1: sub reg_mlen, reg_len mov reg_w, r0 tst #1, r0 bt/s 1f REDUCE /* 1st instruction break only r0 */ ADDB FORWARD1 1: mov #1, r0 cmp/gt r0, reg_mlen bf/s 1f mov reg_w, r0 tst #2, r0 bt/s 1f REDUCE /* 1st instruction break only r0 */ ADDS FORWARD2 1: mov #127, r0 cmp/hi r0, reg_mlen bf 1f do_cksum128: bsr cksum128 nop mov #127, r0 cmp/hi r0, reg_mlen bt do_cksum128 1: bsr cksum128mod nop REDUCE mov #1, r0 cmp/gt r0, reg_mlen bf 1f ADDS FORWARD2 1: mov reg_mlen, r0 tst #1, r0 bt 1f ADDB 1: mbuf_loop_continue: mov.l @(M_NEXT, reg_m), reg_m tst reg_len, reg_len bf/s mbuf_loop mbuf_loop_done: tst reg_byte_swapped, reg_byte_swapped bt/s 1f REDUCE /* 1st instruction break only r0 */ ROL 1: REDUCE REDUCE in_cksum_return: not reg_sum, r0 PIC_EPILOGUE lds.l @sp+, pr rts extu.w r0, r0 out_of_mbufs: mova .L_message_out_of_data, r0 mov.l .L_printf, reg_tmp3 mov.l reg_sum, @-sp /* save: call clobbered register */ 1: CALL reg_tmp3 mov r0, r4 bra in_cksum_return mov.l @sp+, reg_sum /* restore */ .align 2 .L_got: PIC_GOT_DATUM .L_printf: CALL_DATUM(_C_LABEL(printf), 1b) .align 2 /* mova target */ .L_message_out_of_data: .asciz "cksum: out of data (%d byte short)\n" SET_ENTRY_SIZE(cpu_in_cksum) .align 2 cksum128mod: mov reg_mlen, r0 and #124, r0 sub r0, reg_mlen mov r0, reg_tmp3 mova cksum128_tail, r0 sub reg_tmp3, r0 jmp @r0 clrt .align 2 cksum128: add #-128, reg_mlen clrt cksum128_unroll: ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL ADDCL cksum128_tail: mov #0, r0 rts addc r0, reg_sum