1 // Copyright 2016-2018 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma once
16 #include <stdint.h>
17 #include <stddef.h>
18 #include <stdlib.h>
19 #include "esp_err.h"
20 #include "soc/soc.h"
21 #include "ulp_common.h"
22 
23 #ifdef __cplusplus
24 extern "C" {
25 #endif
26 
27 #define ULP_FSM_PREPARE_SLEEP_CYCLES 2    /*!< Cycles spent by FSM preparing ULP for sleep */
28 #define ULP_FSM_WAKEUP_SLEEP_CYCLES  2    /*!< Cycles spent by FSM waking up ULP from sleep */
29 
30 /**
31  * @defgroup ulp_registers ULP coprocessor registers
32  * @{
33  */
34 
35 
36 #define R0 0    /*!< general purpose register 0 */
37 #define R1 1    /*!< general purpose register 1 */
38 #define R2 2    /*!< general purpose register 2 */
39 #define R3 3    /*!< general purpose register 3 */
40 /**@}*/
41 
42 /** @defgroup ulp_opcodes ULP coprocessor opcodes, sub opcodes, and various modifiers/flags
43  *
44  * These definitions are not intended to be used directly.
45  * They are used in definitions of instructions later on.
46  *
47  * @{
48  */
49 
50 #define OPCODE_WR_REG 1         /*!< Instruction: write peripheral register (RTC_CNTL/RTC_IO/SARADC) (not implemented yet) */
51 
52 #define OPCODE_RD_REG 2         /*!< Instruction: read peripheral register (RTC_CNTL/RTC_IO/SARADC) (not implemented yet) */
53 
54 #define RD_REG_PERIPH_RTC_CNTL 0    /*!< Identifier of RTC_CNTL peripheral for RD_REG and WR_REG instructions */
55 #define RD_REG_PERIPH_RTC_IO   1    /*!< Identifier of RTC_IO peripheral for RD_REG and WR_REG instructions */
56 #define RD_REG_PERIPH_SENS     2    /*!< Identifier of SARADC peripheral for RD_REG and WR_REG instructions */
57 #define RD_REG_PERIPH_RTC_I2C  3    /*!< Identifier of RTC_I2C peripheral for RD_REG and WR_REG instructions */
58 
59 #define OPCODE_I2C 3            /*!< Instruction: read/write I2C (not implemented yet) */
60 
61 #define OPCODE_DELAY 4          /*!< Instruction: delay (nop) for a given number of cycles */
62 
63 #define OPCODE_ADC 5            /*!< Instruction: SAR ADC measurement (not implemented yet) */
64 
65 #define OPCODE_ST 6             /*!< Instruction: store indirect to RTC memory */
66 #define SUB_OPCODE_ST 4         /*!< Store 32 bits, 16 MSBs contain PC, 16 LSBs contain value from source register */
67 
68 #define OPCODE_ALU 7            /*!< Arithmetic instructions */
69 #define SUB_OPCODE_ALU_REG 0    /*!< Arithmetic instruction, both source values are in register */
70 #define SUB_OPCODE_ALU_IMM 1    /*!< Arithmetic instruction, one source value is an immediate */
71 #define SUB_OPCODE_ALU_CNT 2    /*!< Arithmetic instruction between counter register and an immediate (not implemented yet)*/
72 #define ALU_SEL_ADD 0           /*!< Addition */
73 #define ALU_SEL_SUB 1           /*!< Subtraction */
74 #define ALU_SEL_AND 2           /*!< Logical AND */
75 #define ALU_SEL_OR  3           /*!< Logical OR */
76 #define ALU_SEL_MOV 4           /*!< Copy value (immediate to destination register or source register to destination register */
77 #define ALU_SEL_LSH 5           /*!< Shift left by given number of bits */
78 #define ALU_SEL_RSH 6           /*!< Shift right by given number of bits */
79 
80 #define OPCODE_BRANCH 8         /*!< Branch instructions */
81 #define SUB_OPCODE_BX  0        /*!< Branch to absolute PC (immediate or in register) */
82 #define BX_JUMP_TYPE_DIRECT 0   /*!< Unconditional jump */
83 #define BX_JUMP_TYPE_ZERO 1     /*!< Branch if last ALU result is zero */
84 #define BX_JUMP_TYPE_OVF 2      /*!< Branch if last ALU operation caused and overflow */
85 #define SUB_OPCODE_B  1         /*!< Branch to a relative offset */
86 #define B_CMP_L 0               /*!< Branch if R0 is less than an immediate */
87 #define B_CMP_GE 1              /*!< Branch if R0 is greater than or equal to an immediate */
88 
89 #define OPCODE_END 9            /*!< Stop executing the program */
90 #define SUB_OPCODE_END 0        /*!< Stop executing the program and optionally wake up the chip */
91 #define SUB_OPCODE_SLEEP 1      /*!< Stop executing the program and run it again after selected interval */
92 
93 #define OPCODE_TSENS 10         /*!< Instruction: temperature sensor measurement (not implemented yet) */
94 
95 #define OPCODE_HALT 11          /*!< Halt the coprocessor */
96 
97 #define OPCODE_LD 13            /*!< Indirect load lower 16 bits from RTC memory */
98 
99 #define OPCODE_MACRO 15         /*!< Not a real opcode. Used to identify labels and branches in the program */
100 #define SUB_OPCODE_MACRO_LABEL 0    /*!< Label macro */
101 #define SUB_OPCODE_MACRO_BRANCH 1   /*!< Branch macro */
102 /**@}*/
103 
104 /**
105  * @brief Instruction format structure
106  *
107  * All ULP instructions are 32 bit long.
108  * This union contains field layouts used by all of the supported instructions.
109  * This union also includes a special "macro" instruction layout.
110  * This is not a real instruction which can be executed by the CPU. It acts
111  * as a token which is removed from the program by the
112  * ulp_process_macros_and_load function.
113  *
114  * These structures are not intended to be used directly.
115  * Preprocessor definitions provided below fill the fields of these structure with
116  * the right arguments.
117  */
118 union ulp_insn {
119 
120     struct {
121         uint32_t cycles : 16;       /*!< Number of cycles to sleep */
122         uint32_t unused : 12;       /*!< Unused */
123         uint32_t opcode : 4;        /*!< Opcode (OPCODE_DELAY) */
124     } delay;                        /*!< Format of DELAY instruction */
125 
126     struct {
127         uint32_t dreg : 2;          /*!< Register which contains data to store */
128         uint32_t sreg : 2;          /*!< Register which contains address in RTC memory (expressed in words) */
129         uint32_t unused1 : 6;       /*!< Unused */
130         uint32_t offset : 11;       /*!< Offset to add to sreg */
131         uint32_t unused2 : 4;       /*!< Unused */
132         uint32_t sub_opcode : 3;    /*!< Sub opcode (SUB_OPCODE_ST) */
133         uint32_t opcode : 4;        /*!< Opcode (OPCODE_ST) */
134     } st;                           /*!< Format of ST instruction */
135 
136     struct {
137         uint32_t dreg : 2;          /*!< Register where the data should be loaded to */
138         uint32_t sreg : 2;          /*!< Register which contains address in RTC memory (expressed in words) */
139         uint32_t unused1 : 6;       /*!< Unused */
140         uint32_t offset : 11;       /*!< Offset to add to sreg */
141         uint32_t unused2 : 7;       /*!< Unused */
142         uint32_t opcode : 4;        /*!< Opcode (OPCODE_LD) */
143     } ld;                           /*!< Format of LD instruction */
144 
145     struct {
146         uint32_t unused : 28;       /*!< Unused */
147         uint32_t opcode : 4;        /*!< Opcode (OPCODE_HALT) */
148     } halt;                         /*!< Format of HALT instruction */
149 
150     struct {
151         uint32_t dreg : 2;          /*!< Register which contains target PC, expressed in words (used if .reg == 1) */
152         uint32_t addr : 11;         /*!< Target PC, expressed in words (used if .reg == 0) */
153         uint32_t unused : 8;        /*!< Unused */
154         uint32_t reg : 1;           /*!< Target PC in register (1) or immediate (0) */
155         uint32_t type : 3;          /*!< Jump condition (BX_JUMP_TYPE_xxx) */
156         uint32_t sub_opcode : 3;    /*!< Sub opcode (SUB_OPCODE_BX) */
157         uint32_t opcode : 4;        /*!< Opcode (OPCODE_BRANCH) */
158     } bx;                           /*!< Format of BRANCH instruction (absolute address) */
159 
160     struct {
161         uint32_t imm : 16;          /*!< Immediate value to compare against */
162         uint32_t cmp : 1;           /*!< Comparison to perform: B_CMP_L or B_CMP_GE */
163         uint32_t offset : 7;        /*!< Absolute value of target PC offset w.r.t. current PC, expressed in words */
164         uint32_t sign : 1;          /*!< Sign of target PC offset: 0: positive, 1: negative */
165         uint32_t sub_opcode : 3;    /*!< Sub opcode (SUB_OPCODE_B) */
166         uint32_t opcode : 4;        /*!< Opcode (OPCODE_BRANCH) */
167     } b;                            /*!< Format of BRANCH instruction (relative address) */
168 
169     struct {
170         uint32_t dreg : 2;          /*!< Destination register */
171         uint32_t sreg : 2;          /*!< Register with operand A */
172         uint32_t treg : 2;          /*!< Register with operand B */
173         uint32_t unused : 15;       /*!< Unused */
174         uint32_t sel : 4;           /*!< Operation to perform, one of ALU_SEL_xxx */
175         uint32_t sub_opcode : 3;    /*!< Sub opcode (SUB_OPCODE_ALU_REG) */
176         uint32_t opcode : 4;        /*!< Opcode (OPCODE_ALU) */
177     } alu_reg;                      /*!< Format of ALU instruction (both sources are registers) */
178 
179     struct {
180         uint32_t dreg : 2;          /*!< Destination register */
181         uint32_t sreg : 2;          /*!< Register with operand A */
182         uint32_t imm : 16;          /*!< Immediate value of operand B */
183         uint32_t unused : 1;        /*!< Unused */
184         uint32_t sel : 4;           /*!< Operation to perform, one of ALU_SEL_xxx */
185         uint32_t sub_opcode : 3;    /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */
186         uint32_t opcode : 4;        /*!< Opcode (OPCODE_ALU) */
187     } alu_imm;                      /*!< Format of ALU instruction (one source is an immediate) */
188 
189     struct {
190         uint32_t addr : 8;          /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */
191         uint32_t periph_sel : 2;    /*!< Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) */
192         uint32_t data : 8;          /*!< 8 bits of data to write */
193         uint32_t low : 5;           /*!< Low bit */
194         uint32_t high : 5;          /*!< High bit */
195         uint32_t opcode : 4;        /*!< Opcode (OPCODE_WR_REG) */
196     } wr_reg;                       /*!< Format of WR_REG instruction */
197 
198     struct {
199         uint32_t addr : 8;          /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */
200         uint32_t periph_sel : 2;    /*!< Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) */
201         uint32_t unused : 8;        /*!< Unused */
202         uint32_t low : 5;           /*!< Low bit */
203         uint32_t high : 5;          /*!< High bit */
204         uint32_t opcode : 4;        /*!< Opcode (OPCODE_WR_REG) */
205     } rd_reg;                       /*!< Format of RD_REG instruction */
206 
207     struct {
208         uint32_t dreg : 2;          /*!< Register where to store ADC result */
209         uint32_t mux : 4;           /*!< Select SARADC pad (mux + 1) */
210         uint32_t sar_sel : 1;       /*!< Select SARADC0 (0) or SARADC1 (1) */
211         uint32_t unused1 : 1;       /*!< Unused */
212         uint32_t cycles : 16;       /*!< TBD, cycles used for measurement */
213         uint32_t unused2 : 4;       /*!< Unused */
214         uint32_t opcode: 4;         /*!< Opcode (OPCODE_ADC) */
215     } adc;                          /*!< Format of ADC instruction */
216 
217     struct {
218         uint32_t dreg : 2;          /*!< Register where to store temperature measurement result */
219         uint32_t wait_delay: 14;    /*!< Cycles to wait after measurement is done */
220         uint32_t reserved: 12;      /*!< Reserved, set to 0 */
221         uint32_t opcode: 4;         /*!< Opcode (OPCODE_TSENS) */
222     } tsens;                        /*!< Format of TSENS instruction */
223 
224     struct {
225         uint32_t i2c_addr : 8;      /*!< I2C slave address */
226         uint32_t data : 8;          /*!< Data to read or write */
227         uint32_t low_bits : 3;      /*!< TBD */
228         uint32_t high_bits : 3;     /*!< TBD */
229         uint32_t i2c_sel : 4;       /*!< TBD, select reg_i2c_slave_address[7:0] */
230         uint32_t unused : 1;        /*!< Unused */
231         uint32_t rw : 1;            /*!< Write (1) or read (0) */
232         uint32_t opcode : 4;        /*!< Opcode (OPCODE_I2C) */
233     } i2c;                          /*!< Format of I2C instruction */
234 
235     struct {
236         uint32_t wakeup : 1;        /*!< Set to 1 to wake up chip */
237         uint32_t unused : 24;       /*!< Unused */
238         uint32_t sub_opcode : 3;    /*!< Sub opcode (SUB_OPCODE_WAKEUP) */
239         uint32_t opcode : 4;        /*!< Opcode (OPCODE_END) */
240     } end;                          /*!< Format of END instruction with wakeup */
241 
242     struct {
243         uint32_t cycle_sel : 4;     /*!< Select which one of SARADC_ULP_CP_SLEEP_CYCx_REG to get the sleep duration from */
244         uint32_t unused : 21;       /*!< Unused */
245         uint32_t sub_opcode : 3;    /*!< Sub opcode (SUB_OPCODE_SLEEP) */
246         uint32_t opcode : 4;        /*!< Opcode (OPCODE_END) */
247     } sleep;                        /*!< Format of END instruction with sleep */
248 
249     struct {
250         uint32_t label : 16;        /*!< Label number */
251         uint32_t unused : 8;        /*!< Unused */
252         uint32_t sub_opcode : 4;    /*!< SUB_OPCODE_MACRO_LABEL or SUB_OPCODE_MACRO_BRANCH */
253         uint32_t opcode: 4;         /*!< Opcode (OPCODE_MACRO) */
254     } macro;                        /*!< Format of tokens used by LABEL and BRANCH macros */
255 
256 };
257 
258 typedef union ulp_insn ulp_insn_t;
259 
260 _Static_assert(sizeof(ulp_insn_t) == 4, "ULP coprocessor instruction size should be 4 bytes");
261 
262 /**
263  * Delay (nop) for a given number of cycles
264  */
265 #define I_DELAY(cycles_) { .delay = {\
266     .cycles = cycles_, \
267     .unused = 0, \
268     .opcode = OPCODE_DELAY } }
269 
270 /**
271  * Halt the coprocessor.
272  *
273  * This instruction halts the coprocessor, but keeps ULP timer active.
274  * As such, ULP program will be restarted again by timer.
275  * To stop the program and prevent the timer from restarting the program,
276  * use I_END(0) instruction.
277  */
278 #define I_HALT() { .halt = {\
279     .unused = 0, \
280     .opcode = OPCODE_HALT } }
281 
282 /**
283  * Map SoC peripheral register to periph_sel field of RD_REG and WR_REG
284  * instructions.
285  *
286  * @param reg peripheral register in RTC_CNTL_, RTC_IO_, SENS_, RTC_I2C peripherals.
287  * @return periph_sel value for the peripheral to which this register belongs.
288  */
SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg)289 static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg)
290 {
291     uint32_t ret = 3;
292     if (reg < DR_REG_RTCCNTL_BASE) {
293         assert(0 && "invalid register base");
294     } else if (reg < DR_REG_RTCIO_BASE) {
295         ret = RD_REG_PERIPH_RTC_CNTL;
296     } else if (reg < DR_REG_SENS_BASE) {
297         ret = RD_REG_PERIPH_RTC_IO;
298     } else if (reg < DR_REG_RTC_I2C_BASE) {
299         ret = RD_REG_PERIPH_SENS;
300     } else if (reg < DR_REG_IO_MUX_BASE) {
301         ret = RD_REG_PERIPH_RTC_I2C;
302     } else {
303         assert(0 && "invalid register base");
304     }
305     return ret;
306 }
307 
308 /**
309  * Write literal value to a peripheral register
310  *
311  * reg[high_bit : low_bit] = val
312  * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
313  */
314 #define I_WR_REG(reg, low_bit, high_bit, val) {.wr_reg = {\
315     .addr = (reg & 0xff) / sizeof(uint32_t), \
316     .periph_sel = SOC_REG_TO_ULP_PERIPH_SEL(reg), \
317     .data = val, \
318     .low = low_bit, \
319     .high = high_bit, \
320     .opcode = OPCODE_WR_REG } }
321 
322 /**
323  * Read from peripheral register into R0
324  *
325  * R0 = reg[high_bit : low_bit]
326  * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
327  */
328 #define I_RD_REG(reg, low_bit, high_bit) {.rd_reg = {\
329     .addr = (reg & 0xff) / sizeof(uint32_t), \
330     .periph_sel = SOC_REG_TO_ULP_PERIPH_SEL(reg), \
331     .unused = 0, \
332     .low = low_bit, \
333     .high = high_bit, \
334     .opcode = OPCODE_RD_REG } }
335 
336 /**
337  * Set or clear a bit in the peripheral register.
338  *
339  * Sets bit (1 << shift) of register reg to value val.
340  * This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
341  */
342 #define I_WR_REG_BIT(reg, shift, val) I_WR_REG(reg, shift, shift, val)
343 
344 /**
345  * Wake the SoC from deep sleep.
346  *
347  * This instruction initiates wake up from deep sleep.
348  * Use esp_deep_sleep_enable_ulp_wakeup to enable deep sleep wakeup
349  * triggered by the ULP before going into deep sleep.
350  * Note that ULP program will still keep running until the I_HALT
351  * instruction, and it will still be restarted by timer at regular
352  * intervals, even when the SoC is woken up.
353  *
354  * To stop the ULP program, use I_HALT instruction.
355  *
356  * To disable the timer which start ULP program, use I_END()
357  * instruction. I_END instruction clears the
358  * RTC_CNTL_ULP_CP_SLP_TIMER_EN_S bit of RTC_CNTL_STATE0_REG
359  * register, which controls the ULP timer.
360  */
361 #define I_WAKE() { .end = { \
362         .wakeup = 1, \
363         .unused = 0, \
364         .sub_opcode = SUB_OPCODE_END, \
365         .opcode = OPCODE_END } }
366 
367 /**
368  * Stop ULP program timer.
369  *
370  * This is a convenience macro which disables the ULP program timer.
371  * Once this instruction is used, ULP program will not be restarted
372  * anymore until ulp_run function is called.
373  *
374  * ULP program will continue running after this instruction. To stop
375  * the currently running program, use I_HALT().
376  */
377 #define I_END() \
378     I_WR_REG_BIT(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN_S, 0)
379 /**
380  * Select the time interval used to run ULP program.
381  *
382  * This instructions selects which of the SENS_SLEEP_CYCLES_Sx
383  * registers' value is used by the ULP program timer.
384  * When the ULP program stops at I_HALT instruction, ULP program
385  * timer start counting. When the counter reaches the value of
386  * the selected SENS_SLEEP_CYCLES_Sx register, ULP program
387  * start running again from the start address (passed to the ulp_run
388  * function).
389  * There are 5 SENS_SLEEP_CYCLES_Sx registers, so 0 <= timer_idx < 5.
390  *
391  * By default, SENS_SLEEP_CYCLES_S0 register is used by the ULP
392  * program timer.
393  */
394 #define I_SLEEP_CYCLE_SEL(timer_idx) { .sleep = { \
395         .cycle_sel = timer_idx, \
396         .unused = 0, \
397         .sub_opcode = SUB_OPCODE_SLEEP, \
398         .opcode = OPCODE_END } }
399 
400 /**
401  * Perform temperature sensor measurement and store it into reg_dest.
402  *
403  * Delay can be set between 1 and ((1 << 14) - 1). Higher values give
404  * higher measurement resolution.
405  */
406 #define I_TSENS(reg_dest, delay) { .tsens = { \
407         .dreg = reg_dest, \
408         .wait_delay = delay, \
409         .reserved = 0, \
410         .opcode = OPCODE_TSENS } }
411 
412 /**
413  * Perform ADC measurement and store result in reg_dest.
414  *
415  * adc_idx selects ADC (0 or 1).
416  * pad_idx selects ADC pad (0 - 7).
417  */
418 #define I_ADC(reg_dest, adc_idx, pad_idx) { .adc = {\
419         .dreg = reg_dest, \
420         .mux = pad_idx + 1, \
421         .sar_sel = adc_idx, \
422         .unused1 = 0, \
423         .cycles = 0, \
424         .unused2 = 0, \
425         .opcode = OPCODE_ADC } }
426 
427 /**
428  * Store value from register reg_val into RTC memory.
429  *
430  * The value is written to an offset calculated by adding value of
431  * reg_addr register and offset_ field (this offset is expressed in 32-bit words).
432  * 32 bits written to RTC memory are built as follows:
433  * - bits [31:21] hold the PC of current instruction, expressed in 32-bit words
434  * - bits [20:16] = 5'b1
435  * - bits [15:0] are assigned the contents of reg_val
436  *
437  * RTC_SLOW_MEM[addr + offset_] = { 5'b0, insn_PC[10:0], val[15:0] }
438  */
439 #define I_ST(reg_val, reg_addr, offset_) { .st = { \
440     .dreg = reg_val, \
441     .sreg = reg_addr, \
442     .unused1 = 0, \
443     .offset = offset_, \
444     .unused2 = 0, \
445     .sub_opcode = SUB_OPCODE_ST, \
446     .opcode = OPCODE_ST } }
447 
448 
449 /**
450  * Load value from RTC memory into reg_dest register.
451  *
452  * Loads 16 LSBs from RTC memory word given by the sum of value in reg_addr and
453  * value of offset_.
454  */
455 #define I_LD(reg_dest, reg_addr, offset_) { .ld = { \
456     .dreg = reg_dest, \
457     .sreg = reg_addr, \
458     .unused1 = 0, \
459     .offset = offset_, \
460     .unused2 = 0, \
461     .opcode = OPCODE_LD } }
462 
463 
464 /**
465  *  Branch relative if R0 less than immediate value.
466  *
467  *  pc_offset is expressed in words, and can be from -127 to 127
468  *  imm_value is a 16-bit value to compare R0 against
469  */
470 #define I_BL(pc_offset, imm_value) { .b = { \
471     .imm = imm_value, \
472     .cmp = B_CMP_L, \
473     .offset = abs(pc_offset), \
474     .sign = (pc_offset >= 0) ? 0 : 1, \
475     .sub_opcode = SUB_OPCODE_B, \
476     .opcode = OPCODE_BRANCH } }
477 
478 /**
479  *  Branch relative if R0 greater or equal than immediate value.
480  *
481  *  pc_offset is expressed in words, and can be from -127 to 127
482  *  imm_value is a 16-bit value to compare R0 against
483  */
484 #define I_BGE(pc_offset, imm_value) { .b = { \
485     .imm = imm_value, \
486     .cmp = B_CMP_GE, \
487     .offset = abs(pc_offset), \
488     .sign = (pc_offset >= 0) ? 0 : 1, \
489     .sub_opcode = SUB_OPCODE_B, \
490     .opcode = OPCODE_BRANCH } }
491 
492 /**
493  * Unconditional branch to absolute PC, address in register.
494  *
495  * reg_pc is the register which contains address to jump to.
496  * Address is expressed in 32-bit words.
497  */
498 #define I_BXR(reg_pc) { .bx = { \
499     .dreg = reg_pc, \
500     .addr = 0, \
501     .unused = 0, \
502     .reg = 1, \
503     .type = BX_JUMP_TYPE_DIRECT, \
504     .sub_opcode = SUB_OPCODE_BX, \
505     .opcode = OPCODE_BRANCH } }
506 
507 /**
508  *  Unconditional branch to absolute PC, immediate address.
509  *
510  *  Address imm_pc is expressed in 32-bit words.
511  */
512 #define I_BXI(imm_pc) { .bx = { \
513     .dreg = 0, \
514     .addr = imm_pc, \
515     .unused = 0, \
516     .reg = 0, \
517     .type = BX_JUMP_TYPE_DIRECT, \
518     .sub_opcode = SUB_OPCODE_BX, \
519     .opcode = OPCODE_BRANCH } }
520 
521 /**
522  * Branch to absolute PC if ALU result is zero, address in register.
523  *
524  * reg_pc is the register which contains address to jump to.
525  * Address is expressed in 32-bit words.
526  */
527 #define I_BXZR(reg_pc) { .bx = { \
528     .dreg = reg_pc, \
529     .addr = 0, \
530     .unused = 0, \
531     .reg = 1, \
532     .type = BX_JUMP_TYPE_ZERO, \
533     .sub_opcode = SUB_OPCODE_BX, \
534     .opcode = OPCODE_BRANCH } }
535 
536 /**
537  * Branch to absolute PC if ALU result is zero, immediate address.
538  *
539  * Address imm_pc is expressed in 32-bit words.
540  */
541 #define I_BXZI(imm_pc) { .bx = { \
542     .dreg = 0, \
543     .addr = imm_pc, \
544     .unused = 0, \
545     .reg = 0, \
546     .type = BX_JUMP_TYPE_ZERO, \
547     .sub_opcode = SUB_OPCODE_BX, \
548     .opcode = OPCODE_BRANCH } }
549 
550 /**
551  * Branch to absolute PC if ALU overflow, address in register
552  *
553  * reg_pc is the register which contains address to jump to.
554  * Address is expressed in 32-bit words.
555  */
556 #define I_BXFR(reg_pc) { .bx = { \
557     .dreg = reg_pc, \
558     .addr = 0, \
559     .unused = 0, \
560     .reg = 1, \
561     .type = BX_JUMP_TYPE_OVF, \
562     .sub_opcode = SUB_OPCODE_BX, \
563     .opcode = OPCODE_BRANCH } }
564 
565 /**
566  * Branch to absolute PC if ALU overflow, immediate address
567  *
568  * Address imm_pc is expressed in 32-bit words.
569  */
570 #define I_BXFI(imm_pc) { .bx = { \
571     .dreg = 0, \
572     .addr = imm_pc, \
573     .unused = 0, \
574     .reg = 0, \
575     .type = BX_JUMP_TYPE_OVF, \
576     .sub_opcode = SUB_OPCODE_BX, \
577     .opcode = OPCODE_BRANCH } }
578 
579 
580 /**
581  * Addition: dest = src1 + src2
582  */
583 #define I_ADDR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
584     .dreg = reg_dest, \
585     .sreg = reg_src1, \
586     .treg = reg_src2, \
587     .unused = 0, \
588     .sel = ALU_SEL_ADD, \
589     .sub_opcode = SUB_OPCODE_ALU_REG, \
590     .opcode = OPCODE_ALU } }
591 
592 /**
593  * Subtraction: dest = src1 - src2
594  */
595 #define I_SUBR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
596     .dreg = reg_dest, \
597     .sreg = reg_src1, \
598     .treg = reg_src2, \
599     .unused = 0, \
600     .sel = ALU_SEL_SUB, \
601     .sub_opcode = SUB_OPCODE_ALU_REG, \
602     .opcode = OPCODE_ALU } }
603 
604 /**
605  * Logical AND: dest = src1 & src2
606  */
607 #define I_ANDR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
608     .dreg = reg_dest, \
609     .sreg = reg_src1, \
610     .treg = reg_src2, \
611     .unused = 0, \
612     .sel = ALU_SEL_AND, \
613     .sub_opcode = SUB_OPCODE_ALU_REG, \
614     .opcode = OPCODE_ALU } }
615 
616 /**
617  * Logical OR: dest = src1 | src2
618  */
619 #define I_ORR(reg_dest, reg_src1, reg_src2)  { .alu_reg = { \
620     .dreg = reg_dest, \
621     .sreg = reg_src1, \
622     .treg = reg_src2, \
623     .unused = 0, \
624     .sel = ALU_SEL_OR, \
625     .sub_opcode = SUB_OPCODE_ALU_REG, \
626     .opcode = OPCODE_ALU } }
627 
628 /**
629  * Copy: dest = src
630  */
631 #define I_MOVR(reg_dest, reg_src) { .alu_reg = { \
632     .dreg = reg_dest, \
633     .sreg = reg_src, \
634     .treg = 0, \
635     .unused = 0, \
636     .sel = ALU_SEL_MOV, \
637     .sub_opcode = SUB_OPCODE_ALU_REG, \
638     .opcode = OPCODE_ALU } }
639 
640 /**
641  * Logical shift left: dest = src << shift
642  */
643 #define I_LSHR(reg_dest, reg_src, reg_shift)  { .alu_reg = { \
644     .dreg = reg_dest, \
645     .sreg = reg_src, \
646     .treg = reg_shift, \
647     .unused = 0, \
648     .sel = ALU_SEL_LSH, \
649     .sub_opcode = SUB_OPCODE_ALU_REG, \
650     .opcode = OPCODE_ALU } }
651 
652 
653 /**
654  * Logical shift right: dest = src >> shift
655  */
656 #define I_RSHR(reg_dest, reg_src, reg_shift)  { .alu_reg = { \
657     .dreg = reg_dest, \
658     .sreg = reg_src, \
659     .treg = reg_shift, \
660     .unused = 0, \
661     .sel = ALU_SEL_RSH, \
662     .sub_opcode = SUB_OPCODE_ALU_REG, \
663     .opcode = OPCODE_ALU } }
664 
665 /**
666  * Add register and an immediate value: dest = src1 + imm
667  */
668 #define I_ADDI(reg_dest, reg_src, imm_) { .alu_imm = { \
669     .dreg = reg_dest, \
670     .sreg = reg_src, \
671     .imm = imm_, \
672     .unused = 0, \
673     .sel = ALU_SEL_ADD, \
674     .sub_opcode = SUB_OPCODE_ALU_IMM, \
675     .opcode = OPCODE_ALU } }
676 
677 
678 /**
679  *  Subtract register and an immediate value: dest = src - imm
680  */
681 #define I_SUBI(reg_dest, reg_src, imm_) { .alu_imm = { \
682     .dreg = reg_dest, \
683     .sreg = reg_src, \
684     .imm = imm_, \
685     .unused = 0, \
686     .sel = ALU_SEL_SUB, \
687     .sub_opcode = SUB_OPCODE_ALU_IMM, \
688     .opcode = OPCODE_ALU } }
689 
690 /**
691  * Logical AND register and an immediate value: dest = src & imm
692  */
693 #define I_ANDI(reg_dest, reg_src, imm_) { .alu_imm = { \
694     .dreg = reg_dest, \
695     .sreg = reg_src, \
696     .imm = imm_, \
697     .unused = 0, \
698     .sel = ALU_SEL_AND, \
699     .sub_opcode = SUB_OPCODE_ALU_IMM, \
700     .opcode = OPCODE_ALU } }
701 
702 /**
703  * Logical OR register and an immediate value: dest = src | imm
704  */
705 #define I_ORI(reg_dest, reg_src, imm_) { .alu_imm = { \
706     .dreg = reg_dest, \
707     .sreg = reg_src, \
708     .imm = imm_, \
709     .unused = 0, \
710     .sel = ALU_SEL_OR, \
711     .sub_opcode = SUB_OPCODE_ALU_IMM, \
712     .opcode = OPCODE_ALU } }
713 
714 /**
715  * Copy an immediate value into register: dest = imm
716  */
717 #define I_MOVI(reg_dest, imm_) { .alu_imm = { \
718     .dreg = reg_dest, \
719     .sreg = 0, \
720     .imm = imm_, \
721     .unused = 0, \
722     .sel = ALU_SEL_MOV, \
723     .sub_opcode = SUB_OPCODE_ALU_IMM, \
724     .opcode = OPCODE_ALU } }
725 
726 /**
727  * Logical shift left register value by an immediate: dest = src << imm
728  */
729 #define I_LSHI(reg_dest, reg_src, imm_) { .alu_imm = { \
730     .dreg = reg_dest, \
731     .sreg = reg_src, \
732     .imm = imm_, \
733     .unused = 0, \
734     .sel = ALU_SEL_LSH, \
735     .sub_opcode = SUB_OPCODE_ALU_IMM, \
736     .opcode = OPCODE_ALU } }
737 
738 
739 /**
740  * Logical shift right register value by an immediate: dest = val >> imm
741  */
742 #define I_RSHI(reg_dest, reg_src, imm_) { .alu_imm = { \
743     .dreg = reg_dest, \
744     .sreg = reg_src, \
745     .imm = imm_, \
746     .unused = 0, \
747     .sel = ALU_SEL_RSH, \
748     .sub_opcode = SUB_OPCODE_ALU_IMM, \
749     .opcode = OPCODE_ALU } }
750 
751 /**
752  * Define a label with number label_num.
753  *
754  * This is a macro which doesn't generate a real instruction.
755  * The token generated by this macro is removed by ulp_process_macros_and_load
756  * function. Label defined using this macro can be used in branch macros defined
757  * below.
758  */
759 #define M_LABEL(label_num) { .macro = { \
760     .label = label_num, \
761     .unused = 0, \
762     .sub_opcode = SUB_OPCODE_MACRO_LABEL, \
763     .opcode = OPCODE_MACRO } }
764 
765 /**
766  * Token macro used by M_B and M_BX macros. Not to be used directly.
767  */
768 #define M_BRANCH(label_num) { .macro = { \
769     .label = label_num, \
770     .unused = 0, \
771     .sub_opcode = SUB_OPCODE_MACRO_BRANCH, \
772     .opcode = OPCODE_MACRO } }
773 
774 /**
775  * Macro: branch to label label_num if R0 is less than immediate value.
776  *
777  * This macro generates two ulp_insn_t values separated by a comma, and should
778  * be used when defining contents of ulp_insn_t arrays. First value is not a
779  * real instruction; it is a token which is removed by ulp_process_macros_and_load
780  * function.
781  */
782 #define M_BL(label_num, imm_value) \
783     M_BRANCH(label_num), \
784     I_BL(0, imm_value)
785 
786 /**
787  * Macro: branch to label label_num if R0 is greater or equal than immediate value
788  *
789  * This macro generates two ulp_insn_t values separated by a comma, and should
790  * be used when defining contents of ulp_insn_t arrays. First value is not a
791  * real instruction; it is a token which is removed by ulp_process_macros_and_load
792  * function.
793  */
794 #define M_BGE(label_num, imm_value) \
795     M_BRANCH(label_num), \
796     I_BGE(0, imm_value)
797 
798 /**
799  * Macro: unconditional branch to label
800  *
801  * This macro generates two ulp_insn_t values separated by a comma, and should
802  * be used when defining contents of ulp_insn_t arrays. First value is not a
803  * real instruction; it is a token which is removed by ulp_process_macros_and_load
804  * function.
805  */
806 #define M_BX(label_num) \
807     M_BRANCH(label_num), \
808     I_BXI(0)
809 
810 /**
811  * Macro: branch to label if ALU result is zero
812  *
813  * This macro generates two ulp_insn_t values separated by a comma, and should
814  * be used when defining contents of ulp_insn_t arrays. First value is not a
815  * real instruction; it is a token which is removed by ulp_process_macros_and_load
816  * function.
817  */
818 #define M_BXZ(label_num) \
819     M_BRANCH(label_num), \
820     I_BXZI(0)
821 
822 /**
823  * Macro: branch to label if ALU overflow
824  *
825  * This macro generates two ulp_insn_t values separated by a comma, and should
826  * be used when defining contents of ulp_insn_t arrays. First value is not a
827  * real instruction; it is a token which is removed by ulp_process_macros_and_load
828  * function.
829  */
830 #define M_BXF(label_num) \
831     M_BRANCH(label_num), \
832     I_BXFI(0)
833 
834 
835 
836 #define RTC_SLOW_MEM ((uint32_t*) 0x50000000)       /*!< RTC slow memory, 8k size */
837 
838 #ifdef __cplusplus
839 }
840 #endif
841