This document discusses translating classic arcade games like Asteroids from the 6502 processor to JavaScript. It begins by explaining emulation versus recompilation approaches. It then describes translating the 6502 assembly code to JavaScript by representing registers as variables and memory as arrays. Challenges like conditional branches are addressed. Optimization techniques like redundant flag calculation elimination are discussed, linking the translation to compiler theory topics like liveness analysis. The goal is a browser-playable version of Asteroids that demonstrates translating a real-world 6502 application to JavaScript.
2. Automatic Program Translation
Is Exciting
Objective: exact conversion of the original
The traditional way: emulators
Interesting alternative: static binary
translation (static recompilation)
Examples: Asteroids (1979), Astro Fighter
(1980), Centipede (1981)
3. Translating 6502 to JavaScript
Emulation vs. Recompilation of
„Asteroids“
The Source: the 6502
The Target: JavaScript
„Naive“ Translation Patterns
Code Optimization and the Exciting
Journey into Compiler Theory
4. The Asteroids Arcade Machine
is Based on the 6502 Processor
Program ROM
6800–7fff
Work RAM
0000–02ff
Vector ROM
5000–57ff
Vector RAM
4000–47ff
6502 DVG
Game Logic Video Hardware
5. Traditional Emulation of the
Hardware ...
Program ROM
6800–7fff
Work RAM
0000–02ff
Vector ROM
5000–57ff
Vector RAM
4000–47ff
6502 DVG
Emulator in
JavaScript
6. ... or Translating the Game
Program to JavaScript, …
Program ROM
6800–7fff
Work RAM
0000–02ff
Vector ROM
5000–57ff
Vector RAM
4000–47ff
6502 DVG
JavaScript
Emulator in
JavaScript
7. … and by that Create a Stand-
Alone Application
Program ROM
6800–7fff
Work RAM
0000–02ff
Vector ROM
5000–57ff
Vector RAM
4000–47ff
6502 DVG
JavaScript
Emulator in
JavaScript
8. Translating 6502 to JavaScript
Emulation vs. Recompilation of
„Asteroids“
The Source: the 6502
The Target: JavaScript
„Naive“ Translation Patterns
Code Optimization and the Exciting
Journey into Compiler Theory
9. The 6502 was a Popular
Microprocessor in the 1980s
10. The 6502 Is Simple and Has
Only a Few Registers
Accumulator (A)
X Register (X)
Y Register (Y)
Program Counter (PC)
Flags: NV-BDIZC
00000001 Stack Pointer (S)
0000-00ff: Zero Page
0100-01ff: Stack
0200-ffff: Program
Registers Memory
11. The 6502 Instructions Can Have
Three Formats
Op Code
Op Code
Para-
meter
Op Code
Address
Low
Address
High
$a9 $03 … lda #3
$8d $07 $19 … sta $1907
$0a … asl
12. Some Instruction Examples
lda #1 Load accu with 1
sta 1000 Store accu in 1000
inx Add 1 to X
adc #7 Add 7 to the accu
jmp 3000 Jump to 3000
beq 2000 Conditional branch,
if Z (zero) flag is set
13. Translating 6502 to JavaScript
Emulation vs. Recompilation of
„Asteroids“
The Source: the 6502
The Target: JavaScript
„Naive“ Translation Patterns
Code Optimization and the Exciting
Journey into Compiler Theory
14. JavaScript is the Target
Variables and arrays
Assignments and arithmetics
if (cond) { stmt1 } else { stmt2 };
switch (var) {
case a: stmt1; break;
case b: stmt2; break;
case c: stmt3; break;
…
};
15. Translating 6502 to JavaScript
Emulation vs. Recompilation of
„Asteroids“
The Source: the 6502
The Target: JavaScript
„Naive“ Translation Patterns
Code Optimization and the Exciting
Journey into Compiler Theory
17. Then, Make a Code Generator
Out of It
…
… ldx #$44 x=44;
… lda #$02 a=2;
… sta $02 mem[2]=a;
… stx $03 mem[3]=x;
…
…
A2 44
A9 02
85 02
86 03
…
Program ROM
(from Asteroids)
JavaScript code instead of disassembler listing
18. 6502 Registers and Memory
Become Variables and Arrays
Accumulator
X register
Y register
C flag
N flag
…
Memory
var a;
var x;
var y;
var c;
var n;
var mem = new
Array(65536);
19. „Normal“ Instructions Are Easy
to Translate
lda 1000
sta 1001
inc 1000
ldx #10
sta 2000,x
inx
a = mem[1000];
mem[1001] = a;
mem[1000] =
(mem[1000]+1)&0xff;
x = 10;
mem[2000+x] = a;
x = (x+1) & 0xff;
20. „GOTO Considered Harmful“
Considered Harmful
…
1000: ldx #0 ; x = 0
1002: inx ; x = x + 1
1003: stx $d020 ; x screen color
1006: jmp 1002 ; go to 1002
…
But, JavaScript has no (real) GOTO !
21. An Old „Fortran to C“ Trick
pc = 1000;
while (true) {
switch (pc) {
case 1000: x = 0; //ldx
case 1002: x = (x+1) & 0xff; //inx
case 1003: mem[0xd020] = x; //stx
case 1006: pc = 1002; break; //jmp
…
};
};
22. Case Labels Are Only Needed
For Jump Targets
pc = 1000;
while (true) {
switch (pc) {
case 1000: x = 0; //ldx
case 1002: x = (x+1) & 0xff; //inx
case 1003: mem[0xd020] = x; //stx
case 1006: pc = 1002; break; //jmp
…
};
};
24. Dr. Sheldon Cooper‘s „Fun with
Flags“
Many 6502 instructions set flags as their
side effect
Example:
lda 1000 if zero Z=1 else Z=0
if neg. N=1 else N=0
beq 4711
…
25. Instructions Need Additional
Flag Calculation Code
lda 1000
lda 1000
a = mem[1000];
a = mem[1000];
if (a==0) z=1; else z=0;
if (a<0) n=1; else n=0;
Resulting programs are correct but big
26. Translating 6502 to JavaScript
Emulation vs. Recompilation of
„Asteroids“
The Source: the 6502
The Target: JavaScript
„Naive“ Translation Patterns
Code Optimization and the Exciting
Journey into Compiler Theory
27. Flag Calculations Are Often
Redundant …
lda 1000 a = mem[1000];
if (a==0) z=1; else z=0;
if (a<0) n=1; else n=0;
ldx 1200 x = mem[1200];
if (x==0) z=1; else z=0;
if (x<0) n=1; else n=0;
beq 4711 if (z==1) …
28. Flag Calculations Are Often
Redundant …
lda 1000 a = mem[1000];
if (a==0) z=1; else z=0;
if (a<0) n=1; else n=0;
ldx 1200 x = mem[1200];
if (x==0) z=1; else z=0;
if (x<0) n=1; else n=0;
beq 4711 if (z==1) …
29. ?:
yes:
… But Not Always
lda 1000 a = mem[1000];
if (a==0) z=1; else z=0;
if (a<0) n=1; else n=0;
ldx 1200 x = mem[1200];
if (x==0) z=1; else z=0;
if (x<0) n=1; else n=0;
beq 4711 if (z==1) …
30. Redundant Code Elimination Is
Difficult and Interesting
„Liveness analysis“ problem
Solution with fixpoint iteration, or more
elegantly with Datalog programs
Many exciting further directions:
More optimizations (combinations, high-level
structure detection,…)
LLVM
asm.js
Datalog, Logic Programming, …
31. Summary: From Asteroids to
Liveness Analysis
Browser-playable „Asteroids“ as an
example
6502 Processor
Translating 6502 code to JavaScript
Optimizing: Redundant Code Elimination