[Project Log] Python on the 6502/C64, 8080, 6800, 6809 and AVR

pass is trivial.

poke is working.

Now to do bitwise and…

Hello world the easy way…

print('Hello world!')

and the hard way…

poke(-12288, 72)
poke(-12288, 101)
poke(-12288, 108)
poke(-12288, 108)
poke(-12288, 111)
poke(-12288, 32)
poke(-12288, 87)
poke(-12288, 111)
poke(-12288, 114)
poke(-12288, 108)
poke(-12288, 100)
poke(-12288, 33)
poke(-12288, 13)
poke(-12288, 10)

How about …

for c in "Hello World!":
	poke(-12288, ord(c))
2 Likes

Unfortunately, iterators are still far off. I do not fully understand how to create one yet.

That is why I have a while loop but not a for loop.

Bitwise and is in there and this code

while peek(-12287) & 8 == 0:
	pass
poke(-12288, peek(-12288))

works as expected.

How about

i = 65
while i < 91:
	poke(-12288, i)
	i = i + 1
1 Like

Draco

The generated code:

 			  00098	; 00001	i = 65
 			  00099
 020E AE 287E	      [4] 00100		ldx	_i
 0211 AD 287F	      [4] 00101		lda	_i+1
 0214 20 04A5	      [6] 00102		jsr	DeRef
 			  00103
 0217 A2 77	      [2] 00104		ldx	#I_00065&$FF
 0219 A9 28	      [2] 00105		lda	#I_00065>>8
 021B 8E 287E	      [4] 00106		stx	_i
 021E 8D 287F	      [4] 00107		sta	_i+1
 			  00108	; 00002	while i < 91:
 0221			  00109	L00000
 0221 A2 79	      [2] 00110		ldx	#I_00091&$FF
 0223 A9 28	      [2] 00111		lda	#I_00091>>8
 0225 86 1A	      [3] 00112		stx	Ptr1
 0227 85 1B	      [3] 00113		sta	Ptr1+1
 0229 A2 7E	      [2] 00114		ldx	#_i&$FF
 022B A9 28	      [2] 00115		lda	#_i>>8
 022D 20 0C40	      [6] 00116		jsr	GetObject
 0230 86 18	      [3] 00117		stx	Ptr0
 0232 85 19	      [3] 00118		sta	Ptr0+1
 0234 20 1A86	      [6] 00119		jsr	object.__lt__
 0237 20 0646	      [6] 00120		jsr	object.__bool__
 023A D0 03 (023F)  [2/3] 00121		bne	L00001
 023C 4C 0292	      [3] 00122		jmp	L00002
 023F			  00123	L00001
 			  00124	; 00003		poke(-12288, i)
 023F A9 02	      [2] 00125		lda	#2
 0241 A2 00	      [2] 00126		ldx	#0
 0243 20 0C58	      [6] 00127		jsr	AllocPargsAndKargs
 0246 A0 05	      [2] 00128		ldy	#5
 0248 A2 7E	      [2] 00129		ldx	#_i&$FF
 024A A9 28	      [2] 00130		lda	#_i>>8
 024C 20 0C40	      [6] 00131		jsr	GetObject
 024F 20 0CBE	      [6] 00132		jsr	StoreParg
 0252 A2 7B	      [2] 00133		ldx	#I__12288&$FF
 0254 A9 28	      [2] 00134		lda	#I__12288>>8
 0256 20 0CBE	      [6] 00135		jsr	StoreParg
 0259 A2 83	      [2] 00136		ldx	#_poke&$FF
 025B A9 28	      [2] 00137		lda	#_poke>>8
 025D 20 0C40	      [6] 00138		jsr	GetObject
 0260 20 0D03	      [6] 00139		jsr	object.__call__
 0263 20 0CE0	      [6] 00140		jsr	FreePargsAndKargs
 			  00141	; 00004		i = i + 1
 0266 A2 75	      [2] 00142		ldx	#I_00001&$FF
 0268 A9 28	      [2] 00143		lda	#I_00001>>8
 026A 86 1A	      [3] 00144		stx	Ptr1
 026C 85 1B	      [3] 00145		sta	Ptr1+1
 026E A2 7E	      [2] 00146		ldx	#_i&$FF
 0270 A9 28	      [2] 00147		lda	#_i>>8
 0272 20 0C40	      [6] 00148		jsr	GetObject
 0275 86 18	      [3] 00149		stx	Ptr0
 0277 85 19	      [3] 00150		sta	Ptr0+1
 0279 20 1049	      [6] 00151		jsr	object.__add__
 			  00152
 027C AE 287E	      [4] 00153		ldx	_i
 027F AD 287F	      [4] 00154		lda	_i+1
 0282 20 04A5	      [6] 00155		jsr	DeRef
 			  00156
 0285 A6 16	      [3] 00157		ldx	PtrA
 0287 A5 17	      [3] 00158		lda	PtrA+1
 0289 8E 287E	      [4] 00159		stx	_i
 028C 8D 287F	      [4] 00160		sta	_i+1
 028F 4C 0221	      [3] 00161		jmp	L00000
 0292			  00162	L00002
 			  00163
 0292 60	      [6] 00164		rts
1 Like

Great! … thanks for that :grin::vcc_8bit::grin:

Was the invalid opcode error a way to exit? You could poke something to exit, I suppose

1 Like

Yes, I am currently emulating just the processor, RAM and a serial port. There is no operating system to exit to. So the invalid instruction passes control back to the debugger.

1 Like

I’ve been working on assembly/disassembly and learning several machine languages … currently, delving more into x86 and also tms34010 (one of the first graphics processors from TI) and m68k assembly. I’m still wanting to convert them into an intermediate language and back into source or other assembly languages. The latter two are part of the Robotic Arm Controller.

I know 68K…


Excellent … I may have a few questions for you from time to time … but it is not just about the assembly but the system. I am having to figure out where the memory mapped I/O is and all of that. It is interesting because there are many CPUs of different architectures using the same memory at the same time, communicating between each other using interrupts and memory.

1 Like

Have you ever used Radare2? It is a great Disassembler. It also graphs like IDA Pro but it is free.
https://rada.re/r/

It is all text based and has I high learning curve because of all the commands but it can emulate processors and disassemble/assembly on the fly. It has some issues with some of the non-popular architectures but I’m also working on improving them.

Architectures:

6502, 8051, CRIS, H8/300, LH5801, T8200, arc, arm, avr, bf, blackfin, xap, dalvik, dcpu16, gameboy, i386, i4004, i8080, m68k, malbolge, mips, msil, msp430, nios II, powerpc, rar, sh, snes, sparc, tms320 (c54x c55x c55+), V810, x86-64, zimg, risc-v.

File Formats:

bios, CGC, dex, elf, elf64, filesystem, java, fatmach0, mach0, mach0-64, MZ, PE, PE+, TE, COFF, plan9, dyldcache, Commodore VICE emulator, Game Boy (Advance), Nintendo DS ROMs and Nintendo 3DS FIRMs.

Operating Systems:

Android, GNU/Linux, [Net|Free|Open]BSD, iOS, OSX, QNX, w32, w64, Solaris, Haiku, FirefoxOS

Bindings:

Vala/Genie, Python (2, 3), NodeJS, Lua, Go, Perl, Guile, php5, newlisp, Ruby, Java, OCaml, …

Never heard of it.
_

It uses internally

Unicorn Engine for emulation

Capstone for disassembly

What I like about it is it will analyse the code and find functions/symbols … break it apart into sections

It looks like they forked them and added a bunch on to them to support other arches

The compiler with native big number support just came to life.

I can now compile and run Dave’s program:

n  =  30000 + 40000
print(n)
n  =  30000 - 40000
print(n)
n  =  90000 + 40000
print(n)
n  =  1000000 + 40000
print(n)
n  =  500000 + 40000
print(n)

What is missing is the constant folding optimization - all of these calculations are currently being done at run-time. It may be awhile before I get constant folding back to the way I had it.

While working on this, I managed to sneak in:

  • peek function

  • poke function

  • bitwise and & operator

  • bitwise exclusive or ^ operator

  • bitwise or | operator

I still have several weeks until the retrocomputing meeting when I plan to make a release. What kind of things should I try to implement between now and then?

I doubt I can let you define your own functions in that time.

I can implement input, but without string indexing and slicing, there is not much you can do with it. I suppose I can implement the int function to convert a string to a number…

Other ideas?

A little bit of foreshadowing of what is to come…

 			  00101	; 00001	b = ''
 			  00102
 020E AE 2DD1	      [4] 00103		ldx	_b
 0211 AD 2DD2	      [4] 00104		lda	_b+1
 0214 20 04E8	      [6] 00105		jsr	DeRef
 			  00106
 0217 A2 CE	      [2] 00107		ldx	#S_00000&$FF
 0219 A9 2D	      [2] 00108		lda	#S_00000>>8
 021B 8E 2DD1	      [4] 00109		stx	_b
 021E 8D 2DD2	      [4] 00110		sta	_b+1
 			  00111	; 00002	while b != 'n':
 0221			  00112	L00000
 0221 A2 BE	      [2] 00113		ldx	#S_00001&$FF
 0223 A9 2D	      [2] 00114		lda	#S_00001>>8
 0225 86 1A	      [3] 00115		stx	Ptr1
 0227 85 1B	      [3] 00116		sta	Ptr1+1
 0229 A2 D1	      [2] 00117		ldx	#_b&$FF
 022B A9 2D	      [2] 00118		lda	#_b>>8
 022D 20 0C89	      [6] 00119		jsr	GetObject
 0230 86 18	      [3] 00120		stx	Ptr0
 0232 85 19	      [3] 00121		sta	Ptr0+1
 0234 20 1D6A	      [6] 00122		jsr	object.__ne__
 0237 86 26	      [3] 00123		stx	Tmp0
 0239 85 27	      [3] 00124		sta	Tmp0+1
 023B 20 0689	      [6] 00125		jsr	object.__bool__
 023E 8A	      [2] 00126		txa
 023F 48	      [3] 00127		pha
 0240 A6 26	      [3] 00128		ldx	Tmp0
 0242 A5 27	      [3] 00129		lda	Tmp0+1
 0244 20 04E8	      [6] 00130		jsr	DeRef
 0247 68	      [4] 00131		pla
 0248 C9 B8	      [2] 00132		cmp	#False&$FF
 024A D0 03 (024F)  [2/3] 00133		bne	L00001
 024C 4C 02CD	      [3] 00134		jmp	L00002
 024F			  00135	L00001
 			  00136	; 00003		print(randint(1, 10))
 024F A9 02	      [2] 00137		lda	#2
 0251 A2 00	      [2] 00138		ldx	#0
 0253 20 0CA1	      [6] 00139		jsr	AllocPargsAndKargs
 0256 A0 05	      [2] 00140		ldy	#5
 0258 A2 CC	      [2] 00141		ldx	#I_10&$FF
 025A A9 2D	      [2] 00142		lda	#I_10>>8
 025C 20 0D07	      [6] 00143		jsr	StoreParg
 025F A2 BC	      [2] 00144		ldx	#I_1&$FF
 0261 A9 2D	      [2] 00145		lda	#I_1>>8
 0263 20 0D07	      [6] 00146		jsr	StoreParg
 0266 A2 DF	      [2] 00147		ldx	#_randint&$FF
 0268 A9 2D	      [2] 00148		lda	#_randint>>8
 026A 20 0C89	      [6] 00149		jsr	GetObject
 026D 20 0D4C	      [6] 00150		jsr	object.__call__
 0270 20 0D29	      [6] 00151		jsr	FreePargsAndKargs
 0273 A5 17	      [3] 00152		lda	PtrA+1
 0275 48	      [3] 00153		pha
 0276 A5 16	      [3] 00154		lda	PtrA
 0278 48	      [3] 00155		pha
 0279 A9 01	      [2] 00156		lda	#1
 027B A2 00	      [2] 00157		ldx	#0
 027D 20 0CA1	      [6] 00158		jsr	AllocPargsAndKargs
 0280 A0 03	      [2] 00159		ldy	#3
 0282 68	      [4] 00160		pla
 0283 AA	      [2] 00161		tax
 0284 68	      [4] 00162		pla
 0285 20 0D07	      [6] 00163		jsr	StoreParg
 0288 A2 D6	      [2] 00164		ldx	#_print&$FF
 028A A9 2D	      [2] 00165		lda	#_print>>8
 028C 20 0C89	      [6] 00166		jsr	GetObject
 028F 20 0D4C	      [6] 00167		jsr	object.__call__
 0292 A0 02	      [2] 00168		ldy	#2
 0294 20 0D17	      [6] 00169		jsr	DerefParg
 0297 20 0D29	      [6] 00170		jsr	FreePargsAndKargs
 			  00171	; 00004		b = input('again? ')
 029A A9 01	      [2] 00172		lda	#1
 029C A2 00	      [2] 00173		ldx	#0
 029E 20 0CA1	      [6] 00174		jsr	AllocPargsAndKargs
 02A1 A0 03	      [2] 00175		ldy	#3
 02A3 A2 C2	      [2] 00176		ldx	#S_00002&$FF
 02A5 A9 2D	      [2] 00177		lda	#S_00002>>8
 02A7 20 0D07	      [6] 00178		jsr	StoreParg
 02AA A2 EA	      [2] 00179		ldx	#_input&$FF
 02AC A9 2D	      [2] 00180		lda	#_input>>8
 02AE 20 0C89	      [6] 00181		jsr	GetObject
 02B1 20 0D4C	      [6] 00182		jsr	object.__call__
 02B4 20 0D29	      [6] 00183		jsr	FreePargsAndKargs
 			  00184
 02B7 AE 2DD1	      [4] 00185		ldx	_b
 02BA AD 2DD2	      [4] 00186		lda	_b+1
 02BD 20 04E8	      [6] 00187		jsr	DeRef
 			  00188
 02C0 A6 16	      [3] 00189		ldx	PtrA
 02C2 A5 17	      [3] 00190		lda	PtrA+1
 02C4 8E 2DD1	      [4] 00191		stx	_b
 02C7 8D 2DD2	      [4] 00192		sta	_b+1
 02CA 4C 0221	      [3] 00193		jmp	L00000
 02CD			  00194	L00002

Revisited while and implemented else, break and continue.

Now this code

repeat = 0
while repeat < 2:
	counter = 0
	while counter < 5:
		if counter == 2:
			counter = counter + 1
			continue	# Skip 2
		print(counter, ': Inside loop')
		if repeat == 0:
			if counter == 3:
				break		# Quit after 3 the first time
		counter = counter + 1
	else:
		print('Inside else')
	repeat = repeat + 1

gives this output

0 : Inside loop
1 : Inside loop
3 : Inside loop
0 : Inside loop
1 : Inside loop
3 : Inside loop
4 : Inside loop
Inside else
1 Like

This is the document to go with my first public release of the compiler.

Please read and comment. Thanks.

PY65.PDF (65.9 KB)

There are a few additional features which may sneak in.

Edit: Dang, Missed it by >< that much. The size was almost 65.02 KB…

2 Likes