상수를 표현하기 더 좋다. 나머지 16bit는 몽땅 immediate field이다.
ori $11(01011), $9(01001), 0x8000 를 변환하면 다음과 같다.
-> I-format: 001101 01001 01011 1000000000000000
-> 2진수: 0011 0101 0010 1011 1000 0000 0000 0000
-> 16진수: 0x352B8000
andi $12, $0, 0xffff 을 변환하면 다음과 같다.
-> I-format: 001100 00000 01100 1111111111111111
-> 2진수: 0011 0000 0000 1100 1111 1111 1111 1111
-> 16진수: 0x300CFFFF
저 I-format instructions을 Processor가 가져오고, Control이 I-format인지 확인하고 Register 값을 읽는다.
예를 들어, $0번 레지스터의 32bit(32개)의 0을 가져오면 ALU에서 계산한다. 나머지 operand는 instruction의 일부인 immediate field에서 가져온다.
하지만, ALU의 경우 input으로 32bit 두개를 받아서, 32bit 출력을 만들어 내는 회로인데..
immediate field는 16bit 밖에 안된다. 그러면 어떻게 해야하나?
😀 바로, 32bit로 늘려줘야한다!
$0번 레지스터에서 읽어온 값은 32bit 0인데, immediate에는 16bit밖에 없다.
이거를 0으로 채워서 and 연산을 해준다.
-> 결국, $12번 레지스터는 32bit 0이 된다.
addi의 opcode는 08 = 001000로 표현이 된다.
이 명령어를 Processor가 Memory에서 가져와서 수행하기 위해서는, 덧셈을 해야한다.
덧셈을 하는 회로가 ALU라는 회로이고, 저 빨간 네모가 ALU이다.
두번째 operand는 instruction의 immediate field에서 가져오는데, 이게 16bit밖에 안되므로 나머지 물음표를 채워야한다.
🤔 여기서 물음표를 zero extension이 아닌 모두 1로 채우는데, 왜 그러냐?
immediate field의 sign bit가 1이므로, 그 값을 채워준다. -> 이것이 sign extension!
하지만, spim의 assembler는 16진수로 쓴 상수는 항상 sign extension을 하지 않는다.
signed number로 쓰인 10진수는 sign extension을 한다.
결국, out-of-range error가 나오는 경우가 생긴다.
spim이 봤을 때 저 0x8000이 16진수로 표현되어 있기 때문에 unsigned number로 해석한다.
따라서, -32768로 해석되는게 아닌 +32768로 해석되어 out-of-range error가 된다.
여기서 OK를 누르면, 다른 instruction으로 바꿔주는데..
addi instruction은 out-of-range error가 발생한 후, 0x8000이 16진수로 쓰여있었으므로 $10번 레지스터에 sign extension이 되지 않은 값을 원한다고 예측한다.
따라서, 내가 addi로 쓰더라도 이렇게 ori $10, $0, -32768 으로 바꾸어 수행한다.
이렇게 addi $10, $0, 0x8000 과 ori $10, $0, 0x8000 은 같은 결과를 낸다는 것을 볼 수 있다.