OpenCores
URL https://opencores.org/ocsvn/neo430/neo430/trunk

Subversion Repositories neo430

[/] [neo430/] [trunk/] [neo430/] [sw/] [lib/] [neo430/] [source/] [neo430_cpu.c] - Blame information for rev 198

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 198 zero_gravi
// #################################################################################################
2
// #  < neo430_cpu.c - CPU helper functions >                                                      #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6
// # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
7
// #                                                                                               #
8
// # Redistribution and use in source and binary forms, with or without modification, are          #
9
// # permitted provided that the following conditions are met:                                     #
10
// #                                                                                               #
11
// # 1. Redistributions of source code must retain the above copyright notice, this list of        #
12
// #    conditions and the following disclaimer.                                                   #
13
// #                                                                                               #
14
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
15
// #    conditions and the following disclaimer in the documentation and/or other materials        #
16
// #    provided with the distribution.                                                            #
17
// #                                                                                               #
18
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
19
// #    endorse or promote products derived from this software without specific prior written      #
20
// #    permission.                                                                                #
21
// #                                                                                               #
22
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
23
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
24
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
25
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
26
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
27
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
28
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
29
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
30
// # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
31
// # ********************************************************************************************* #
32
// # The NEO430 Processor - https://github.com/stnolting/neo430                                    #
33
// #################################################################################################
34
 
35
#include "neo430.h"
36
#include "neo430_cpu.h"
37
 
38
// Private variables
39
static uint16_t __neo430_sreg __attribute__((unused)); // do not ouput a warning when this variable is unused
40
 
41
 
42
/* ------------------------------------------------------------
43
 * INFO Beginning of critical section (store SREG and disable interrupts)
44
 * ------------------------------------------------------------ */
45
void neo430_critical_start(void) {
46
 
47
  register uint16_t d;
48
  asm volatile ("mov r2, %0" : "=r" (d));
49
  __neo430_sreg = d; // store current SREG
50
 
51
  asm volatile ("dint");
52
  asm volatile ("nop");
53
}
54
 
55
 
56
/* ------------------------------------------------------------
57
 * INFO End of critical section (restore original SREG)
58
 * ------------------------------------------------------------ */
59
void neo430_critical_end(void) {
60
 
61
  register uint16_t r = __neo430_sreg;
62
  asm volatile ("mov %0, r2" : : "r" (r));
63
}
64
 
65
 
66
/* ------------------------------------------------------------
67
 * INFO Enable global interrupt flag
68
 * ------------------------------------------------------------ */
69
void neo430_eint(void){
70
 
71
  asm volatile ("eint");
72
  asm volatile ("nop");
73
}
74
 
75
 
76
/* ------------------------------------------------------------
77
 * INFO Disable global interrupt flag
78
 * ------------------------------------------------------------ */
79
void neo430_dint(void){
80
 
81
  asm volatile ("dint");
82
  asm volatile ("nop");
83
}
84
 
85
 
86
/* ------------------------------------------------------------
87
 * INFO Read stack pointer (for debugging only)
88
 * RETURN current stack pointer
89
 * ------------------------------------------------------------ */
90
uint16_t neo430_get_sp(void){
91
 
92
  register uint16_t d;
93
  asm volatile ("mov r1, %0" : "=r" (d));
94
  uint16_t r = d;
95
  return r;
96
}
97
 
98
 
99
/* ------------------------------------------------------------
100
 * INFO Read status register
101
 * RETURN current status register
102
 * ------------------------------------------------------------ */
103
uint16_t neo430_get_sreg(void){
104
 
105
  register uint16_t d;
106
  asm volatile ("mov r2, %0" : "=r" (d));
107
  uint16_t r = d;
108
  return r;
109
}
110
 
111
 
112
/* ------------------------------------------------------------
113
 * INFO Set status register
114
 * PARAM d new value for status register
115
 * ------------------------------------------------------------ */
116
void neo430_set_sreg(uint16_t d){
117
 
118
  register uint16_t r = d;
119
  asm volatile ("mov %0, r2" : : "r" (r));
120
}
121
 
122
 
123
/* ------------------------------------------------------------
124
 * INFO Get parity of value
125
 * WARNING MAKE SURE THIS OPTION IS SYNTHESIZED (package switch "use_ext_alu_c")!!!
126
 * PARAM d input value
127
 * RETURN Resulting parity (1=even number of 1s, 0=odd number of 1s)
128
 * ------------------------------------------------------------ */
129
uint16_t neo430_get_parity(uint16_t d){
130
 
131
  register uint16_t r = d;
132
  asm volatile ("mov %0, %0" : "=r" (r) : "r" (r)); // just get value through alu
133
 
134
  if (neo430_get_sreg() & (1<<P_FLAG)) // get parity flag from SR
135
    return 1;
136
  else
137
    return 0;
138
}
139
 
140
 
141
/* ------------------------------------------------------------
142
 * INFO Set CPU to sleep mode
143
 * ------------------------------------------------------------ */
144
void neo430_sleep(void){
145
 
146
  asm volatile ("bis %0, r2" : : "i" (1<<S_FLAG));
147
}
148
 
149
 
150
/* ------------------------------------------------------------
151
 * INFO Clear CPU pending IRQ buffer
152
 * ------------------------------------------------------------ */
153
void neo430_clear_irq_buffer(void){
154
 
155
  asm volatile ("bis %0, r2" : : "i" (1<<Q_FLAG));
156
  // no need to reset the flag as it automatically clears again
157
}
158
 
159
 
160
/* ------------------------------------------------------------
161
 * INFO Simple wait function
162
 * PARAM Amount of ~2^16 machine cycles to wait
163
 * ------------------------------------------------------------ */
164
void neo430_cpu_delay(uint16_t t) {
165
 
166
  register uint16_t i = 0;
167
  while (t--) {
168
    for (i=0; i<0xFFFF; i++)
169
      asm volatile ("nop");
170
  }
171
}
172
 
173
 
174
/* ------------------------------------------------------------
175
 * INFO Waits <ms> microseconds (not very precise!)
176
 * PARAM ms time in microseconds to wait
177
 * ------------------------------------------------------------ */
178
void neo430_cpu_delay_ms(uint16_t ms) {
179
 
180
  // empirical ;)
181
  uint32_t a = ((uint32_t)CLOCKSPEED_HI) << 1;
182
  register uint32_t cnt = a * (uint32_t)ms;
183
 
184
  while(cnt--) {
185
    asm volatile ("nop");
186
  }
187
}
188
 
189
 
190
/* ------------------------------------------------------------
191
 * INFO Perform a soft reset by jumping to beginning of IMEM
192
 * ------------------------------------------------------------ */
193
void neo430_soft_reset(void) {
194
 
195
  asm volatile ("mov #0x0000, r0");
196
}
197
 
198
 
199
/* ------------------------------------------------------------
200
 * INFO Jump to address
201
 * PARAM Destination address
202
 * ------------------------------------------------------------ */
203
void neo430_jump_address(uint16_t addr) {
204
 
205
  register uint16_t r = addr;
206
  asm volatile ("mov %0, r0" : : "r" (r));
207
}
208
 
209
 
210
/* ------------------------------------------------------------
211
 * INFO Call address and save return address to stack
212
 * PARAM Destination address
213
 * ------------------------------------------------------------ */
214
void neo430_call_address(uint16_t addr) {
215
 
216
  register uint16_t r = addr;
217
  asm volatile ("call %0" : : "r" (r));
218
}
219
 
220
 
221
/* ------------------------------------------------------------
222
 * INFO Perform byte swap of 16-bit word (e.g., for endianness conversion)
223
 * PARAM 16-bit input word
224
 * RETURN 16-bit word with swapped bytes
225
 * ------------------------------------------------------------ */
226
uint16_t neo430_bswap(uint16_t a) {
227
 
228
  register uint16_t r = a;
229
  asm volatile ("swpb %0, %1" : "=r" (r) : "r" (r));
230
  return r;
231
}
232
 
233
 
234
/* ------------------------------------------------------------
235
 * INFO Combine two bytes into one word
236
 * PARAM hi will be put in result's high byte
237
 * PARAM lo will be put in result's low byte
238
 * RETURN 16-bit combined word
239
 * ------------------------------------------------------------ */
240
uint16_t neo430_combine_bytes(uint8_t hi, uint8_t lo) {
241
 
242
  register uint16_t r = neo430_bswap((uint16_t)hi);
243
  return r | (uint16_t)lo;
244
}
245
 
246
 
247
/* ------------------------------------------------------------
248
 * INFO Memory initialization (byte-wise)
249
 * PARAM dst: Byte-pointer to beginning of target memory space
250
 * PARAM data: Init data
251
 * PARAM num: Number of bytes to initialize
252
 * ------------------------------------------------------------ */
253
void neo430_memset(uint8_t *dst, uint8_t data, uint16_t num) {
254
 
255
  while (num--)
256
    *dst++ = data;
257
}
258
 
259
 
260
/* ------------------------------------------------------------
261
 * INFO Compare memory to memory
262
 * PARAM dst: Pointer to beginning of first memory space
263
 * PARAM src: Pointer to beginning of second memory space
264
 * PARAM num: Number of bytes to compare
265
 * RETURN 0 if src == dst
266
 * ------------------------------------------------------------ */
267
uint8_t neo430_memcmp(uint8_t *dst, uint8_t *src, uint16_t num) {
268
 
269
  while (num--) {
270
    if (*dst++ != *src++)
271
      return 1;
272
  }
273
  return 0;
274
}
275
 
276
 
277
/* ------------------------------------------------------------
278
 * INFO Copy memory space SRC to DST (byte by byte)
279
 * PARAM dst: Pointer to beginning destination memory space
280
 * PARAM src: Pointer to beginning source memory space
281
 * PARAM num: Number of bytes to copy
282
 * ------------------------------------------------------------ */
283
void neo430_memcpy(uint8_t *dst, uint8_t *src, uint16_t num) {
284
 
285
  while (num--)
286
    *dst++ = *src++;
287
}
288
 
289
 
290
/* ------------------------------------------------------------
291
 * INFO 16-bit bit reversal
292
 * PARAM input operand to be reversed
293
 * RETURN reversed bit pattern
294
 * ------------------------------------------------------------ */
295
uint16_t neo430_bit_rev16(uint16_t x) {
296
 
297
  register uint16_t z = x;
298
  register uint16_t y = 0;
299
  uint8_t i = 0;
300
 
301
  for (i=0; i<8; i++) { // two-times unrolled
302
    asm volatile ("rrc %[a], %[b]" : [b] "=r" (z) : "[b]" (z), [a] "r" (z));
303
    asm volatile ("rlc %[c], %[d]" : [d] "=r" (y) : "[d]" (y), [c] "r" (y));
304
 
305
    asm volatile ("rrc %[a], %[b]" : [b] "=r" (z) : "[b]" (z), [a] "r" (z));
306
    asm volatile ("rlc %[c], %[d]" : [d] "=r" (y) : "[d]" (y), [c] "r" (y));
307
  }
308
  return y;
309
}
310
 
311
 
312
/* ------------------------------------------------------------
313
 * INFO rotate word right by one position
314
 * PARAM input operand to be rotated
315
 * RETURN rotated result
316
 * ------------------------------------------------------------ */
317
uint16_t neo430_rotate_right_w(uint16_t x) {
318
 
319
  uint16_t tmp = x;
320
  asm volatile ("rrc.w %[b]" : [b] "=r" (tmp) : "[b]" (tmp)); // get carry flag
321
  asm volatile ("rrc.w %[b]" : [b] "=r" (x) : "[b]" (x)); // rotate input with according carry input
322
  return x;
323
}
324
 
325
 
326
/* ------------------------------------------------------------
327
 * INFO rotate word left by one position
328
 * PARAM input operand to be rotated
329
 * RETURN rotated result
330
 * ------------------------------------------------------------ */
331
uint16_t neo430_rotate_left_w(uint16_t x) {
332
 
333
  uint16_t tmp = x;
334
  asm volatile ("rlc.w %[b]" : [b] "=r" (tmp) : "[b]" (tmp)); // get carry flag
335
  asm volatile ("rlc.w %[b]" : [b] "=r" (x) : "[b]" (x)); // rotate input with according carry input
336
  return x;
337
}
338
 
339
 
340
/* ------------------------------------------------------------
341
 * INFO rotate byte right by one position
342
 * PARAM input operand to be rotated
343
 * RETURN rotated result
344
 * ------------------------------------------------------------ */
345
uint8_t neo430_rotate_right_b(uint8_t x) {
346
 
347
  uint8_t tmp = x;
348
  asm volatile ("rrc.b %[b]" : [b] "=r" (tmp) : "[b]" (tmp)); // get carry flag
349
  asm volatile ("rrc.b %[b]" : [b] "=r" (x) : "[b]" (x)); // rotate input with according carry input
350
  return x;
351
}
352
 
353
 
354
/* ------------------------------------------------------------
355
 * INFO rotate byte left by one position
356
 * PARAM input operand to be rotated
357
 * RETURN rotated result
358
 * ------------------------------------------------------------ */
359
uint8_t neo430_rotate_left_b(uint8_t x) {
360
 
361
  uint8_t tmp = x;
362
  asm volatile ("rlc.b %[b]" : [b] "=r" (tmp) : "[b]" (tmp)); // get carry flag
363
  asm volatile ("rlc.b %[b]" : [b] "=r" (x) : "[b]" (x)); // rotate input with according carry input
364
  return x;
365
}
366
 
367
 
368
/* ------------------------------------------------------------
369
 * INFO Pseudo-random number generator
370
 * RETURN 32-bit random data
371
 * ------------------------------------------------------------ */
372
uint32_t neo430_xorshift32(void) {
373
 
374
  static uint32_t x32 = 314159265;
375
 
376
  x32 ^= x32 << 13;
377
  x32 ^= x32 >> 17;
378
  x32 ^= x32 << 5;
379
 
380
  return x32;
381
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.