Skip to content

Commit b81a21d

Browse files
committed
feat(instruction): AssemblyScript interoperability
1 parent ad40366 commit b81a21d

File tree

2 files changed

+48
-34
lines changed

2 files changed

+48
-34
lines changed

Diff for: src/cpu/instruction.ts

+38-34
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,13 @@
88
* the datasheet)
99
*
1010
* Copyright (C) 2019, 2020 Uri Shaked
11+
* Copyright (C) 2021 Dario Götze
1112
*/
1213

14+
import { u8, u16, u32 } from '../types';
1315
import { CPU } from './cpu';
14-
import { u16 } from '../types';
1516

16-
function isTwoWordInstruction(opcode: u16) {
17+
function isTwoWordInstruction(opcode: u16): boolean {
1718
return (
1819
/* LDS */
1920
(opcode & 0xfe0f) === 0x9000 ||
@@ -26,8 +27,8 @@ function isTwoWordInstruction(opcode: u16) {
2627
);
2728
}
2829

29-
export function avrInstruction(cpu: CPU) {
30-
const opcode = cpu.progMem[cpu.pc];
30+
export function avrInstruction(cpu: CPU): void {
31+
const opcode: u32 = cpu.progMem[cpu.pc];
3132

3233
if ((opcode & 0xfc00) === 0x1c00) {
3334
/* ADC, 0001 11rd dddd rrrr */
@@ -63,7 +64,7 @@ export function avrInstruction(cpu: CPU) {
6364
const addr = 2 * ((opcode & 0x30) >> 4) + 24;
6465
const value = cpu.dataView.getUint16(addr, true);
6566
const R = (value + ((opcode & 0xf) | ((opcode & 0xc0) >> 2))) & 0xffff;
66-
cpu.dataView.setUint16(addr, R, true);
67+
cpu.dataView.setUint16(addr, u16(R), true);
6768
let sreg = cpu.data[95] & 0xe0;
6869
sreg |= R ? 0 : 2;
6970
sreg |= 0x8000 & R ? 4 : 0;
@@ -104,38 +105,38 @@ export function avrInstruction(cpu: CPU) {
104105
cpu.data[95] = sreg;
105106
} else if ((opcode & 0xff8f) === 0x9488) {
106107
/* BCLR, 1001 0100 1sss 1000 */
107-
cpu.data[95] &= ~(1 << ((opcode & 0x70) >> 4));
108+
cpu.data[95] &= ~(1 << u8((opcode & 0x70) >> 4));
108109
} else if ((opcode & 0xfe08) === 0xf800) {
109110
/* BLD, 1111 100d dddd 0bbb */
110111
const b = opcode & 7;
111112
const d = (opcode & 0x1f0) >> 4;
112-
cpu.data[d] = (~(1 << b) & cpu.data[d]) | (((cpu.data[95] >> 6) & 1) << b);
113+
cpu.data[d] = (~(1 << b) & cpu.data[d]) | (((cpu.data[95] >> 6) & 1) << u8(b));
113114
} else if ((opcode & 0xfc00) === 0xf400) {
114115
/* BRBC, 1111 01kk kkkk ksss */
115-
if (!(cpu.data[95] & (1 << (opcode & 7)))) {
116+
if (!(cpu.data[95] & (1 << u8(opcode & 7)))) {
116117
cpu.pc = cpu.pc + (((opcode & 0x1f8) >> 3) - (opcode & 0x200 ? 0x40 : 0));
117118
cpu.cycles++;
118119
}
119120
} else if ((opcode & 0xfc00) === 0xf000) {
120121
/* BRBS, 1111 00kk kkkk ksss */
121-
if (cpu.data[95] & (1 << (opcode & 7))) {
122+
if (cpu.data[95] & (1 << u8(opcode & 7))) {
122123
cpu.pc = cpu.pc + (((opcode & 0x1f8) >> 3) - (opcode & 0x200 ? 0x40 : 0));
123124
cpu.cycles++;
124125
}
125126
} else if ((opcode & 0xff8f) === 0x9408) {
126127
/* BSET, 1001 0100 0sss 1000 */
127-
cpu.data[95] |= 1 << ((opcode & 0x70) >> 4);
128+
cpu.data[95] |= 1 << u8((opcode & 0x70) >> 4);
128129
} else if ((opcode & 0xfe08) === 0xfa00) {
129130
/* BST, 1111 101d dddd 0bbb */
130131
const d = cpu.data[(opcode & 0x1f0) >> 4];
131132
const b = opcode & 7;
132-
cpu.data[95] = (cpu.data[95] & 0xbf) | ((d >> b) & 1 ? 0x40 : 0);
133+
cpu.data[95] = (cpu.data[95] & 0xbf) | ((d >> u8(b)) & 1 ? 0x40 : 0);
133134
} else if ((opcode & 0xfe0e) === 0x940e) {
134135
/* CALL, 1001 010k kkkk 111k kkkk kkkk kkkk kkkk */
135136
const k = cpu.progMem[cpu.pc + 1] | ((opcode & 1) << 16) | ((opcode & 0x1f0) << 13);
136137
const ret = cpu.pc + 2;
137138
const sp = cpu.dataView.getUint16(93, true);
138-
const { pc22Bits } = cpu;
139+
const pc22Bits = cpu.pc22Bits;
139140
cpu.data[sp] = 255 & ret;
140141
cpu.data[sp - 1] = (ret >> 8) & 255;
141142
if (pc22Bits) {
@@ -146,10 +147,10 @@ export function avrInstruction(cpu: CPU) {
146147
cpu.cycles += pc22Bits ? 4 : 3;
147148
} else if ((opcode & 0xff00) === 0x9800) {
148149
/* CBI, 1001 1000 AAAA Abbb */
149-
const A = opcode & 0xf8;
150-
const b = opcode & 7;
150+
const A = u16(opcode) & 0xf8;
151+
const b = u8(opcode) & 7;
151152
const R = cpu.readData((A >> 3) + 32);
152-
const mask = 1 << b;
153+
const mask: u8 = 1 << b;
153154
cpu.writeData((A >> 3) + 32, R & ~mask, mask);
154155
} else if ((opcode & 0xfe0f) === 0x9400) {
155156
/* COM, 1001 010d dddd 0000 */
@@ -292,7 +293,7 @@ export function avrInstruction(cpu: CPU) {
292293
/* ICALL, 1001 0101 0000 1001 */
293294
const retAddr = cpu.pc + 1;
294295
const sp = cpu.dataView.getUint16(93, true);
295-
const { pc22Bits } = cpu;
296+
const pc22Bits = cpu.pc22Bits;
296297
cpu.data[sp] = retAddr & 255;
297298
cpu.data[sp - 1] = (retAddr >> 8) & 255;
298299
if (pc22Bits) {
@@ -307,7 +308,7 @@ export function avrInstruction(cpu: CPU) {
307308
cpu.cycles++;
308309
} else if ((opcode & 0xf800) === 0xb000) {
309310
/* IN, 1011 0AAd dddd AAAA */
310-
const i = cpu.readData(((opcode & 0xf) | ((opcode & 0x600) >> 5)) + 32);
311+
const i = cpu.readData(u16((opcode & 0xf) | ((opcode & 0x600) >> 5)) + 32);
311312
cpu.data[(opcode & 0x1f0) >> 4] = i;
312313
} else if ((opcode & 0xfe0f) === 0x9403) {
313314
/* INC, 1001 010d dddd 0011 */
@@ -393,7 +394,7 @@ export function avrInstruction(cpu: CPU) {
393394
cpu.cycles++;
394395
cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(
395396
cpu.dataView.getUint16(28, true) +
396-
((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8))
397+
u16((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8))
397398
);
398399
} else if ((opcode & 0xfe0f) === 0x8000) {
399400
/* LDZ, 1000 000d dddd 0000 */
@@ -419,7 +420,7 @@ export function avrInstruction(cpu: CPU) {
419420
cpu.cycles++;
420421
cpu.data[(opcode & 0x1f0) >> 4] = cpu.readData(
421422
cpu.dataView.getUint16(30, true) +
422-
((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8))
423+
u16((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8))
423424
);
424425
} else if (opcode === 0x95c8) {
425426
/* LPM, 1001 0101 1100 1000 */
@@ -511,7 +512,10 @@ export function avrInstruction(cpu: CPU) {
511512
cpu.data[95] = sreg;
512513
} else if ((opcode & 0xf800) === 0xb800) {
513514
/* OUT, 1011 1AAr rrrr AAAA */
514-
cpu.writeData(((opcode & 0xf) | ((opcode & 0x600) >> 5)) + 32, cpu.data[(opcode & 0x1f0) >> 4]);
515+
cpu.writeData(
516+
u16((opcode & 0xf) | ((opcode & 0x600) >> 5)) + 32,
517+
cpu.data[(opcode & 0x1f0) >> 4]
518+
);
515519
} else if ((opcode & 0xfe0f) === 0x900f) {
516520
/* POP, 1001 000d dddd 1111 */
517521
const value = cpu.dataView.getUint16(93, true) + 1;
@@ -529,7 +533,7 @@ export function avrInstruction(cpu: CPU) {
529533
const k = (opcode & 0x7ff) - (opcode & 0x800 ? 0x800 : 0);
530534
const retAddr = cpu.pc + 1;
531535
const sp = cpu.dataView.getUint16(93, true);
532-
const { pc22Bits } = cpu;
536+
const pc22Bits = cpu.pc22Bits;
533537
cpu.data[sp] = 255 & retAddr;
534538
cpu.data[sp - 1] = (retAddr >> 8) & 255;
535539
if (pc22Bits) {
@@ -540,7 +544,7 @@ export function avrInstruction(cpu: CPU) {
540544
cpu.cycles += pc22Bits ? 3 : 2;
541545
} else if (opcode === 0x9508) {
542546
/* RET, 1001 0101 0000 1000 */
543-
const { pc22Bits } = cpu;
547+
const pc22Bits = cpu.pc22Bits;
544548
const i = cpu.dataView.getUint16(93, true) + (pc22Bits ? 3 : 2);
545549
cpu.dataView.setUint16(93, i, true);
546550
cpu.pc = (cpu.data[i - 1] << 8) + cpu.data[i] - 1;
@@ -550,7 +554,7 @@ export function avrInstruction(cpu: CPU) {
550554
cpu.cycles += pc22Bits ? 4 : 3;
551555
} else if (opcode === 0x9518) {
552556
/* RETI, 1001 0101 0001 1000 */
553-
const { pc22Bits } = cpu;
557+
const pc22Bits = cpu.pc22Bits;
554558
const i = cpu.dataView.getUint16(93, true) + (pc22Bits ? 3 : 2);
555559
cpu.dataView.setUint16(93, i, true);
556560
cpu.pc = (cpu.data[i - 1] << 8) + cpu.data[i] - 1;
@@ -603,23 +607,23 @@ export function avrInstruction(cpu: CPU) {
603607
cpu.data[95] = sreg;
604608
} else if ((opcode & 0xff00) === 0x9a00) {
605609
/* SBI, 1001 1010 AAAA Abbb */
606-
const target = ((opcode & 0xf8) >> 3) + 32;
607-
const mask = 1 << (opcode & 7);
610+
const target = u16((opcode & 0xf8) >> 3) + 32;
611+
const mask: u8 = 1 << u8(opcode & 7);
608612
cpu.writeData(target, cpu.readData(target) | mask, mask);
609613
cpu.cycles++;
610614
} else if ((opcode & 0xff00) === 0x9900) {
611615
/* SBIC, 1001 1001 AAAA Abbb */
612-
const value = cpu.readData(((opcode & 0xf8) >> 3) + 32);
613-
if (!(value & (1 << (opcode & 7)))) {
616+
const value = cpu.readData(u16((opcode & 0xf8) >> 3) + 32);
617+
if (!(value & (1 << u8(opcode & 7)))) {
614618
const nextOpcode = cpu.progMem[cpu.pc + 1];
615619
const skipSize = isTwoWordInstruction(nextOpcode) ? 2 : 1;
616620
cpu.cycles += skipSize;
617621
cpu.pc += skipSize;
618622
}
619623
} else if ((opcode & 0xff00) === 0x9b00) {
620624
/* SBIS, 1001 1011 AAAA Abbb */
621-
const value = cpu.readData(((opcode & 0xf8) >> 3) + 32);
622-
if (value & (1 << (opcode & 7))) {
625+
const value = cpu.readData(u16((opcode & 0xf8) >> 3) + 32);
626+
if (value & (1 << u8(opcode & 7))) {
623627
const nextOpcode = cpu.progMem[cpu.pc + 1];
624628
const skipSize = isTwoWordInstruction(nextOpcode) ? 2 : 1;
625629
cpu.cycles += skipSize;
@@ -629,7 +633,7 @@ export function avrInstruction(cpu: CPU) {
629633
/* SBIW, 1001 0111 KKdd KKKK */
630634
const i = 2 * ((opcode & 0x30) >> 4) + 24;
631635
const a = cpu.dataView.getUint16(i, true);
632-
const l = (opcode & 0xf) | ((opcode & 0xc0) >> 2);
636+
const l = u16((opcode & 0xf) | ((opcode & 0xc0) >> 2));
633637
const R = a - l;
634638
cpu.dataView.setUint16(i, R, true);
635639
let sreg = cpu.data[95] & 0xc0;
@@ -643,15 +647,15 @@ export function avrInstruction(cpu: CPU) {
643647
cpu.cycles++;
644648
} else if ((opcode & 0xfe08) === 0xfc00) {
645649
/* SBRC, 1111 110r rrrr 0bbb */
646-
if (!(cpu.data[(opcode & 0x1f0) >> 4] & (1 << (opcode & 7)))) {
650+
if (!(cpu.data[(opcode & 0x1f0) >> 4] & (1 << u8(opcode & 7)))) {
647651
const nextOpcode = cpu.progMem[cpu.pc + 1];
648652
const skipSize = isTwoWordInstruction(nextOpcode) ? 2 : 1;
649653
cpu.cycles += skipSize;
650654
cpu.pc += skipSize;
651655
}
652656
} else if ((opcode & 0xfe08) === 0xfe00) {
653657
/* SBRS, 1111 111r rrrr 0bbb */
654-
if (cpu.data[(opcode & 0x1f0) >> 4] & (1 << (opcode & 7))) {
658+
if (cpu.data[(opcode & 0x1f0) >> 4] & (1 << u8(opcode & 7))) {
655659
const nextOpcode = cpu.progMem[cpu.pc + 1];
656660
const skipSize = isTwoWordInstruction(nextOpcode) ? 2 : 1;
657661
cpu.cycles += skipSize;
@@ -715,7 +719,7 @@ export function avrInstruction(cpu: CPU) {
715719
/* STDY, 10q0 qq1r rrrr 1qqq */
716720
cpu.writeData(
717721
cpu.dataView.getUint16(28, true) +
718-
((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)),
722+
u16((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)),
719723
cpu.data[(opcode & 0x1f0) >> 4]
720724
);
721725
cpu.cycles++;
@@ -743,7 +747,7 @@ export function avrInstruction(cpu: CPU) {
743747
/* STDZ, 10q0 qq1r rrrr 0qqq */
744748
cpu.writeData(
745749
cpu.dataView.getUint16(30, true) +
746-
((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)),
750+
u16((opcode & 7) | ((opcode & 0xc00) >> 7) | ((opcode & 0x2000) >> 8)),
747751
cpu.data[(opcode & 0x1f0) >> 4]
748752
);
749753
cpu.cycles++;

Diff for: src/types.ts

+10
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1+
/*
2+
* These types are used for interoperability with AssemblyScript.
3+
* See https://www.assemblyscript.org/portability.html
4+
*/
5+
16
export type u8 = number;
27
export type u16 = number;
38
export type i16 = number;
49
export type u32 = number;
10+
11+
export const u8 = (x: number) => x as u8;
12+
export const i16 = (x: number) => x as i16;
13+
export const u16 = (x: number) => x as u16;
14+
export const u32 = (x: number) => x as u32;

0 commit comments

Comments
 (0)