This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Thumb32 assembler (6/69)
- From: Zack Weinberg <zack at codesourcery dot com>
- To: binutils <binutils at sourceware dot org>
- Date: Tue, 26 Apr 2005 02:52:58 -0700
- Subject: Thumb32 assembler (6/69)
Part of this patch has already been submitted. It introduces a new
interface to hash.c, hash_find_n, which takes the length of the key as
an explicit argument; this is convenient when the key is part of the
string passed to md_assemble, as it then does not have to munge that
string. In subsequent patches, tc-arm.c will make extensive use of
this feature.
Note that there is a bug in this edition of hash_find_n; the fix shows
up several patches later.
zw
* hash.c (hash_lookup): Delete unnecessary forward declaration.
Add 'len' parameter. Take this as length of key; do not look for
a NUL terminator; use strncmp when searching collision chains.
All callers changed to match.
(hash_find_n): New function.
* hash.h: Declare hash_find_n.
* config/tc-arm.c (md_assemble): Use hash_find_n; no need to
mutate the string.
===================================================================
Index: gas/hash.c
--- gas/hash.c (revision 6)
+++ gas/hash.c (revision 8)
@@ -120,19 +120,13 @@
Each time we look up a string, we move it to the start of the list
for its hash code, to take advantage of referential locality. */
-static struct hash_entry *hash_lookup (struct hash_control *,
- const char *,
- struct hash_entry ***,
- unsigned long *);
-
static struct hash_entry *
-hash_lookup (struct hash_control *table, const char *key,
+hash_lookup (struct hash_control *table, const char *key, size_t len,
struct hash_entry ***plist, unsigned long *phash)
{
- register unsigned long hash;
- unsigned int len;
- register const unsigned char *s;
- register unsigned int c;
+ unsigned long hash;
+ size_t n;
+ unsigned int c;
unsigned int index;
struct hash_entry **list;
struct hash_entry *p;
@@ -143,13 +137,11 @@
#endif
hash = 0;
- len = 0;
- s = (const unsigned char *) key;
- while ((c = *s++) != '\0')
+ for (n = 0; n < len; n++)
{
+ c = key[n];
hash += c + (c << 17);
hash ^= hash >> 2;
- ++len;
}
hash += len + (len << 17);
hash ^= hash >> 2;
@@ -176,7 +168,7 @@
++table->string_compares;
#endif
- if (strcmp (p->string, key) == 0)
+ if (p->string[len] == '\0' && strncmp (p->string, key, len) == 0)
{
if (prev != NULL)
{
@@ -207,7 +199,7 @@
struct hash_entry **list;
unsigned long hash;
- p = hash_lookup (table, key, &list, &hash);
+ p = hash_lookup (table, key, strlen (key), &list, &hash);
if (p != NULL)
return "exists";
@@ -237,7 +229,7 @@
struct hash_entry **list;
unsigned long hash;
- p = hash_lookup (table, key, &list, &hash);
+ p = hash_lookup (table, key, strlen (key), &list, &hash);
if (p != NULL)
{
#ifdef HASH_STATISTICS
@@ -274,7 +266,7 @@
struct hash_entry *p;
PTR ret;
- p = hash_lookup (table, key, NULL, NULL);
+ p = hash_lookup (table, key, strlen (key), NULL, NULL);
if (p == NULL)
return NULL;
@@ -297,13 +289,28 @@
{
struct hash_entry *p;
- p = hash_lookup (table, key, NULL, NULL);
+ p = hash_lookup (table, key, strlen (key), NULL, NULL);
if (p == NULL)
return NULL;
return p->data;
}
+/* As hash_find, but KEY is of length LEN and is not guaranteed to be
+ NUL-terminated. */
+
+PTR
+hash_find_n (struct hash_control *table, const char *key, size_t len)
+{
+ struct hash_entry *p;
+
+ p = hash_lookup (table, key, len, NULL, NULL);
+ if (p == NULL)
+ return NULL;
+
+ return p->data;
+}
+
/* Delete an entry from a hash table. This returns the value stored
for that entry, or NULL if there is no such entry. */
@@ -313,7 +320,7 @@
struct hash_entry *p;
struct hash_entry **list;
- p = hash_lookup (table, key, &list, NULL);
+ p = hash_lookup (table, key, strlen (key), &list, NULL);
if (p == NULL)
return NULL;
===================================================================
Index: gas/hash.h
--- gas/hash.h (revision 6)
+++ gas/hash.h (revision 8)
@@ -59,6 +59,11 @@
extern PTR hash_find (struct hash_control *, const char *key);
+/* As hash_find, but KEY is of length LEN and is not guaranteed to be
+ NUL-terminated. */
+
+extern PTR hash_find_n (struct hash_control *, const char *key, size_t len);
+
/* Delete an entry from a hash table. This returns the value stored
for that entry, or NULL if there is no such entry. */
===================================================================
Index: gas/config/tc-arm.c
--- gas/config/tc-arm.c (revision 6)
+++ gas/config/tc-arm.c (revision 8)
@@ -9985,9 +9985,7 @@
void
md_assemble (char * str)
{
- char c;
char *p;
- char *start;
/* Align the previous label if needed. */
if (last_label_seen != NULL)
@@ -10004,7 +10002,7 @@
/* Scan up to the end of the op-code, which must end in white space or
end of string. */
- for (start = p = str; *p != '\0'; p++)
+ for (p = str; *p != '\0'; p++)
if (*p == ' ')
break;
@@ -10018,10 +10016,7 @@
{
const struct thumb_opcode * opcode;
- c = *p;
- *p = '\0';
- opcode = (const struct thumb_opcode *) hash_find (arm_tops_hsh, str);
- *p = c;
+ opcode = hash_find_n (arm_tops_hsh, str, p - str);
if (opcode)
{
@@ -10044,10 +10039,7 @@
{
const struct asm_opcode * opcode;
- c = *p;
- *p = '\0';
- opcode = (const struct asm_opcode *) hash_find (arm_ops_hsh, str);
- *p = c;
+ opcode = hash_find_n (arm_ops_hsh, str, p - str);
if (opcode)
{
@@ -10072,7 +10064,7 @@
if (create_register_alias (str, p))
return;
- as_bad (_("bad instruction `%s'"), start);
+ as_bad (_("bad instruction `%s'"), str);
}
/* Various frobbings of labels and their addresses. */