/*1* This file contains assembly-language implementations2* of IP-style 1's complement checksum routines.3*4* Copyright (C) 1995-1996 Gary Thomas ([email protected])5*6* This program is free software; you can redistribute it and/or7* modify it under the terms of the GNU General Public License8* as published by the Free Software Foundation; either version9* 2 of the License, or (at your option) any later version.10*11* Severely hacked about by Paul Mackerras ([email protected]).12*/1314#include <linux/sys.h>15#include <asm/processor.h>16#include <asm/errno.h>17#include <asm/ppc_asm.h>1819.text2021/*22* ip_fast_csum(buf, len) -- Optimized for IP header23* len is in words and is always >= 5.24*/25_GLOBAL(ip_fast_csum)26lwz r0,0(r3)27lwzu r5,4(r3)28addic. r4,r4,-229addc r0,r0,r530mtctr r431blelr-321: lwzu r4,4(r3)33adde r0,r0,r434bdnz 1b35addze r0,r0 /* add in final carry */36rlwinm r3,r0,16,0,31 /* fold two halves together */37add r3,r0,r338not r3,r339srwi r3,r3,1640blr4142/*43* Compute checksum of TCP or UDP pseudo-header:44* csum_tcpudp_magic(saddr, daddr, len, proto, sum)45*/46_GLOBAL(csum_tcpudp_magic)47rlwimi r5,r6,16,0,15 /* put proto in upper half of len */48addc r0,r3,r4 /* add 4 32-bit words together */49adde r0,r0,r550adde r0,r0,r751addze r0,r0 /* add in final carry */52rlwinm r3,r0,16,0,31 /* fold two halves together */53add r3,r0,r354not r3,r355srwi r3,r3,1656blr5758/*59* computes the checksum of a memory block at buff, length len,60* and adds in "sum" (32-bit)61*62* csum_partial(buff, len, sum)63*/64_GLOBAL(csum_partial)65addic r0,r5,066subi r3,r3,467srwi. r6,r4,268beq 3f /* if we're doing < 4 bytes */69andi. r5,r3,2 /* Align buffer to longword boundary */70beq+ 1f71lhz r5,4(r3) /* do 2 bytes to get aligned */72addi r3,r3,273subi r4,r4,274addc r0,r0,r575srwi. r6,r4,2 /* # words to do */76beq 3f771: mtctr r6782: lwzu r5,4(r3) /* the bdnz has zero overhead, so it should */79adde r0,r0,r5 /* be unnecessary to unroll this loop */80bdnz 2b81andi. r4,r4,3823: cmpwi 0,r4,283blt+ 4f84lhz r5,4(r3)85addi r3,r3,286subi r4,r4,287adde r0,r0,r5884: cmpwi 0,r4,189bne+ 5f90lbz r5,4(r3)91slwi r5,r5,8 /* Upper byte of word */92adde r0,r0,r5935: addze r3,r0 /* add in final carry */94blr9596/*97* Computes the checksum of a memory block at src, length len,98* and adds in "sum" (32-bit), while copying the block to dst.99* If an access exception occurs on src or dst, it stores -EFAULT100* to *src_err or *dst_err respectively, and (for an error on101* src) zeroes the rest of dst.102*103* csum_partial_copy_generic(src, dst, len, sum, src_err, dst_err)104*/105_GLOBAL(csum_partial_copy_generic)106addic r0,r6,0107subi r3,r3,4108subi r4,r4,4109srwi. r6,r5,2110beq 3f /* if we're doing < 4 bytes */111andi. r9,r4,2 /* Align dst to longword boundary */112beq+ 1f11381: lhz r6,4(r3) /* do 2 bytes to get aligned */114addi r3,r3,2115subi r5,r5,211691: sth r6,4(r4)117addi r4,r4,2118addc r0,r0,r6119srwi. r6,r5,2 /* # words to do */120beq 3f1211: srwi. r6,r5,4 /* # groups of 4 words to do */122beq 10f123mtctr r612471: lwz r6,4(r3)12572: lwz r9,8(r3)12673: lwz r10,12(r3)12774: lwzu r11,16(r3)128adde r0,r0,r612975: stw r6,4(r4)130adde r0,r0,r913176: stw r9,8(r4)132adde r0,r0,r1013377: stw r10,12(r4)134adde r0,r0,r1113578: stwu r11,16(r4)136bdnz 71b13710: rlwinm. r6,r5,30,30,31 /* # words left to do */138beq 13f139mtctr r614082: lwzu r9,4(r3)14192: stwu r9,4(r4)142adde r0,r0,r9143bdnz 82b14413: andi. r5,r5,31453: cmpwi 0,r5,2146blt+ 4f14783: lhz r6,4(r3)148addi r3,r3,2149subi r5,r5,215093: sth r6,4(r4)151addi r4,r4,2152adde r0,r0,r61534: cmpwi 0,r5,1154bne+ 5f15584: lbz r6,4(r3)15694: stb r6,4(r4)157slwi r6,r6,8 /* Upper byte of word */158adde r0,r0,r61595: addze r3,r0 /* add in final carry */160blr161162/* These shouldn't go in the fixup section, since that would163cause the ex_table addresses to get out of order. */164165src_error_4:166mfctr r6 /* update # bytes remaining from ctr */167rlwimi r5,r6,4,0,27168b 79f169src_error_1:170li r6,0171subi r5,r5,217295: sth r6,4(r4)173addi r4,r4,217479: srwi. r6,r5,2175beq 3f176mtctr r6177src_error_2:178li r6,017996: stwu r6,4(r4)180bdnz 96b1813: andi. r5,r5,3182beq src_error183src_error_3:184li r6,0185mtctr r5186addi r4,r4,318797: stbu r6,1(r4)188bdnz 97b189src_error:190cmpwi 0,r7,0191beq 1f192li r6,-EFAULT193stw r6,0(r7)1941: addze r3,r0195blr196197dst_error:198cmpwi 0,r8,0199beq 1f200li r6,-EFAULT201stw r6,0(r8)2021: addze r3,r0203blr204205.section __ex_table,"a"206.long 81b,src_error_1207.long 91b,dst_error208.long 71b,src_error_4209.long 72b,src_error_4210.long 73b,src_error_4211.long 74b,src_error_4212.long 75b,dst_error213.long 76b,dst_error214.long 77b,dst_error215.long 78b,dst_error216.long 82b,src_error_2217.long 92b,dst_error218.long 83b,src_error_3219.long 93b,dst_error220.long 84b,src_error_3221.long 94b,dst_error222.long 95b,dst_error223.long 96b,dst_error224.long 97b,dst_error225226227