Some questions about SH4 asm instruction

If you have any questions on programming, this is the place to ask them, whether you're a newbie or an experienced programmer. Discussion on programming in general is also welcome. We will help you with programming homework, but we will not do your work for you! Any porting requests must be made in Developmental Ideas.
Post Reply
User avatar
Newbie
Insane DCEmu
Insane DCEmu
Posts: 171
Joined: Sat Jul 27, 2013 1:16 pm
Has liked: 0
Been liked: 0

Some questions about SH4 asm instruction

Post by Newbie » Sun Feb 07, 2021 3:00 pm

Hi everybody,

I hope you're all safe and in good condition :)

I have a question about MOVe global data instructions group :

Code: Select all


MOV.B @(disp,GBR),R0 
MOV.W @(disp,GBR), R0 
MOV.L @(disp,GBR),R0 
MOV.B R0,@(disp,GBR)  
MOV.W R0,@(disp,GBR) 
MOV.L R0,@(disp,GBR)  

I do not understand what the disp value could be calculated.

Imagine I have (in my mind) a displacement value I want to apply to GBR to point somewhere and a size of data I want to transfer from R0 in it.

For example I want to transfer a word at GBR + 725 from R0.

How the compiler make the calculation to see if it is possible and obtain the disp value to compile the instruction ?

I look for the theoretical process not any code or hardware implementation.

Thanks for tour help.

Regards
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5467
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has liked: 3 times
Been liked: 24 times
Contact:

Re: Some questions about SH4 asm instruction

Post by BlueCrab » Sun Feb 07, 2021 10:12 pm

The displacement allowed in that instruction is 8 bits in all cases. However, in each of them, the displacement added to GBR is multiplied by the operand size, so that leads to different amounts of displacement that can be used with each:
  • mov.b maximum displacement = ( ( 2^8 ) - 1 ) = 255 bytes
  • mov.w maximum displacement = 2 * ( ( 2 ^ 8 ) - 1 ) = 510 bytes
  • mov.l maximum displacement = 4 * ( ( 2 ^ 8 ) - 1 ) = 1020 bytes
You are only allowed to do accesses on evenly aligned operand-sized boundaries, so your example as given cannot be done.

Also, the assembler will do the work for you of turning your displacement into the proper value for the instruction, so you'd still specify something like "mov.l @(724, gbr), r0" to do a 4-byte transfer from (gbr + 724) into r0.

TL;DR:
The displacement value is just the actual (aligned) displacement you wish to use divided by the operand size.
User avatar
Newbie
Insane DCEmu
Insane DCEmu
Posts: 171
Joined: Sat Jul 27, 2013 1:16 pm
Has liked: 0
Been liked: 0

Re: Some questions about SH4 asm instruction

Post by Newbie » Mon Feb 08, 2021 1:24 pm

Hi,

Thanks for your answer.

I understand better.
The value of the displacement that we give in the instruction for the parameter dsp is what we actually want to do as the displacement (724).
The compiler is therefore responsible for internally finding the right value to encode in the 8-bit instruction (724/4 = 181).
It's easier.
I was confusing the parameter value in the instruction syntax and the 8 bit encoded value.

To finish, I offer you a code in pseudo language to check if I understood correctly the process of validation of the parameter of the instruction.

By having this:

Code: Select all

bool IsEven(ushort value);

enum OperandSize {Byte, Word, Long}
Check could be :

Code: Select all

bool DisplacementTheoreticalCheckFunction(OperandSize size, ushort displacementWanted)
{	
			switch(size)
			{
			   case OperandSize.Byte :           // I guess we could move  a byte to odd addresses so no even check (?) 
			   
			   return displacementWanted <= 255; 
			   
			   case OperandSize.Word :
			   
			   if(IsEven(displacementWanted))
			   {
				return displacementWanted <= 520;
	                   }		   
			   return false;
			   			   
			   OperandSize.Long :
			   
			   if(IsEven(displacementWanted))
			   {
				return displacementWanted <= 1020;
			   }
			   return false;
			}
}
Thanks.
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5467
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has liked: 3 times
Been liked: 24 times
Contact:

Re: Some questions about SH4 asm instruction

Post by BlueCrab » Mon Feb 08, 2021 1:32 pm

Bytes can indeed be on any address since they are single byte aligned.

Long values must be aligned to a 4 byte boundary, not just on an even address.

Otherwise, it looks like you have the right idea.
User avatar
Newbie
Insane DCEmu
Insane DCEmu
Posts: 171
Joined: Sat Jul 27, 2013 1:16 pm
Has liked: 0
Been liked: 0

Re: Some questions about SH4 asm instruction

Post by Newbie » Mon Feb 08, 2021 2:00 pm

Long values must be aligned to a 4 byte boundary, not just on an even address.
Do you mean that long values should be divisible by four ?
User avatar
BlueCrab
The Crabby Overlord
The Crabby Overlord
Posts: 5467
Joined: Mon May 27, 2002 11:31 am
Location: Sailing the Skies of Arcadia
Has liked: 3 times
Been liked: 24 times
Contact:

Re: Some questions about SH4 asm instruction

Post by BlueCrab » Mon Feb 08, 2021 3:16 pm

Newbie wrote:
Mon Feb 08, 2021 2:00 pm
Long values must be aligned to a 4 byte boundary, not just on an even address.
Do you mean that long values should be divisible by four ?
The final displacement must be divisible by 4, yes. The SH4 cannot do unaligned accesses to memory, so any 32-bit sized access must be done on a 4-byte boundary.
User avatar
Newbie
Insane DCEmu
Insane DCEmu
Posts: 171
Joined: Sat Jul 27, 2013 1:16 pm
Has liked: 0
Been liked: 0

Re: Some questions about SH4 asm instruction

Post by Newbie » Mon Feb 08, 2021 4:31 pm

Perfect :)

Updating pseudo code :

Code: Select all

bool IsDivisibleByTwo(ushort value);

bool IsDivisibleByFour(ushort value);

enum OperandSize {Byte, Word, Long}

bool DisplacementTheoreticalCheckFunction(OperandSize size, ushort displacementWanted)
{	
			switch(size)
			{
			   case OperandSize.Byte :           
			   return displacementWanted < 256; 
			   
			   case OperandSize.Word :
			   if(IsDivisibleByTwo(displacementWanted))
			   {
					return displacementWanted < 521;
	                   }		   
			   return false;
			   			   
			   OperandSize.Long :
			   if(IsDivisibleByFour(displacementWanted))
			   {
					return displacementWanted < 1021;
			   }
			   return false;
			}
}
This ends the session.

Regards
nymus
DC Developer
DC Developer
Posts: 962
Joined: Tue Feb 11, 2003 4:12 pm
Location: In a Dream
Has liked: 2 times
Been liked: 3 times

Re: Some questions about SH4 asm instruction

Post by nymus » Fri Feb 12, 2021 9:49 am

It is interesting to note that GNU as (gas) expects you to provide aligned/pre-calculated displacements, which is apparently different from the official assembler. I haven't used it but the examples in the SH4 programming manual show that the displacement in both source and binary is an index just like a C-array.

In C, you always index by the (nth - 1) element and the compiler will do "index * sizeof(T)." The SH4 does the same internally and in the official assembler. Gas, however, expects you to do the (index * sizeof(char/short/long) and then it converts that back to an index in the encoded instruction. I suppose this is for historical clarity, consistency with other instruction sets or born of painful experiences with misaligned memory ops... Still, I wish the official syntax was available because it retains the feel of higher-level languages.

In kos/arch/dreamcast/kernel/entry.s

Code: Select all

mov.l		r8,@(0x20,r0)	! save R8
mov.l		r9,@(0x24,r0)	! save R9
mov.l		r10,@(0x28,r0)	! save R10
Note that the displacement grows by 4 and not by 1

in the SH4 programming manual these are the examples shown
@(disp, GBR)

Code: Select all

mov.l @(2,gbr),r0     ;before execution (gbr+8) = h'12345670
                           ;after execution r0 = (h'12345670)
mov.b r0, @(1, gbr)  ;before execution r0 = h'ffff7f80
                           ;after execution (gbr+1) = h'80
Note the first instruction gives a displacement of 2 and not 4 for a long access. (0x10)

@(disp, RN)

Code: Select all

           
mov.l @(3,pc),r3   ;r3 = h'12345678
Note that 3 is given as a displacement for a long access and not 3 * 4 (0x0C)

If you try to compile the same code using gas...

Code: Select all

mov.l @(2,gbr),r0
mov.b r0,@(1,gbr)
mov.l @(3,pc),r3 
You get this:

Code: Select all

sh4-mov.s: Assembler messages:
sh4-mov.s:1: Error: misaligned offset
sh4-mov.s:3: Error: offset to unaligned destination

behold the mind
inspired by Dreamcast
Post Reply