public inbox for crossgcc@sourceware.org
 help / color / mirror / Atom feed
* Invalid Operands with Inline assembly
@ 2000-10-25 14:23 Robert Floyd
  2000-10-26  0:12 ` Keith Wright
  0 siblings, 1 reply; 11+ messages in thread
From: Robert Floyd @ 2000-10-25 14:23 UTC (permalink / raw)
  To: crossgcc

I am attempting to embed inline assembly into my C code but during the
compilation, I keep getting the error "invalid operands for opcode". 
Here is one of my lines:

asm("mov %r14, %r15");

I don't see why this should cause an error.  mov is a valid Hitachi SH
opcode, r14 and r15 are valid registers, the quotations are necessary as
well as the % before each register.  I don't see what else I am
missing.  I am using my Hitachi cross-compiler I built which has been
working like a champion except when I use inline assembly.  Is there
some parameter I need to add on the Command Line before I compile my
file?

Thanks for any help.

Robert F.

------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sourceware.cygnus.com

^ permalink raw reply	[flat|nested] 11+ messages in thread
* RE: Invalid Operands with Inline assembly
@ 2000-10-26  4:46 David Korn
  0 siblings, 0 replies; 11+ messages in thread
From: David Korn @ 2000-10-26  4:46 UTC (permalink / raw)
  To: crossgcc

>I am attempting to embed inline assembly into my C code but during the
>compilation, I keep getting the error "invalid operands for opcode". 
>Here is one of my lines:
>
>asm("mov %r14, %r15");

  I've found (on PPC; it might apply to SH also) that you can't put a
space between the two operands. gas expects the entire operand list to
be in one field, the space acts as a separator, and it parses what you've
typed as

    mov %r14,

followed by a comment field that contains the text "%r15". So try again
without the space. What that other guy said about %-signs might matter too.

    DaveK
-- 
SEAL Team 6 World Trade Center Serbian Cocaine [Hello to all my fans
in domestic surveillance] cracking KGB nuclear arrangements CIA
counter-intelligence smuggle fissionable ammunition SDI

------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sourceware.cygnus.com

^ permalink raw reply	[flat|nested] 11+ messages in thread
[parent not found: <A7FF74878269D411A56F00A0C9ACE7CE75A2@golden.ctc-control.com>]
* RE: Invalid Operands with Inline assembly
@ 2000-10-26 12:12 Stan Katz
  2000-10-27 11:01 ` Robert Floyd
  0 siblings, 1 reply; 11+ messages in thread
From: Stan Katz @ 2000-10-26 12:12 UTC (permalink / raw)
  To: 'Robert Floyd', Stan Katz; +Cc: crossgcc

Robert Floyd [ mailto:robert.floyd@inet.com ] Wrote:
>>Snip
> I have a particular assembly source file that
> contains everything I need to use the serial port on the 
> Hitachi part. 
> For example, it contains one piece of code that allows one to send a
> string out the serial port.  So in another assembly file if I want to
> send out "Hello World", I do the following:
> 
> DoHelloWorld:
> 	mov.l	pTxString,r4		! address loaded for 
> global TxStr function
> 	mova	pHelloStr,r0		! get 'Hello World' 
> string and put in r0
> 	jsr	@r4			! jump to address in r4 
> (global TxStr)
> 
> ---and at the bottom of my file I have----
> 
> pTxString:	.long	TxStr		    ! TxStr is a global 
> function in another asm
> file 
> pHelloStr:	.asciz	"\n\rHello World "   ! my ascii string
> 
> 
> Since I really want to write my code in C but I also don't want to
> recreate the wheel, since there is alot of assembly language 
> functions I
> could use, how could I write this DoHelloWorld function in C.  
>> Snip

This is a case where the parameters for the asm function can help, I would
try something like the following (based on the code that you sent and I
snipped)

extern long TxChar;

int main()
{
   char pHelloStr[6] = "Hello";
   
   while(1)
   {
   register long *pointer;
   register long *string;

      asm( 
          " mov  %0, r4;"         /* Move function pointer to r4 */
          " mov  %1, r0;"          /* And string pointer to r0 */
          " jsr  @r4;"             /* And jump via r4 */
          :                        /* no outputs */
          : "r" (pointer),         /* %0 is Input 0, a register, use C
variable pointer */
            "r" (string),          /* %1 is Input 1, a register, use C
variable string */
          : "r0", "r4"             /* and uses r0 and r4 as scratch */
          );
   }
   
   return(0);
}

This lets the C compiler handle the assignment of the addresses to the
registers which are passed as parameters to the asm function. Since the
compiler seems to concatenate all the asm strings into one long string, I
use a single asm statement and let it concatenate the strings before
processing the asm.
The last 3 lines of the asm routine define the Output parameters, Input
Parameters and Registers affected by the asm routine. For more details on
this look at the "Using GNU GCC" manual, Chapter 3 - "Extensions to the C
language Family", section 3.30. 

I have not tried to get very fancy with the parameter specifications, and
usually just use register variables that are assigned in a surrounding
block.

BTW, you could probably eliminate the " mov %0,r4;" and simply do " jsr
@%0;".

Stan

------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sourceware.cygnus.com

^ permalink raw reply	[flat|nested] 11+ messages in thread
* RE: Invalid Operands with Inline assembly
@ 2000-10-27 13:37 Stan Katz
  0 siblings, 0 replies; 11+ messages in thread
From: Stan Katz @ 2000-10-27 13:37 UTC (permalink / raw)
  To: 'Robert Floyd', Stan Katz; +Cc: crossgcc

Robert Floyd [ mailto:robert.floyd@inet.com ] wrote :
>> snip
> Why would not the following work just as well...
> 
> extern long TxStr;		  /* defined as .globl TxStr in external asm
file */
> 
> int main()
> {
>    char pHelloStr[6] = "Hello";
>    
>    while(1)
>    {
> 
>       asm( 
>           " mov  %0, r4;"          /* Move global asm label TxStr to r4 */
>           " mov  %1, r0;"          /* And string to r0 */
>           " jsr  @r4;"             /* And jump via r4 */
>           :                        /* no outputs */
>           : "r" (TxStr),           /* %0 is Input 0, a register, use TxStr
*/
>             "r" (pHelloStr)        /* %1 is Input 1, a register, use
pHelloStr */
>           : "r0", "r4"             /* and uses r0 and r4 as scratch */
>           );
>    }
>    
>    return(0);
> }
> 
> int __main() {}                     /* I was told I need this for gcc,
> don't know why */
> 

The reason I added the pointers is to make sure that the data is already in
a register because TxStr is actually a long value and pHelloStr is a pointer
to a constant string which is probably in the same segment as the code but
may not be within the range of the offset from the PC addressing mode. These
are definitely not registers. The "r" specifiers for the inputs to the asm
block specify the parameters as registers so I need to make sure that the
data is available in a register and the pointers leave it up the compiler to
get the data where it is needed.

GNU allows other (or multiple) specifiers for the asm block. The ones that I
have used are "i" for an input which specifies immediate data (for the SH2
this is limited to signed 8 bits which is sign extended) and "0" to "9"
where I use the same register for input and output. From the manual "m"
(address), "o" (offsettable address) and some other are allowed but when I
tried to use them I found that I was having trouble specifying the address
mode, it ended up easier for me to use the "r" specification and let the
compiler assign the value to a local (block scope) register variable.

BTW, __main() is called by GCC as part of the C++ initialization before
calling main(), if you don't supply one it will grab it from the library (if
it is linked) or complain.

------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sourceware.cygnus.com

^ permalink raw reply	[flat|nested] 11+ messages in thread
[parent not found: <A7FF74878269D411A56F00A0C9ACE7CE75A6@golden.ctc-control.com>]
* RE: Invalid Operands with Inline assembly
@ 2000-10-31 16:59 Stan Katz
  2000-11-01  6:09 ` Sobhy Gad
  2000-11-01 13:56 ` Robert Floyd
  0 siblings, 2 replies; 11+ messages in thread
From: Stan Katz @ 2000-10-31 16:59 UTC (permalink / raw)
  To: 'Robert Floyd', Stan Katz; +Cc: crossgcc

Robert Floyd [ mailto:robert.floyd@inet.com ] wrote:
>
> I used your example and everything compiles and links just 
> great.  With
> one slight problem that you might be aware of with your Hitachi SH
> experience...
> 
snip

Thanks for the feedback, glad to have helped

> I have asm files that initialize the chip, turns on an LED to RED and
> sends out a boot string over the serial port to my PC.  These actually
> work.  I used the example that you set up for me as a C file 
> with inline
> assembly that I wanted to link into my working assembly 
> language files. 

I tend to do all this is C anyway, the only time I use assembly is when I
need to either put in some interrupt handling code (which usually calls a C
routine for processing anyway) or when I want to use the mul/mac/div
instructions to get a faster scaling routine.

> Well after the chip runs thru all the asm code (which I can see is
> working ok because the LED comes on and the boot string comes out over
> the serial port), I simply... 
> 
> bra pmain	! branch to global _main in another object file
> 
> This pmain is a label in the asm file, i.e. pmain:   .long _main
> 
> But instead the chip seems to branch off into the weeds because after
> several seconds the chip resets, (watchdog timeout?).  I actually went
> thru the code, looked at the srec file and can see that the linker did
> put in the right address for _main.  But oddly enough, nothing happens
> except it eventually resets itself.  Do you think that I should be
> branching to the dummy global ___main instead?  Thanks for 
> any advice on
> this.

It looks as if you are branching to the address pmain, which contains a 32
bit value equivalent to _main and is executing that as code, what happens
depends on the actual value of _main but is not likely to get you back with
the PC equal to _main either. You want to branch to the value that is at the
address pmain (assuming _main is too far away to go directly there) probably
want to do something like:
	mov.l  pmain, r4
	bra    @r4

Although you may be able to use 
	bra _main

Try the second and if the address of _main is too far from the bra
instruction to be assembled you will get an error message from the compiler
or assembler.

Stan

------
Want more information?  See the CrossGCC FAQ, http://www.objsw.com/CrossGCC/
Want to unsubscribe? Send a note to crossgcc-unsubscribe@sourceware.cygnus.com

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2000-11-01 13:56 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-10-25 14:23 Invalid Operands with Inline assembly Robert Floyd
2000-10-26  0:12 ` Keith Wright
2000-10-26  4:46 David Korn
     [not found] <A7FF74878269D411A56F00A0C9ACE7CE75A2@golden.ctc-control.com>
2000-10-26 11:39 ` Robert Floyd
2000-10-26 12:12 Stan Katz
2000-10-27 11:01 ` Robert Floyd
2000-10-27 13:37 Stan Katz
     [not found] <A7FF74878269D411A56F00A0C9ACE7CE75A6@golden.ctc-control.com>
2000-10-31 14:46 ` Robert Floyd
2000-10-31 16:59 Stan Katz
2000-11-01  6:09 ` Sobhy Gad
2000-11-01 13:56 ` Robert Floyd

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).