Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sign extend a nine-bit number in C

Tags:

I have a short, instr, that looks like this:

1110xxx111111111 

I need to pull out bits 0-9, which I do with (instr & 0x1FF). This quantity is then stored in a new short. The problem is that when this occurs, it becomes 0x0000000111111111, not 0x1111111111111111 like I want. How can I fix this? Thanks!

EDIT

Here's the code:

short instr = state->mem[state->pc]; unsigned int reg = instr >> 9 & 7; // 0b111 state->regs[reg] = state->pc + (instr & 0x1FF); 

This is a simulator that reads in assembly. state is the machine, regs[] are the registers and pc is the address of the current instruction in mem[].

This is fine if the last nine bits represent a positive number, but if they're representing -1, it's stored as all 1's, which is interpreted as a positive value by my code.

like image 899
Chris Long Avatar asked Apr 28 '11 05:04

Chris Long


People also ask

How do you sign a bit extend?

Sign-extending means copying the sign bit of the unextended value to all bits on the left side of the larger-size value. The same way as leading zeroes do not affect values of a positive numbers, leading 1s do not affect values of a negative numbers. Sign-extend operation is often abbreviated SEXT.

What is the extension of bit?

A BIT file is an . MP3 audio file with the . bit file extension, which was used in the early 1990s before being replaced by the . mp3 extension in 1995.

What is sign extend and zero extend?

Sign extension is used for signed loads of bytes (8 bits using the lb instruction) and halfwords (16 bits using the lh instruction). Sign extension replicates the most significant bit loaded into the remaining bits. Zero extension is used for unsigned loads of bytes ( lbu ) and halfwords ( lhu ).

How do you extend a two's complement number?

When a two's complement number is extended to more bits, the sign bit must be copied into the most significant bit positions. This process is called sign extension. For example, the numbers 3 and −3 are written as 4-bit two's complement numbers 0011 and 1101, respectively.


1 Answers

Assuming a short is 16 bits:

You can do it manually: (instr & 0x1FF) | ((instr & 0x100) ? 0xFE00 : 0). This tests the sign bit (the uppermost bit you are retaining, 0x100) and sets all the bits above it if the sign bit is set. You can extend this to 5 bits by adapting the masks to 0x1F, 0x10 and 0xFFE0, being the lower 5 bits, the 5th bit itself and all the bits 5-16 respectively.

Or you can find some excuse to assign the bits to the upper part of a signed short and shift them down (getting a sign-extension in the process): short x = (instr & 0x1FF) << 7; x >>= 7; The latter may actually end up being more straightforward in assembly and will not involve a branch. If instr is signed this can be done in a single expression: (instr & 0x1FF) << 7 >> 7. Since that already removes the upper bits it simplifies to instr << 7 >> 7. Replace 7 with 11 for 5 bits (16-5).

like image 124
Ben Jackson Avatar answered Oct 12 '22 07:10

Ben Jackson