You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is not an issue but a contribution. I have implemented the ULP disassembler in objdump.exe.
Three files modified:
opcodes/esp32ulp-dis.c (contains the disassembler)
opcodes/disassemble.c : to tell objdump that we handle ESP32ULP architecture
include/dis-asm.h : to enable ESP32ULP architecture
objdump reads ELF files and can be used on the the .elf file or intermediate .o files.
syntax : esp32ulp-elf-objdump.exe -d file
Enjoy !
disassemble.c: add following lines #define ARCH_esp32ulp in line 38 #ifdef ARCH_esp32ulp case bfd_arch_esp32ulp: disassemble = print_insn_esp32ulp; break; #endif in line 246
dis-asm.h: extern int print_insn_esp32ulp (bfd_vma, disassemble_info *); in line 234
esp32-ulp.c:
/* ESPULP ELF support for BFD.
Copyright (c) 2016-2017 Espressif Systems (Shanghai) PTE LTD.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
/* Disassembler for ESP32 ULP processor
file to be put in folder opcodes/disassemble
typedef struct
{
unsigned int operand: 28;
unsigned int opcode : 4;
} esp32ulp_inst;
static void disasm_esp32ulp_instruction(esp32ulp_inst inst, unsigned int addr);
static void unknown(void);
static void regwr(unsigned int operand);
static void regrd(unsigned int operand);
static void i2c(unsigned int operand);
static void wait(unsigned int operand);
static void adc(unsigned int operand);
static void store(unsigned int operand);
static void operation(unsigned int operand);
static void operation_reg(unsigned int operand);
static void operation_imm(unsigned int operand);
static void operation_stage(unsigned int operand);
static void jmp(unsigned int operand, unsigned int address);
static void jump(unsigned int operand, unsigned int address);
static void jumpr(unsigned int operand, unsigned int address);
static void jumps(unsigned int operand, unsigned int address);
static void wakesleep(unsigned int operand);
static void tsens(unsigned int operand);
static void halt(unsigned int operand);
static void load(unsigned int operand);
unsigned int operand = inst.operand;
switch(inst.opcode)
{
case 1: regwr(operand); break;
case 2: regrd(operand); break;
case 3: i2c(operand); break;
case 4: wait(operand); break;
case 5: adc(operand); break;
case 6: store(operand); break;
case 7: operation(operand); break;
case 8: jmp(operand, addr); break;
case 9: wakesleep(operand); break;
case 10: tsens(operand); break;
case 11: halt(operand); break;
case 13: load(operand); break;
default: unknown(); break;
}
typedef struct {
unsigned int addr:10;
unsigned int data:8;
unsigned int low: 5;
unsigned int high: 5;
} fregwr;
static void regwr(unsigned int operand)
{
fregwr op;
COPY(op, operand);
unsigned int addr = INST_TO_ADDR(op.addr)+DR_REG_RTCCNTL_BASE;
unsigned int base;
unsigned int offset;
char* pstr;
if (addr>=DR_REG_RTC_I2C_BASE) { base = DR_REG_RTC_I2C_BASE; pstr = "RTC_I2C_BASE"; }
else if (addr>=DR_REG_SENS_BASE) { base = DR_REG_SENS_BASE; pstr = "SENS_BASE"; }
else if (addr>=DR_REG_RTCIO_BASE) { base = DR_REG_RTCIO_BASE; pstr = "RTCIO_BASE"; }
else { base = DR_REG_RTCCNTL_BASE ;pstr = "RTCCNTL_BASE"; }
offset = addr - base;
dinfo->fprintf_func(dinfo->stream, "REG_WR ");
dinfo->fprintf_func(dinfo->stream, "0x%x+0x%x, %d, %d, 0x%x", base, offset, op.high, op.low, op.data );
dinfo->fprintf_func(dinfo->stream, "\t // REG(%s+0x%x)[%d:%d]=0x%x", pstr, offset, op.high, op.low, op.data);
}
typedef struct {
unsigned int addr:10;
unsigned int dummy:8;
unsigned int low: 5;
unsigned int high: 5;
} fregrd;
static void regrd(unsigned int operand)
{
fregrd op;
COPY(op, operand);
unsigned int addr = INST_TO_ADDR(op.addr)+DR_REG_RTCCNTL_BASE;
unsigned int base;
unsigned int offset;
char* pstr;
if (addr>=DR_REG_RTC_I2C_BASE) { base = DR_REG_RTC_I2C_BASE; pstr = "RTC_I2C_BASE"; }
else if (addr>=DR_REG_SENS_BASE) { base = DR_REG_SENS_BASE; pstr = "SENS_BASE"; }
else if (addr>=DR_REG_RTCIO_BASE) { base = DR_REG_RTCIO_BASE; pstr = "RTCIO_BASE"; }
else { base = DR_REG_RTCCNTL_BASE ;pstr = "RTCCNTL_BASE"; }
offset = addr - base;
dinfo->fprintf_func(dinfo->stream, "REG_RD ");
dinfo->fprintf_func(dinfo->stream, "0x%x+0x%x, %d, %d", base, offset, op.high, op.low);
dinfo->fprintf_func(dinfo->stream, "\t\t // REG(%s+0x%x)[%d:%d]=0x%x", pstr, offset, op.high, op.low);
}
typedef struct {
unsigned int subaddr:8;
unsigned int data:8;
unsigned int low: 3;
unsigned int high: 3;
unsigned int sel: 4;
unsigned int dummy:1;
unsigned int rw: 1;
} fi2c;
static void i2c(unsigned int operand)
{
fi2c op;
COPY(op, operand);
typedef struct
{
unsigned int operand:25;
unsigned int choice: 3;
} fop;
typedef struct
{
unsigned int Rdst: 2;
unsigned int Rsrc1: 2;
unsigned int Rsrc2: 2;
unsigned int dummy:15;
unsigned int sel: 4;
unsigned int choice:3; // 0
} fop_reg;
typedef struct
{
unsigned int Rdst: 2;
unsigned int Rsrc1: 2;
unsigned int imm: 16;
unsigned int dummy1:1;
unsigned int sel: 4;
unsigned int choice:3; // 1
} fop_imm;
typedef struct
{
unsigned int dummy: 4;
unsigned int imm: 8;
unsigned int dummy2:9;
unsigned int sel: 4;
unsigned int choice:3; // 2
} fop_stage;
static void operation(unsigned int operand)
{
fop op;
COPY(op, operand);
switch(op.choice)
{
case 0: operation_reg(operand); break;
case 1: operation_imm(operand); break;
case 2: operation_stage(operand); break;
default: dinfo->fprintf_func(dinfo->stream, "ALU ???"); break;
}
}
static void operation_reg(unsigned int operand)
{
fop_reg opr;
COPY(opr, operand);
static void operation_stage(unsigned int operand)
{
fop_stage ops;
COPY(ops, operand);
switch(ops.sel)
{
case 0: dinfo->fprintf_func(dinfo->stream, "STAGE_INC %d", ops.imm); break;
case 1: dinfo->fprintf_func(dinfo->stream, "STAGE_DEC %d", ops.imm); break;
case 2: dinfo->fprintf_func(dinfo->stream, "STAGE_RST"); break;
default: dinfo->fprintf_func(dinfo->stream, "ALU ????"); break;
}
}
typedef struct
{
unsigned int operand:25;
unsigned int choice:3;
} fjmp;
typedef struct
{
unsigned int rdest:2;
unsigned int addr:11;
unsigned int dummy:8;
unsigned int sel: 1;
unsigned int type: 2;
unsigned int choice:3; // 0
} fjump;
typedef struct
{
unsigned int thres:16;
unsigned int cond: 1;
unsigned int step: 8;
unsigned int choice:3; // 1
} fjumpr;
typedef struct
{
unsigned int thres: 8;
unsigned int dummy: 7;
unsigned int cond: 2;
unsigned int step: 8;
unsigned int choice:3; // 2
} fjumps;
static void jmp(unsigned int operand, unsigned int address)
{
fjmp op;
COPY(op, operand);
switch(op.choice)
{
case 0: jump(operand, address); break;
case 1: jumpr(operand, address); break;
case 2: jumps(operand, address); break;
default: dinfo->fprintf_func(dinfo->stream, "JUMP????"); break;
}
}
static void jump(unsigned int operand, unsigned int address)
{
fjump op;
COPY(op, operand);
address = address; // fake instruction to astatic void compiler warning (unused parameter)
dinfo->fprintf_func(dinfo->stream, "JUMP ");
if (op.sel==0)
dinfo->fprintf_func(dinfo->stream, "0x%04x", INST_TO_ADDR(op.addr));
else
dinfo->fprintf_func(dinfo->stream, "R%d", op.rdest);
switch(op.type)
{
case 1: dinfo->fprintf_func(dinfo->stream, ",EQ \t\t\t\t\t // if operation==0 THEN JUMP"); break;
case 2: dinfo->fprintf_func(dinfo->stream, ",OV \t\t\t\t\t // if overflow THEN JUMP"); break;
}
}
static void jumpr(unsigned int operand, unsigned int address)
{
fjumpr op;
COPY(op, operand);
unsigned int relative = INST_TO_ADDR(op.step&0x7F);
int sign = (op.step&0x80 ? -1 : +1);
dinfo->fprintf_func(dinfo->stream, "JUMPR ");
dinfo->fprintf_func(dinfo->stream, "0x%04x, %d, %s", address+sign*relative, op.thres, (op.cond==0?"lt":"ge") );
dinfo->fprintf_func(dinfo->stream, "\t\t\t\t\t // IF R0%s%d THEN JUMP TO [0x%04x%c0x%02x]", (op.cond==0?"<":">="), op.thres, address, (sign>0?'+':'-'), relative);
}
static void jumps(unsigned int operand, unsigned int address)
{
fjumps op;
COPY(op, operand);
typedef struct {
unsigned int Rdst:2;
unsigned int Rsrc:2;
unsigned int null:6;
unsigned int offset:11;
unsigned int null2: 4;
unsigned int cent: 3;
} fstore;
static void store(unsigned int operand)
{
fstore op;
COPY(op, operand);
Uh oh!
There was an error while loading. Please reload this page.
Hi,
This is not an issue but a contribution. I have implemented the ULP disassembler in objdump.exe.
Three files modified:
opcodes/esp32ulp-dis.c (contains the disassembler)
opcodes/disassemble.c : to tell objdump that we handle ESP32ULP architecture
include/dis-asm.h : to enable ESP32ULP architecture
objdump reads ELF files and can be used on the the .elf file or intermediate .o files.
syntax : esp32ulp-elf-objdump.exe -d file
Enjoy !
disassemble.c: add following lines
#define ARCH_esp32ulp
in line 38#ifdef ARCH_esp32ulp case bfd_arch_esp32ulp: disassemble = print_insn_esp32ulp; break; #endif
in line 246dis-asm.h:
extern int print_insn_esp32ulp (bfd_vma, disassemble_info *);
in line 234esp32-ulp.c:
/* ESPULP ELF support for BFD.
Copyright (c) 2016-2017 Espressif Systems (Shanghai) PTE LTD.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
/* Disassembler for ESP32 ULP processor
file to be put in folder opcodes/disassemble
don't forget to add:
opcodes/disassemble.c:
#define ARCH_esp32ulp
..
#ifdef ARCH_esp32ulp
case bfd_arch_esp32ulp:
disassemble = print_insn_esp32ulp;
break;
#endif
extern int print_insn_esp32ulp (bfd_vma, disassemble_info *);
*/
#include "sysdep.h"
#include "dis-asm.h"
#include "floatformat.h"
#include "libiberty.h"
#include "opintl.h"
typedef struct
{
unsigned int operand: 28;
unsigned int opcode : 4;
} esp32ulp_inst;
static void disasm_esp32ulp_instruction(esp32ulp_inst inst, unsigned int addr);
static void unknown(void);
static void regwr(unsigned int operand);
static void regrd(unsigned int operand);
static void i2c(unsigned int operand);
static void wait(unsigned int operand);
static void adc(unsigned int operand);
static void store(unsigned int operand);
static void operation(unsigned int operand);
static void operation_reg(unsigned int operand);
static void operation_imm(unsigned int operand);
static void operation_stage(unsigned int operand);
static void jmp(unsigned int operand, unsigned int address);
static void jump(unsigned int operand, unsigned int address);
static void jumpr(unsigned int operand, unsigned int address);
static void jumps(unsigned int operand, unsigned int address);
static void wakesleep(unsigned int operand);
static void tsens(unsigned int operand);
static void halt(unsigned int operand);
static void load(unsigned int operand);
#define ESP32ULP_INSTR_SIZE 4
#define INST_TO_ADDR(inst) ((inst)*ESP32ULP_INSTR_SIZE)
#define ADDR_TO_INST(addr) ((addr)/ESP32ULP_INSTR_SIZE)
#define COPY(a,b) memcpy(&a, &b, sizeof(a));
/* Maximum length of an instruction. */
#define MAXLEN ESP32ULP_INSTR_SIZE
struct private
{
/* Points to first byte not fetched. */
bfd_byte *max_fetched;
bfd_byte the_buffer[MAXLEN];
bfd_vma insn_start;
};
/* Make sure that bytes from INFO->PRIVATE_DATA->BUFFER (inclusive)
to ADDR (exclusive) are valid. Returns 1 for success, 0 on error. */
#define FETCH_DATA(info, addr)
((addr) <= ((struct private *) (info->private_data))->max_fetched
? 1 : fetch_data ((info), (addr)))
static int
fetch_data (struct disassemble_info *info, bfd_byte *addr)
{
int status;
struct private *priv = (struct private *)info->private_data;
bfd_vma start = priv->insn_start + (priv->max_fetched - priv->the_buffer);
status = (*info->read_memory_func) (start,
priv->max_fetched,
addr - priv->max_fetched,
info);
if (status != 0)
{
(*info->memory_error_func) (status, start, info);
return 0;
}
else
priv->max_fetched = addr;
return 1;
}
struct disassemble_info* dinfo ;
int
print_insn_esp32ulp (bfd_vma memaddr, disassemble_info *info)
{
dinfo = info;
}
static void disasm_esp32ulp_instruction(esp32ulp_inst inst, unsigned int addr)
{
// dinfo->fprintf_func(dinfo->stream, "%04x %04x %01x%07x ", ADDR_TO_INST(addr), addr, inst.opcode, inst.operand);
}
static void unknown(void)
{
dinfo->fprintf_func(dinfo->stream, "????");
}
// from soc.h
#define DR_REG_RTCCNTL_BASE 0x3ff48000
#define DR_REG_RTCIO_BASE 0x3ff48400
#define DR_REG_SENS_BASE 0x3ff48800
#define DR_REG_RTC_I2C_BASE 0x3ff48C00
typedef struct {
unsigned int addr:10;
unsigned int data:8;
unsigned int low: 5;
unsigned int high: 5;
} fregwr;
static void regwr(unsigned int operand)
{
fregwr op;
COPY(op, operand);
}
typedef struct {
unsigned int addr:10;
unsigned int dummy:8;
unsigned int low: 5;
unsigned int high: 5;
} fregrd;
static void regrd(unsigned int operand)
{
fregrd op;
COPY(op, operand);
}
typedef struct {
unsigned int subaddr:8;
unsigned int data:8;
unsigned int low: 3;
unsigned int high: 3;
unsigned int sel: 4;
unsigned int dummy:1;
unsigned int rw: 1;
} fi2c;
static void i2c(unsigned int operand)
{
fi2c op;
COPY(op, operand);
}
typedef struct {
unsigned int cycles:16;
unsigned int dummy:8;
} fwait;
static void wait(unsigned int operand)
{
fwait op;
COPY(op, operand);
}
typedef struct {
unsigned int Rdst:2;
unsigned int Sarmux:4;
unsigned int sel:1;
unsigned int dummy:21;
} fadc;
static void adc(unsigned int operand)
{
fadc op;
COPY(op, operand);
}
typedef struct
{
unsigned int operand:25;
unsigned int choice: 3;
} fop;
typedef struct
{
unsigned int Rdst: 2;
unsigned int Rsrc1: 2;
unsigned int Rsrc2: 2;
unsigned int dummy:15;
unsigned int sel: 4;
unsigned int choice:3; // 0
} fop_reg;
typedef struct
{
unsigned int Rdst: 2;
unsigned int Rsrc1: 2;
unsigned int imm: 16;
unsigned int dummy1:1;
unsigned int sel: 4;
unsigned int choice:3; // 1
} fop_imm;
typedef struct
{
unsigned int dummy: 4;
unsigned int imm: 8;
unsigned int dummy2:9;
unsigned int sel: 4;
unsigned int choice:3; // 2
} fop_stage;
static void operation(unsigned int operand)
{
fop op;
COPY(op, operand);
}
static void operation_reg(unsigned int operand)
{
fop_reg opr;
COPY(opr, operand);
}
static void operation_imm(unsigned int operand)
{
fop_imm opi;
COPY(opi, operand);
}
static void operation_stage(unsigned int operand)
{
fop_stage ops;
COPY(ops, operand);
}
typedef struct
{
unsigned int operand:25;
unsigned int choice:3;
} fjmp;
typedef struct
{
unsigned int rdest:2;
unsigned int addr:11;
unsigned int dummy:8;
unsigned int sel: 1;
unsigned int type: 2;
unsigned int choice:3; // 0
} fjump;
typedef struct
{
unsigned int thres:16;
unsigned int cond: 1;
unsigned int step: 8;
unsigned int choice:3; // 1
} fjumpr;
typedef struct
{
unsigned int thres: 8;
unsigned int dummy: 7;
unsigned int cond: 2;
unsigned int step: 8;
unsigned int choice:3; // 2
} fjumps;
static void jmp(unsigned int operand, unsigned int address)
{
fjmp op;
COPY(op, operand);
}
static void jump(unsigned int operand, unsigned int address)
{
fjump op;
COPY(op, operand);
}
static void jumpr(unsigned int operand, unsigned int address)
{
fjumpr op;
COPY(op, operand);
}
static void jumps(unsigned int operand, unsigned int address)
{
fjumps op;
COPY(op, operand);
}
typedef struct {
unsigned int reg:4;
unsigned int dummy:19;
unsigned int wakeorsleep:1;
} fwakesleep;
static void wakesleep(unsigned int operand)
{
fwakesleep op;
COPY(op, operand);
}
typedef struct {
unsigned int Rdst:2;
unsigned int delay:14;
unsigned int dummy:12;
} ftsens;
static void tsens(unsigned int operand)
{
ftsens op;
COPY(op, operand);
}
static void halt(unsigned int operand)
{
operand = operand; // fake instruction to astatic void compiler warning (unused parameter)
}
typedef struct {
unsigned int Rdst:2;
unsigned int Rsrc:2;
unsigned int dummy:6;
unsigned int offset:11;
unsigned int dummy2: 7;
} fload;
static void load(unsigned int operand)
{
fload op;
COPY(op, operand);
}
typedef struct {
unsigned int Rdst:2;
unsigned int Rsrc:2;
unsigned int null:6;
unsigned int offset:11;
unsigned int null2: 4;
unsigned int cent: 3;
} fstore;
static void store(unsigned int operand)
{
fstore op;
COPY(op, operand);
}
esp32ulp-dis.txt
The text was updated successfully, but these errors were encountered: