File size: 4,006 Bytes
d8afd6f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8d577f5
 
d8afd6f
 
 
 
 
8d577f5
d8afd6f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import fs from 'fs';
import { createESP32, ESP32 } from '../web/js/soc.js';
const wasmBytes = fs.readFileSync(new URL('../wasm/xtensa.wasm', import.meta.url));
for (const eng of ['wasm', 'js']) {
  const soc = eng === 'wasm' ? await createESP32({ wasmBytes }) : new ESP32({});
  soc.reset('power');
  // program at 0x40080000 (IRAM): mixed loop
  const code = [];
  const e = (...b) => code.push(...b);
  // movi a2, 0x7fff? use loop counter in a3 via l32r-free sequence: movi a3,1000(?) up to 2047 via movi (imm12)
  // loop: addi a4,a4,1 ; add a5,a4,a3 ; xor a6,a5,a4 ; s32i a6,a1?no. use a7 as pointer to DRAM
  // encode by assembling with objdump-free manual encodings:
  // movi a3, 2000  -> 0xA3 0x07 0xD0? use: movi a3, -1 ... keep simple: use loop instruction.
  // We'll use: loopgtz a3, end ; addi.n a4,a4,1 ; add.n a5,a4,a4 ; xor a6,a5,a4 ; s32i a6,a7,0 ; l32i a8,a7,0 ; end: ; j start
  const asm = [
    0xa0, 0x20, 0x00,                // placeholder will be replaced
  ];
  const mem = soc.h8; const base = 0x40080000;
  const off = (soc.cpus[0].rd[base >>> 12] + base) | 0;
  // bytes: movi a3, 2047 : r=10 (MOVI) imm8=0xFF, s=7 (imm12 hi), t=3 => inst = imm8<<16 | 0xA<<12 | s<<8 | t<<4 | 2
  const w = (i) => [i & 255, (i >> 8) & 255, (i >> 16) & 255];
  const prog = [];
  prog.push(...w((0xFF << 16) | (0xA << 12) | (7 << 8) | (3 << 4) | 2));      // movi a3, 2047
  // movi a7, DRAM addr: use l32r? skip: use a1 (sp) region: a1 holds 0? set a7 via movi 0x...: use add.n? simply movi a7, 0x7ff? that's addr 0x7ff (unmapped slow!). use window: set a7 = pc-based? use call0 trick -> skip, use address in IRAM-literal: l32r a7, lit
  // literal at start+0x40: value 0x3ffb0000
  const litAddr = base + 0x40;
  // l32r a7, lit : imm16 = ((lit - ((pc+3)&~3))>>2) & 0xFFFF
  const pcL = base + 3; const imm16 = (((litAddr - ((pcL + 3) & ~3)) >> 2) & 0xFFFF);
  prog.push(...w((imm16 << 8) | (7 << 4) | 1));                                // l32r a7, lit
  const loopStart = base + prog.length;
  // loopgtz a3, end  (BI1 m=1 B1 r=10): inst= imm8<<16 | 10<<12 | s<<8 | (n=3,m=1 -> t=0b0111) <<4 | 6
  const bodyIns = [];
  bodyIns.push(0x4a, 0x1b);                         // addi.n a4,a4,1 ? (placeholder replaced below)
  const narrow = (op0, t, s, r) => [(t << 4) | op0, (r << 4) | s];
  const body = [];
  const ONLY_ADD = process.env.ONLY_ADD === '1';
  if (ONLY_ADD) { for (let k = 0; k < 8; k++) body.push(...narrow(0xA, 4, 4, 5)); } else {
  body.push(...narrow(0xB, 1, 4, 4));               // addi.n a4,a4,1 (t=1) r=4,s=4
  body.push(...narrow(0xA, 4, 4, 5));               // add.n a5,a4,a4
  body.push(...w((0x3 << 20) | (0x0 << 16) | (6 << 12) | (5 << 8) | (4 << 4) | 0)); // xor a6,a5,a4 (op2=3 op1=0)
  body.push(...w((0x06 << 12) | (7 << 8) | (6 << 4) | 2) .map((b,i)=>b)); // s32i a6,a7,0 : r=6 -> inst = imm8(0)<<16 | r=6<<12 | s=7<<8 | t=6<<4 | 2
  body.push(...w((0x02 << 12) | (7 << 8) | (8 << 4) | 2));                   // l32i a8,a7,0 (r=2)
  body.push(...narrow(0xA, 9, 8, 6)); }
  const loopLen = body.length;
  // loop instr: lend = pc+4+imm8
  const loopInst = (loopLen << 16) | (10 << 12) | (3 << 8) | (0x7 << 4) | 6;
  prog.push(...w(loopInst));
  prog.push(...body);
  // j start (backwards): J: op0=6,n=0 imm18 = off ; target = pc+4+off
  const jpc = base + prog.length; const joff = (loopStart - 4 - 0 - jpc); // jump back to the loop instruction
  const j18 = ((loopStart - (jpc + 4)) & 0x3FFFF);
  prog.push(...w((j18 << 6) | 6));
  while (prog.length < 0x40) prog.push(0);
  prog.push(0, 0, 0xfb, 0x3f);                     // literal 0x3ffb0000
  mem.set(prog, off);
  const c = soc.cpus[0];
  c.pc = base; c.ps = 0x20; c.cpenable = 0; c.chkInt = false; c.intenable = 0;
  const N = 30e6; const t0 = process.hrtime.bigint();
  for (let i = 0; i < N; i += 100000) c.run(100000);
  const dt = Number(process.hrtime.bigint() - t0) / 1e9;
  console.log(eng, (N / dt / 1e6).toFixed(1), 'MIPS', 'pc', (c.pc >>> 0).toString(16), 'a4', c.ar[(c.wb4 + 4) & 63]);
}