Home | History | Annotate | Download | only in libasm
      1 /* Add signed little endian base 128 integer to a section.
      2    Copyright (C) 2002 Red Hat, Inc.
      3    Written by Ulrich Drepper <drepper (at) redhat.com>, 2002.
      4 
      5    This program is Open Source software; you can redistribute it and/or
      6    modify it under the terms of the Open Software License version 1.0 as
      7    published by the Open Source Initiative.
      8 
      9    You should have received a copy of the Open Software License along
     10    with this program; if not, you may obtain a copy of the Open Software
     11    License version 1.0 from http://www.opensource.org/licenses/osl.php or
     12    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
     13    3001 King Ranch Road, Ukiah, CA 95482.   */
     14 
     15 #ifdef HAVE_CONFIG_H
     16 # include <config.h>
     17 #endif
     18 
     19 #include <inttypes.h>
     20 #include <string.h>
     21 
     22 #include <libasmP.h>
     23 
     24 
     25 int
     26 asm_addsleb128 (asmscn, num)
     27      AsmScn_t *asmscn;
     28      int32_t num;
     29 {
     30   if (asmscn == NULL)
     31     return -1;
     32 
     33   if (asmscn->type == SHT_NOBITS && unlikely (num != 0))
     34     {
     35       __libasm_seterrno (ASM_E_TYPE);
     36       return -1;
     37     }
     38 
     39   if (unlikely (asmscn->ctx->textp))
     40     printf ("\t.sleb128\t%" PRId32 "\n", num);
     41   else
     42     {
     43       char tmpbuf[(sizeof (num) * 8 + 6) / 7];
     44       char *dest = tmpbuf;
     45       uint32_t byte;
     46       int32_t endval = num >> 31;
     47 
     48       if (num == 0)
     49 	byte = 0;
     50       else
     51 	while (1)
     52 	  {
     53 	    byte = num & 0x7f;
     54 
     55 	    num >>= 7;
     56 	    if (num == endval)
     57 	      /* This is the last byte.  */
     58 	      break;
     59 
     60 	    *dest++ = byte | 0x80;
     61 	  }
     62 
     63       *dest++ = byte;
     64 
     65       /* Number of bytes produced.  */
     66       size_t nbytes = dest - tmpbuf;
     67 
     68       /* Make sure we have enough room.  */
     69       if (__libasm_ensure_section_space (asmscn, nbytes) != 0)
     70 	return -1;
     71 
     72       /* Copy the bytes.  */
     73       if (likely (asmscn->type != SHT_NOBITS))
     74 	memcpy (&asmscn->content->data[asmscn->content->len], tmpbuf, nbytes);
     75 
     76       /* Adjust the pointer in the data buffer.  */
     77       asmscn->content->len += nbytes;
     78 
     79       /* Increment the offset in the (sub)section.  */
     80       asmscn->offset += nbytes;
     81     }
     82 
     83   return 0;
     84 }
     85