Giter Club home page Giter Club logo

Comments (7)

serisman avatar serisman commented on August 9, 2024

It seems like even with the latest SDCC nightly snapshot (v4.0.2 #11715) it still generates much less efficient code:

With the current code:

  #define PDK_USE_FACTORY_IHRCR_16MHZ() \
    __asm__( \
      "call #("_STR(FACTORY_IHRCR_ADDR)")   \n" \
      "mov "_STR_VAR(IHRCR)",a              \n" \
    )

... the following assembly is generated (2 words, 5 cycles):

	call	#(0x07ed)   ; 2 cycles + 2 cycles for ret I
	mov	__ihrcr,a      ; 1 cycle

With the new code:

  #define FACTORY_IHRCR (*((const unsigned char*)(FACTORY_IHRCR_ADDR)))
  #define PDK_USE_FACTORY_IHRCR_16MHZ()     IHRCR = FACTORY_IHRCR

... it still generates this less efficient (larger/slower) code (5 words + 12 words for __gptrget, 6 cycles + 15 cycles for __gptrget):

	mov	a, #0xed     ; 1 cycle
	mov	p, a             ; 1 cycle
	mov	a, #0x07     ; 1 cycle
	call	__gptrget   ; 2 cycles
	mov	__ihrcr, a    ; 1 cycle

__gptrget:
	sub	a, #0x80    ; 1 cycle
	t1sn	f, c             ; 1 cycle (skip not taken)
	  goto	code  ; 2 cycles
	idxm	a, p    ; (not executed)
	ret                     ; (not executed)
code:
	xch	a, p            ; 1 cycle
	push	af       ; 1 cycle
	mov	a, sp           ; 1 cycle
	add	a, #-1         ; 1 cycle
	xch	a, p            ; 1 cycle
	idxm	p, a    ; 2 cycles
	ret                     ; 2 cycles + 2 cycles for ret I (this jumps to the address pointed at in code which contains a ret I)

Were you expecting something more efficient to be generated?

Granted, depending on the program, the 12 word __gptrget method may already be included, but even so, it is still larger/slower than the existing code.

The most likely place for this factory calibration code to be used is the _sdcc_external_startup method, which should really be kept to the bare minimum anyway.

from pdk-includes.

serisman avatar serisman commented on August 9, 2024

Ok, I may have found a better solution:

This code:

  typedef unsigned char (*funcptr)(void);
  #define GET_FACTORY_IHRCR ((funcptr)FACTORY_IHRCR_ADDR)
  #define PDK_USE_FACTORY_IHRCR_16MHZ()     IHRCR = GET_FACTORY_IHRCR()

... generates the same efficient assembly (2 words, 5 cycles):

	call	0x07ED     ; 2 cycles + 2 cycles for ret I
	mov	__ihrcr, a   ; 1 cycle

from pdk-includes.

serisman avatar serisman commented on August 9, 2024

Fixed with: 451f449

from pdk-includes.

spth avatar spth commented on August 9, 2024

Ok, I may have found a better solution:

This code:

  typedef unsigned char (*funcptr)(void);
  #define GET_FACTORY_IHRCR ((funcptr)FACTORY_IHRCR_ADDR)
  #define PDK_USE_FACTORY_IHRCR_16MHZ()     IHRCR = GET_FACTORY_IHRCR()

... generates the same efficient assembly (2 words, 5 cycles):

	call	0x07ED     ; 2 cycles + 2 cycles for ret I
	mov	__ihrcr, a   ; 1 cycle

But SDCC would have to assume that the called function might change p or a flag. SDCC could thus generate better code when it knows it is a read from code memory that would not do such things.

from pdk-includes.

spth avatar spth commented on August 9, 2024

SDCC can generate the best code for simple assignment:

#define FACTORY_IHRCR (*(const unsigned char *)0x87ed)
__sfr __at(0x0b) IHRCR;

void f(void)
{
	IHRCR = FACTORY_IHRCR;
}

Will give the same code as your function pointer use above, but now SDCC can keep p in use at the point of the read (since it knows there will be a ret k, which does not change registers, at the called location).

from pdk-includes.

serisman avatar serisman commented on August 9, 2024

Ok, I may have found a better solution:
This code:

  typedef unsigned char (*funcptr)(void);
  #define GET_FACTORY_IHRCR ((funcptr)FACTORY_IHRCR_ADDR)
  #define PDK_USE_FACTORY_IHRCR_16MHZ()     IHRCR = GET_FACTORY_IHRCR()

... generates the same efficient assembly (2 words, 5 cycles):

	call	0x07ED     ; 2 cycles + 2 cycles for ret I
	mov	__ihrcr, a   ; 1 cycle

But SDCC would have to assume that the called function might change p or a flag. SDCC could thus generate better code when it knows it is a read from code memory that would not do such things.

Well, the called function does change a, so that pars is ok. It doesn't change p, but because the normal place to initialize this code (i.e. _sdcc_external_startup method) is generally kept so minimal, SDCC doesn't (usually) generate inefficient code for this.

from pdk-includes.

serisman avatar serisman commented on August 9, 2024

SDCC can generate the best code for simple assignment:

#define FACTORY_IHRCR (*(const unsigned char *)0x87ed)
__sfr __at(0x0b) IHRCR;

void f(void)
{
	IHRCR = FACTORY_IHRCR;
}

Will give the same code as your function pointer use above, but now SDCC can keep p in use at the point of the read (since it knows there will be a ret k, which does not change registers, at the called location).

I still can't get this to generate good code.

Your specific example does generate efficient code, but the address isn't correct. I'm not sure where 0x87ed comes from, but SDCC changes that to 0x07ed for some reason and generates this:

	call	#0x07ed
	mov	__ihrcr, a

That might work for the PFS154, but not for other devices.

Whey I try to replace the 0x87ed with a real address (i.e. 0x0bed), SDCC reverts back to using the inefficient __gptrget code.

Can you explain where the 0x87ed comes from, and why SDCC is converting that to 0x07ed, and why using a real address doesn't generate the efficient code?

from pdk-includes.

Related Issues (9)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.