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

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.

Related

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

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

What Does Assembly Instruction Shift Do?

I came across a pretty interesting
article that demonstrated how to remove nullbyte characters from shellcode. Among the techniques used, the assembly instructions shl and shr seemed to occupy a rather important role in the code.
I realize that the assembly instructions mov $0x3b, %rax and mov $59, %rax each actually generate the machine code instructions 48 c7 c0 3b 00 00 00. So to cope for this, the author instead uses mov $0x1111113b, %rax to fill the register with the system call number, which generates instead the machine code 48 c7 c0 3b 11 11 11, which successfully removes nullbytes.
Unfortunately, the code still doesn't execute because syscall treats 3b 11 11 11 as an illegal instruction, or this causes the code to seg fault. So what the author then did was shift %rax back and forth 56 bytes with the commands
shl $0x38, %rax
shr $0x38, %rax
After this shift, the code executes perfectly. What I want to know is how the shift instructions fixes the 48 c7 c0 3b 11 11 11 issue, and somehow makes %rax proper and syscall'able. I know that the shl/shr shifts bits left and right, meaning that shifting left moves the bits up into higher bits, and shifting right makes them lower again, because binary is read right to left. But how does this at all change the code and make it executable? Doesn't shifting back and forth essentially change nothing, putting the shifted bits exactly back where they were in the beginning?
My only theory is that shifting bits away leaves behind zeros. But I still don't see how shifting %rax forward and then back fixes the solution, because wouldn't it bring back the 11 11 11 section anyway?
Anyways, I thought this was interesting as I had never seen the shift operands before today. Thanks in advance.
Shifting is a lossy operation - if bits are shifted outside of the register, they just disappear. (Sometimes one of them is stored in a carry flag, but that's not important here.) See http://en.wikibooks.org/wiki/X86_Assembly/Shift_and_Rotate#Logical_Shift_Instructions .
The shift left (shl) operation does this:
0x000000001111113b << 0x38 = 0x3b00000000000000
The 0x111111 part would have occupied bit 64, 65, 66 etc., but %rax is a 64-bit register, so those bits vanish. Then, the logical shift right (shr) operation does this:
0x3b00000000000000 >> 0x38 = 0x000000000000003b
Giving you the number that you want. And that's all there is to it.

x64 Intel Opcode 81 /2

How does the processor differentiate between these two instructions?
81 /2 iw - Add with carry imm16 to r/m16.
81 /2 id - Add with carry imm32 to r/m32.
The only thing different I can see in the instruction is the size of the immediate value and that isn't enough, right? I mean if the immediate is two bytes an instruction could be right after it and the processor wouldn't know if it was 4 bytes of immediate or 2 bytes and another instruction.
Also am I supposed to add a REX prefix to these for 64-bit operation or just REX.R for the 9-16 registers?
Mode and operand size prefix. In 16 bit mode, 81 /2 will be adc rm16, imm16. In 32 or 64 bit mode, it will be adc rm32, imm32. Unless you add the operand size override, then they switch places.
To make it adc rm64, imm32 (there is no adc rm64, imm64), it needs an REX.W prefix, REX.R is useless since there is no r operand, REX.B/X will just allow you to use extended registers as (part of) the rm operand, and don't change the operand size. So for example adc r8d, 0xDEADBEEF is valid and would be 41 81 D0 EF BE AD DE.

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