Subject: gcc question

From: "Adam 'WeirdArms' Wiggins" <[email-masked]>
Date: Fri, 3 Sep 1999 22:53:40 +1000 (EST)

I have a question with regards to the procedure call standard. Is
it possible to override the C procedure call standard for single
functions?

	Its probably not the best way of going about things but I'm
participating in a C implimentation of a micro-kernel who's syscalls in
general have more then 4 arguments and return more then one. Its important
to avoid copying. The ABI defines which registers are what and that all
registers less the user SP are undefined after the syscall except where
they are allocated for results from the syscall. 
	Thats probably not very clear but if anyone can help or suggest
something please let me know

	Thanks in advance, Adam

unsubscribe: body of `unsubscribe linux-arm' to [email-masked]

---

From: Philip Blundell <[email-masked]>
Date: Fri, 03 Sep 1999 14:42:28 +0100

>they are allocated for results from the syscall. 

I don't quite understand what you're trying to do.  Are you saying you want to 
arrange for certain functions to have a non-standard calling sequence where 
all regs are clobbered and a greater than usual number are used for args and 
return values?

If so, this isn't possible without some hacking of the compiler.  It wouldn't 
be especially hard to add a new configuration with these quirks though.  Under 
Linux the compiler doesn't know anything at all about syscalls and the C 
library does all the necessary magic.

If you can explain what the exact mechanism for syscalls under your kernel is, 
that would probably help.

p.

---

From: "Adam 'WeirdArms' Wiggins" <[email-masked]>
Date: Sat, 4 Sep 1999 00:38:15 +1000 (EST)

> all regs are clobbered and a greater than usual number are used for args and 

	Yes, For example the IPC system call only leaves the user stack
pointer untouched all other registers are IPC arguments and most are
return values. Since the kernel being implimentated here is in C it seems
you have to have a fair bit of messy inline asm and something like a
no-return attribute to avoid the function call saving and restoring the
saved registers of the calling convention.
> library does all the necessary magic.

	for user space or inside the kernel?
> that would probably help.

	Syscalls are register only arguments and return values. Inline
ASM is used to call them from user code. The heaviest syscal (ipc) uses
all registers as arguments and return values less the user SP. Usually the
kernel is implimented totally in assembly so there is no problem. Since
this is a research implimentation its written in a high level language and
the calling standard is getting in the way a bit.
	How does linux impliment its system calls?

	Cheers Adam > > p. >

---

From: Philip Blundell <[email-masked]>
Date: Fri, 03 Sep 1999 16:04:20 +0100

>saved registers of the calling convention.

Yes.  I suspect you may end up writing some assembler to do the glue.  There 
isn't any neat way to express in C what you want to do.

>	for user space or inside the kernel?

Sorry, I was talking about user space so I guess we were at cross purposes 
rather.  The first level of system call handling in the kernel is all coded 
in assembler (which is one of the things that makes syscalls as quick as 
they are) and all the register manipulation happens there.

>	How does linux impliment its system calls?

For the kernel, see arch/arm/kernel/entry-common.S.  For user space, see the 
libc sources (mostly in sysdeps/unix/sysv/linux/arm/).

p.

---

From: "Adam 'WeirdArms' Wiggins" <[email-masked]>
Date: Sat, 4 Sep 1999 01:13:19 +1000 (EST)

> isn't any neat way to express in C what you want to do.

	That was clear, I'm just trying to find the right balance. The
code should be highly readable and flexible, but I'm trying to maintain
the speed.
> they are) and all the register manipulation happens there.

	I think in this case the micro-kenel should aost be totally asm
but its not my choice :( 
> libc sources (mostly in sysdeps/unix/sysv/linux/arm/).
	I'll check out the kernel entry points

	Cheers Adam

---

From: Paul Koning <[email-masked]>
Date: Fri, 3 Sep 1999 11:19:20 -0400

>>>>> "Philip" == Philip Blundell <[email-masked]> writes:

 >> participating in a C implimentation of a micro-kernel who's
 >> syscalls in general have more then 4 arguments and return more
 >> then one. Its important to avoid copying. The ABI defines which
 >> registers are what and that all registers less the user SP are
 >> undefined after the syscall except where they are allocated for
 >> results from the syscall.

 Philip> I don't quite understand what you're trying to do.  Are you
 Philip> saying you want to arrange for certain functions to have a
 Philip> non-standard calling sequence where all regs are clobbered
 Philip> and a greater than usual number are used for args and return
 Philip> values?

 Philip> If so, this isn't possible without some hacking of the
 Philip> compiler. 

Couldn't you do it with the extended form of the asm statement that
GCC supports?  That gives a whole lot of control over how parameters
are passed in and out of the asm block.  If the asm block in turn is a 
function call (or syscall) instruction, that may do the job.

	paul

---

From: Philip Blundell <[email-masked]>
Date: Fri, 03 Sep 1999 16:31:55 +0100

>function call (or syscall) instruction, that may do the job.

Yes, you can do more or less anything with an asm.  I thought Adam wanted a 
"clean" way to do this with function attributes or the like.

(Actually, an asm that clobbers all registers might well bring the compiler to 
a sticky end.  It can't always handle that sort of situation properly.)

p.

---

From: "Adam 'WeirdArms' Wiggins" <[email-masked]>
Date: Sat, 4 Sep 1999 01:41:34 +1000 (EST)

> function call (or syscall) instruction, that may do the job.
	This would be fine but how do you make the function call without
saving registers? Ideally we would associate all registers used with
variables then write the syscall in C. The probablem is the calling
standard will save register which are scratch anyway which represends
wasted cycles. There isn't much point of register only arguments if they
have to be stacked to call C from the asm exception entry point.
	I noticed that the SWI handler in linux has a comment saying still
have a problem with >4 argument functions. hat is this refering too?
Syscall functions? Also isn't checking the SWI constant expensive? You
pollute your data cache with code, why check this when the syscall number
is in a register?

	Cheers Adam

---

From: Philip Blundell <[email-masked]>
Date: Fri, 03 Sep 1999 16:49:27 +0100

>have a problem with >4 argument functions. hat is this refering too?

I think that's a historical relic.  5 argument syscalls should be OK now.

>Also isn't checking the SWI constant expensive? You

The syscall number isn't in a register for the Linux/ARM syscall standard.  
With hindsight that was probably a mistake though we need to check it anyway
for compatibility with BSD, RISC OS and so on.  The way I plan to do 
Linux/Thumb we will indeed put the syscall number in a register and ignore 
the comment field.

p.

---

From: "Adam 'WeirdArms' Wiggins" <[email-masked]>
Date: Sat, 4 Sep 1999 01:52:20 +1000 (EST)

> "clean" way to do this with function attributes or the like.

	Would specifying the function as no_return avoid register saving?
This combined with a small asm block to associate registers to vaiables
might be what I'm looking for.
> a sticky end.  It can't always handle that sort of situation properly.)

	Any tips o what behaviour will result from this (so I can keep an
eye out for it)? Also what optimisation levels are 'safe' for kernel
coding? I seem to remember some mention of optimisations on ARM gcc
producing broken code.

	Cheers Adam

---

From: "Adam 'WeirdArms' Wiggins" <[email-masked]>
Date: Sat, 4 Sep 1999 02:00:06 +1000 (EST)

> The syscall number isn't in a register for the Linux/ARM syscall standard.  

	Ah I was looking at a later called function not the entry point.
This could actually cause a problem for us with L4/Linux on ARM. L4 is
using r0 as the syscall number so we'd have probablems supporting
unmodified binaries since we ignore the SWI imediate for the reasons I
mentioned before.

> Linux/Thumb we will indeed put the syscall number in a register and ignore 

	Linux/Thumb? How will this differ from current Arm/Linux? Will the
kernel contain thumb code or only support user thumb code?

	Cheers Adam

---

From: Philip Blundell <[email-masked]>
Date: Fri, 03 Sep 1999 17:37:15 +0100

>	Would specifying the function as no_return avoid register saving?

I think so, but you will then have to take care of actually doing the return 
yourself.

>eye out for it)?

I think the compiler will abort if it runs out of registers totally.  It 
shouldn't generate bad code these days.

>Also what optimisation levels are 'safe' for kernel

Anything should be safe, but -O3 or higher will probably start to generate 
worse code than -O2.

p.

---

From: Philip Blundell <[email-masked]>
Date: Fri, 03 Sep 1999 17:41:42 +0100

>kernel contain thumb code or only support user thumb code?

All I'm interested in at the moment is supporting Thumb code in user space.  
There is no particular reason why compiling the kernel as Thumb should be 
especially difficult if anybody wanted to do that.

p.

---

From: Russell King - ARM Linux Admin <[email-masked]>
Date: Fri, 3 Sep 1999 19:29:05 +0100 (BST)

> With hindsight that was probably a mistake though we need to check it anyway

This 'mistake' only happened because someone decided to split the I and
D caches.  It wasn't a mistake before that happened.  Therefore, by
definition, it cannot be called a mistake at all, but a 'misdesign
of the ARM architecture' as a whole.

However, if you really think about it, not to put the syscall number in
the comment field would have been an even bigger mistake to have made
(since then you have to copy the user r1..r3,[sp],[sp,#4] to kernel
r0..r4,[sp], which would waste more cycles than reading the SWI instruction
and masking it.
   _____
  |_____| ------------------------------------------------- ---+---+-
  |   |        Russell King       [email-masked]      --- ---
  | | | |  http://www.arm.linux.org.uk/~rmk/armlinux.html    /  /  |
  | +-+-+                                                     --- -+-
  /   |               THE developer of ARM Linux              |+| /|\
 /  | | |                                                     ---  |
    +-+-+ -------------------------------------------------  /\\\  |
unsubscribe: body of `unsubscribe linux-arm' to [email-masked]

---

From: Philip Blundell <[email-masked]>
Date: Fri, 03 Sep 1999 20:28:58 +0100

>of the ARM architecture' as a whole.

Well, "mistake" was a bit strong.  But even with a unified cache it is still 
marginally more expensive to load and mask the SWI instruction than to have 
user space load the value into a register.

>(since then you have to copy the user r1..r3,[sp],[sp,#4] to kernel

Well, you could put the syscall number in R12 or something, and do the args 
precisely as they are done at the moment.  As I mentioned, this is the route I 
plan to take for Thumb, partly because the comment field is too small to be of 
any real use and partly because it seems like a generally better plan with the 
current state of the world.

p.

---

From: Ben Williamson <[email-masked]>
Date: Fri, 3 Sep 1999 17:06:17 -0700 (PDT)

> current state of the world.

I'm wondering if you considered this option for Thumb:  In the instruction
slot immediately following the SWI, place a 16-bit comment field.  Then
have the SWI handler step over it to return to the instruction slot
following the extra comment field.  How would that stack up?  Just a
thought.

Cheers,

- Ben.

-------------------------------------------------------------------
Ben Williamson       [email-masked]     http://www.pobox.com/~benw/

---

From: Philip Blundell <[email-masked]>
Date: Sat, 04 Sep 1999 10:57:54 +0100

>following the extra comment field.  How would that stack up?  Just a

Well, it's certainly a possibility but it doesn't seem that attractive.  Are 
there any particular advantages you can think of to that approach?

p.

---

From: Ben Williamson <[email-masked]>
Date: Sat, 4 Sep 1999 08:07:01 -0700 (PDT)

> there any particular advantages you can think of to that approach?

I was just thinking of code density, and symmetry with ARM mode to some
extent.  It results in a total 24-bit comment field, and it doesn't need
any instructions in the calling code to load a register with an immediate
value.  Then again, maybe SWIs aren't very common if they all live inside
wrapper functions in libc.  I'm wondering how the performance would
compare when you take into account settting up r12 or whatever.

Cheers,

- Ben.

---

From: Richard Atterer <[email-masked]>
Date: Sat, 04 Sep 1999 23:49:10 +0200

In article <[email-masked]>
    Ben Williamson <[email-masked]> wrote:

> > > I'm wondering if you considered this option for Thumb:  In the
> > > instruction slot immediately following the SWI, place a 16-bit
> > > comment field.  Then have the SWI handler step over it to return
> > > to the instruction slot following the extra comment field.
[...]
> I was just thinking of code density, and symmetry with ARM mode to
> some extent.  It results in a total 24-bit comment field, and it
> doesn't need any instructions in the calling code to load a register
> with an immediate value.  Then again, maybe SWIs aren't very common if
> they all live inside wrapper functions in libc.  I'm wondering how the
> performance would compare when you take into account settting up r12
> or whatever.

Hm, but conditional execution of SWIs isn't possible with this system.
The extra branch would affect both performance and code density.

Cheers,

  Richard

-- 
  __   _
  |_) /|  Richard Atterer
  | \/¯|  http://www.in.tum.de/~atterer/                      raFS V1.16
  ¯ ´` ¯
If they give you ruled paper, write the other way    -- Juan Ramón Jiménez

unsubscribe: body of `unsubscribe linux-arm' to [email-masked]

---

From: Philip Blundell <[email-masked]>
Date: Sun, 05 Sep 1999 00:55:24 +0100

>compare when you take into account settting up r12 or whatever.

Symmetry with ARM code doesn't cut a great deal of ice as far as I am 
concerned; the two ABIs are going to be different anyway and there seems 
no point in trying to make them look the same.

I'm also not convinced by your other arguments.  In terms of code density I 
think SWIs are fairly irrelevant.  A typical program doesn't contain any at 
all, and even the libc doesn't have all that many - it's just that the few 
that do exist are executed rather frequently.  In terms of execution time, I 
suspect a two-halfword instruction would also lose out.  The kernel would have 
to load it with two LDRH instructions since the alignment is unknown, then 
mask and combine the two parts.  I think that is going to be worse than just 
loading a constant into the work register, particularly when you take into 
account cache effects.

p.

---

From: Philip Blundell <[email-masked]>
Date: Sun, 05 Sep 1999 00:36:52 +0100

>The extra branch would affect both performance and code density.

Well, in practice SWIs are almost never conditional anyway - you normally 
decide whether or not you are going to do the syscall before you start 
marshalling arguments and so on.  The only exception that comes to mind is 
breakpoints; offhand I can't think of an efficient way to make them work.

p.

unsubscribe: body of `unsubscribe linux-arm' to [email-masked]
This is a backup list for [email-masked], and the subscription
list is regularly synchronised.

---

From: Ben Williamson <[email-masked]>
Date: Sat, 4 Sep 1999 17:11:38 -0700 (PDT)

> loading a constant into the work register, particularly when you take into 

Right, I think I agree.  Thanks for your thoughts,

- Ben.

---

From: Nicholas Clark <[email-masked]>
Date: Mon, 6 Sep 1999 12:33:56 +0100 (BST)

In the last mail Philip Blundell said:

> breakpoints; offhand I can't think of an efficient way to make them work.

Having written ARM assembler to talk to RISC OS I can see good reason to use
conditional SWIs - mostly common would be a string of SWIs you don't expect
to fail with all bar the first VC, to save 1 VS instruction per SWI to branch
or return the error case.

However, RISC OS SWI calls
  (1) appear to be designed for an assembly language (rather than C) interface
  (2) (almost) all return VS to signal errors
  (3) sometimes take arguments direct from one SWI call into the next

I've never programmed in assembler for ARM based Unix, so don't know what the
calling interface is like, but would suspect that the three conditions above
are all not met, hence the opportunities to usefully use conditional SWI calls
would be much less on ARM unix.

[You can see how the later RISC OS SWIs appear to be designed more for a C
interface - they always return a result in R0, even if the next SWI you
logically call has that value in R1. (DDEUtils long CLI calls, IIRC)(contrast
with WIMP SWI calls, if you're interested]

Nick

---

From: Matthew Wilcox <[email-masked]>
Date: Mon, 6 Sep 1999 13:44:53 +0200

> would be much less on ARM unix.

The Linux system call interface returns a negative error number
(indicating which error occurred), and a positive value on success.  Um.
_nearly_ always.  Virtually all programs call glibc to do the system calls
on their behalf, so modern programs shouldn't contain any SWIs themselves.
This was not the case for libc4 programs, which do contain SWIs.

-- 
Matthew Wilcox <[email-masked]>
"Windows and MacOS are products, contrived by engineers in the service of
specific companies. Unix, by contrast, is not so much a product as it is a
painstakingly compiled oral history of the hacker subculture." - N Stephenson