1ESP32-S2 ULP coprocessor instruction set
2========================================
3
4This document provides details about the instructions used by ESP32-S2 ULP coprocessor assembler.
5
6ULP coprocessor has 4 16-bit general purpose registers, labeled R0, R1, R2, R3. It also has an 8-bit counter register (stage_cnt) which can be used to implement loops. Stage count regiter is accessed using special instructions.
7
8ULP coprocessor can access 8k bytes of RTC_SLOW_MEM memory region. Memory is addressed in 32-bit word units. It can also access peripheral registers in RTC_CNTL, RTC_IO, and SENS peripherals.
9
10All instructions are 32-bit. Jump instructions, ALU instructions, peripheral register and memory access instructions are executed in 1 cycle. Instructions which work with peripherals (TSENS, ADC, I2C) take variable number of cycles, depending on peripheral operation.
11
12The instruction syntax is case insensitive. Upper and lower case letters can be used and intermixed arbitrarily. This is true both for register names and instruction names.
13
14
15Note about addressing
16---------------------
17ESP32-S2 ULP coprocessor's JUMP, ST, LD instructions which take register as an argument (jump address, store/load base address) expect the argument to be expressed in 32-bit words.
18
19Consider the following example program::
20
21  entry:
22          NOP
23          NOP
24          NOP
25          NOP
26  loop:
27          MOVE R1, loop
28          JUMP R1
29
30When this program is assembled and linked, address of label ``loop`` will be equal to 16 (expressed in bytes). However `JUMP` instruction expects the address stored in register to be expressed in 32-bit words. To account for this common use case, assembler will convert the address of label `loop` from bytes to words, when generating ``MOVE`` instruction, so the code generated code will be equivalent to::
31
32  0000    NOP
33  0004    NOP
34  0008    NOP
35  000c    NOP
36  0010    MOVE R1, 4
37  0014    JUMP R1
38
39The other case is when the argument of ``MOVE`` instruction is not a label but a constant. In this case assembler will use the value as is, without any conversion::
40
41          .set        val, 0x10
42          MOVE        R1, val
43
44In this case, value loaded into R1 will be ``0x10``.
45
46Similar considerations apply to ``LD`` and ``ST`` instructions. Consider the following code::
47
48          .global array
49  array:  .long 0
50          .long 0
51          .long 0
52          .long 0
53
54          MOVE R1, array
55          MOVE R2, 0x1234
56          ST R2, R1, 0      // write value of R2 into the first array element,
57                            // i.e. array[0]
58
59          ST R2, R1, 4      // write value of R2 into the second array element
60                            // (4 byte offset), i.e. array[1]
61
62          ADD R1, R1, 2     // this increments address by 2 words (8 bytes)
63          ST R2, R1, 0      // write value of R2 into the third array element,
64                            // i.e. array[2]
65
66
67Note about instruction execution time
68-------------------------------------
69
70ULP coprocessor is clocked from RTC_FAST_CLK, which is normally derived from the internal 8MHz oscillator. Applications which need to know exact ULP clock frequency can calibrate it against the main XTAL clock::
71
72    #include "soc/rtc.h"
73
74    // calibrate 8M/256 clock against XTAL, get 8M/256 clock period
75    uint32_t rtc_8md256_period = rtc_clk_cal(RTC_CAL_8MD256, 100);
76    uint32_t rtc_fast_freq_hz = 1000000ULL * (1 << RTC_CLK_CAL_FRACT) * 256 / rtc_8md256_period;
77
78ULP coprocessor needs certain number of clock cycles to fetch each instruction, plus certain number of cycles to execute it, depending on the instruction. See description of each instruction below for details on the execution time.
79
80Instruction fetch time is:
81
82- 2 clock cycles — for instructions following ALU and branch instructions.
83- 4 clock cycles — in other cases.
84
85Note that when accessing RTC memories and RTC registers, ULP coprocessor has lower priority than the main CPUs. This means that ULP coprocessor execution may be suspended while the main CPUs access same memory region as the ULP.
86
87
88Difference between ESP32 ULP and ESP32-S2 ULP Instruction sets
89--------------------------------------------------------------
90
91Compare to the ESP32 ULP coprocessor, the ESP-S2 ULP coprocessor has extended instruction set. The ESP32-S2 ULP is not binary compatible with ESP32 ULP,
92but the assembled program that was written for the ESP32 ULP will also work on the ESP32-S2 ULP after rebuild.
93The list of the new instructions that was added to the ESP32-S2 ULP is: LDL, LDH, STO, ST32, STI32.
94The detailed description of these commands please see below.
95
96
97**NOP** - no operation
98----------------------
99
100**Syntax**
101  **NOP**
102**Operands**
103  None
104**Cycles**
105  2 cycle to execute, 4 cycles to fetch next instruction
106**Description**
107  No operation is performed. Only the PC is incremented.
108
109**Example**::
110
111  1:    NOP
112
113
114**ADD** - Add to register
115-------------------------
116
117**Syntax**
118    **ADD**      *Rdst, Rsrc1, Rsrc2*
119
120    **ADD**      *Rdst, Rsrc1, imm*
121
122
123**Operands**
124  - *Rdst* - Register R[0..3]
125  - *Rsrc1* - Register R[0..3]
126  - *Rsrc2* - Register R[0..3]
127  - *Imm* - 16-bit signed value
128
129**Cycles**
130  2 cycles to execute, 4 cycles to fetch next instruction
131
132**Description**
133  The instruction adds source register to another source register or to a 16-bit signed value and stores result to the destination register.
134
135**Examples**::
136
137  1:    ADD R1, R2, R3        //R1 = R2 + R3
138
139  2:    Add R1, R2, 0x1234    //R1 = R2 + 0x1234
140
141  3:    .set value1, 0x03     //constant value1=0x03
142        Add R1, R2, value1    //R1 = R2 + value1
143
144
145  4:    .global label         //declaration of variable label
146        Add R1, R2, label     //R1 = R2 + label
147          ...
148        label: nop            //definition of variable label
149
150
151**SUB** - Subtract from register
152--------------------------------
153
154**Syntax**
155  **SUB** *Rdst, Rsrc1, Rsrc2*
156
157  **SUB** *Rdst, Rsrc1, imm*
158
159**Operands**
160  - *Rdst*  - Register R[0..3]
161  - *Rsrc1* - Register R[0..3]
162  - *Rsrc2* - Register R[0..3]
163  - *Imm*   - 16-bit signed value
164
165**Cycles**
166  2 cycles to execute, 4 cycles to fetch next instruction
167
168**Description**
169  The instruction subtracts the source register from another source register or subtracts 16-bit signed value from a source register, and stores result to the destination register.
170
171**Examples**::
172
173  1:         SUB R1, R2, R3             //R1 = R2 - R3
174
175  2:         sub R1, R2, 0x1234         //R1 = R2 - 0x1234
176
177  3:         .set value1, 0x03          //constant value1=0x03
178             SUB R1, R2, value1         //R1 = R2 - value1
179  4:         .global label              //declaration of variable label
180             SUB R1, R2, label          //R1 = R2 - label
181               ....
182    label:   nop                        //definition of variable label
183
184
185**AND** - Logical AND of two operands
186-------------------------------------
187
188**Syntax**
189    **AND** *Rdst, Rsrc1, Rsrc2*
190
191    **AND** *Rdst, Rsrc1, imm*
192
193**Operands**
194  - *Rdst* - Register R[0..3]
195  - *Rsrc1* - Register R[0..3]
196  - *Rsrc2* - Register R[0..3]
197  - *Imm* - 16-bit signed value
198
199**Cycles**
200  2 cycles to execute, 4 cycles to fetch next instruction
201
202**Description**
203  The instruction does logical AND of a source register and another source register or 16-bit signed value and stores result to the destination register.
204
205**Examples**::
206
207  1:        AND R1, R2, R3          //R1 = R2 & R3
208
209  2:        AND R1, R2, 0x1234      //R1 = R2 & 0x1234
210
211  3:        .set value1, 0x03       //constant value1=0x03
212            AND R1, R2, value1      //R1 = R2 & value1
213
214  4:        .global label           //declaration of variable label
215            AND R1, R2, label       //R1 = R2 & label
216                ...
217    label:  nop                     //definition of variable label
218
219
220**OR** - Logical OR of two operands
221-----------------------------------
222
223**Syntax**
224  **OR** *Rdst, Rsrc1, Rsrc2*
225
226  **OR** *Rdst, Rsrc1, imm*
227
228**Operands**
229  - *Rdst* - Register R[0..3]
230  - *Rsrc1* - Register R[0..3]
231  - *Rsrc2* - Register R[0..3]
232  - *Imm* - 16-bit signed value
233
234**Cycles**
235  2 cycles to execute, 4 cycles to fetch next instruction
236
237**Description**
238  The instruction does logical OR of a source register and another source register or 16-bit signed value and stores result to the destination register.
239
240**Examples**::
241
242  1:       OR R1, R2, R3           //R1 = R2 \| R3
243
244  2:       OR R1, R2, 0x1234       //R1 = R2 \| 0x1234
245
246  3:       .set value1, 0x03       //constant value1=0x03
247           OR R1, R2, value1       //R1 = R2 \| value1
248
249  4:       .global label           //declaration of variable label
250           OR R1, R2, label        //R1 = R2 \|label
251           ...
252    label: nop                     //definition of variable label
253
254
255**LSH** - Logical Shift Left
256----------------------------
257
258**Syntax**
259  **LSH** *Rdst, Rsrc1, Rsrc2*
260
261  **LSH** *Rdst, Rsrc1, imm*
262
263**Operands**
264  - *Rdst* - Register R[0..3]
265  - *Rsrc1* - Register R[0..3]
266  - *Rsrc2* - Register R[0..3]
267  - *Imm* - 16-bit signed value
268
269**Cycles**
270  2 cycles to execute, 4 cycles to fetch next instruction
271
272**Description**
273   The instruction does logical shift to left of source register to number of bits from another source register or 16-bit signed value and store result to the destination register.
274
275**Examples**::
276
277  1:       LSH R1, R2, R3            //R1 = R2 << R3
278
279  2:       LSH R1, R2, 0x03          //R1 = R2 << 0x03
280
281  3:       .set value1, 0x03         //constant value1=0x03
282           LSH R1, R2, value1        //R1 = R2 << value1
283
284  4:       .global label             //declaration of variable label
285           LSH R1, R2, label         //R1 = R2 << label
286           ...
287    label:  nop                       //definition of variable label
288
289
290**RSH** - Logical Shift Right
291-----------------------------
292
293**Syntax**
294   **RSH** *Rdst, Rsrc1, Rsrc2*
295
296   **RSH** *Rdst, Rsrc1, imm*
297
298**Operands**
299  *Rdst* - Register R[0..3]
300  *Rsrc1* - Register R[0..3]
301  *Rsrc2* - Register R[0..3]
302  *Imm* - 16-bit signed value
303
304**Cycles**
305  2 cycles to execute, 4 cycles to fetch next instruction
306
307**Description**
308  The instruction does logical shift to right of source register to number of bits from another source register or 16-bit signed value and store result to the destination register.
309
310**Examples**::
311
312  1:        RSH R1, R2, R3              //R1 = R2 >> R3
313
314  2:        RSH R1, R2, 0x03            //R1 = R2 >> 0x03
315
316  3:        .set value1, 0x03           //constant value1=0x03
317            RSH R1, R2, value1          //R1 = R2 >> value1
318
319  4:        .global label               //declaration of variable label
320            RSH R1, R2, label           //R1 = R2 >> label
321    label:  nop                         //definition of variable label
322
323
324**MOVE** – Move to register
325---------------------------
326
327**Syntax**
328  **MOVE**     *Rdst, Rsrc*
329
330  **MOVE**     *Rdst, imm*
331
332**Operands**
333  - *Rdst* – Register R[0..3]
334  - *Rsrc* – Register R[0..3]
335  - *Imm*  – 16-bit signed value
336
337**Cycles**
338  2 cycles to execute, 4 cycles to fetch next instruction
339
340**Description**
341   The instruction move to destination register value from source register or 16-bit signed value.
342
343   Note that when a label is used as an immediate, the address of the label will be converted from bytes to words. This is because LD, ST, and JUMP instructions expect the address register value to be expressed in words rather than bytes. To avoid using an extra instruction
344
345
346**Examples**::
347
348  1:        MOVE       R1, R2            //R1 = R2
349
350  2:        MOVE       R1, 0x03          //R1 = 0x03
351
352  3:        .set       value1, 0x03      //constant value1=0x03
353            MOVE       R1, value1        //R1 = value1
354
355  4:        .global     label            //declaration of label
356            MOVE        R1, label        //R1 = address_of(label) / 4
357            ...
358    label:  nop                          //definition of label
359
360
361**STL**/**ST** – Store data to the low 16 bits of 32-bits memory
362----------------------------------------------------------------
363
364**Syntax**
365  **ST**     *Rsrc, Rdst, offset, Label*
366  **STL**    *Rsrc, Rdst, offset, Label*
367
368**Operands**
369  - *Rsrc* – Register R[0..3], holds the 16-bit value to store
370  - *Rdst* – Register R[0..3], address of the destination, in 32-bit words
371  - *Offset* – 11-bit signed value, offset in bytes
372  - *Label* – 2-bit user defined unsigned value
373
374**Cycles**
375  4 cycles to execute, 4 cycles to fetch next instruction
376
377**Description**
378  The instruction stores the 16-bit value of Rsrc to the lower half-word of memory with address Rdst+offset::
379
380    Mem[Rdst + offset / 4]{15:0} = {Rsrc[15:0]}
381    Mem[Rdst + offset / 4]{15:0} = {Label[1:0],Rsrc[13:0]}
382
383  The ST command introduced to make compatibility with previous versions of UPL core.
384  The application can use higher 16 bits to determine which instruction in the ULP program has written any particular word into memory.
385
386**Examples**::
387
388  1:        STL  R1, R2, 0x12        //MEM[R2+0x12] = R1
389
390  2:        .data                   //Data section definition
391    Addr1:  .word     123           // Define label Addr1 16 bit
392            .set      offs, 0x00    // Define constant offs
393            .text                   //Text section definition
394            MOVE      R1, 1         // R1 = 1
395            MOVE      R2, Addr1     // R2 = Addr1
396            STL       R1, R2, offs  // MEM[R2 +  0] = R1
397                                    // MEM[Addr1 + 0] will be 32'hxxxx0001
398  3:
399            MOVE      R1, 1             // R1 = 1
400            STL       R1, R2, 0x12,1    // MEM[R2+0x12] 0xxxxx4001
401
402
403**STH** – Store data to the high 16 bits of 32-bits memory
404----------------------------------------------------------
405
406**Syntax**
407  **STH**     *Rsrc, Rdst, offset, Label*
408
409**Operands**
410  - *Rsrc* – Register R[0..3], holds the 16-bit value to store
411  - *Rdst* – Register R[0..3], address of the destination, in 32-bit words
412  - *Offset* – 11-bit signed value, offset in bytes
413  - *Label* – 2-bit user defined unsigned value
414
415**Cycles**
416  4 cycles to execute, 4 cycles to fetch next instruction
417
418**Description**
419  The instruction stores the 16-bit value of Rsrc to the high half-word of memory with address Rdst+offset::
420
421    Mem[Rdst + offset / 4]{31:16} = {Rsrc[15:0]}
422    Mem[Rdst + offset / 4]{31:16} = {Label[1:0],Rsrc[13:0]}
423
424**Examples**::
425
426  1:        STH  R1, R2, 0x12       //MEM[R2+0x12][31:16] = R1
427
428  2:        .data                   //Data section definition
429    Addr1:  .word     123           // Define label Addr1 16 bit
430            .set      offs, 0x00    // Define constant offs
431            .text                   //Text section definition
432            MOVE      R1, 1         // R1 = 1
433            MOVE      R2, Addr1     // R2 = Addr1
434            STH       R1, R2, offs  // MEM[R2 +  0] = R1
435                                    // MEM[Addr1 + 0] will be 32'h0001xxxx
436  3:
437            MOVE      R1, 1              // R1 = 1
438            STH       R1, R2, 0x12, 1    //MEM[R2+0x12] 0x4001xxxx
439
440
441**STO** – Set offset value for auto increment operation
442-------------------------------------------------------
443
444**Syntax**
445  **STO**     *offset*
446
447**Operands**
448  - *Offset* – 11-bit signed value, offset in bytes
449
450**Cycles**
451  4 cycles to execute, 4 cycles to fetch next instruction
452
453**Description**
454  The instruction set 16-bit value to the offset register::
455
456    offset = value/ 4
457
458**Examples**::
459
460  1:        STO  0x12               // Offset = 0x12/4
461
462  2:        .data                   //Data section definition
463    Addr1:  .word     123           // Define label Addr1 16 bit
464            .set      offs, 0x00    // Define constant offs
465            .text                   //Text section definition
466            STO       offs          // Offset = 0x00
467
468
469**STI** – Store data to the 32-bits memory with auto increment of predefined offset address
470-------------------------------------------------------------------------------------------
471
472**Syntax**
473  **STI**     *Rsrc, Rdst, Label*
474
475**Operands**
476  - *Rsrc* – Register R[0..3], holds the 16-bit value to store
477  - *Rdst* – Register R[0..3], address of the destination, in 32-bit words
478  - *Label* – 2-bit user defined unsigned value
479
480**Cycles**
481  4 cycles to execute, 4 cycles to fetch next instruction
482
483**Description**
484  The instruction stores the 16-bit value of Rsrc to the low and high half-word of memory with address Rdst+offset with
485  auto increment of offset::
486
487    Mem[Rdst + offset / 4]{15:0/31:16} = {Rsrc[15:0]}
488    Mem[Rdst + offset / 4]{15:0/31:16} = {Label[1:0],Rsrc[13:0]}
489
490**Examples**::
491
492  1:        STO  0                  // Set offset to 0
493            STI  R1, R2, 0x12       //MEM[R2+0x12][15:0] = R1
494            STI  R1, R2, 0x12       //MEM[R2+0x12][31:16] = R1
495
496  2:        .data                   //Data section definition
497    Addr1:  .word     123           // Define label Addr1 16 bit
498            .set      offs, 0x00    // Define constant offs
499            .text                   //Text section definition
500            STO       0             // Set offset to 0
501            MOVE      R1, 1         // R1 = 1
502            MOVE      R2, Addr1     // R2 = Addr1
503            STI       R1, R2        // MEM[R2 +  0] = R1
504                                    // MEM[Addr1 + 0] will be 32'hxxxx0001
505            STIx       R1, R2        // MEM[R2 +  0] = R1
506                                    // MEM[Addr1 + 0] will be 32'h00010001
507  3:
508            STO       0             // Set offset to 0
509            MOVE      R1, 1         // R1 = 1
510            STI       R1, R2, 1     //MEM[R2+0x12] 0xxxxx4001
511            STI       R1, R2, 1     //MEM[R2+0x12] 0x40014001
512
513
514**ST32** – Store 32-bits data to the 32-bits memory
515---------------------------------------------------
516
517**Syntax**
518  **ST32**     *Rsrc, Rdst, offset, Label*
519
520**Operands**
521  - *Rsrc* – Register R[0..3], holds the 16-bit value to store
522  - *Rdst* – Register R[0..3], address of the destination, in 32-bit words
523  - *Offset* – 11-bit signed value, offset in bytes
524  - *Label* – 2-bit user defined unsigned value
525
526**Cycles**
527  4 cycles to execute, 4 cycles to fetch next instruction
528
529**Description**
530  The instruction stores 11 bits of the PC value, label value and the 16-bit value of Rsrc to the 32-bits memory with address Rdst+offset::
531
532    Mem[Rdst + offset / 4]{31:0} = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]}
533
534**Examples**::
535
536  1:        ST32  R1, R2, 0x12, 0   //MEM[R2+0x12][31:0] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]}
537
538  2:        .data                   //Data section definition
539    Addr1:  .word     123           // Define label Addr1 16 bit
540            .set      offs, 0x00    // Define constant offs
541            .text                   //Text section definition
542            MOVE      R1, 1         // R1 = 1
543            MOVE      R2, Addr1     // R2 = Addr1
544            ST32      R1, R2, offs,1// MEM[R2 +  0] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]}
545                                    // MEM[Addr1 + 0] will be 32'h00010001
546
547
548**STI32** – Store 32-bits data to the 32-bits memory with auto increment of adress offset
549-----------------------------------------------------------------------------------------
550
551**Syntax**
552  **STI32**     *Rsrc, Rdst, Label*
553
554**Operands**
555  - *Rsrc* – Register R[0..3], holds the 16-bit value to store
556  - *Rdst* – Register R[0..3], address of the destination, in 32-bit words
557  - *Label* – 2-bit user defined unsigned value
558
559**Cycles**
560  4 cycles to execute, 4 cycles to fetch next instruction
561
562**Description**
563  The instruction stores 11 bits of the PC value, label value and the 16-bit value of Rsrc to the 32-bits memory with address Rdst+offset::
564
565    Mem[Rdst + offset / 4]{31:0} = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]}
566
567  Where offset value set by STO instruction
568
569**Examples**::
570
571  1:        STO    0x12
572            STI32  R1, R2, 0   //MEM[R2+0x12][31:0] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]}
573            STI32  R1, R2, 0   //MEM[R2+0x13][31:0] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]}
574
575  2:        .data                   //Data section definition
576    Addr1:  .word     123           // Define label Addr1 16 bit
577            .set      offs, 0x00    // Define constant offs
578            .text                   //Text section definition
579            MOVE      R1, 1         // R1 = 1
580            MOVE      R2, Addr1     // R2 = Addr1
581            STO       offs
582            STI32     R1, R2, 1// MEM[R2 +  0] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]}
583                                    // MEM[Addr1 + 0] will be 32'h00010001
584            ST32      R1, R2, 1// MEM[R2 +  1] = {PC[10:0],0[2:0],Label[1:0],Rsrc[15:0]}
585                                    // MEM[Addr1 + 1] will be 32'h00010001
586
587
588**LDL**/**LD** – Load data from low part of the 32-bits memory
589--------------------------------------------------------------
590
591**Syntax**
592   **LD**      *Rdst, Rsrc, offset*
593   **LDL**     *Rdst, Rsrc, offset*
594
595**Operands**
596   *Rdst*  – Register R[0..3], destination
597
598   *Rsrc* – Register R[0..3], holds address of destination, in 32-bit words
599
600   *Offset* – 13-bit signed value, offset in bytes
601
602**Cycles**
603  4 cycles to execute, 4 cycles to fetch next instruction
604
605**Description**
606   The instruction loads lower 16-bit half-word from memory with address Rsrc+offset into the destination register Rdst::
607
608     Rdst[15:0] = Mem[Rsrc + offset / 4][15:0]
609
610   The LD command do the same as LDL, and included for compatibility with previous versions of ULP core.
611
612**Examples**::
613
614  1:        LDL  R1, R2, 0x12            //R1 = MEM[R2+0x12]
615
616  2:        .data                       //Data section definition
617    Addr1:  .word     123               // Define label Addr1 16 bit
618            .set      offs, 0x00        // Define constant offs
619            .text                       //Text section definition
620            MOVE      R1, 1             // R1 = 1
621            MOVE      R2, Addr1         // R2 = Addr1 / 4 (address of label is converted into words)
622            LDL       R1, R2, offs      // R1 = MEM[R2 +  0]
623                                        // R1 will be 123
624
625
626**LDH** – Load data from high part of the 32-bits memory
627--------------------------------------------------------
628
629**Syntax**
630   **LDH**     *Rdst, Rsrc, offset*
631
632**Operands**
633   *Rdst*  – Register R[0..3], destination
634
635   *Rsrc* – Register R[0..3], holds address of destination, in 32-bit words
636
637   *Offset* – 13-bit signed value, offset in bytes
638
639**Cycles**
640  4 cycles to execute, 4 cycles to fetch next instruction
641
642**Description**
643   The instruction loads higher 16-bit half-word from memory with address Rsrc+offset into the destination register Rdst::
644
645     Rdst[15:0] = Mem[Rsrc + offset / 4][15:0]
646
647   The LD command do the same as LDL, and included for compatibility with previous versions of ULP core.
648
649**Examples**::
650
651  1:        LDH  R1, R2, 0x12            //R1 = MEM[R2+0x12]
652
653  2:        .data                       //Data section definition
654    Addr1:  .word     0x12345678               // Define label Addr1 16 bit
655            .set      offs, 0x00        // Define constant offs
656            .text                       //Text section definition
657            MOVE      R1, 1             // R1 = 1
658            MOVE      R2, Addr1         // R2 = Addr1 / 4 (address of label is converted into words)
659            LDH       R1, R2, offs      // R1 = MEM[R2 +  0]
660                                        // R1 will be 0x1234
661
662
663**JUMP** – Jump to an absolute address
664--------------------------------------
665
666**Syntax**
667  **JUMP**        *Rdst*
668
669  **JUMP**        *ImmAddr*
670
671  **JUMP**        *Rdst, Condition*
672
673  **JUMP**        *ImmAddr, Condition*
674
675
676**Operands**
677  - *Rdst* – Register R[0..3] containing address to jump to (expressed in 32-bit words)
678
679  - *ImmAddr* – 13 bits address (expressed in bytes), aligned to 4 bytes
680
681  - *Condition*:
682     - EQ – jump if last ALU operation result was zero
683     - OV – jump if last ALU has set overflow flag
684
685**Cycles**
686  2 cycles to execute, 2 cycles to fetch next instruction
687
688**Description**
689  The instruction makes jump to the specified address. Jump can be either unconditional or based on an ALU flag.
690
691**Examples**::
692
693  1:        JUMP       R1            // Jump to address in R1 (address in R1 is in 32-bit words)
694
695  2:        JUMP       0x120, EQ     // Jump to address 0x120 (in bytes) if ALU result is zero
696
697  3:        JUMP       label         // Jump to label
698            ...
699    label:  nop                      // Definition of label
700
701  4:        .global    label         // Declaration of global label
702
703            MOVE       R1, label     // R1 = label (value loaded into R1 is in words)
704            JUMP       R1            // Jump to label
705            ...
706    label:  nop                      // Definition of label
707
708
709
710**JUMPR** – Jump to a relative offset (condition based on R0)
711-------------------------------------------------------------
712
713**Syntax**
714   **JUMPR**        *Step, Threshold, Condition*
715
716**Operands**
717   - *Step*          – relative shift from current position, in bytes
718   - *Threshold*     – threshold value for branch condition
719   - *Condition*:
720      - *EQ* (equal) – jump if value in R0 == threshold
721      - *LT* (less than) – jump if value in R0 < threshold
722      - *LE* (less or equal) – jump if value in R0 <= threshold
723      - *GT* (greater than) – jump if value in R0 > threshold
724      - *GE* (greater or equal) – jump if value in R0 >= threshold
725
726**Cycles**
727  Conditions *EQ*, *GT* and *LT*: 2 cycles to execute, 2 cycles to fetch next instruction
728
729  Conditions *LE* and *GE* are implemented in the assembler using two **JUMPR** instructions::
730
731    // JUMPR target, threshold, LE is implemented as:
732
733             JUMPR target, threshold, EQ
734             JUMPR target, threshold, LT
735
736    // JUMPR target, threshold, GE is implemented as:
737
738             JUMPR target, threshold, EQ
739             JUMPR target, threshold, GT
740
741  Therefore the execution time will depend on the branches taken: either 2 cycles to execute + 2 cycles to fetch, or 4 cycles to execute + 4 cycles to fetch.
742
743**Description**
744   The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of R0 register value and the threshold value.
745
746**Examples**::
747
748  1:pos:    JUMPR       16, 20, GE   // Jump to address (position + 16 bytes) if value in R0 >= 20
749
750  2:        // Down counting loop using R0 register
751            MOVE        R0, 16       // load 16 into R0
752    label:  SUB         R0, R0, 1    // R0--
753            NOP                      // do something
754            JUMPR       label, 1, GE // jump to label if R0 >= 1
755
756
757
758**JUMPS** – Jump to a relative address (condition based on stage count)
759-----------------------------------------------------------------------
760
761**Syntax**
762   **JUMPS**        *Step, Threshold, Condition*
763
764**Operands**
765   - *Step*       – relative shift from current position, in bytes
766   - *Threshold*  – threshold value for branch condition
767   - *Condition*:
768       - *EQ* (equal) – jump if value in stage_cnt == threshold
769       - *LT* (less than) –  jump if value in stage_cnt < threshold
770       - *LE* (less or equal) - jump if value in stage_cnt <= threshold
771       - *GT* (greater than) –  jump if value in stage_cnt > threshold
772       - *GE* (greater or equal) — jump if value in stage_cnt >= threshold
773
774**Cycles**
775  2 cycles to execute, 2 cycles to fetch next instruction::
776
777    // JUMPS target, threshold, EQ is implemented as:
778
779             JUMPS next, threshold, LT
780             JUMPS target, threshold, LE
781    next:
782
783    // JUMPS target, threshold, GT is implemented as:
784
785             JUMPS next, threshold, LE
786             JUMPS target, threshold, GE
787    next:
788
789  Therefore the execution time will depend on the branches taken: either 2 cycles to execute + 2 cycles to fetch, or 4 cycles to execute + 4 cycles to fetch.
790
791
792**Description**
793    The instruction makes a jump to a relative address if condition is true. Condition is the result of comparison of count register value and threshold value.
794
795**Examples**::
796
797   1:pos:    JUMPS     16, 20, EQ     // Jump to (position + 16 bytes) if stage_cnt == 20
798
799   2:        // Up counting loop using stage count register
800             STAGE_RST                  // set stage_cnt to 0
801     label:  STAGE_INC  1               // stage_cnt++
802             NOP                        // do something
803             JUMPS       label, 16, LT  // jump to label if stage_cnt < 16
804
805
806
807**STAGE_RST** – Reset stage count register
808------------------------------------------
809**Syntax**
810     **STAGE_RST**
811
812**Operands**
813   No operands
814
815**Description**
816   The instruction sets the stage count register to 0
817
818**Cycles**
819  2 cycles to execute, 4 cycles to fetch next instruction
820
821**Examples**::
822
823   1:       STAGE_RST      // Reset stage count register
824
825
826
827**STAGE_INC** – Increment stage count register
828----------------------------------------------
829
830**Syntax**
831  **STAGE_INC**      *Value*
832
833**Operands**
834   - *Value* – 8 bits value
835
836**Cycles**
837  2 cycles to execute, 4 cycles to fetch next instruction
838
839**Description**
840   The instruction increments stage count register by given value.
841
842**Examples**::
843
844  1:        STAGE_INC      10          // stage_cnt += 10
845
846  2:        // Up counting loop example:
847            STAGE_RST                  // set stage_cnt to 0
848    label:  STAGE_INC  1               // stage_cnt++
849            NOP                        // do something
850            JUMPS      label, 16, LT   // jump to label if stage_cnt < 16
851
852
853**STAGE_DEC** – Decrement stage count register
854----------------------------------------------
855
856**Syntax**
857  **STAGE_DEC**      *Value*
858
859**Operands**
860   - *Value* – 8 bits value
861
862**Cycles**
863  2 cycles to execute, 4 cycles to fetch next instruction
864
865**Description**
866   The instruction decrements stage count register by given value.
867
868**Examples**::
869
870  1:        STAGE_DEC      10        // stage_cnt -= 10;
871
872  2:        // Down counting loop exaple
873            STAGE_RST                // set stage_cnt to 0
874            STAGE_INC  16            // increment stage_cnt to 16
875    label:  STAGE_DEC  1             // stage_cnt--;
876            NOP                      // do something
877            JUMPS      label, 0, GT  // jump to label if stage_cnt > 0
878
879
880**HALT** – End the program
881--------------------------
882
883**Syntax**
884  **HALT**
885
886**Operands**
887  No operands
888
889**Cycles**
890  2 cycles to execute
891
892**Description**
893   The instruction halts the ULP coprocessor and restarts ULP wakeup timer, if it is enabled.
894
895**Examples**::
896
897  1:       HALT      // Halt the coprocessor
898
899
900
901**WAKE** – Wake up the chip
902---------------------------
903
904**Syntax**
905   **WAKE**
906
907**Operands**
908  No operands
909
910**Cycles**
911  2 cycles to execute, 4 cycles to fetch next instruction
912
913**Description**
914  The instruction sends an interrupt from ULP to RTC controller.
915
916  - If the SoC is in deep sleep mode, and ULP wakeup is enabled, this causes the SoC to wake up.
917
918  - If the SoC is not in deep sleep mode, and ULP interrupt bit (RTC_CNTL_ULP_CP_INT_ENA) is set in RTC_CNTL_INT_ENA_REG register, RTC interrupt will be triggered.
919
920  Note that before using WAKE instruction, ULP program may needs to wait until RTC controller is ready to wake up the main CPU. This is indicated using RTC_CNTL_RDY_FOR_WAKEUP bit of RTC_CNTL_LOW_POWER_ST_REG register. If WAKE instruction is executed while RTC_CNTL_RDY_FOR_WAKEUP is zero, it has no effect (wake up does not occur).
921
922**Examples**::
923
924  1: is_rdy_for_wakeup:                   // Read RTC_CNTL_RDY_FOR_WAKEUP bit
925            READ_RTC_FIELD(RTC_CNTL_LOW_POWER_ST_REG, RTC_CNTL_RDY_FOR_WAKEUP)
926            AND r0, r0, 1
927            JUMP is_rdy_for_wakeup, eq    // Retry until the bit is set
928            WAKE                          // Trigger wake up
929            REG_WR 0x006, 24, 24, 0       // Stop ULP timer (clear RTC_CNTL_ULP_CP_SLP_TIMER_EN)
930            HALT                          // Stop the ULP program
931            // After these instructions, SoC will wake up,
932            // and ULP will not run again until started by the main program.
933
934
935
936**WAIT** – wait some number of cycles
937-------------------------------------
938
939**Syntax**
940   **WAIT**   *Cycles*
941
942**Operands**
943   - *Cycles* – number of cycles for wait
944
945**Cycles**
946  2 + *Cycles* cycles to execute, 4 cycles to fetch next instruction
947
948**Description**
949   The instruction delays for given number of cycles.
950
951**Examples**::
952
953  1:        WAIT     10         // Do nothing for 10 cycles
954
955  2:        .set  wait_cnt, 10  // Set a constant
956            WAIT  wait_cnt      // wait for 10 cycles
957
958
959**TSENS** – do measurement with temperature sensor
960--------------------------------------------------
961
962**Syntax**
963   - **TSENS**   *Rdst, Wait_Delay*
964
965**Operands**
966  - *Rdst* – Destination Register R[0..3], result will be stored to this register
967  - *Wait_Delay* – number of cycles used to perform the measurement
968
969**Cycles**
970  2 + *Wait_Delay* + 3 * TSENS_CLK to execute, 4 cycles to fetch next instruction
971
972**Description**
973   The instruction performs measurement using TSENS and stores the result into a general purpose register.
974
975**Examples**::
976
977  1:        TSENS     R1, 1000     // Measure temperature sensor for 1000 cycles,
978                                   // and store result to R1
979
980
981**ADC** – do measurement with ADC
982---------------------------------
983
984**Syntax**
985  - **ADC**   *Rdst, Sar_sel, Mux*
986
987  - **ADC**   *Rdst, Sar_sel, Mux, 0* — deprecated form
988
989**Operands**
990  - *Rdst* – Destination Register R[0..3], result will be stored to this register
991  - *Sar_sel* – Select ADC: 0 = SARADC1, 1 = SARADC2
992  - *Mux*  -  selected PAD, SARADC Pad[Mux-1] is enabled. If the user passes Mux value 1, then ADC pad 0 gets used.
993
994**Cycles**
995  ``23 + max(1, SAR_AMP_WAIT1) + max(1, SAR_AMP_WAIT2) + max(1, SAR_AMP_WAIT3) + SARx_SAMPLE_CYCLE + SARx_SAMPLE_BIT`` cycles to execute, 4 cycles to fetch next instruction
996
997**Description**
998  The instruction makes measurements from ADC.
999
1000**Examples**::
1001
1002   1:        ADC      R1, 0, 1      // Measure value using ADC1 pad 2 and store result into R1
1003
1004
1005**REG_RD** – read from peripheral register
1006------------------------------------------
1007
1008**Syntax**
1009   **REG_RD**   *Addr, High, Low*
1010
1011**Operands**
1012  - *Addr* – Register address, in 32-bit words
1013  - *High* – Register end bit number
1014  - *Low* – Register start bit number
1015
1016**Cycles**
1017  4 cycles to execute, 4 cycles to fetch next instruction
1018
1019**Description**
1020  The instruction reads up to 16 bits from a peripheral register into a general purpose register: ``R0 = REG[Addr][High:Low]``.
1021
1022  This instruction can access registers in RTC_CNTL, RTC_IO, SENS, and RTC_I2C peripherals. Address of the the register, as seen from the ULP, can be calculated from the address of the same register on the PeriBUS1 as follows::
1023
1024    addr_ulp = (addr_peribus1 - DR_REG_RTCCNTL_BASE) / 4
1025
1026**Examples**::
1027
1028  1:        REG_RD      0x120, 7, 4     // load 4 bits: R0 = {12'b0, REG[0x120][7:4]}
1029
1030
1031**REG_WR** – write to peripheral register
1032-----------------------------------------
1033
1034**Syntax**
1035  **REG_WR**   *Addr, High, Low, Data*
1036
1037**Operands**
1038  - *Addr* – Register address, in 32-bit words.
1039  - *High* – Register end bit number
1040  - *Low* – Register start bit number
1041  - *Data* – Value to write, 8 bits
1042
1043**Cycles**
1044  8 cycles to execute, 4 cycles to fetch next instruction
1045
1046**Description**
1047  The instruction writes up to 8 bits from an immediate data value into a peripheral register: ``REG[Addr][High:Low] = data``.
1048
1049  This instruction can access registers in RTC_CNTL, RTC_IO, SENS, and RTC_I2C peripherals. Address of the the register, as seen from the ULP, can be calculated from the address of the same register on the PeriBUS1 as follows::
1050
1051    addr_ulp = (addr_peribus1 - DR_REG_RTCCNTL_BASE) / 4
1052
1053**Examples**::
1054
1055   1:        REG_WR      0x120, 7, 0, 0x10   // set 8 bits: REG[0x120][7:0] = 0x10
1056
1057
1058Convenience macros for peripheral registers access
1059--------------------------------------------------
1060
1061ULP source files are passed through C preprocessor before the assembler. This allows certain macros to be used to facilitate access to peripheral registers.
1062
1063Some existing macros are defined in ``soc/soc_ulp.h`` header file. These macros allow access to the fields of peripheral registers by their names.
1064Peripheral registers names which can be used with these macros are the ones defined in ``soc/rtc_cntl_reg.h``, ``soc/rtc_io_reg.h``, ``soc/sens_reg.h``, and ``soc/rtc_i2c_reg.h``.
1065
1066READ_RTC_REG(rtc_reg, low_bit, bit_width)
1067  Read up to 16 bits from rtc_reg[low_bit + bit_width - 1 : low_bit] into R0. For example::
1068
1069    #include "soc/soc_ulp.h"
1070    #include "soc/rtc_cntl_reg.h"
1071
1072    /* Read 16 lower bits of RTC_CNTL_TIME0_REG into R0 */
1073    READ_RTC_REG(RTC_CNTL_TIME0_REG, 0, 16)
1074
1075READ_RTC_FIELD(rtc_reg, field)
1076  Read from a field in rtc_reg into R0, up to 16 bits. For example::
1077
1078    #include "soc/soc_ulp.h"
1079    #include "soc/sens_reg.h"
1080
1081    /* Read 8-bit SENS_TSENS_OUT field of SENS_SAR_SLAVE_ADDR3_REG into R0 */
1082    READ_RTC_FIELD(SENS_SAR_SLAVE_ADDR3_REG, SENS_TSENS_OUT)
1083
1084WRITE_RTC_REG(rtc_reg, low_bit, bit_width, value)
1085  Write immediate value into rtc_reg[low_bit + bit_width - 1 : low_bit], bit_width <= 8. For example::
1086
1087    #include "soc/soc_ulp.h"
1088    #include "soc/rtc_io_reg.h"
1089
1090    /* Set BIT(2) of RTC_GPIO_OUT_DATA_W1TS field in RTC_GPIO_OUT_W1TS_REG */
1091    WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S + 2, 1, 1)
1092
1093WRITE_RTC_FIELD(rtc_reg, field, value)
1094  Write immediate value into a field in rtc_reg, up to 8 bits. For example::
1095
1096    #include "soc/soc_ulp.h"
1097    #include "soc/rtc_cntl_reg.h"
1098
1099    /* Set RTC_CNTL_ULP_CP_SLP_TIMER_EN field of RTC_CNTL_STATE0_REG to 0 */
1100    WRITE_RTC_FIELD(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN, 0)
1101