Using Memory Mapped I/O to load a 2-digit integer in MIPS Assembly - mips

I am working with MIPS Assembly in the Mars simulator and I am attempting to set it up so that I can enter any 2-digit number (ex: 24) into the Keyboard and Display MMIO Simulator and then take it from MMIO addresses and put it into my registers for manipulation. This technique will use polling, which I understand to some degree.
I can load individual characters and place their ascii value into my registers using the following code (inside .text):
main:
lui $t0, 0xFFFF #$t0 = 0xFFFF0000
poll: # polling procedure
lw $t1, 0($t0)
andi $t1, $t1, 0x0001
beq $t1, $zero, poll
lw $a0, 4($t0) # load word into register $a0
Is it possible in this case for MMIO to treat the input as an immediate and to take in two at once? If not, then are there any known workarounds to this? Thanks.

Related

MIPS Pipeline Stalls: SW after LW

I am confused as to how a Store Word Instruction coming after an LW using the same $rt causes a pipeline stall in MIPS.
Consider this block of code:
lw $s0, 0($t0)
sw $s0, 12($t0)
lw $s1, 4($t0)
sw $s1, 16($t0)
lw $s2, 8($t0)
sw $s2, 20($t0)
Here 3 words are being shifted around in memory. For e.g in the first 2 lines, $s0 is loaded into ,
and then its contents are saved back in the memory. I'm not sure if the sw instruction required $s0 in EX stage or in MEM stage. if it is needed in MEM stage, wouldn't it be resolved just by forwarding without needing to stall the pipeline?
Hypothetically, yes. Forwarding into the MEM stage directly would make it possible to execute dependent LW and SW back-to-back. As long as the loaded word is stored by the SW at least. It wouldn't be possible to have the SW use that loaded word as the base of the address without a pipeline bubble, otherwise it would require forwarding back in time.
But typically you would see a pipeline such as below (source: a model of a 5 stage pipelined MIPS in SIM-PL), with only one forwarder which feeds into EX. With a setup like that, there is no way to forward from LW into SW, the hardware required for it isn't there.

how can I know number of instruction access?

I'm studying computer architecture. I'm confused about some quiz.
when executing n instructions in load-store arch.
lw $t0, 32($s3)
add $t0, $s2, $t0
sw $t0, 48($s3)
then what is number of memory access, and number of instruction access?
I think num of memory access is 2 and num of instruction access is 3. Is it right?
Yes it's right, Just for the sake of understanding it better here is some explanation.
MIPS using load word instruction lw to read data word from memory into register and
store word sw to write a word in memory.
lw $t0, 32($s3)
This load a word from memory into register $t0
add $t0, $s2, $t0
This means you are on the register side no memory involved.
sw $t0, 48($s3) This store a word in memory.
You are using 3 instruction which two of them involve with memory access

Write into next byte of a register

I understand that registers in memory are 32 bits. I also understand that lb will load contents from memory into the lower 8 bits of a register, and that if I did
lb $t1, $a3
lb $t1, 4($a3)
The second lb command will overwrite the contents loaded in the first. However, is there a way to write into the second byte of a register (loading from a different part in memory, so not two bytes right next to each other) and preserve the information of the first byte?
I am assuming what you want to use here is lbu (load byte unsigned) and not lb because you don't want the register to be sign extended (e.g. copying the byte AA in the register will result in 000000AA, and not FFFFFFAA).
If you want to write to the second byte of a register you can first use lbu to load the byte from memory to another register, then shift left 8 bits, and addu it to the original register.
For example:
lbu $t1, $a3 # 0x000000AA
lbu $t2, 4($a3) # 0x000000BB
sll $t2, $t2, 8 # 0x000000BB -> 0x0000BB00
addu $t1, $t1, $t2 # 0x000000AA + 0x0000BB00 = 0x0000BBAA

What happens when I give an offset to a "temporary register" in MIPS

For example:
$t0 = A
$t1 = B
$t2 = C
If I do the following command
lw $t1, 4($t0)
would it load $t2 into $t1?
As long as your temporary registers are next to each other in memory.
i.e.
Reference: $t1 $t2
Mem Blocks: [byte][byte][byte][byte][byte][byte][byte][byte]...
Programs like Logisim should have the registers packed tightly.
Helpful page here from UC Berkeley.
If I do the following command
lw $t1, 4($t0)
would it load $t2 into $t1?
No, it would not. The lw instruction is used to load data from memory, not to copy the value of one register into another register. To quote from the MIPS manual:
LW rt, offset(base) MIPS32 (MIPS I)
Purpose:
To load a word from memory as a signed value
Description: rt ← memory[base+offset]
The contents of the 32-bit word at the memory location specified by the aligned effective address are fetched,
sign-extended to the GPR register length if necessary, and placed in GPR rt. The 16-bit signed offset is added to the
contents of GPR base to form the effective address.
In other words, what lw $t1, 4($t0) does is form an effective address by adding the value of $t0 with the value 4, and load a word (four bytes) from that address into register $t1.

MIPS: Code Scheduling To remove Stalls

I have the following MIPS code:
addi $s1, $0, 10
lw $t0, 4($s0)
srl $t1, $t0, 1 [STALL becausee $t0 depends on lw's $t0]
add $t2, $t1, $s1 [STALL because $t1 depends on srl's $t1]
sw $t2, 4($s0)
How can I rearrange it to avoid any stalls. I see that all the 2 to 5 line's sequence can't change. We can only move the first line in between srl and add OR lw and srl. Any ideas?
There are 4 read after write (RAW) dependencies in your code: addi->add, lw->srl, srl->add, add->sw. These can't be fixed as you pointed out.
What you can do is move the addi instruction. I would think the best place to move this instruction would be after the lw because in the MIPS architecture all load instructions use a load delay slot. This means that the instruction immediately after the load does not have access to the contents of the load. If you are using this code in a simulator such as spim or MARS this may not be simulated, but assuming you mean to use the loaded value of $t0 in the srl instruction, your assembly above is actually incorrect. For this to work, there should be a nop in between the lw and srl.
For that reason, it would be best to move the addi in between the lw and srl so as to utilize the lw load delay slot.