RISC-V: Do 12-bit immediate logical operations operate on the whole register? - riscv

I am trying to write a simulator for a RISC-V CPU and can not find a definitve answer to my question.
Let's say I want to use
ANDI rs1, rd, 0xFFF
with rs1 containing 0xFFFFFFFF and the immediate value being 0xFFF.
Does the ANDI operate on the full register and just fill the remaining 20 bit of the immediate with zeros so the result in rd will be 0x000000FFF?
Or are the higher 20 bits ignored and the result in rd will still be 0xFFFFFFFF?
Same question for XORI and ORI commands.

The Immediate value is sign extended,
12 bit FFF will translate to 32'hFFFFF_FFF for RV32
so the values being AND-ed will be
rs1_data & 0xFFFFF_FFF

Related

68000- How to move a hexadecimal number in a register 2 units to the left?

I want to move the number 01,02,03,04 individually into the register D1 so that after all the moves have completed the result in register D1 will be 01020304.
The way I'm thinking of solving this problem is, move 01 to D1. Then somehow shift it 2 digits to the left and then move 02 in. And so on to get the solution.
How should I do this?
this can be done in several ways, the most logical is to load the intended topmost byte first, then left-shift the register (by 8 bits = 1 byte) and load the next byte:
move.b #$01,d0
lsl.w #8,d0 ; could lsl.l here, too
move.b #$02,d0
lsl.l #8,d0
move.b #$03,d0
lsl.l #8,d0
move.b #$04,d0
; d0 = $01020304
A somewhat more confusing, but (on the 68000) faster method is load the most significant word as desribed above into the lower word, then use the SWAP instruction to switch register halves, then load the least significant word normally:
move.b #$01,d0
lsl.w #8,d0
move.b #$02,d0
swap d0
move.b #$03,d0
lsl.w #8,d0
move.b #$04,d0
; d0 = $01020304
The point here is that SWAP performs a rotate by 16 on the entire register, so the individual rotations can be performed using word sized shifts. Also, since the 68000 doesn't have a barrel shifter, shifting performance is dependent on shift distance, meaning shifting a register by 8 is relatively slow, while SWAP performs quickly.
On the "bigger" 68K members you won't see much performance difference, because they shift quickly, regardless of shift distance.

Overflow flag cleared after SBC with overflow in 6502 emulation?

I've "finished" emulating my 6502 processor, and I'm in the testing phase right now. Being the beginner that I am, I've been stuck on this one issue for a couple of hours already. I'm following an NES test which basically is just a homebrew ROM and a log someone made, and it says what value is supposed to be in every register after a step through the memory. I'm stuck on one part where the log is showing that the overflow flag is cleared after an immediate SBC instruction, even though the accumulator has the value 0x40, and first argument (memory pc + 1) is equal to 0x41. That means that 0x40 - 0x41 should be 0xFF, i.e. -1, so that means that there was an overflow, right? I read some article about the overflow flag, and it states that an overflow is produced when a value is too big or too small to be held in a signed byte, and therefore overflows to the other side (i.e. 2 8 bit positives become an 8 bit negative, and vice versa). So am I thinking the wrong way? This is the log line:
CBC6 E9 41 SBC #$41 A:40 X:AA Y:73 P:E5
The line after that states that the P register has become 0xA4, which would mean the carry and overflow flags are both cleared. I get the carry part, but not the overflow part. This is the next line, if care for it:
CBC8 20 62 F9 JSR $F962 A:FF X:AA Y:73 P:A4
By the way; that second line proves my point: the A register has indeed become 0xFF, and 0xFF in a signed byte would equal 256 - 255 = -1........
As you correctly say, overflow is for signed operations if the result doesn't fit. Note that a signed byte can hold values between -128 and +127, and as such -1 fits nicely in that range. That it has crossed zero is not relevant for signed overflow because 0 is in the middle of the representable range. It's only interesting for unsigned carry. For overflow the boundary is at 0x80 (-128) which in turn is irrelevant for unsigned operations.

What does 4'b1001 , 32'h0 represent (VERA SYNTAX)?

I am new to vera and trying to understand the syntax. What does 4b' and 32' represent ? Is this like 4 bit and 32 bit?
I am so confused and have to work on something related to this.
Another question is what does bit [31:0] mean ? does that mean anything from bit 31 and 0 ?
Thnks
The number number format is:
[width]'[base][value]
So 4'b1001 is a 4-bit, binary value 1001 (9)
32'h0 is a 32-bit, hex value 0.
Sometimes you'll see 'd as well which is decimal.
Appended to the end of a bus, [n:m] is a part select, which means, select the bits from n to m of this bus. So [31:0] selects the lower 32 bits of a bus (or all of the bus if it's 32-bit wide).

Game Boy: What constitutes a "half-carry"?

The Game Boy Z80 CPU has a half-carry flag, and I can't seem to find much information about when to set/clear it.
What I understand so far is that any 8-bit add, subtract, shift, or rotate operation (and maybe others?) set it to bit 4 of the result(?), and the DAA instruction sets/uses this somehow. What I'm not sure is how 16-bit instructions affect it and whether it's affected or not by the use of certain registers.
It's the carry from bit 3 to bit 4, just like the normal carry flag records carry from bit 7. So, e.g. to get the half carry bit in an add:
((a&0xf) + (value&0xf))&0x10
Which gives 0x10 if half carry should be set, 0 otherwise. Getting half carry from the other relevant ops follows naturally - the questions is whether there was carry from the low nibble to the high.
To put things in perspective, the z80 has a 4bit ALU and performs 8bit ops by doing two 4bit ops. So it gets half carry very naturally, as an intermediate result.
DAA is interested in the flag because if half carry is set then two digits that add up to more than 16 were added in the low nibble; that will have correctly produced carry into the upper nibble but will have left the low nibble 6 lower than it should be, since there were six more values between 10, when it should have generated carry, and 16, when it did.
For 16-bit operations, the carry from bit 3 to bit 4 in the register's high byte sets the flag. In other words, bit 11 to bit 12.
(Note the above bits are labeled 0-15, from least to most significant)
See here: http://www.z80.info/z80code.htm
16 bit arithmetic
If you want to add numbers that are more than the 0-255 that can
be stored in the A register, then the HL, IX or IY registers can
be used. Thus LD HL,1000H:LD BC,2000H:ADD HL,BC will give
A CZPSNH BC DE HL IX IY A' CZPSNH' BC' DE' HL' SP
00 000000 2000 0000 3000 0000 0000 00 000000 0000 0000 0000 0000
The flags are set as follows.
C or carry flag 1 if answer >65535 else 0
Z or zero flag not changed
P flag not changed
S or sign flag not changed
N flag 0
H or half carry flag 1 if carry from bit 11 to bit 12 else 0
Since the half-carry flag is one of the most common stumbling blocks for Game Boy emulator makers, I'll take the liberty to post a link to a recent question of mine regarding the subject as an answer:
Game Boy: Half-carry flag and 16-bit instructions (especially opcode 0xE8)
A summary of the above thread (answer by #gekkio):
It depends on the instruction, but the flags are always updated based on the same bit positions if you think in terms of 8-bit values...it just varies whether we're talking about the high or low byte of the 16-bit value. Bit 11 is just bit 3 of the high byte.
ADD SP, e: H from bit 3, C from bit 7 (flags from low byte op)
LD HL, SP+e: H from bit 3, C from bit 7 (flags from low byte op)
ADD HL, rr: H from bit 11, C from bit 15 (flags from high byte op)
INC rr: no flag updates (executed by the 16-bit inc/dec unit)
DEC rr: no flag updates (executed by the 16-bit inc/dec unit)

operand of LIDT is displacement/absolute address

I stumbled upon a statement in Intel Software developers manual:
"For LGDT, LIDT, LLDT, LTR, SGDT, SIDT, SLDT, STR, the exit qualification receives the value of the instruction’s displacement field, which is sign-extended to 64 bits if necessary (32 bits on processors that do not support Intel 64 architecture). If the instruction has no displacement (for example, has a register operand), zero is stored into the exit qualification. "
Now if I have an instruction LIDT 0xf290, then is "0xf290" a displacement? I think answer is yes.
So, my confusion is what all constitute as displacement? I was under impression that displacement is something which is calculated with respect to current eip value.
For eg. jmp xxx (In intrasegment jumps this will be a displacement. But for intersegment jumps, it should be absolute address.) If that is the case then why LIDT loads a relative address?
A displacement is just an offset from some origin, which may be a Base+Index*Scale, or 0. The other operand x86 has that can hold large values is immediate, which is useful for things like adding constants (e.g. ADD $42, %eax).
Incidentally, it appears that relative jumps use the immediate field, probably because they modify EIP by a constant.

Resources