Skip to content

Commit

Permalink
test(rp2040): add missing opcodeXXX (#18)
Browse files Browse the repository at this point in the history
Replace obscure opcodes with functions that correspond to the assembly instructions
  • Loading branch information
Turro75 authored May 11, 2021
1 parent eccaac8 commit 9198f6a
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 18 deletions.
51 changes: 33 additions & 18 deletions src/instructions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,43 @@ import {
opcodeBICS,
opcodeBL,
opcodeBLX,
opcodeBT1,
opcodeBT2,
opcodeBX,
opcodeCMN,
opcodeCMPimm,
opcodeCMPregT1,
opcodeCMPregT2,
opcodeDMBSY,
opcodeDSBSY,
opcodeEORS,
opcodeISBSY,
opcodeLDMIA,
opcodeLDRB,
opcodeLDRBreg,
opcodeLDRH,
opcodeLDRHreg,
opcodeLDRimm,
opcodeLDRlit,
opcodeLDRreg,
opcodeLDRSB,
opcodeLDRSH,
opcodeLDRsp,
opcodeLSLSimm,
opcodeLSLSreg,
opcodeLSRS,
opcodeLSRSreg,
opcodeMOV,
opcodeMOVS,
opcodeMOVSreg,
opcodeMRS,
opcodeMSR,
opcodeMULS,
opcodeMVNS,
opcodeNOP,
opcodeORRS,
opcodePOP,
opcodePUSH,
opcodeREV,
opcodeREV16,
opcodeREVSH,
Expand All @@ -59,6 +72,8 @@ import {
opcodeSVC,
opcodeSXTB,
opcodeSXTH,
opcodeTST,
opcodeUDF,
opcodeUDF2,
opcodeUXTB,
opcodeUXTH,
Expand Down Expand Up @@ -356,7 +371,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should execute a `b.n .-20` instruction', async () => {
await cpu.setPC(0x20000000 + 9 * 2);
await cpu.writeUint16(0x20000000 + 9 * 2, 0xe7f6); // b.n .-20
await cpu.writeUint16(0x20000000 + 9 * 2, opcodeBT2(0xfec));
await cpu.singleStep();
const registers = await cpu.readRegisters();
expect(registers.pc).toEqual(0x20000002);
Expand All @@ -365,7 +380,7 @@ describe('Cortex-M0+ Instruction Set', () => {
it('should execute a `bne.n .-6` instruction', async () => {
await cpu.setPC(0x20000000 + 9 * 2);
await cpu.setRegisters({ Z: false });
await cpu.writeUint16(0x20000000 + 9 * 2, 0xd1fc); // bne.n .-6
await cpu.writeUint16(0x20000000 + 9 * 2, opcodeBT1(1,0x1f8));
await cpu.singleStep();
const registers = await cpu.readRegisters();
expect(registers.pc).toEqual(0x2000000e);
Expand Down Expand Up @@ -397,7 +412,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should execute an `cmp r5, #66` instruction', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint16(0x20000000, 0x2d42); // cmp r5, #66
await cpu.writeUint16(0x20000000, opcodeCMPimm(r5,66));
await cpu.setRegisters({ r5: 60 });
await cpu.singleStep();
const registers = await cpu.readRegisters();
Expand All @@ -409,7 +424,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should execute an `cmp r5, r0` instruction', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint16(0x20000000, 0x4285); // cmp r5, r0
await cpu.writeUint16(0x20000000, opcodeCMPregT1(r5,r0));
await cpu.setRegisters({ r5: 60 });
await cpu.setRegisters({ r0: 56 });
await cpu.singleStep();
Expand All @@ -422,7 +437,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should execute an `cmp ip, r6` instruction', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint16(0x20000000, 0x45b4); // cmp ip (r12), r6
await cpu.writeUint16(0x20000000, opcodeCMPregT2(ip,r6));
await cpu.setRegisters({ r6: 56, r12: 60 });
await cpu.singleStep();
const registers = await cpu.readRegisters();
Expand All @@ -434,15 +449,15 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should correctly decode a `dmb sy` instruction', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint32(0x20000000, 0x8f50f3bf); // DMB SY
await cpu.writeUint32(0x20000000, opcodeDMBSY());
await cpu.singleStep();
const registers = await cpu.readRegisters();
expect(registers.pc).toBe(0x20000004);
});

it('should correctly decode a `dsb sy` instruction', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint32(0x20000000, 0x8f4ff3bf); // DSB SY
await cpu.writeUint32(0x20000000, opcodeDSBSY());
await cpu.singleStep();
const registers = await cpu.readRegisters();
expect(registers.pc).toBe(0x20000004);
Expand All @@ -462,7 +477,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should correctly decode a `isb sy` instruction', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint32(0x20000000, 0x8f6ff3bf); // ISB SY
await cpu.writeUint32(0x20000000, opcodeISBSY());
await cpu.singleStep();
const registers = await cpu.readRegisters();
expect(registers.pc).toBe(0x20000004);
Expand Down Expand Up @@ -583,7 +598,7 @@ describe('Cortex-M0+ Instruction Set', () => {
it('should execute a `push {r4, r5, r6, lr}` instruction', async () => {
await cpu.setPC(0x20000000);
await cpu.setRegisters({ sp: RAM_START_ADDRESS + 0x100 });
await cpu.writeUint16(0x20000000, 0xb570); // push {r4, r5, r6, lr}
await cpu.writeUint16(0x20000000, opcodePUSH(true,(1 << r4) | (1 << r5) | (1 << r6)));
await cpu.setRegisters({ r4: 0x40, r5: 0x50, r6: 0x60, lr: 0x42 });
await cpu.singleStep();
const registers = await cpu.readRegisters();
Expand Down Expand Up @@ -651,7 +666,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should execute an `ldr r0, [pc, #148]` instruction', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint16(0x20000000, 0x4825); // ldr r0, [pc, #148]
await cpu.writeUint16(0x20000000, opcodeLDRlit(r0,148));
await cpu.writeUint32(0x20000000 + 152, 0x42);
await cpu.singleStep();
const registers = await cpu.readRegisters();
Expand All @@ -661,7 +676,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should execute an `ldr r3, [r2, #24]` instruction', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint16(0x20000000, 0x6993); // ldr r3, [r2, #24]
await cpu.writeUint16(0x20000000,opcodeLDRimm(r3,r2,24));
await cpu.setRegisters({ r2: 0x20000000 });
await cpu.writeUint8(0x20000000 + 24, 0x55);
await cpu.singleStep();
Expand Down Expand Up @@ -766,7 +781,7 @@ describe('Cortex-M0+ Instruction Set', () => {
const breakMock = jest.fn();
const rp2040 = new RP2040();
rp2040.PC = 0x20000000;
rp2040.writeUint16(0x20000000, 0xde01); // udf 1
rp2040.writeUint16(0x20000000, opcodeUDF(0x1));
rp2040.onBreak = breakMock;
rp2040.executeInstruction();
expect(rp2040.PC).toEqual(0x20000002);
Expand All @@ -786,7 +801,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should execute a `lsls r5, r5, #18` instruction', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint16(0x20000000, 0x04ad); // lsls r5, r5, #18
await cpu.writeUint16(0x20000000, opcodeLSLSimm(r5,r5,18));
await cpu.setRegisters({ r5: 0b00000000000000000011 });
await cpu.singleStep();
const registers = await cpu.readRegisters();
Expand All @@ -809,7 +824,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should execute a `lsls r5, r5, #18` instruction with carry', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint16(0x20000000, 0x04ad); // lsls r5, r5, #18
await cpu.writeUint16(0x20000000, opcodeLSLSimm(r5,r5,18));
await cpu.setRegisters({ r5: 0x00004001 });
await cpu.singleStep();
const registers = await cpu.readRegisters();
Expand All @@ -821,7 +836,7 @@ describe('Cortex-M0+ Instruction Set', () => {
await cpu.setPC(0x20000000);
await cpu.writeUint16(0x20000000, opcodeLSRSreg(r5, r0));
await cpu.setRegisters({ r5: 0xff00000f });
await cpu.setRegisters({ r0: 0xff003302 }); // Shift amount: 02
await cpu.setRegisters({ r0: 0xff003302 });
await cpu.singleStep();
const registers = await cpu.readRegisters();
expect(registers.r5).toEqual(0x3fc00003);
Expand Down Expand Up @@ -853,7 +868,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should execute a `movs r6, r5` instruction', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint16(0x20000000, 0x002e); // movs r6, r5
await cpu.writeUint16(0x20000000, opcodeMOVSreg(r6,r5));
await cpu.setRegisters({ r5: 0x50 });
await cpu.singleStep();
const registers = await cpu.readRegisters();
Expand Down Expand Up @@ -1154,7 +1169,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should execute an `tst r1, r3` instruction when the result is negative', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint16(0x20000000, 0x4219); // tst r1, r3
await cpu.writeUint16(0x20000000, opcodeTST(r1,r3));
await cpu.setRegisters({ r1: 0xf0000000 });
await cpu.setRegisters({ r3: 0xf0004000 });
await cpu.singleStep();
Expand All @@ -1164,7 +1179,7 @@ describe('Cortex-M0+ Instruction Set', () => {

it('should execute an `tst r1, r3` instruction when the registers are different', async () => {
await cpu.setPC(0x20000000);
await cpu.writeUint16(0x20000000, 0x4219); // tst r1, r3
await cpu.writeUint16(0x20000000, opcodeTST(r1,r3));
await cpu.setRegisters({ r1: 0xf0, r3: 0x0f });
await cpu.singleStep();
const registers = await cpu.readRegisters();
Expand Down
60 changes: 60 additions & 0 deletions src/utils/assembler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ export function opcodeASRSreg(Rdn: number, Rm: number) {
return (0b0100000100 << 6) | ((Rm & 0x7) << 3) | ((Rm & 0x7) << 3) | (Rdn & 0x7);
}

export function opcodeBT1(cond: number , imm8 : number) {
return (0b1101 << 12 ) | ((cond & 0xf) << 8) |((imm8 >> 1) & 0x1ff);
}

export function opcodeBT2(imm11 : number) {
return (0b11100 << 11 ) | ((imm11 >> 1 ) & 0x7ff);
}

export function opcodeBICS(Rdn: number, Rm: number) {
return (0b0100001110 << 6) | ((Rm & 7) << 3) | (Rdn & 7);
}
Expand Down Expand Up @@ -69,10 +77,34 @@ export function opcodeCMN(Rn: number, Rm: number) {
return (0b0100001011 << 6) | ((Rm & 0x7) << 3) | (Rn & 0x7);
}

export function opcodeCMPimm(Rn: number, Imm8: number) {
return (0b00101 << 11) | ((Rn & 0x7) << 8) | (Imm8 & 0xff);
}

export function opcodeCMPregT1(Rn: number, Rm: number) {
return (0b0100001010 << 6) | ((Rm & 0x7) << 3) | (Rn & 0x7);
}

export function opcodeCMPregT2(Rn: number, Rm: number) {
return (0b01000101 << 8) | ((Rn >> 3) & 0x1) << 7 | ((Rm & 0x7) << 3) | (Rn & 0x7);
}

export function opcodeDMBSY() {
return 0x8f50f3bf;
}

export function opcodeDSBSY() {
return 0x8f4ff3bf;
}

export function opcodeEORS(Rdn: number, Rm: number) {
return (0b0100000001 << 6) | ((Rm & 0x7) << 3) | (Rdn & 0x7);
}

export function opcodeISBSY() {
return 0x8f6ff3bf;
}

export function opcodeLDMIA(Rn: number, registers: number) {
return (0b11001 << 11) | ((Rn & 0x7) << 8) | (registers & 0xff);
}
Expand All @@ -81,6 +113,14 @@ export function opcodeLDRreg(Rt: number, Rn: number, Rm: number) {
return (0b0101100 << 9) | ((Rm & 0x7) << 6) | ((Rn & 0x7) << 3) | (Rt & 0x7);
}

export function opcodeLDRimm(Rt: number, Rn: number, imm5: number) {
return (0b01101 << 11) | (((imm5 >> 2 )& 0x1f) << 6) | ((Rn & 0x7) << 3) | (Rt & 0x7);
}

export function opcodeLDRlit(Rt: number, imm8: number) {
return (0b01001 << 11) | (imm8 >>2 & 0xff) | ((Rt & 0x7) << 8);
}

export function opcodeLDRB(Rt: number, Rn: number, imm5: number) {
return (0b01111 << 11) | ((imm5 & 0x1f) << 6) | ((Rn & 0x7) << 3) | (Rt & 0x7);
}
Expand Down Expand Up @@ -113,6 +153,10 @@ export function opcodeLSLSreg(Rdn: number, Rm: number) {
return (0b0100000010 << 6) | ((Rm & 0x7) << 3) | (Rdn & 0x7);
}

export function opcodeLSLSimm(Rd: number, Rm: number, Imm5 : number) {
return (0b00000 << 11) | ((Imm5 & 0x1f) << 6) |((Rm & 0x7) << 3) | (Rd & 0x7);
}

export function opcodeLSRS(Rd: number, Rm: number, imm5: number) {
return (0b00001 << 11) | ((imm5 & 0x1f) << 6) | ((Rm & 0x7) << 3) | (Rd & 0x7);
}
Expand All @@ -129,6 +173,9 @@ export function opcodeMOVS(Rd: number, imm8: number) {
return (0b00100 << 11) | ((Rd & 0x7) << 8) | (imm8 & 0xff);
}

export function opcodeMOVSreg(Rd: number, Rm: number) {
return (0b000000000 << 6) | ((Rm & 0x7) << 3) | (Rd & 0x7);
}
export function opcodeMRS(Rd: number, specReg: number) {
return (
((0b1000 << 28) | ((Rd & 0xf) << 24) | ((specReg & 0xff) << 16) | 0b1111001111101111) >>> 0
Expand Down Expand Up @@ -159,6 +206,10 @@ export function opcodePOP(P: boolean, registerList: number) {
return (0b1011110 << 9) | ((P ? 1 : 0) << 8) | registerList;
}

export function opcodePUSH(M: boolean, registerList: number) {
return (0b1011010 << 9) | ((M ? 1 : 0) << 8) | registerList;
}

export function opcodeREV(Rd: number, Rn: number) {
return (0b1011101000 << 6) | ((Rn & 0x7) << 3) | (Rd & 0x7);
}
Expand Down Expand Up @@ -243,10 +294,18 @@ export function opcodeSXTH(Rd: number, Rm: number) {
return (0b1011001000 << 6) | ((Rm & 7) << 3) | (Rd & 7);
}

export function opcodeTST(Rm: number, Rn: number) {
return (0b0100001000 << 6) | ((Rn & 7) << 3) | (Rm & 7);
}

export function opcodeUXTB(Rd: number, Rm: number) {
return (0b1011001011 << 6) | ((Rm & 7) << 3) | (Rd & 7);
}

export function opcodeUDF(imm8: number) {
return ((0b11011110 << 8) | (imm8 & 0xff)) >>> 0;
}

export function opcodeUDF2(imm16: number) {
const imm12 = imm16 & 0xfff;
const imm4 = (imm16 >> 12) & 0xf;
Expand All @@ -264,3 +323,4 @@ export function opcodeWFI() {
export function opcodeYIELD() {
return 0b1011111100010000;
}

0 comments on commit 9198f6a

Please sign in to comment.