1/*- 2 * Copyright (c) 2012 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Matt Thomas of 3am Software Foundry. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30/* 31 * This file is intended to be included at the end of a in_cksum routine 32 * to reduce the 33-bit sum in <carry>, ip to a 16-bit return value. 33 */ 34 /* 35 * We now have a 33-bit (r0 + carry) sum which needs to resolved to a 36 * 16-bit sum. But first, let's put 0xffff in a register. 37 */ 38#ifdef _ARM_ARCH_7 39 movw r1, #0xffff /* load 0xffff */ 40#else 41 mov r1, #0x10000 /* load 0x10000 */ 42 sub r1, r1, #1 /* subtract by 1 to get 0xffff */ 43#endif 44 45 /* 46 * Add the final carry bit. If it overflows, we have a 33-bit value 47 * of 0x1.0000.0000 which we know is just equivalent to 1. Since we 48 * return a complement of the lower halfword, that's 0xfffe. 49 */ 50 adcs ip, ip, #0 /* add final carry bit */ 51 beq 1f /* 0? return 0xfffe */ 52 53 /* 54 * Now prevent the adding of 0xffff to 0xffff by making sure the upper 55 * halfword isn't 0xffff. If it is, just complement all 32-bits 56 * which clears the upper halfword and complements the lower halfword. 57 */ 58 cmp ip, r1, lsl #16 /* is the upper halfword 0xffff? */ 59 beq 2f /* yes, complement and return */ 60 /* 61 * Finally add the lower halfword to the upper halfword. If we have 62 * a result >= 0x10000, carry will be set. The maximum result will 63 * be 0x[1]fffe. So if the carry bit is set, just add 0x10000 64 * (which is equivalent to subtracting 0xffff.0000). 65 */ 66 adds ip, ip, ip, lsl #16 67 addcs ip, ip, #0x10000 68 eor r0, r1, ip, lsr #16 69 RET 70 711: sub r0, r1, #1 /* set return value to 0xfffe */ 72 RET /* return */ 732: mvn r0, ip /* complement */ 74 RET /* return */ 75 76