diff --git a/esp32_ulp/opcodes.py b/esp32_ulp/opcodes.py index 98d7284..6910081 100644 --- a/esp32_ulp/opcodes.py +++ b/esp32_ulp/opcodes.py @@ -358,9 +358,7 @@ def get_cond(arg): def _soc_reg_to_ulp_periph_sel(reg): # Map SoC peripheral register to periph_sel field of RD_REG and WR_REG instructions. - if reg < DR_REG_MAX_DIRECT: - ret = RD_REG_PERIPH_RTC_CNTL - elif reg < DR_REG_RTCCNTL_BASE: + if reg < DR_REG_RTCCNTL_BASE: raise ValueError("invalid register base") elif reg < DR_REG_RTCIO_BASE: ret = RD_REG_PERIPH_RTC_CNTL @@ -377,11 +375,12 @@ def _soc_reg_to_ulp_periph_sel(reg): def i_reg_wr(reg, high_bit, low_bit, val): reg = get_imm(reg) - if reg < DR_REG_MAX_DIRECT: # see https://github.com/espressif/binutils-esp32ulp/blob/master/gas/config/tc-esp32ulp_esp32.c - _wr_reg.addr = reg + if reg <= DR_REG_MAX_DIRECT: # see https://github.com/espressif/binutils-esp32ulp/blob/master/gas/config/tc-esp32ulp_esp32.c + _wr_reg.addr = reg & 0xff + _wr_reg.periph_sel = (reg & 0x300) >> 8 else: _wr_reg.addr = (reg & 0xff) >> 2 - _wr_reg.periph_sel = _soc_reg_to_ulp_periph_sel(reg) + _wr_reg.periph_sel = _soc_reg_to_ulp_periph_sel(reg) _wr_reg.data = get_imm(val) _wr_reg.low = get_imm(low_bit) _wr_reg.high = get_imm(high_bit) @@ -391,11 +390,12 @@ def i_reg_wr(reg, high_bit, low_bit, val): def i_reg_rd(reg, high_bit, low_bit): reg = get_imm(reg) - if reg < DR_REG_MAX_DIRECT: # see https://github.com/espressif/binutils-esp32ulp/blob/master/gas/config/tc-esp32ulp_esp32.c - _rd_reg.addr = reg + if reg <= DR_REG_MAX_DIRECT: # see https://github.com/espressif/binutils-esp32ulp/blob/master/gas/config/tc-esp32ulp_esp32.c + _rd_reg.addr = reg & 0xff + _rd_reg.periph_sel = (reg & 0x300) >> 8 else: _rd_reg.addr = (reg & 0xff) >> 2 - _rd_reg.periph_sel = _soc_reg_to_ulp_periph_sel(reg) + _rd_reg.periph_sel = _soc_reg_to_ulp_periph_sel(reg) _rd_reg.unused = 0 _rd_reg.low = get_imm(low_bit) _rd_reg.high = get_imm(high_bit) diff --git a/tests/02_compat_rtc_tests.sh b/tests/02_compat_rtc_tests.sh index 05a3ee2..b609bb6 100755 --- a/tests/02_compat_rtc_tests.sh +++ b/tests/02_compat_rtc_tests.sh @@ -51,6 +51,42 @@ build_defines_db() { esp-idf/components/esp_common/include/*.h 1>$log_file } +patch_test() { + local test_name=$1 + local out_file="${test_name}.tmp" + + if [ "${test_name}" = esp32ulp_jumpr ]; then + ( + cd binutils-esp32ulp/gas/testsuite/gas/esp32ulp/esp32 + cp ${test_name}.s ${out_file} + echo -e "\tPatching test to work around binutils-esp32ulp .global bug" + cat >> ${out_file} < ${out_file} + echo -e "\tPatching test to work around binutils-esp32ulp .global bug" + cat >> ${out_file} <$log_file # generates $ulp_file diff --git a/tests/opcodes.py b/tests/opcodes.py index f14829a..85cd710 100644 --- a/tests/opcodes.py +++ b/tests/opcodes.py @@ -108,10 +108,78 @@ def assert_raises(exception, func, *args): assert raised +def test_reg_direct_ulp_addressing(): + """ + Test direct ULP addressing of peripheral registers + input must be <= 0x3ff (10 bits) + periph_sel == high 2 bits from input + addr == low 8 bits from input + """ + + ins = make_ins(""" + addr : 8 # Address within either RTC_CNTL, RTC_IO, or SARADC + periph_sel : 2 # Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) + unused : 8 # Unused + low : 5 # Low bit + high : 5 # High bit + opcode : 4 # Opcode (OPCODE_RD_REG) + """) + + ins.all = opcodes.i_reg_rd("0x0", "0", "0") + assert ins.periph_sel == 0 + assert ins.addr == 0x0 + + ins.all = opcodes.i_reg_rd("0x012", "0", "0") + assert ins.periph_sel == 0 + assert ins.addr == 0x12 + + ins.all = opcodes.i_reg_rd("0x123", "0", "0") + assert ins.periph_sel == 1 + assert ins.addr == 0x23 + + ins.all = opcodes.i_reg_rd("0x2ee", "0", "0") + assert ins.periph_sel == 2 + assert ins.addr == 0xee + + ins.all = opcodes.i_reg_rd("0x3ff", "0", "0") + assert ins.periph_sel == 3 + assert ins.addr == 0xff + + # anything bigger than 0x3ff must be a valid full address + assert_raises(ValueError, opcodes.i_reg_rd, "0x400", "0", "0") + + +def test_reg_address_translations(): + """ + Test addressing of peripheral registers using full DPORT bus addresses + """ + + ins = make_ins(""" + addr : 8 # Address within either RTC_CNTL, RTC_IO, or SARADC + periph_sel : 2 # Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) + unused : 8 # Unused + low : 5 # Low bit + high : 5 # High bit + opcode : 4 # Opcode (OPCODE_RD_REG) + """) + + # direct ULP address is derived from full address as follows: + # full:0x3ff484a8 == ulp:(0x3ff484a8-DR_REG_RTCCNTL_BASE) / 4 + # full:0x3ff484a8 == ulp:(0x3ff484a8-0x3ff48000) / 4 + # full:0x3ff484a8 == ulp:0x4a8 / 4 + # full:0x3ff484a8 == ulp:0x12a + # see: https://github.com/espressif/binutils-esp32ulp/blob/249ec34/gas/config/tc-esp32ulp_esp32.c#L149 + ins.all = opcodes.i_reg_rd("0x3ff484a8", "0", "0") + assert ins.periph_sel == 1 # high 2 bits of 0x12a + assert ins.addr == 0x2a # low 8 bits of 0x12a + + test_make_ins_struct_def() test_make_ins() test_arg_qualify() test_get_reg() test_get_imm() test_get_cond() -test_eval_arg() \ No newline at end of file +test_eval_arg() +test_reg_direct_ulp_addressing() +test_reg_address_translations()