About C / Z80 optimizations (SDCC)

Page 9/15
2 | 3 | 4 | 5 | 6 | 7 | 8 | | 10 | 11 | 12 | 13 | 14

By ARTRAG

Enlighted (6228)

ARTRAG's picture

11-09-2019, 10:47

The Hi-Tech C cross compiler uses first registers and later stack for parameter passing in functions.
It is a option in compiling parameters

64                           ;CIRCLE.C: 63: vrampoke (0x2000,0xF1);
   65                           	line	63
   66   0059' 0E F1             	ld	c,-15
   67   005B' 11 2000           	ld	de,02000h
   68   005E' CD 0019'          	call	_vrampoke

By zPasi

Champion (410)

zPasi's picture

11-09-2019, 11:01

ARTRAG wrote:

The Hi-Tech C cross compiler uses first registers and later stack for parameter passing in functions.

Yes but does it help much?

Here you call plotpoints:

	ld	l,(ix+-8)
	ld	h,(ix+-7)
	push	hl
	ld	l,(ix+-10)
	ld	h,(ix+-9)
	push	hl
	ld	c,(ix+-4)
	ld	b,(ix+-3)
	ld	e,(ix+-2)
	ld	d,(ix+-1)
	call	_plotpoints

y is in bc, x in de. Fine. But this is the beginning of plotpoints:

_plotpoints:
	push	ix
	ld	ix,0
	add	ix,sp
	push	bc
	push	bc
;circle.c: 76: pset((unsigned char)cx+x,(unsigned char)cy+y);
;_y stored from bc
	ld	(ix+-2),c
	ld	(ix+-1),b
;_x stored from de
	ld	(ix+-4),e
	ld	(ix+-3),d

It stores them in stack anyway!

By DarkSchneider

Paladin (854)

DarkSchneider's picture

11-09-2019, 11:03

On SDCC you can pass only 1 parameter on registers I think. Also, be sure to compile with -mz80 and --opt-code-speed parameters. And the --std-xx could affect the code generated, as depending the rules applied could change how values are promoted and more things.

By ARTRAG

Enlighted (6228)

ARTRAG's picture

11-09-2019, 14:22

zPasi that's normal, due to the fact that the function parameters are repeatedly involved additions and subtractions so the compiler have to save them as they were automatic variables

By PingPong

Prophet (3413)

PingPong's picture

11-09-2019, 18:49

zPasi wrote:

And, also Hi-Tech C uses stack for parameters and locals, so I doubt the difference is significant.

It does. In more efficient way. The use of 16 bit stack with two 8bit vars works.
Plus it can use more effectively registers to pass in parameters.

By PingPong

Prophet (3413)

PingPong's picture

11-09-2019, 18:57

zPasi wrote:
ARTRAG wrote:

The Hi-Tech C cross compiler uses first registers and later stack for parameter passing in functions.

Yes but does it help much?

it does both in size and speed.
Obviously if you pass 30 parameters to a function it cannot do miracles but in majority of situations the gain in significant
Even because there is no need to generate code to rebalance the stack after the call

By zPasi

Champion (410)

zPasi's picture

11-09-2019, 19:50

ARTRAG wrote:

zPasi that's normal, due to the fact that the function parameters are repeatedly involved additions and subtractions so the compiler have to save them as they were automatic variables

Sure it is. But if SDCC does this:

  ld h, something
  ld l, something
  push hl
  call _myFunction
...
_myFunction:
  push	ix
  ld	ix,0
  add	ix,sp

and Hi-Tech does this:

  ld b, something
  ld c, something
  call _myFunction
...
_myFunction:
  push	ix
  ld	ix,0
  add	ix,sp
  push bc
  ld	(ix+-2),c
  ld	(ix+-1),b

Which one uses more cycles? Right, the Hi-Tech version!

By zPasi

Champion (410)

zPasi's picture

11-09-2019, 20:02

PingPong wrote:
zPasi wrote:
ARTRAG wrote:

The Hi-Tech C cross compiler uses first registers and later stack for parameter passing in functions.

Yes but does it help much?

it does both in size and speed.

It certainly doesn't seem so.

Quote:

Even because there is no need to generate code to rebalance the stack after the call

So, what is it doing here?

	ld	sp,ix
	pop	ix
	pop	hl
	pop	af
	pop	af
	jp	(hl)

I'm still not impressed.

By ARTRAG

Enlighted (6228)

ARTRAG's picture

11-09-2019, 20:09

Sorry, your example if very partial.
When the function parameters do not need to be stored, e.g. when they do not appear in repeated expressions the Hi-tech compiler is much faster that SDCC. Look at this other example, where parameters are stored in registers only:

   21   000B'                   _vrampeek:
   22                           ;CIRCLE.C: 19: asm("di");
   23                           	line	19
   19   000B' F3                di ;#
   20                           ;CIRCLE.C: 20: (*(port unsigned char *)(0x99) = 
                                (addr & 255));
   21                           	line	20
   22   000C' 7B                	ld	a,e
   23   000D' D3 99             	out	(099h),a
   24                           ;CIRCLE.C: 21: (*(port unsigned char *)(0x99) = 
                                ((addr >> 8) & 0x3f));
   25                           	line	21
   26   000F' 7A                	ld	a,d
   27   0010' E6 3F             	and	03Fh
   28   0012' D3 99             	out	(099h),a
   29                           ;CIRCLE.C: 22: asm("ei");
   30                           	line	22
   22   0014' FB                ei ;#
   23                           ;CIRCLE.C: 23: return (*(port unsigned char *)(0
                                x98));
   24                           	line	23
   25   0015' DB 98             	in	a,(098h)
   26   0017' 6F                	ld	l,a
   27   0018' C9                	ret

By DarkSchneider

Paladin (854)

DarkSchneider's picture

11-09-2019, 21:09

In the case of ports SDCC uses something custom for doing that way. It has been posted above I think, but it is mentioned in manual in any case. It is defining variables in a special way. It also includes some interesting function definition. IMO it is worth to take a look at SDCC manual. Not sure completely as I have read it very fast, but looks like it mention that sometimes could use some memory locations to store local variables instead the stack unless using parameters to force the use of the stack.

Page 9/15
2 | 3 | 4 | 5 | 6 | 7 | 8 | | 10 | 11 | 12 | 13 | 14