1/* $OpenBSD: in_cksum.S,v 1.4 2023/01/04 14:58:04 jsg Exp $ */ 2/* $NetBSD: in_cksum.S,v 1.2 2001/08/10 20:53:11 eeh Exp $ */ 3 4/* 5 * Copyright (c) 2001 Eduardo Horvath 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "assym.h" 29#include <machine/asm.h> 30 31/* 32 * int in_cksum(struct mbuf *m, int len) 33 * int in_cksum_internal(struct mbuf *m, int len, int offset, int sum) 34 * 35 * The only fields of the mbuf we really care about 36 * is m_next and m_len and m_data. 37 * 38 * 39 * Register usage: 40 * 41 * %o0 - mbuf 42 * %o1 - len 43 * %o2 - mlen 44 * %o3 - sum 45 * %o4 - temp 46 * %o5 - mdata 47 * %g1 - swapped 48 * %g4 - temp 49 * %g5 - temp 50 */ 51 52#define IALIGN .align 32 53 54ENTRY(in_cksum) 55 clr %o3 ! sum = 0; 56 clr %o2 57_ENTRY(in_cksum_internal) 58 brz %o0, Lfinish ! for (; m && len > 0; m->m_next) { 59 clr %g1 ! swapped = 0; 60 brlez %o1, Lfinish 61 mov %o2, %o4 ! Stash this elsewhere for a bit 62 63 lduw [%o0 + M_LEN], %o2 ! Code duplicated at Lloop 64 srlx %o3, 32, %g4 ! REDUCE bigtime 65 sethi %hi(0xffff), %g5 66 ldx [%o0 + M_DATA], %o5 67 srl %o3, 0, %o3 68 or %g5, %lo(0xffff), %g5 69 70 sub %o2, %o4, %o2 ! Correct for initial offset 71 ba,pt %icc, 0f 72 add %o5, %o4, %o5 73 74 IALIGN 75Lloop: 76 lduw [%o0 + M_LEN], %o2 77 srlx %o3, 32, %g4 ! REDUCE bigtime 78 sethi %hi(0xffff), %g5 79 ldx [%o0 + M_DATA], %o5 80 srl %o3, 0, %o3 81 or %g5, %lo(0xffff), %g5 820: 83 add %o3, %g4, %o3 84 brz %o2, Lnext ! if (m->m_len == 0) continue; 85 86 cmp %o1, %o2 ! if (len < mlen) 87 movl %icc, %o1, %o2 ! mlen = len; 88 89 btst 3, %o5 ! if (!(*w & 3)) { 90 bz Lint_aligned 91 sub %o1, %o2, %o1 ! len -= mlen 92 93 srlx %o3, 16, %o4 ! REDUCE {sum = (sum & 0xffff) + (sum >> 16);} 94 and %o3, %g5, %o3 95 96 add %o3, %o4, %o3 97 btst 1, %o5 ! if (!(*w & 3) && 98 bz Lshort_aligned 99 nop 100 101 deccc %o2 102 bl,a,pn %icc, Lnext ! mlen >= 1) { 103 inc %o2 104 ldub [%o5], %o4 ! ADDBYTE {ROL; sum += *w; byte_swapped ^= 1;} 105 sllx %o3, 8, %o3 ! ROL { sum = sum << 8; } 106 inc %o5 ! } 107 add %o3, %o4, %o3 108 xor %g1, 1, %g1 ! Flip byte_swapped 109 110Lshort_aligned: 111 btst 2, %o5 ! if (!(*w & 3) && 112 bz Lint_aligned 113 nop 114 115 deccc 2, %o2 ! mlen >= 1) { 116 bl,a,pn %icc, Lfinish_byte 117 inc 2, %o2 118 lduh [%o5], %o4 ! ADDSHORT {sum += *(u_short *)w;} 119 inc 2, %o5 ! } 120 add %o3, %o4, %o3 ! } 121Lint_aligned: 122 deccc 0xc, %o2 ! while (mlen >= 12) { 123 ble,pn %icc, Ltoofar 124 clr %g5 125 ba,pt %icc, 0f 126 clr %g4 127 IALIGN 1280: 129 lduw [%o5 + 0x00], %o4 130 add %o3, %g4, %o3 131 deccc 0xc, %o2 132 lduw [%o5 + 0x04], %g4 133 add %o3, %g5, %o3 134 lduw [%o5 + 0x08], %g5 135 inc 0xc, %o5 ! ADVANCE(12) } 136 bg,pt %icc, 0b 137 add %o3, %o4, %o3 138 add %o3, %g4, %o3 139 add %o3, %g5, %o3 140Ltoofar: 141 inc 0xc, %o2 142 143Ldo_int: 144 deccc 4, %o2 145 bl,pn %icc, Lfinish_short 146 nop 1470: 148 lduw [%o5], %o4 149 inc 4, %o5 150 deccc 4, %o2 151 bge,pt %icc, 0b 152 add %o3, %o4, %o3 153 154Lfinish_short: 155 btst 2, %o2 156 bz Lfinish_byte 157 nop 158 lduh [%o5], %o4 159 inc 2, %o5 160 add %o3, %o4, %o3 161 162Lfinish_byte: 163 btst 1, %o2 164 bz Lnext 165 nop 166 ldub [%o5], %o4 167 sllx %o3, 8, %o3 ! ROL { sum = sum << 8; } 168 inc %o5 169 xor %g1, 1, %g1 ! Flip byte_swapped 170 add %o3, %o4, %o3 171 172Lnext: 173 ldx [%o0 + M_NEXT], %o0 174Lfinish: 175 srlx %o3, 32, %o4 ! Reduce to 32-bits 176 srl %o3, 0, %o3 177 brz,pt %o0, 1f ! In general there is only one mbuf 178 add %o3, %o4, %o3 179 brgz,pt %o1, Lloop ! But usually all need to be fully checksummed 180 nop 1811: 182 sethi %hi(0x0000ffff), %o5 ! data ptr not needed any more 183 184 srlx %o3, 16, %o4 185 or %o5, %lo(0x0000ffff), %o5 186 187 and %o3, %o5, %o3 188 189 add %o3, %o4, %o3 190 brz,pt %g1, 0f ! if (byte_swapped) { 191 nop 192 193 sllx %o3, 8, %o3 ! ROL 194 195 srlx %o3, 16, %o4 ! REDUCE 196 and %o3, %o5, %o3 197 198 add %o3, %o4, %o3 1990: 200 subcc %o3, %o5, %o4 ! if (sum > 0xffff) 201 movg %icc, %o4, %o3 ! sum -= 0xffff; 202 203 clr %g4 ! In case we are using EMBEDANY (ick) 204 retl 205 xor %o3, %o5, %o0 ! return (0xffff ^ sum); 206