#define (from C) in Python

S

Santiago Romero

Is there a Python version of C's language #define statements?

Example:

#define ReadMem( (x) ) memory[ (x) ]

Instead of using a function, when you call to ReadMem(), the code is
INCLUDED, (no function is called, the "compiler" just substitues the
ReadMem( expression ) with memory[ (expression) ] .

I want to avoid function calls to speed up a program by sacrifizing
the resulting size ...

Is that possible?
 
D

Diez B. Roggisch

Santiago said:
Is there a Python version of C's language #define statements?

Example:

#define ReadMem( (x) ) memory[ (x) ]

Instead of using a function, when you call to ReadMem(), the code is
INCLUDED, (no function is called, the "compiler" just substitues the
ReadMem( expression ) with memory[ (expression) ] .

I want to avoid function calls to speed up a program by sacrifizing
the resulting size ...

Is that possible?

Not without taking the extra step of a ... preprocessor. As C does.

Diez
 
M

Michele Simionato

Is there a Python version of C's language #define statements?

Example:

#define ReadMem( (x) )    memory[ (x) ]

 Instead of using a function, when you call to ReadMem(), the code is
INCLUDED, (no function is called, the "compiler" just substitues the
ReadMem( expression ) with memory[ (expression) ] .

 I want to avoid function calls to speed up a program by sacrifizing
the resulting size ...

 Is that possible?

Python is a slow language and people usually do not even think of such
micro-optimizations.
 
S

Stefan Behnel

Santiago Romero, 12.11.2009 17:43:
Is there a Python version of C's language #define statements?

Example:

#define ReadMem( (x) ) memory[ (x) ]

Yes:

ReadMem = memory.__getitem__

Stefan
 
S

Santiago Romero

Santiago Romero, 12.11.2009 17:43:
Is there a Python version of C's language #define statements?

#define ReadMem( (x) )    memory[ (x) ]

Yes:

        ReadMem = memory.__getitem__

Stefan


Well, In the above concrete example, that would work, but I was
talking for multiple code lines, like:


#define LD_r_n(reg) (reg) = Z80ReadMem(r_PC++)

#define LD_rr_nn(reg) r_opl = Z80ReadMem(r_PC); r_PC++; \
r_oph = Z80ReadMem(r_PC); r_PC++; \
reg = r_op

#define LOAD_r(dreg, saddreg) (dreg)=Z80ReadMem((saddreg))

#define LOAD_rr_nn(dreg) r_opl = Z80ReadMem(r_PC); r_PC++; \
r_oph = Z80ReadMem(r_PC); r_PC++; \
r_tmpl = Z80ReadMem(r_op); \
r_tmph = Z80ReadMem((r_op)+1); \
dreg=r_tmp

#define STORE_nn_rr(dreg) \
r_opl = Z80ReadMem(r_PC); r_PC++;\
r_oph = Z80ReadMem(r_PC); r_PC++; \
r_tmp = dreg; \
Z80WriteMem((r_op),r_tmpl, regs); \
Z80WriteMem((r_op+1),r_tmph, regs)


But it seems that is not possible :-(
 
S

Stefan Behnel

Santiago Romero, 12.11.2009 18:23:
#define LD_r_n(reg) (reg) = Z80ReadMem(r_PC++)

#define LD_rr_nn(reg) r_opl = Z80ReadMem(r_PC); r_PC++; \
r_oph = Z80ReadMem(r_PC); r_PC++; \
reg = r_op

#define LOAD_r(dreg, saddreg) (dreg)=Z80ReadMem((saddreg))

#define LOAD_rr_nn(dreg) r_opl = Z80ReadMem(r_PC); r_PC++; \
r_oph = Z80ReadMem(r_PC); r_PC++; \
r_tmpl = Z80ReadMem(r_op); \
r_tmph = Z80ReadMem((r_op)+1); \
dreg=r_tmp

#define STORE_nn_rr(dreg) \
r_opl = Z80ReadMem(r_PC); r_PC++;\
r_oph = Z80ReadMem(r_PC); r_PC++; \
r_tmp = dreg; \
Z80WriteMem((r_op),r_tmpl, regs); \
Z80WriteMem((r_op+1),r_tmph, regs)

But it seems that is not possible :-(

As Michele said, this is a micro optimisation, likely premature. A function
is usually good enough for this. If you need more speed (and you seem to be
targeting direct memory access or something like that), take a look at Cython.

Stefan
 
T

TerryP

If it's such a big hairy deal, just recompile a copy of the C Pre
Processor to use something other then #, and hook it up to your python
scripts in a pipe line from a shell wrapper.

Personally, I'd rather have Lisps lambda or perls sub then Cs
preprocessor, and even in those cases, Python suffices perfectly
fine ;).
 
G

greg

TerryP said:
If it's such a big hairy deal, just recompile a copy of the C Pre
Processor to use something other then #, and hook it up to your python
scripts in a pipe line from a shell wrapper.

Or use a different preprocessor, such as m4, that
doesn't clash with the # character.
 
U

Ulrich Eckhardt

Santiago said:
Well, In the above concrete example, that would work, but I was
talking for multiple code lines, like:


#define LD_r_n(reg) (reg) = Z80ReadMem(r_PC++)

#define LD_rr_nn(reg) r_opl = Z80ReadMem(r_PC); r_PC++; \
r_oph = Z80ReadMem(r_PC); r_PC++; \
reg = r_op

#define LOAD_r(dreg, saddreg) (dreg)=Z80ReadMem((saddreg))

#define LOAD_rr_nn(dreg) r_opl = Z80ReadMem(r_PC); r_PC++; \
r_oph = Z80ReadMem(r_PC); r_PC++; \
r_tmpl = Z80ReadMem(r_op); \
r_tmph = Z80ReadMem((r_op)+1); \
dreg=r_tmp

#define STORE_nn_rr(dreg) \
r_opl = Z80ReadMem(r_PC); r_PC++;\
r_oph = Z80ReadMem(r_PC); r_PC++; \
r_tmp = dreg; \
Z80WriteMem((r_op),r_tmpl, regs); \
Z80WriteMem((r_op+1),r_tmph, regs)

Someone writing such code and calling it C should be taken behind the barn
and shot. Which system runs Python but doesn't have a C compiler that knows
inlining?
But it seems that is not possible :-(

Thank getenv("DEITY") not!

Uli
 
S

Santiago Romero

Someone writing such code and calling it C should be taken
behind the barn and shot.

That code is mine and maybe you should look the context
before doing such kind of affirmations.

In the Intel Pentium and P-II ages, I started to wrote the
very first Spectrum emulator in C. With that "cpu power", emulators
had to be written in ASM to be capable to emulate the destination
machines at 100% full speed in multitasking systems.

In the emulation world, every CPU cycle you can save is gold,
and writing the above code as inline code saved lots of CALLS,
PUSHs/POPs (parameters to stack), and RETs. That allowed ASpectrum
to run 100% speed on old computers and even to be ported to the
Sega Dreamcast's 200Mhz CPU.

Think that Z80ReadMem() can be called up to 6 times in each
emulated CPU-cycle. Saving 6 CALLs, 6 PUSHes, 6 POPs, and 6 RETs
in each cycle of the 3.500.000 of Hz **did** make the difference
that allow Aspectrum to run at 100% speed in ancient machines.

Obviously, I prefer to write well structured code but I had to
sacrifize SIZE by SPEED (size as inline code is included in the
binary executable file).

Each coding technique has their application environment and using
inline macros, like loop unrolling or using "register" variables
fall bellow all the techniques needed to write a fast emulator.

Now I'm porting the emulator to a scripted language, so I need
even more previous design ideas before starting to code, so that
I can achieve (I hope I'll be able to do it with this group's help)
100% cpu speed in an standard desktop PC.
Thank getenv("DEITY") not!

Well, I don't agree with that, "constants" and "macros" wouldn't
hurt python, when using them in the right situations.

Thanks a lot anyway for all your help :)
 
B

Bearophile

Santiago Romero:
Obviously, I prefer to write well structured code but I had to sacrifize SIZE by SPEED<

In C99 you have "inline" (and gcc/gcc-llvm usually inline small
functions anyway) that helps avoid many macros.

 Now I'm porting the emulator to a scripted language, so I need
even more previous design ideas before starting to code, so that
I can achieve (I hope I'll be able to do it with this group's help)
100% cpu speed in an standard desktop PC.

The tecniques needed to speed up Python code are very different from
the ones you use in C. You may need a lot of time to learn Python
performance tricks. Psyco helps a lot.

 Well, I don't agree with that, "constants" and "macros" wouldn't
hurt python, when using them in the right situations.

I miss true constants in Python, but it may be impossible to add them
to this language, because of how it uses references. In Python you
rely on convention, writing their names ALL_UPPERCASE.

Bye,
bearophile
 
G

garabik-news-2005-05

Santiago Romero said:
That code is mine and maybe you should look the context
before doing such kind of affirmations.

In the Intel Pentium and P-II ages, I started to wrote the
very first Spectrum emulator in C. With that "cpu power", emulators
had to be written in ASM to be capable to emulate the destination
machines at 100% full speed in multitasking systems.

Hey, I got 100% with ASM ZX Spectrum emulator on a low end 386 :) (I do
not remember the CPU freqeuncy anymore, maybe 25MHz). First emulator in
C that appeared on the emu-scene (I guess it was x128) needed 486
(~80MHz?) to run at realtime. Pentium and Pentium II was A LOT of
power :)

....
Now I'm porting the emulator to a scripted language, so I need
even more previous design ideas before starting to code, so that
I can achieve (I hope I'll be able to do it with this group's help)
100% cpu speed in an standard desktop PC.

http://perl-spectrum.sourceforge.net/

It is quite fast IMHO.
Just remember to use psyco...

--
-----------------------------------------------------------
| Radovan Garabík http://kassiopeia.juls.savba.sk/~garabik/ |
| __..--^^^--..__ garabik @ kassiopeia.juls.savba.sk |
-----------------------------------------------------------
Antivirus alert: file .signature infected by signature virus.
Hi! I'm a signature virus! Copy me into your signature file to help me spread!
 
S

Santiago Romero

Hey, I got 100% with ASM ZX Spectrum emulator on a low end 386 :) (I do
not remember the CPU freqeuncy anymore, maybe 25MHz).

Yes, in ASM a simple 25 or 33Mhz 386 computer was able to emulate
the
Spectrum. At least, under MSDOS, like did Warajevo, Z80, x128 and
"Spectrum"
from Pedro Gimeno.
First emulator in C that appeared on the emu-scene (I guess it
was x128) needed 486 (~80MHz?) to run at realtime. Pentium and
Pentium II was A LOT of power :)

x128 was not pure C. The first emulator written in pure C was
Aspectrum,
although Philip Kendall "finished" FUSE (Free UNIX Spectrum Emulator)
before my emulator was able to emulate 128K models.

But currently only FUSE and ASpectrum can be compiled in lost of
platforms
(Wii, Dreamcast, PocketPC, NDS...) just by translating the O.S.
dependent
functions or if the destination platform supports the Allegro
library...

And at least a P1-P2 is needed for that :)

It does not run 100% in my 1.8Ghz centrino computer :-(, but almost.
At least, is a good start to see that is possible, at least no current
DualCore computers :)

Thanks!
 
G

garabik-news-2005-05

Santiago Romero said:
Yes, in ASM a simple 25 or 33Mhz 386 computer was able to emulate
the
Spectrum. At least, under MSDOS, like did Warajevo, Z80, x128 and
"Spectrum"
from Pedro Gimeno.

And my very own, (sadly, rather little known at the time) 'Nuclear ZX'
:) It did not use a dispatch table - rather, each Z80 instruction was
taken as a high byte of the pointer to a 64KB block of 8086 code, low
byte being zero for unprefixed instructions or a given value for
prefixed ones. This approach saved one lookup (several cycles) and one
indirect jump (another several cycles) per instruction. Another
optimization would be to unroll the return jump from each of the
emulated instructions and replace it directly with inline
read-the-next-instruction-and-jump-there code, but I never got around to
that (would save one 8086 jump per one Z80 instruction :))

It does not run 100% in my 1.8Ghz centrino computer :-(, but almost.
At least, is a good start to see that is possible, at least no current
DualCore computers :)

Python IS slower than perl, especially since you are dealing with
objects. However, I'd suggest go the cPickle route - have a Z80Cpu
module, and its C equivalent, cZ80, and use that one if available. This
way, the emulator will be actually usable everywhere.


--
-----------------------------------------------------------
| Radovan Garabík http://kassiopeia.juls.savba.sk/~garabik/ |
| __..--^^^--..__ garabik @ kassiopeia.juls.savba.sk |
-----------------------------------------------------------
Antivirus alert: file .signature infected by signature virus.
Hi! I'm a signature virus! Copy me into your signature file to help me spread!
 
S

Santiago Romero

Python IS slower than perl, especially since you are dealing with
objects. However, I'd suggest go the cPickle route - have a Z80Cpu
module, and its C equivalent, cZ80, and use that one if available. This
way, the emulator will be actually usable everywhere.

Thanks for the advice but ... my (currently working) emulator is
already written in C, I don't see the point of calling it from a
python module. I had 2 options: port the emulator from C+Allegro to C
+SDL or port it to Python+Pygame+SDL...

And the fun is trying to write it in pure python with pygame, without
external C :)

I'll do a quick test, if I see that I can't achieve 100% speed in my
other computer (DualCore2 1.82Ghz, the basic-standard-minimum computer
nowadays), then I'll give up, but at least I want to try it X-D

Today or tomorrow I'm finishing the pyinliner.py preprocessor X-D.
I'll paste the results here :)

Thanks for your answer :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,184
Messages
2,570,976
Members
47,536
Latest member
MistyLough

Latest Threads

Top