1/* $NetBSD: cpu_in_cksum.S,v 1.12 2024/02/07 04:20:27 msaitoh Exp $ */ 2 3/*- 4 * Copyright (c) 2000 SHIMIZU Ryo 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30#ifndef _LOCORE 31#define _LOCORE 32#endif 33#include <machine/endian.h> 34#include <machine/asm.h> 35#include "assym.h" 36 37__KERNEL_RCSID(0, "$NetBSD: cpu_in_cksum.S,v 1.12 2024/02/07 04:20:27 msaitoh Exp $") 38 39 40#define reg_byte_swapped r1 41#define reg_mlen r2 42#define reg_tmp3 r3 43#define reg_m r4 44#define reg_len r5 45#define reg_off r6 46#define reg_w r6 /* recycle */ 47#define reg_sum r7 48 49 50#define REDUCE \ 51 swap.w reg_sum, r0 ; \ 52 extu.w reg_sum, reg_sum ; \ 53 extu.w r0, r0 ; \ 54 add r0, reg_sum 55 56#define ROL \ 57 shll8 reg_sum 58 59#if _BYTE_ORDER == BIG_ENDIAN 60#define ADDB \ 61 mov.b @reg_w+, r0 ; \ 62 ROL ; \ 63 extu.b r0, r0 ; \ 64 add r0, reg_sum ; \ 65 not reg_byte_swapped, reg_byte_swapped 66#else 67#define ADDB \ 68 mov.b @reg_w+, r0 ; \ 69 extu.b r0, r0 ; \ 70 add r0, reg_sum ; \ 71 ROL ; \ 72 not reg_byte_swapped, reg_byte_swapped 73#endif 74 75 76#define ADDS \ 77 mov.w @reg_w+, r0 ; \ 78 extu.w r0, r0 ; \ 79 add r0, reg_sum 80 81#define ADDCL \ 82 mov.l @reg_w+, r0 ; \ 83 addc r0, reg_sum 84 85#define FORWARD1 \ 86 add #-1, reg_mlen 87 88#define FORWARD2 \ 89 add #-2, reg_mlen 90 91 92/* 93 * LINTSTUB: include <sys/param.h> 94 * LINTSTUB: include <sys/mbuf.h> 95 * 96 * LINTSTUB: Func: int cpu_in_cksum(struct mbuf *m, int len, int off, uint32_t initial_sum); 97 */ 98ENTRY(cpu_in_cksum) 99 sts.l pr, @-sp 100 PIC_PROLOGUE(.L_got) 101 102 tst reg_len, reg_len 103 bt/s mbuf_loop_done 104 mov #0, reg_byte_swapped 105 106.L_mbuf_skip: 107 tst reg_m, reg_m 108 bt out_of_mbufs 109 110 mov.l @(M_LEN, reg_m), reg_mlen 111 cmp/gt reg_off, reg_mlen /* mlen > off ? */ 112 bt .L_mbuf_found 113 114 !! while (off >= mlen) 115 mov.l @(M_NEXT, reg_m), reg_m ! m = m->m_next 116 bra .L_mbuf_skip 117 sub reg_mlen, reg_off ! off -= mlen 118 119 120.L_mbuf_found: !! if (mlen > off) 121 mov.l @(M_DATA, reg_m), reg_tmp3 122 sub reg_off, reg_mlen ! mlen -= off 123 bra .L_mbuf_loop_enter 124 add reg_tmp3, reg_off ! w = m->m_data + off 125 126#undef reg_off /* it is dead now and we recycle it for reg_w */ 127 128 129mbuf_loop: 130 tst reg_m, reg_m 131 bt out_of_mbufs 132 133 mov.l @(M_LEN, reg_m), reg_mlen 134 tst reg_mlen, reg_mlen 135 bt/s mbuf_loop_continue 136 mov.l @(M_DATA, reg_m), reg_w 137 138 139 !! Entry point for mbuf loop. We jump here after we have 140 !! found the mbuf (reg_m) that contains data at the specified 141 !! offset. reg_mlen and reg_w were adjusted to point at the 142 !! first interesting byte of data. 143.L_mbuf_loop_enter: 144 cmp/ge reg_mlen, reg_len 145 bt 1f 146 mov reg_len, reg_mlen 1471: 148 sub reg_mlen, reg_len 149 150 151 mov reg_w, r0 152 tst #1, r0 153 bt/s 1f 154 REDUCE /* 1st instruction break only r0 */ 155 ADDB 156 FORWARD1 1571: 158 159 160 mov #1, r0 161 cmp/gt r0, reg_mlen 162 bf/s 1f 163 mov reg_w, r0 164 tst #2, r0 165 bt/s 1f 166 REDUCE /* 1st instruction break only r0 */ 167 ADDS 168 FORWARD2 1691: 170 171 172 173 mov #127, r0 174 cmp/hi r0, reg_mlen 175 bf 1f 176 177do_cksum128: 178 bsr cksum128 179 nop 180 181 mov #127, r0 182 cmp/hi r0, reg_mlen 183 bt do_cksum128 1841: 185 186 187 bsr cksum128mod 188 nop 189 190 REDUCE 191 192 mov #1, r0 193 cmp/gt r0, reg_mlen 194 bf 1f 195 ADDS 196 FORWARD2 1971: 198 199 mov reg_mlen, r0 200 tst #1, r0 201 bt 1f 202 ADDB 2031: 204 205 206mbuf_loop_continue: 207 mov.l @(M_NEXT, reg_m), reg_m 208 209 tst reg_len, reg_len 210 bf/s mbuf_loop 211mbuf_loop_done: 212 213 214 tst reg_byte_swapped, reg_byte_swapped 215 bt/s 1f 216 REDUCE /* 1st instruction break only r0 */ 217 ROL 2181: 219 220 REDUCE 221 REDUCE 222 223in_cksum_return: 224 not reg_sum, r0 225 PIC_EPILOGUE 226 lds.l @sp+, pr 227 rts 228 extu.w r0, r0 229 230 231out_of_mbufs: 232 mova .L_message_out_of_data, r0 233 mov.l .L_printf, reg_tmp3 234 235 mov.l reg_sum, @-sp /* save: call clobbered register */ 236 2371: CALL reg_tmp3 238 mov r0, r4 239 240 bra in_cksum_return 241 mov.l @sp+, reg_sum /* restore */ 242 243 .align 2 244.L_got: 245 PIC_GOT_DATUM 246.L_printf: 247 CALL_DATUM(_C_LABEL(printf), 1b) 248 249 .align 2 /* mova target */ 250.L_message_out_of_data: 251 .asciz "cksum: out of data (%d byte short)\n" 252 253 SET_ENTRY_SIZE(cpu_in_cksum) 254 255 256 .align 2 257cksum128mod: 258 mov reg_mlen, r0 259 and #124, r0 260 sub r0, reg_mlen 261 mov r0, reg_tmp3 262 263 mova cksum128_tail, r0 264 sub reg_tmp3, r0 265 jmp @r0 266 clrt 267 268 .align 2 269cksum128: 270 add #-128, reg_mlen 271 clrt 272 273cksum128_unroll: 274 ADDCL 275 ADDCL 276 ADDCL 277 ADDCL 278 ADDCL 279 ADDCL 280 ADDCL 281 ADDCL 282 ADDCL 283 ADDCL 284 ADDCL 285 ADDCL 286 ADDCL 287 ADDCL 288 ADDCL 289 ADDCL 290 ADDCL 291 ADDCL 292 ADDCL 293 ADDCL 294 ADDCL 295 ADDCL 296 ADDCL 297 ADDCL 298 ADDCL 299 ADDCL 300 ADDCL 301 ADDCL 302 ADDCL 303 ADDCL 304 ADDCL 305 ADDCL 306cksum128_tail: 307 mov #0, r0 308 rts 309 addc r0, reg_sum 310