···11+/*22+ * Copyright 2011 Tilera Corporation. All Rights Reserved.33+ *44+ * This program is free software; you can redistribute it and/or55+ * modify it under the terms of the GNU General Public License66+ * as published by the Free Software Foundation, version 2.77+ *88+ * This program is distributed in the hope that it will be useful, but99+ * WITHOUT ANY WARRANTY; without even the implied warranty of1010+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or1111+ * NON INFRINGEMENT. See the GNU General Public License for1212+ * more details.1313+ */1414+1515+#if defined (__BIG_ENDIAN__)1616+#include <linux/byteorder/big_endian.h>1717+#elif defined (__LITTLE_ENDIAN__)118#include <linux/byteorder/little_endian.h>1919+#else2020+#error "__BIG_ENDIAN__ or __LITTLE_ENDIAN__ must be defined."2121+#endif
+5
arch/tile/include/asm/elf.h
···4444#else4545#define ELF_CLASS ELFCLASS324646#endif4747+#ifdef __BIG_ENDIAN__4848+#define ELF_DATA ELFDATA2MSB4949+#else4750#define ELF_DATA ELFDATA2LSB5151+#endif48524953/*5054 * There seems to be a bug in how compat_binfmt_elf.c works: it···6359 */6460#define elf_check_arch(x) \6561 ((x)->e_ident[EI_CLASS] == ELF_CLASS && \6262+ (x)->e_ident[EI_DATA] == ELF_DATA && \6663 (x)->e_machine == CHIP_ELF_TYPE())67646865/* The module loader only handles a few relocation types. */
+16
arch/tile/include/hv/hypervisor.h
···494494/** Tile coordinate */495495typedef struct496496{497497+#ifndef __BIG_ENDIAN__497498 /** X coordinate, relative to supervisor's top-left coordinate */498499 int x;499500500501 /** Y coordinate, relative to supervisor's top-left coordinate */501502 int y;503503+#else504504+ int y;505505+ int x;506506+#endif502507} HV_Coord;503508504509···991986/** A range of ASID values. */992987typedef struct993988{989989+#ifndef __BIG_ENDIAN__994990 HV_ASID start; /**< First ASID in the range. */995991 unsigned int size; /**< Number of ASIDs. Zero for an invalid range. */992992+#else993993+ unsigned int size; /**< Number of ASIDs. Zero for an invalid range. */994994+ HV_ASID start; /**< First ASID in the range. */995995+#endif996996} HV_ASIDRange;997997998998/** Returns information about a range of ASIDs.···13181308/** Message recipient. */13191309typedef struct13201310{13111311+#ifndef __BIG_ENDIAN__13211312 /** X coordinate, relative to supervisor's top-left coordinate */13221313 unsigned int x:11;13231314···1327131613281317 /** Status of this recipient */13291318 HV_Recip_State state:10;13191319+#else //__BIG_ENDIAN__13201320+ HV_Recip_State state:10;13211321+ unsigned int y:11;13221322+ unsigned int x:11;13231323+#endif13301324} HV_Recipient;1331132513321326/** Send a message to a set of recipients.
+11-1
arch/tile/kernel/module.c
···159159160160 switch (ELF_R_TYPE(rel[i].r_info)) {161161162162-#define MUNGE(func) (*location = ((*location & ~func(-1)) | func(value)))162162+#ifdef __LITTLE_ENDIAN163163+# define MUNGE(func) \164164+ (*location = ((*location & ~func(-1)) | func(value)))165165+#else166166+/*167167+ * Instructions are always little-endian, so when we read them as data,168168+ * we have to swap them around before and after modifying them.169169+ */170170+# define MUNGE(func) \171171+ (*location = swab64((swab64(*location) & ~func(-1)) | func(value)))172172+#endif163173164174#ifndef __tilegx__165175 case R_TILE_32:
+12-4
arch/tile/kernel/single_step.c
···172172 return (tilepro_bundle_bits) 0;173173 }174174175175-#ifndef __LITTLE_ENDIAN176176-# error We assume little-endian representation with copy_xx_user size 2 here177177-#endif178175 /* Handle unaligned load/store */179176 if (mem_op == MEMOP_LOAD || mem_op == MEMOP_LOAD_POSTINCR) {180177 unsigned short val_16;···192195 state->update = 1;193196 }194197 } else {198198+ unsigned short val_16;195199 val = (val_reg == TREG_ZERO) ? 0 : regs->regs[val_reg];196196- err = copy_to_user(addr, &val, size);200200+ switch (size) {201201+ case 2:202202+ val_16 = val;203203+ err = copy_to_user(addr, &val_16, sizeof(val_16));204204+ break;205205+ case 4:206206+ err = copy_to_user(addr, &val, sizeof(val));207207+ break;208208+ default:209209+ BUG();210210+ }197211 }198212199213 if (err) {
+3-5
arch/tile/lib/memchr_64.c
···1515#include <linux/types.h>1616#include <linux/string.h>1717#include <linux/module.h>1818+#include "string-endian.h"18191920void *memchr(const void *s, int c, size_t n)2021{···40394140 /* Read the first word, but munge it so that bytes before the array4241 * will not match goal.4343- *4444- * Note that this shift count expression works because we know4545- * shift counts are taken mod 64.4642 */4747- before_mask = (1ULL << (s_int << 3)) - 1;4343+ before_mask = MASK(s_int);4844 v = (*p | before_mask) ^ (goal & before_mask);49455046 /* Compute the address of the last byte. */···6365 /* We found a match, but it might be in a byte past the end6466 * of the array.6567 */6666- ret = ((char *)p) + (__insn_ctz(bits) >> 3);6868+ ret = ((char *)p) + (CFZ(bits) >> 3);6769 return (ret <= last_byte_ptr) ? ret : NULL;6870}6971EXPORT_SYMBOL(memchr);
+21-2
arch/tile/lib/memcpy_64.c
···1515#include <linux/types.h>1616#include <linux/string.h>1717#include <linux/module.h>1818-#define __memcpy memcpy1918/* EXPORT_SYMBOL() is in arch/tile/lib/exports.c since this should be asm. */20192120/* Must be 8 bytes in size. */···187188188189 /* n != 0 if we get here. Write out any trailing bytes. */189190 dst1 = (char *)dst8;191191+#ifndef __BIG_ENDIAN__190192 if (n & 4) {191193 ST4((uint32_t *)dst1, final);192194 dst1 += 4;···202202 }203203 if (n)204204 ST1((uint8_t *)dst1, final);205205+#else206206+ if (n & 4) {207207+ ST4((uint32_t *)dst1, final >> 32);208208+ dst1 += 4;209209+ }210210+ else211211+ {212212+ final >>= 32;213213+ }214214+ if (n & 2) {215215+ ST2((uint16_t *)dst1, final >> 16);216216+ dst1 += 2;217217+ }218218+ else219219+ {220220+ final >>= 16;221221+ }222222+ if (n & 1)223223+ ST1((uint8_t *)dst1, final >> 8);224224+#endif205225206226 return RETVAL;207227}208208-209228210229#ifdef USERCOPY_FUNC211230#undef ST1
+5-10
arch/tile/lib/strchr_64.c
···1515#include <linux/types.h>1616#include <linux/string.h>1717#include <linux/module.h>1818-1919-#undef strchr1818+#include "string-endian.h"20192120char *strchr(const char *s, int c)2221{···3233 * match neither zero nor goal (we make sure the high bit of each3334 * byte is 1, and the low 7 bits are all the opposite of the goal3435 * byte).3535- *3636- * Note that this shift count expression works because we know shift3737- * counts are taken mod 64.3836 */3939- const uint64_t before_mask = (1ULL << (s_int << 3)) - 1;4040- uint64_t v = (*p | before_mask) ^4141- (goal & __insn_v1shrsi(before_mask, 1));3737+ const uint64_t before_mask = MASK(s_int);3838+ uint64_t v = (*p | before_mask) ^ (goal & __insn_v1shrui(before_mask, 1));42394340 uint64_t zero_matches, goal_matches;4441 while (1) {···5055 v = *++p;5156 }52575353- z = __insn_ctz(zero_matches);5454- g = __insn_ctz(goal_matches);5858+ z = CFZ(zero_matches);5959+ g = CFZ(goal_matches);55605661 /* If we found c before '\0' we got a match. Note that if c == '\0'5762 * then g == z, and we correctly return the address of the '\0'
+33
arch/tile/lib/string-endian.h
···11+/*22+ * Copyright 2011 Tilera Corporation. All Rights Reserved.33+ *44+ * This program is free software; you can redistribute it and/or55+ * modify it under the terms of the GNU General Public License66+ * as published by the Free Software Foundation, version 2.77+ *88+ * This program is distributed in the hope that it will be useful, but99+ * WITHOUT ANY WARRANTY; without even the implied warranty of1010+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or1111+ * NON INFRINGEMENT. See the GNU General Public License for1212+ * more details.1313+ *1414+ * Provide a mask based on the pointer alignment that1515+ * sets up non-zero bytes before the beginning of the string.1616+ * The MASK expression works because shift counts are taken mod 64.1717+ * Also, specify how to count "first" and "last" bits1818+ * when the bits have been read as a word.1919+ */2020+2121+#include <asm/byteorder.h>2222+2323+#ifdef __LITTLE_ENDIAN2424+#define MASK(x) (__insn_shl(1ULL, (x << 3)) - 1)2525+#define NULMASK(x) ((2ULL << x) - 1)2626+#define CFZ(x) __insn_ctz(x)2727+#define REVCZ(x) __insn_clz(x)2828+#else2929+#define MASK(x) (__insn_shl(-2LL, ((-x << 3) - 1)))3030+#define NULMASK(x) (-2LL << (63 - x))3131+#define CFZ(x) __insn_clz(x)3232+#define REVCZ(x) __insn_ctz(x)3333+#endif
+4-7
arch/tile/lib/strlen_64.c
···1515#include <linux/types.h>1616#include <linux/string.h>1717#include <linux/module.h>1818-1919-#undef strlen1818+#include "string-endian.h"20192120size_t strlen(const char *s)2221{···2324 const uintptr_t s_int = (uintptr_t) s;2425 const uint64_t *p = (const uint64_t *)(s_int & -8);25262626- /* Read the first word, but force bytes before the string to be nonzero.2727- * This expression works because we know shift counts are taken mod 64.2828- */2929- uint64_t v = *p | ((1ULL << (s_int << 3)) - 1);2727+ /* Read and MASK the first word. */2828+ uint64_t v = *p | MASK(s_int);30293130 uint64_t bits;3231 while ((bits = __insn_v1cmpeqi(v, 0)) == 0)3332 v = *++p;34333535- return ((const char *)p) + (__insn_ctz(bits) >> 3) - s;3434+ return ((const char *)p) + (CFZ(bits) >> 3) - s;3635}3736EXPORT_SYMBOL(strlen);