I'm confused when it comes to encoding the address for a J-format instruction.
From Class Notes:
Assume L1 is at the address 4194340 in decimal, which is 400024 in hexadecimal. We fill the target field as an address in instructions (0x100009) rather than bytes (0x400024).
Can someone please explain to me why this is?
The j instruction jumps to the passed target.
However, because the instruction set is limited to 32 bits, and 6 are used for the op-code, only 26 may be used for the jump target.
This means that the distance a j instruction can travel is limited as it works by appending its target to some number of the most significant bits of the current IPC.
The MIPS instruction set could have been defined by saying that when a j instruction is encountered you add the first 6 bits of the IPC to the 26 bit target of the j instruction, but instead it was noted that instructions that a program can jump are always "word-aligned". This means that these address are always a multiple of 4 and therefore the last 2 bits of the address are always 0.
This allows us to not encode the last 2 bits in our jump target and instead encode bits 3-28. This means that to get the target of a j instruction you take the first 4 bits of the PC, add the jump target, and then add two zeros.
Hopefully with that explanation out of the way it makes sense why the target 0x400024 is encoded in the j instruction by the bits 0x100009 i.e. 0x400024 >> 2. Because the last two bits are not needed.
Related
I am following an example in my book for direct mapping cache.
The specifications are:
Assume 32bit words, 32bit address, 1 word blocksize (b), 8 word capacity (C).
This means that number of blocks (B) = C/b = 8 and number of set (S) = B = 8
I am confused because I thought each set only contains 1 word (b) thus 32 bits. But in this picture, it shows that data is 32 bits and tag is 27 bits. This gives us a total of 59 bits which is larger than out blocksize (b).
Does this mean that the address is kept elsewhere and only data is kept in the set?
As your picture shows, the data portion is 32b (as you said, each set contains only 1 word).
The tag is a required portion of each set that allows us to know if the requesting address is located in the cache (a "hit"). Your picture says the tag is 27 bits in size.
"59" bits (actually 60 bits) is simply tracking how much actual SRAM is required to build this cache (1 valid bit + 27 tag bits + 32 data bits)*8 sets = 480 bits of SRAM.
However, don't let yourself be confused by thinking the tag is part of the data block. It can (and often is) located elsewhere on the chip, even though conceptually it is coupled with the data portion of the set.
I'd also like to add (and hopefully not further confuse the subject), while it is possible to build a cache as they have shown (both the tags, valid bit, and data in SRAM, which means it will be very dense), you may not actually want to build it that way! The data would be in SRAM, but I suspect it's more likely for the valid bits and tags to be located elsewhere in flip flops. Much faster to access! You should talk to your teacher about how caches are normally built and the trade offs in having the tags and valid bits in SRAM vs flipflops.
In 8051 memory bank (00h to 1Fh), 8051 provide 32 registers as 8 registers(R0 t0 R7) to each of 4 banks.
Why these registers are not given as R0 to R31?
Thanks in Advance..
Many instruction opcodes are only 8 bits long; if all 32 registers were accessible in one of these instructions then there would be only 3 bits left to encode the instruction length and the operation. Similarly, two byte instructions often use the second byte to encode a full 8-bit operand (eg., an address), and have effectively the same constraint.
In many instances it is possible to refer to the register you need by its absolute address, using a longer instruction, but if you will access it frequently then it may be better to change the active bank so that you can use more short opcodes.
As far as I remember you can access only 8 of those register at a time. To access one of the other groups you need to switch the bank. I guess it has something to do with a instruction operand being only 3 bits long (and not 5 bits).
Let’s say we have a 32-bit address, so each bit can be either 1 or 0.
So the total number of combinations is equal to 2^32.
So we can represent 2^32 addresses (without unit).
But why do people say a 32-bit address can represent 2^32 byte addresses (why “byte” addresses)?
I already read Why does a 32-bit OS support 4 GB of RAM?
Won’t it become 2^32 * 8 bits addresses? Why can people simply add “byte” at the end?
Because memory is byte-addressable rather than bit-addressable.
The address 0x100 refers to a single byte and the address 0x101 refers the following byte.
Each address points to a byte. In memory, it is not the single bits that are addressed but instead bytes.
So, 32bits will give you an addressable space of 2^32 items, each item being a full byte. Yes, it could have been made so that each address points to a specific bit, but no, they made each address point to a byte.
http://www.alex-ionescu.com/?p=50.
I read the above post. The author explains why Windows x64 supports only 44-bit virtual memory address with singly linked list example.
struct { // 8-byte header
ULONGLONG Depth:16;
ULONGLONG Sequence:9;
ULONGLONG NextEntry:39;
} Header8;
The first sacrifice to make was to reduce the space for the sequence
number to 9 bits instead of 16 bits, reducing the maximum sequence
number the list could achieve. This still only left 39 bits for the
pointer — a mediocre improvement over 32 bits. By forcing the
structure to be 16-byte aligned when allocated, 4 more bits could be
won, since the bottom bits could now always be assumed to be 0.
Oh, I can't understand.
What "By forcing the structure to be 16-byte aligned when allocated, 4 more bits could be won, since the bottom bits could now always be assumed to be 0." means?
16 is 0010000 in binary
32 is 0100000 in binary
64 is 1000000 in binary
etc
You can see that for all numbers that are multiples of 16, the last four bits are always zero.
So, instead of storing these bits you can leave them out and add them back in when it's time to use the pointer.
For a 2^N-byte aligned pointer, its address is always divisible by 2^N - which means that lower N bits are always zero. You can store additional information in them:
encode ptr payload = ptr | payload
decode_ptr data = data & ~mask
decode_payload data = data & mask
where mask is (1 << N) - 1 - i.e. a number with low N bits set.
This trick is often used to save space in low-level code (payload can be GC flags, type tag, etc.)
In effect you're not storing a pointer, but a number from which a pointer can be extracted. Of course, care should be taken to not dereference the number as a pointer without decoding.
In real mode segmented memory model, a segment always begins on a paragraph boundary. A paragraph is 16 bytes in size so the segment address is always divisible by 16. What is the reason/benefit of having segments on paragraph boundaries?
It's not so much a benefit as an axiom - the 8086's real mode segmentation model is designed at the hardware level such that a segment register specifies a paragraph boundary.
The segment register specified the base address of the upper 16 bits of the 8086's 20 bit address space, the lower 4 bits of that base address were in essence forced to zero.
The segmented architecture was one way to have the 8086's 16-bit register architecture be able to address a full megabyte(!) of address space (which requires 20 bits of addressing).
For a little more history, the next step that Intel took in the x86 architecture was to abstract the segment registers from directly defining the base address. That was the 286 protected mode, where the segment register held a 'selector' that instead of defining the bits for a physical base address was an index into a a set of descriptor tables that held information about the physical address, permissions for access to the physical memory, and other things.
The segment registers in modern 32-bit or larger x86 processors still do that. But with the address offsets being able to specify a full 32-bits of addressing (or 64-bits on the x64 processors) and page tables able to provide virtual memory semantics within the segment defined by a selector, the programming model essentially does away with having to manipulate segment registers at the application level. For the most part, the OS sets the segment registers up once, and nothing else needs to deal with them. So programmers generally don't even need to know they exist anymore.
The 8086 had 20 address lines. The segment was mapped to the top 16, leaving an offset of the bottom 4 lines, or 16 addresses.
The Segment register stores the address of the memory location where that segment starts. But Segment registers stores 16 bit information. This 16 bit is converted to 20 bits by appending 4 bits of 0 to the right end of the address. If a segment register contains 1000H then it is left shifted to get 10000H. Now it is 20 bits.
While converting we added 4 bits of 0 to the end of the address. So every segment in memory must begin with memory location where the last 4 bits are 0.
For ex:
If a segment starts at 10001H memory location, we cannot access it because the last 4 bits are not 0.
Any address in segment register will be appended with 4 bits in right end to convert to 20bits. So there is no way of accessing such an address.