* app.c (do_scrub_next_char): Added new state, 9, to avoid
authorIan Lance Taylor <ian@airs.com>
Thu, 18 Mar 1993 00:52:37 +0000 (00:52 +0000)
committerIan Lance Taylor <ian@airs.com>
Thu, 18 Mar 1993 00:52:37 +0000 (00:52 +0000)
dropping a space immediately following an identifier.
* expr.c, write.c: Rewrote assert expressions to not use multiple
lines; I don't think that can be done portably.
* config/tc-mips.c (macro): Use $AT if target register is zero in
load instruction, which it can be for a floating point load.

Also a bunch more changes to config/obj-ecoff.c, still in flux.

gas/ChangeLog
gas/app.c
gas/config/obj-ecoff.c
gas/config/tc-mips.c

index bfc4e5426fe872f4a3ab999f1c02555198cf484b..209343906f6aaa4593fcbd0a30229829ba40be4f 100644 (file)
@@ -1,3 +1,12 @@
+Wed Mar 17 16:44:06 1993  Ian Lance Taylor  (ian@cygnus.com)
+
+       * app.c (do_scrub_next_char): Added new state, 9, to avoid
+       dropping a space immediately following an identifier.
+       * expr.c, write.c: Rewrote assert expressions to not use multiple
+       lines; I don't think that can be done portably.
+       * config/tc-mips.c (macro): Use $AT if target register is zero in
+       load instruction, which it can be for a floating point load.
+
 Mon Mar 15 12:17:28 1993  Ian Lance Taylor  (ian@cygnus.com)
 
        * write.c (write_contents): Compute the relocs before writing out
index ce75973f45d0841f6f63a76b0c24a14360104806..1983c3ca6a88bfafcb2ca6941d7f6847ecec5b95 100644 (file)
--- a/gas/app.c
+++ b/gas/app.c
@@ -29,7 +29,6 @@
 
 #include <stdio.h>
 #include "as.h"                        /* For BAD_CASE() only */
-#include "read.h"
 
 #if (__STDC__ != 1) && !defined(const)
 #define const                  /* Nothing */
@@ -250,10 +249,18 @@ do_scrub_next_char (get, unget)
          6: putting out \ escape in a "d string.
          7: After putting out a .app-file, put out string.
          8: After putting out a .app-file string, flush until newline.
+         9: After seeing symbol char in state 3 (keep 1white after symchar)
          -1: output string in out_string and go to the state in old_state
          -2: flush text until a '*' '/' is seen, then go to state old_state
          */
 
+  /* I added state 9 because the MIPS ECOFF assembler uses constructs
+     like ``.loc 1 20''.  This was turning into ``.loc 120''.  State 9
+     ensures that a space is never dropped immediately following a
+     character which could appear in a identifier.  It is still
+     dropped following a comma, so this has no effect for most
+     assemblers.  I hope.  Ian Taylor, ian@cygnus.com.  */
+
   register int ch, ch2 = 0;
 
   switch (state)
@@ -399,7 +406,7 @@ do_scrub_next_char (get, unget)
       return ch;
     }
 
-  /* OK, we are somewhere in states 0 through 4 */
+  /* OK, we are somewhere in states 0 through 4 or 9 */
 
   /* flushchar: */
   ch = (*get) ();
@@ -447,7 +454,8 @@ recycle:
        case 1:
          BAD_CASE (state);     /* We can't get here */
        case 2:
-         state++;
+       case 9:
+         state = 3;
          (*unget) (ch);
          return ' ';           /* Sp after opco */
        case 3:
@@ -561,18 +569,22 @@ recycle:
        goto de_fault;
 
       /* FIXME-someday: The two character comment stuff was badly
-    thought out.  On i386, we want '/' as line comment start
-    AND we want C style comments.  hence this hack.  The
-    whole lexical process should be reworked.  xoxorich.  */
+        thought out.  On i386, we want '/' as line comment start AND
+        we want C style comments.  hence this hack.  The whole
+        lexical process should be reworked.  xoxorich.  */
 
-      if (ch == '/' && (ch2 = (*get) ()) == '*')
+      if (ch == '/')
        {
-         state = -2;
-         return (do_scrub_next_char (get, unget));
-       }
-      else
-       {
-         (*unget) (ch2);
+         ch2 = (*get) ();
+         if (ch2 == '*')
+           {
+             state = -2;
+             return (do_scrub_next_char (get, unget));
+           }
+         else
+           {
+             (*unget) (ch2);
+           }
        }                       /* bad hack */
 
       do
@@ -609,6 +621,10 @@ recycle:
       state = 0;
       return '\n';
 
+    case LEX_IS_SYMBOL_COMPONENT:
+      if (state == 3)
+       state = 9;
+      /* Fall through.  */
     default:
     de_fault:
       /* Some relatively `normal' character.  */
@@ -622,6 +638,12 @@ recycle:
          state = 2;            /* Ditto */
          return ch;
        }
+      else if (state == 9)
+       {
+         if (lex[ch] != LEX_IS_SYMBOL_COMPONENT)
+           state = 3;
+         return ch;
+       }
       else
        {
          return ch;            /* Opcode or operands already */
index 1e29ab874c90fdbb9692e2aa45b6bb52ff956db3..d0a9b044e93d0a3c87681719e34c9c3bc5681a99 100644 (file)
@@ -831,6 +831,7 @@ typedef struct scope {
    information we generate.  The gas symbol will be NULL if this is
    only a debugging symbol.  */
 typedef struct localsym {
+  const char *name;            /* symbol name */
   symbolS *as_sym;             /* symbol as seen by gas */
   struct efdr *file_ptr;       /* file pointer */
   struct ecoff_proc *proc_ptr; /* proc pointer */
@@ -1393,7 +1394,8 @@ static alloc_info_t alloc_counts[ (int)alloc_type_last ];
 /* Various statics.  */
 static efdr_t  *cur_file_ptr   = (efdr_t *) 0; /* current file desc. header */
 static proc_t  *cur_proc_ptr   = (proc_t *) 0; /* current procedure header */
-static thead_t *cur_tag_head   = (thead_t *)0; /* current tag head */
+static thead_t *top_tag_head   = (thead_t *) 0; /* top level tag head */
+static thead_t *cur_tag_head   = (thead_t *) 0; /* current tag head */
 #ifdef ECOFF_DEBUG
 static int     debug           = 0;            /* trace functions */
 #endif
@@ -1561,6 +1563,11 @@ obj_read_begin_hook ()
   tag_hash = hash_new ();
   if (tag_hash == (struct hash_control *) NULL)
     as_fatal ("Can't create hash table");
+  top_tag_head = allocate_thead ();
+  top_tag_head->first_tag = (tag_t *) NULL;
+  top_tag_head->free = (thead_t *) NULL;
+  top_tag_head->prev = cur_tag_head;
+  cur_tag_head = top_tag_head;
 }
 
 /* This function is called when a symbol is created.  */
@@ -1683,6 +1690,10 @@ add_ecoff_symbol (str, type, storage, sym_value, value, indx)
 
   psym = &vp->last->datum->sym[ vp->objects_last_page++ ];
 
+  if (str == (const char *) NULL && sym_value != (symbolS *) NULL)
+    psym->name = S_GET_NAME (sym_value);
+  else
+    psym->name = str;
   psym->as_sym = sym_value;
   if (sym_value != (symbolS *) NULL)
     sym_value->ecoff_symbol = 1;
@@ -2194,7 +2205,7 @@ add_procedure (func)
   new_proc_ptr->pdr.iline = -1;
 
   /* Push the start of the function.  */
-  new_proc_ptr->sym = add_ecoff_symbol (func, st_Proc, sc_Text,
+  new_proc_ptr->sym = add_ecoff_symbol ((const char *) NULL, st_Proc, sc_Text,
                                        symbol_find_or_make (func),
                                        (symint_t) 0, (symint_t) 0);
 
@@ -2428,7 +2439,10 @@ obj_ecoff_begin (ignore)
 
   *input_line_pointer = name_end;
 
-  demand_empty_rest_of_line ();
+  /* The line number follows, but we don't use it.  */
+  while (! is_end_of_line[*input_line_pointer])
+    input_line_pointer++;
+  input_line_pointer++;
 }
 \f
 /* Parse .bend directives which have a label as the first argument
@@ -2440,7 +2454,7 @@ obj_ecoff_bend (ignore)
 {
   char *name;
   char name_end;
-  symbolS *begin;
+  symbolS *endsym;
 
   if (cur_file_ptr == (efdr_t *) NULL)
     {
@@ -2460,21 +2474,21 @@ obj_ecoff_bend (ignore)
   name_end = get_symbol_end ();
 
   /* The value is the distance between the .bend directive and the
-     corresponding symbol.  We create a fake symbol to hold the
-     current location, and put in the offset when we write out the
-     symbol.  */
-  begin = symbol_find (name);
-  if (begin == (symbolS *) NULL)
+     corresponding symbol.  We fill in the offset when we write out
+     the symbol.  */
+  endsym = symbol_find (name);
+  if (endsym == (symbolS *) NULL)
     as_warn (".bend directive names unknown symbol");
   else
-    (void) add_ecoff_symbol (name, st_End, sc_Text,
-                            symbol_new ("L0\001", now_seg,
-                                        frag_now_fix (), frag_now),
+    (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text, endsym,
                             (symint_t) 0, (symint_t) 0);
 
   *input_line_pointer = name_end;
 
-  demand_empty_rest_of_line ();
+  /* The line number follows, but we don't use it.  */
+  while (! is_end_of_line[*input_line_pointer])
+    input_line_pointer++;
+  input_line_pointer++;
 }
 \f
 /* COFF debugging information is provided as a series of directives
@@ -2601,15 +2615,8 @@ obj_ecoff_scl (ignore)
 
   val = get_absolute_expression ();
 
-  /* If the symbol is a static or external, we have already gotten the
-     appropriate type and class, so make sure we don't override those
-     values.  This is needed because there are some type and classes
-     that are not in COFF, such as short data, etc.  */
-  if (coff_symbol_type == st_Nil)
-    {
-      coff_symbol_type = map_coff_sym_type[val];
-      coff_storage_class = map_coff_storage[val];
-    }
+  coff_symbol_type = map_coff_sym_type[val];
+  coff_storage_class = map_coff_storage[val];
 
   demand_empty_rest_of_line ();
 }
@@ -2674,6 +2681,7 @@ obj_ecoff_type (ignore)
 {
   long val;
   tq_t *tq_ptr;
+  tq_t *tq_shft;
 
   if (coff_sym_name == (char *) NULL)
     {
@@ -2687,27 +2695,31 @@ obj_ecoff_type (ignore)
   coff_type.orig_type = BTYPE (val);
   coff_type.basic_type = map_coff_types[coff_type.orig_type];
 
-  tq_ptr = &coff_type.type_qualifiers[0];
+  tq_ptr = &coff_type.type_qualifiers[N_TQ];
   while (val &~ N_BTMASK)
     {
-      if (tq_ptr == &coff_type.type_qualifiers[N_TQ])
+      if (tq_ptr == &coff_type.type_qualifiers[0])
        {
          as_warn ("Too derived values in .type argument");
          break;
        }
       if (ISPTR (val))
-       *tq_ptr++ = tq_Ptr;
+       *--tq_ptr = tq_Ptr;
       else if (ISFCN (val))
-       *tq_ptr++ = tq_Proc;
+       *--tq_ptr = tq_Proc;
       else if (ISARY (val))
-       *tq_ptr++ = tq_Array;
+       *--tq_ptr = tq_Array;
       else
        as_fatal ("Unrecognized .type argument");
 
       val = DECREF (val);
     }
 
-  if (tq_ptr != &coff_type.type_qualifiers[0] && tq_ptr[-1] == tq_Proc)
+  tq_shft = &coff_type.type_qualifiers[0];
+  while (tq_ptr != &coff_type.type_qualifiers[N_TQ])
+    *tq_shft++ = *tq_ptr++;
+
+  if (tq_shft != &coff_type.type_qualifiers[0] && tq_shft[-1] == tq_Proc)
     {
       /* If this is a function, ignore it, so that we don't get two
         entries (one from the .ent, and one for the .def that
@@ -2716,9 +2728,12 @@ obj_ecoff_type (ignore)
         MIPS knows what reason, we must strip off the function type
         at this point.  */
       coff_is_function = 1;
-      tq_ptr[-1] = tq_Nil;
+      tq_shft[-1] = tq_Nil;
     }
 
+  while (tq_shft != &coff_type.type_qualifiers[N_TQ])
+    *tq_shft++ = tq_Nil;
+
   demand_empty_rest_of_line ();
 }
 
@@ -2796,6 +2811,7 @@ static void
 obj_ecoff_endef (ignore)
      int ignore;
 {
+  char *name;
   symint_t indx;
   localsym_t *sym;
 
@@ -2807,6 +2823,19 @@ obj_ecoff_endef (ignore)
       return;
     }
 
+  name = coff_sym_name;
+  coff_sym_name = (char *) NULL;
+
+  /* If the symbol is a static or external, we have already gotten the
+     appropriate type and class, so make sure we don't override those
+     values.  This is needed because there are some type and classes
+     that are not in COFF, such as short data, etc.  */
+  if (coff_sym_value != (symbolS *) NULL)
+    {
+      coff_symbol_type = st_Nil;
+      coff_storage_class = sc_Nil;
+    }
+
   coff_type.extra_sizes = coff_tag != (char *) NULL;
   if (coff_type.num_dims > 0)
     {
@@ -2863,7 +2892,7 @@ obj_ecoff_endef (ignore)
        {
          if (coff_tag == (char *) NULL)
            {
-             as_warn ("No tag specified for %s", coff_sym_name);
+             as_warn ("No tag specified for %s", name);
              return;
            }
 
@@ -2908,8 +2937,8 @@ obj_ecoff_endef (ignore)
         name which is always ".eos".  This needs to be done last, so
         that any error reporting above gives the correct name.  */
     case st_End:
-      free (coff_sym_name);
-      coff_sym_name = (char *) NULL;
+      free (name);
+      name = (char *) NULL;
       coff_value = 0;
       coff_inside_enumeration = 0;
       break;
@@ -2927,7 +2956,7 @@ obj_ecoff_endef (ignore)
     }
 
   /* Add the symbol.  */
-  sym = add_ecoff_symbol (coff_sym_name,
+  sym = add_ecoff_symbol (name,
                          coff_symbol_type,
                          coff_storage_class,
                          coff_sym_value,
@@ -2938,7 +2967,7 @@ obj_ecoff_endef (ignore)
   if (coff_symbol_type == st_Block)
     {
       /* Create or update the tag information.  */
-      tag_t *tag_ptr = get_tag (coff_sym_name,
+      tag_t *tag_ptr = get_tag (name,
                                sym,
                                coff_type.basic_type);
       forward_t **pf;
@@ -2998,7 +3027,7 @@ obj_ecoff_end (ignore)
   if (ent == (symbolS *) NULL)
     as_warn (".end directive names unknown symbol");
   else
-    (void) add_ecoff_symbol (name, st_End, sc_Text,
+    (void) add_ecoff_symbol ((const char *) NULL, st_End, sc_Text,
                             symbol_new ("L0\001", now_seg,
                                         frag_now_fix (), frag_now),
                             (symint_t) 0, (symint_t) 0);
@@ -3189,18 +3218,10 @@ obj_ecoff_loc (ignore)
       return;
     }
 
-  /* FIXME: .loc directives look like ``.loc 1 4'' where the first
-     number is the file index and the second number is the line
-     number.  Unfortunately, do_scrub_next_char removes the space,
-     producing ``.loc 14''.  Urrrk.  I'm afraid I'll break something
-     if I change do_scrub_next_char, so instead we do this gross hack.
-     Note that file_index is one less than the value in the .loc,
-     because we adjusted it by one in the call to add_file.  This
-     actually won't work in the unfortunate circumstance of the same
-     file appearing twice with different indices with different
-     numbers of digits, which is possible.  */
+  /* Skip the file number.  */
+  SKIP_WHITESPACE ();
+  get_absolute_expression ();
   SKIP_WHITESPACE ();
-  input_line_pointer += 1 + (cur_file_ptr->file_index + 1) / 10;
 
   list = allocate_lineno_list ();
 
@@ -3599,7 +3620,7 @@ ecoff_build_lineno (buf, bufend, offset, linecntptr)
            }
          else if (delta <= -7)
            {
-             *bufptr++ = 0x0f + (9 << 4);
+             *bufptr++ = 0x0f + (-7 << 4);
              delta += 7;
            }
          else
@@ -3745,6 +3766,7 @@ ecoff_build_symbols (buf,
              for (; sym_ptr < sym_end; sym_ptr++)
                {
                  int local;
+                 symbolS *as_sym;
                  forward_t *f;
 
                  know (sym_ptr->file_ptr == fil_ptr);
@@ -3757,26 +3779,65 @@ ecoff_build_symbols (buf,
                     both if the local provides additional debugging
                     information for the external).  */
                  local = 1;
-                 if (sym_ptr->as_sym != (symbolS *) NULL)
+                 as_sym = sym_ptr->as_sym;
+                 if (as_sym != (symbolS *) NULL)
                    {
-                     sym_ptr->ecoff_sym.value = S_GET_VALUE (sym_ptr->as_sym);
+                     sym_ptr->ecoff_sym.value = S_GET_VALUE (as_sym);
+
+                     /* Get the type and storage class based on where
+                        the symbol actually wound up.  */
+                     if (sym_ptr->ecoff_sym.st == st_Nil
+                         && sym_ptr->ecoff_sym.sc == sc_Nil
+                         && ! MIPS_IS_STAB (&sym_ptr->ecoff_sym))
+                       {
+                         st_t st;
+                         sc_t sc;
+
+                         if (S_IS_EXTERNAL (as_sym)
+                             || ! S_IS_DEFINED (as_sym))
+                           st = st_Global;
+                         else if (S_GET_SEGMENT (as_sym) == text_section)
+                           st = st_Label;
+                         else
+                           st = st_Static;
+
+                         if (! S_IS_DEFINED (as_sym))
+                           sc = sc_Undefined;
+                         else if (S_IS_COMMON (as_sym))
+                           sc = sc_Common;
+                         else if (S_GET_SEGMENT (as_sym) == text_section)
+                           sc = sc_Text;
+                         else if (S_GET_SEGMENT (as_sym) == data_section)
+                           sc = sc_Data;
+                         else if (S_GET_SEGMENT (as_sym) == bss_section)
+                           sc = sc_Bss;
+                         else
+                           abort ();
+
+                         sym_ptr->ecoff_sym.st = (int) st;
+                         sym_ptr->ecoff_sym.sc = (int) sc;
+                       }
 
                      /* This is just an external symbol if it is
-                        outside a procedure and it has a type.  */
-                     if ((S_IS_EXTERNAL (sym_ptr->as_sym)
-                          || ! S_IS_DEFINED (sym_ptr->as_sym))
+                        outside a procedure and it has a type.
+                        FIXME: g++ will generate symbols which have
+                        different names in the debugging information
+                        than the actual symbol.  Should we handle
+                        them here?  */
+                     if ((S_IS_EXTERNAL (as_sym)
+                          || ! S_IS_DEFINED (as_sym))
                          && sym_ptr->proc_ptr == (proc_t *) NULL
                          && sym_ptr->ecoff_sym.st != (int) st_Nil)
                        local = 0;
 
                      /* If an st_end symbol has an associated gas
-                        symbol, then it is a fake created for a .bend
-                        or .end directive.  */
+                        symbol, then it is a local label created for
+                        a .bend or .end directive.  */
                      if (local && sym_ptr->ecoff_sym.st != st_End)
                        sym_ptr->ecoff_sym.iss =
                          add_string (&fil_ptr->strings,
                                      fil_ptr->str_hash,
-                                     S_GET_NAME (sym_ptr->as_sym),
+                                     sym_ptr->name,
                                      (shash_t **) NULL);
                    }
 
@@ -3817,12 +3878,13 @@ ecoff_build_symbols (buf,
                      /* The value of the symbol marking the end of a
                         procedure or block is the size of the
                         procedure or block.  */
-                     if (begin_type == st_Proc || begin_type == st_Block)
+                     if ((begin_type == st_Proc || begin_type == st_Block)
+                         && sym_ptr->ecoff_sym.sc != (int) sc_Info)
                        {
-                         know (sym_ptr->as_sym != (symbolS *) NULL);
+                         know (as_sym != (symbolS *) NULL);
                          know (begin_ptr->as_sym != (symbolS *) NULL);
                          sym_ptr->ecoff_sym.value =
-                           (S_GET_VALUE (sym_ptr->as_sym)
+                           (S_GET_VALUE (as_sym)
                             - S_GET_VALUE (begin_ptr->as_sym));
                        }
                    }
@@ -3855,9 +3917,9 @@ ecoff_build_symbols (buf,
                    }
 
                  /* If this is an external symbol, swap it out.  */
-                 if (sym_ptr->as_sym != (symbolS *) NULL
-                     && (S_IS_EXTERNAL (sym_ptr->as_sym)
-                         || ! S_IS_DEFINED (sym_ptr->as_sym)))
+                 if (as_sym != (symbolS *) NULL
+                     && (S_IS_EXTERNAL (as_sym)
+                         || ! S_IS_DEFINED (as_sym)))
                    {
                      EXTR ext;
 
@@ -3866,7 +3928,7 @@ ecoff_build_symbols (buf,
                      ext.ifd = fil_ptr->file_index;
                      ext.asym.iss = add_string (ext_strings,
                                                 ext_str_hash,
-                                                S_GET_NAME (sym_ptr->as_sym),
+                                                S_GET_NAME (as_sym),
                                                 (shash_t **) NULL);
                      if (*extbufend - (char *) ext_out
                          < sizeof (struct ext_ext))
@@ -3875,7 +3937,7 @@ ecoff_build_symbols (buf,
                                                    (char *) ext_out,
                                                    sizeof (struct ext_ext)));
                      ecoff_swap_ext_out (stdoutput, &ext, ext_out);
-                     ecoff_set_sym_index (sym_ptr->as_sym->bsym, iext);
+                     ecoff_set_sym_index (as_sym->bsym, iext);
                      ++ext_out;
                      ++iext;
                    }
@@ -4245,6 +4307,8 @@ ecoff_frob_symbol (sym)
 void
 ecoff_frob_file ()
 {
+  tag_t *ptag;
+  tag_t *ptag_next;
   efdr_t *fil_ptr;
   efdr_t *hold_file_ptr;
   proc_t * hold_proc_ptr;
@@ -4261,6 +4325,21 @@ ecoff_frob_file ()
   struct hash_control *ext_str_hash;
   char *set;
 
+  /* Handle any top level tags.  */
+  for (ptag = top_tag_head->first_tag;
+       ptag != (tag_t *) NULL;
+       ptag = ptag_next)
+    {
+      if (ptag->forward_ref != (forward_t *) NULL)
+       add_unknown_tag (ptag);
+
+      ptag_next = ptag->same_block;
+      ptag->hash_ptr->tag_ptr = ptag->same_name;
+      free_tag (ptag);
+    }
+
+  free_thead (top_tag_head);
+
   /* Output an ending symbol for all the files.  We have to do this
      here for the last file, so we may as well do it for all of the
      files.  */
@@ -4283,35 +4362,12 @@ ecoff_frob_file ()
   cur_proc_ptr = (proc_t *) NULL;
   for (sym = symbol_rootP; sym != (symbolS *) NULL; sym = symbol_next (sym))
     {
-      st_t st;
-      sc_t sc;
-
       if (sym->ecoff_symbol
          || sym->ecoff_file == (efdr_t *) NULL)
        continue;
 
-      if (S_IS_EXTERNAL (sym) || ! S_IS_DEFINED (sym))
-       st = st_Global;
-      else if (S_GET_SEGMENT (sym) == text_section)
-       st = st_Label;
-      else
-       st = st_Static;
-
-      if (! S_IS_DEFINED (sym))
-       sc = sc_Undefined;
-      else if (S_IS_COMMON (sym))
-       sc = sc_Common;
-      else if (S_GET_SEGMENT (sym) == text_section)
-       sc = sc_Text;
-      else if (S_GET_SEGMENT (sym) == data_section)
-       sc = sc_Data;
-      else if (S_GET_SEGMENT (sym) == bss_section)
-       sc = sc_Bss;
-      else
-       abort ();
-
       cur_file_ptr = sym->ecoff_file;
-      add_ecoff_symbol (S_GET_NAME (sym), st, sc, sym,
+      add_ecoff_symbol ((const char *) NULL, st_Nil, sc_Nil, sym,
                        S_GET_VALUE (sym), indexNil);
     }
   cur_proc_ptr = hold_proc_ptr;
index f59dca2b000902ab09ff1bbc3c145c6483357e18..6a88a5aa5e5d248b5392d4a4ccb37ed82526fb06 100644 (file)
@@ -1096,7 +1096,7 @@ macro (ip)
     case M_LWR_AB:
        s = "lwr";
     ld:
-       if (breg == treg) {
+       if (breg == treg || treg == 0) {
                tempreg = AT;
                used_at = 1;
        } else {