- Posts: 7
- Joined: 16-December 17
- Gender:Not Telling
- Project:Sonic Union

This is my first topic!

Unfortunately I was unable to find the c++ equivalent to the bset, bclr, bchg, bvc and bvs..

If you want to know how to do rol and ror, look there.

Local variables

Conditions

Addiction and subtraction

The clear, swap and exchange instruction

Bitwise operators

The neg, ext

Multiplication and division

Branch on sign

Unfortunately I was unable to find the c++ equivalent to the bset, bclr, bchg, bvc and bvs..

If you want to know how to do rol and ror, look there.

Local variables

Spoiler

Consider the following 68k code:

Here we're moving the value of the constant 'hello' to the register d0 and we're setting the value of the constant 'world' to the register d1.

Moves are basically the equal (=) operator in c++, move.l is int (or long), move.w is short and move.b is char (or byte).

Translating it to c++ we get this:

~~You probably wondered (why the register keyword?), simple. It tells the compiler that the variable value should be a register (if possible) instead of being allocated in the stack. This keyword is not needed when this is a release build though. (which normally has the O2 build option).~~

Nevermind, it shows a warning in c++17 (or c++0z) target.

Consider the following 68k code:

Generic: move.l #hello, d0 move.l #world, d1

Here we're moving the value of the constant 'hello' to the register d0 and we're setting the value of the constant 'world' to the register d1.

Moves are basically the equal (=) operator in c++, move.l is int (or long), move.w is short and move.b is char (or byte).

Translating it to c++ we get this:

int d0 = hello; int d1 = world;

Nevermind, it shows a warning in c++17 (or c++0z) target.

Conditions

Spoiler

Instructions:

cmp.x y, z: compares a register with another. (x should be l or w or b)

cmpi.x y, z: compares z with y (a short number, 0-65535 or -32768-32767). (x should be l or w or b)

tst.x y: compares a register with zero. (x should be l or w or b)

beq x: branch (goto x) if the cmp x, y are equal.

bne x: branch (goto x) if the cmp x, y are not equal.

bge x: branch (goto x) if the cmp x is greater or equal to y.

bgt x: branch (goto x) if the cmp x is greater than y.

ble x: branch (goto x) if the cmp x is less or equal to y.

blt x: branch (goto x) if the cmp x is less or equal to y.

bcc x: branch (goto x) if the cmp x is greater or equal to y. (unsigned)

bhi x: branch (goto x) if the cmp x is greater than y. (unsigned)

bls x: branch (goto x) if the cmp x is less or equal to y. (unsigned)

bcs x: branch (goto x) if the cmp x is less or equal to y. (unsigned)

Consider the following code

Translating, we get:

...But it's wrong. Because there's a useless label there, which makes the code ugly (OH NO). So, to translate it we should negate the compare instructions! Look:

Instructions:

cmp.x y, z: compares a register with another. (x should be l or w or b)

cmpi.x y, z: compares z with y (a short number, 0-65535 or -32768-32767). (x should be l or w or b)

tst.x y: compares a register with zero. (x should be l or w or b)

beq x: branch (goto x) if the cmp x, y are equal.

bne x: branch (goto x) if the cmp x, y are not equal.

bge x: branch (goto x) if the cmp x is greater or equal to y.

bgt x: branch (goto x) if the cmp x is greater than y.

ble x: branch (goto x) if the cmp x is less or equal to y.

blt x: branch (goto x) if the cmp x is less or equal to y.

bcc x: branch (goto x) if the cmp x is greater or equal to y. (unsigned)

bhi x: branch (goto x) if the cmp x is greater than y. (unsigned)

bls x: branch (goto x) if the cmp x is less or equal to y. (unsigned)

bcs x: branch (goto x) if the cmp x is less or equal to y. (unsigned)

Consider the following code

Generic: move.l #hello, d0 move.l #world, d1 cmp.l d0, d1 beq.s Generic2 move.l #$0, d0 Generic2: move.l #$0, d1

Translating, we get:

register int d0 = hello; register int d1 = world; if (d0 == d1) { goto Generic2; } d0 = 0; Generic2: d1 = 0;

...But it's wrong. Because there's a useless label there, which makes the code ugly (OH NO). So, to translate it we should negate the compare instructions! Look:

register int d0 = hello; register int d1 = world; if (d0 != d1) { d0 = 0; } d1 = 0;

Addiction and subtraction

Spoiler

It's easy.

Instructions:

add.x y, z: adds y to z. (x should be l or w or b)

addi.x y, z: adds y (a short number, 0-65535 or -32768-32767) to z. (x should be l or w or b)

add.z x, y(z): adds x to the adress in y + z. (w should be l or w or b)

addi.z x, y(z): adds x (a short number, 0-65535 or -32768-32767) to the adress in y (a register) plus z (a short number, 0-65535 or -32768-32767). (w should be l or w or b)

sub.x y, z: subs y to z. (x should be l or w or b)

subi.x y, z: subs y (a short number, 0-65535 or -32768-32767) to z. (x should be l or w or b)

sub.z x, y(z): subs x to the adress in y + z. (w should be l or w or b)

subi.z x, y(z): subs x (a short number, 0-65535 or -32768-32767) to the adress in y (a register) plus z (a short number, 0-65535 or -32768-32767). (w should be l or w or b)

The following 68k code:

Translated should be like this:

Don't forget that a pointer points to a adress.

It's easy.

Instructions:

add.x y, z: adds y to z. (x should be l or w or b)

addi.x y, z: adds y (a short number, 0-65535 or -32768-32767) to z. (x should be l or w or b)

add.z x, y(z): adds x to the adress in y + z. (w should be l or w or b)

addi.z x, y(z): adds x (a short number, 0-65535 or -32768-32767) to the adress in y (a register) plus z (a short number, 0-65535 or -32768-32767). (w should be l or w or b)

sub.x y, z: subs y to z. (x should be l or w or b)

subi.x y, z: subs y (a short number, 0-65535 or -32768-32767) to z. (x should be l or w or b)

sub.z x, y(z): subs x to the adress in y + z. (w should be l or w or b)

subi.z x, y(z): subs x (a short number, 0-65535 or -32768-32767) to the adress in y (a register) plus z (a short number, 0-65535 or -32768-32767). (w should be l or w or b)

The following 68k code:

add.b d0, d0 add.b #$0001, d0 add.b d0, (a0) add.b #$0001, (a0) sub.b d0, d0 subi.b #$0001, (a0) sub.b d0, (d1) subi.b #$0001, (a0)

Translated should be like this:

register char d0; register char* a0; d0 += d0; d0 += 0x0001; *a0 += d0; *a0 += 0x0001; d0 -= d0; d0 -= 0x0001; *a0 -= d0; *a0 -= 0x0001;

Don't forget that a pointer points to a adress.

The clear, swap and exchange instruction

Spoiler

Instructions:

clr.x y: sets zero to the value of y. (x should be l or w or b)

swap x: swaps the upper word (0xXXXX0000) with the lower word (0x0000XXXX) of x.

exg.x y, z: swaps y with z (x should be l or w or b)

clear in c++ is basically:

So it's not that hard. But the swap is not that simple. It's like this:

(x & 0xFFFF0000) >> 16 is anding x to 0xFFFF0000 and then shifting to right by 16 bits, so, if the value of x is 0xDEADBEEF, after doing this it's value will be 0xDEAD.

(x << 16) is shifting x to left by 16 bits, so, if the value of x is 0xDEADBEEF, after doing this it's value will be 0xBEEF0000.

After doing the two operations, you will or them to get the final result. (0xDEAD0000 | 0xBEEF = 0xBEEFDEAD);

Instructions:

clr.x y: sets zero to the value of y. (x should be l or w or b)

swap x: swaps the upper word (0xXXXX0000) with the lower word (0x0000XXXX) of x.

exg.x y, z: swaps y with z (x should be l or w or b)

clear in c++ is basically:

x = 0;

So it's not that hard. But the swap is not that simple. It's like this:

x = ((x & 0xFFFF0000) >> 16) | x << 16;

(x & 0xFFFF0000) >> 16 is anding x to 0xFFFF0000 and then shifting to right by 16 bits, so, if the value of x is 0xDEADBEEF, after doing this it's value will be 0xDEAD.

(x << 16) is shifting x to left by 16 bits, so, if the value of x is 0xDEADBEEF, after doing this it's value will be 0xBEEF0000.

After doing the two operations, you will or them to get the final result. (0xDEAD0000 | 0xBEEF = 0xBEEFDEAD);

Bitwise operators

Spoiler

Another easy one.

Instructions:

not.x y: nots y (!y). (x should be l or w or b)

and.x y, z: ands y to z. (x should be l or w or b)

andi.x y, z: ands y (a short number, 0-65535 or -32768-32767) to z. (x should be l or w or b)

and.z x, y(z): ands x to the adress in y + z. (w should be l or w or b)

andi.z x, y(z): ands x (a short number, 0-65535 or -32768-32767) to the adress in y (a register) plus z (a short number, 0-65535 or -32768-32767). (w should be l or w or b)

or.x y, z: ors y to z. (x should be l or w or b)

ori.x y, z: ors y (a short number, 0-65535 or -32768-32767) to z. (x should be l or w or b)

or.z x, y(z): ors x to the adress in y + z. (w should be l or w or b)

ori.z x, y(z): ors x (a short number, 0-65535 or -32768-32767) to the adress in y (a register) plus z (a short number, 0-65535 or -32768-32767). (w should be l or w or b)

xor.x y, z: xors y to z. (x should be l or w or b)

xori.x y, z: xors y (a short number, 0-65535 or -32768-32767) to z. (x should be l or w or b)

xor.z x, y(z): xors x to the adress in y + z. (w should be l or w or b)

xori.z x, y(z): xors x (a short number, 0-65535 or -32768-32767) to the adress in y (a register) plus z (a short number, 0-65535 or -32768-32767). (w should be l or w or b)

The following 68k code:

Translated should be like this:

Another easy one.

Instructions:

not.x y: nots y (!y). (x should be l or w or b)

and.x y, z: ands y to z. (x should be l or w or b)

andi.x y, z: ands y (a short number, 0-65535 or -32768-32767) to z. (x should be l or w or b)

and.z x, y(z): ands x to the adress in y + z. (w should be l or w or b)

andi.z x, y(z): ands x (a short number, 0-65535 or -32768-32767) to the adress in y (a register) plus z (a short number, 0-65535 or -32768-32767). (w should be l or w or b)

or.x y, z: ors y to z. (x should be l or w or b)

ori.x y, z: ors y (a short number, 0-65535 or -32768-32767) to z. (x should be l or w or b)

or.z x, y(z): ors x to the adress in y + z. (w should be l or w or b)

ori.z x, y(z): ors x (a short number, 0-65535 or -32768-32767) to the adress in y (a register) plus z (a short number, 0-65535 or -32768-32767). (w should be l or w or b)

xor.x y, z: xors y to z. (x should be l or w or b)

xori.x y, z: xors y (a short number, 0-65535 or -32768-32767) to z. (x should be l or w or b)

xor.z x, y(z): xors x to the adress in y + z. (w should be l or w or b)

xori.z x, y(z): xors x (a short number, 0-65535 or -32768-32767) to the adress in y (a register) plus z (a short number, 0-65535 or -32768-32767). (w should be l or w or b)

The following 68k code:

add.b $#0x0002, d0

Translated should be like this:

d0 ^= 0x0002;

The neg, ext

Spoiler

Instructions:

neg.x negates x (positive becomes negative and negative becomes positive) (x should be l or w or b)

ext.x extends x (will be explained later) (x should be l or w or b)

The neg instruction is basically this:

The ext instruction is already handled in c++, it extends for example, char to short and short to int.

Instructions:

neg.x negates x (positive becomes negative and negative becomes positive) (x should be l or w or b)

ext.x extends x (will be explained later) (x should be l or w or b)

The neg instruction is basically this:

x = -x;

The ext instruction is already handled in c++, it extends for example, char to short and short to int.

Multiplication and division

Spoiler

muls.x y, z: multiplies z with y. (x should be l or w or b)

mulu.x y, z: multiplies z with y. (x should be l or w or b) (unsigned)

divs.x y, z: divides z with y, the remainder will be saved in the upper word of z and the quotient will be saved in the lower word. (x should be l or w or b)

divs.x y, z: divides z with y, the remainder will be saved in the upper word of z and the quotient will be saved in the lower word. (x should be l or w or b) (unsigned)

The division is clearly different in c++.

In this c++ code, we're declaring a variable with the result value of the division of d1 with 2 and declaring another variable with the remainder of the division d1 with 2 (modulo).

muls.x y, z: multiplies z with y. (x should be l or w or b)

mulu.x y, z: multiplies z with y. (x should be l or w or b) (unsigned)

divs.x y, z: divides z with y, the remainder will be saved in the upper word of z and the quotient will be saved in the lower word. (x should be l or w or b)

divs.x y, z: divides z with y, the remainder will be saved in the upper word of z and the quotient will be saved in the lower word. (x should be l or w or b) (unsigned)

The division is clearly different in c++.

register int d0 = d1 / 2; register int d2 = d1 % 2;

In this c++ code, we're declaring a variable with the result value of the division of d1 with 2 and declaring another variable with the remainder of the division d1 with 2 (modulo).

Branch on sign

Spoiler

Instructions:

bpl x: branch (goto x) if the result of cmp x, y (x minus y) is positive.

bmi x: branch (goto x) if the result of cmp x, y (x minus y) is negative.

The following 68k code:

Will look like this in c++:

How to find if a label is a function or just a... label.

Set conditions

[spoiler]

Instructions:

seq x: set if the cmp x, y are equal.

sne x: set if the cmp x, y are not equal.

spl x: set if the result of cmp x, y (x minus y) is positive.

smi x: set if the result of cmp x, y (x minus y) is negative.

sge x: set if the cmp x is greater or equal to y.

sgt x: set if the cmp x is greater than y.

sle x: set if the cmp x is less or equal to y.

slt x: set if the cmp x is less or equal to y.

scc x: set if the cmp x is greater or equal to y. (unsigned)

shi x: set if the cmp x is greater than y. (unsigned)

sls x: set if the cmp x is less or equal to y. (unsigned)

scs x: set if the cmp x is less or equal to y. (unsigned)

for example seq d0 sets d0 to 0xFFFFFFFF if it's true, otherwise it's cleared (set to zero).

Consider the following code

Translating it, we get:

Instructions:

bpl x: branch (goto x) if the result of cmp x, y (x minus y) is positive.

bmi x: branch (goto x) if the result of cmp x, y (x minus y) is negative.

The following 68k code:

Generic: move.l #hello, d0 move.l #world, d1 cmp.l d0, d1 beq.s Generic2 move.l #$0, d0 Generic2: move.l #$0, d1 cmpi.l #0x0020, d0 bpl Generic4 Generic3: clr.l d0 Generic4: clr.l d1

Will look like this in c++:

register int d0 = hello; register int d1 = world; if (d0 != d1) { d0 = 0; } d1 = 0; if (d0 - 0x0020 < 0) { d0 = 0; } d1 = 0;

How to find if a label is a function or just a... label.

Spoiler

Routines and subroutines in 68k are functions in c++, but they don't have a difference to labels, so it's confusing to some people, but it's not that hard, generally routines have a 'rts' in the end, and that's the end of a function (or return), and the instruction that tells the preprocessor that certain label we'll be jumping to is a routine, is the bsr, the others (jmp, bra, branches...) are just for labels.

Routines and subroutines in 68k are functions in c++, but they don't have a difference to labels, so it's confusing to some people, but it's not that hard, generally routines have a 'rts' in the end, and that's the end of a function (or return), and the instruction that tells the preprocessor that certain label we'll be jumping to is a routine, is the bsr, the others (jmp, bra, branches...) are just for labels.

Set conditions

[spoiler]

Instructions:

seq x: set if the cmp x, y are equal.

sne x: set if the cmp x, y are not equal.

spl x: set if the result of cmp x, y (x minus y) is positive.

smi x: set if the result of cmp x, y (x minus y) is negative.

sge x: set if the cmp x is greater or equal to y.

sgt x: set if the cmp x is greater than y.

sle x: set if the cmp x is less or equal to y.

slt x: set if the cmp x is less or equal to y.

scc x: set if the cmp x is greater or equal to y. (unsigned)

shi x: set if the cmp x is greater than y. (unsigned)

sls x: set if the cmp x is less or equal to y. (unsigned)

scs x: set if the cmp x is less or equal to y. (unsigned)

for example seq d0 sets d0 to 0xFFFFFFFF if it's true, otherwise it's cleared (set to zero).

Consider the following code

Generic: move.l #hello, d0 move.l #world, d1 cmp.l d0, d1 beq.s Generic2 move.l #$0, d0 Generic2: move.l #$0, d1 cmpi.l #0x0020, d0 bpl Generic4 Generic3: clr.l d0 Generic4: clr.l d1 cmp d1, d0 seq d0

Translating it, we get:

register int d0 = hello; register int d1 = world; if (d0 != d1) { d0 = 0; } d1 = 0; d0 = (d0 == d1) ? 0xFFFFFFFF : 0x00000000;

This post has been edited by

**Chris Pancake**: 26 January 2018 - 12:27 PM