summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/nios/NM_Macros.S
blob: da6136593a843a9d643d6a8ef977b51970041ea0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473

;------------------------------
; Macros I: Faux Instructions
;
; The following "faux instructions" are
; implemented here as macros:
;
; MOVIP register,constant		MOVI with optional PFX & MOVHI, or BGEN
; ADDIP register,constant		PFX and ADDI with optional PFX
; SUBIP register,constant		PFX and SUBI with optional PFX
; CMPIP register,constant		PFX and CMPI with optional PFX
;
; MOVI16 register,constant		PFX and MOVI
; MOVI32 register,constant		PFX, MOVI, PFX, and MOVHI
; MOVIA  register,constant		PFX and MOVHI on Nios32, and PFX and MOVI
;
; ANDIP register,constant		PFX and ANDI
; ANDNIP register,constant		PFX and ANDN
; ORIP register,constant		PFX and ORI
; XORIP register,constant		PFX and XORI
;
; _BSR address						MOVIP address to %g7, and CALL
; _BR address						MOVIP address to %g7, and JMP
;
; BEQ address						SKPS cc_nz and BR, has delay slot
; BNE address						SKPS cc_z and BR, has delay slot
; BLE address						SKPS cc_gt and BR, has delay slot
; BLT address						SKPS cc_ge and BR, has delay slot
; RESTRET							RESTORE and JMP %i7 
;
;-------------------------------
; Macros II: Printing
;
; These macros are guaranteed *not*
; to have branch delay slot after them.
;
; NM_PrintChar char
; NM_Print "string"
; NM_PrintLn "string"			Follows it with a carriage return
; NM_PrintRegister reg			For debugging, prints register name & value
;
;-------------------------------
; Macros III: Inline Debugging
;
; These macros print various information
; using large sections of expanded inline code.
; They each use either few or no registers.
; Thus, they may be safely used in interrupt handlers.
;
; NM_D_TxChar char			print char to UART, affects no registers
; NM_D_TxRegister char,char,register	prints the two characters, and the hex register value

; --------------------------------------


		.macro	_pfx_op	OP,reg,val,pForce=0
		.if		(\pForce) || ((\val) > (31)) || ((\val) < (0))
		PFX		%hi(\val)
		.endif
		\OP		\reg,%lo(\val)
		.endm

		.macro	_bgen reg,val,bit
		.if ((\val)==(1<<\bit))
		BGEN	\reg,\bit
		.equ	_bgenBit,1
		.endif
		.endm

	;------------------------
	; MOVIP %reg,32-bit-value
		.macro	MOVIP reg,val
		; Methodically test every BGEN possibility...
		.equ	_bgenBit,0
.if 1
		_bgen \reg,\val,0
		_bgen \reg,\val,1
		_bgen \reg,\val,2
		_bgen \reg,\val,3
		_bgen \reg,\val,4
		_bgen \reg,\val,5
		_bgen \reg,\val,6
		_bgen \reg,\val,7
		_bgen \reg,\val,8
		_bgen \reg,\val,9
		_bgen \reg,\val,10
		_bgen \reg,\val,11
		_bgen \reg,\val,12
		_bgen \reg,\val,13
		_bgen \reg,\val,14
		_bgen \reg,\val,15
		_bgen \reg,\val,16
		_bgen \reg,\val,17
		_bgen \reg,\val,18
		_bgen \reg,\val,19
		_bgen \reg,\val,20
		_bgen \reg,\val,21
		_bgen \reg,\val,22
		_bgen \reg,\val,23
		_bgen \reg,\val,24
		_bgen \reg,\val,25
		_bgen \reg,\val,26
		_bgen \reg,\val,27
		_bgen \reg,\val,28
		_bgen \reg,\val,29
		_bgen \reg,\val,30
		_bgen \reg,\val,31

		; If no bgen fit...
.endif
		.if !_bgenBit
			.if ((\val) & 0xFFE0)
				PFX %hi(\val)
			.endif
			MOVI \reg,%lo(\val)
			.if __nios32__
				.if ((\val) & 0xffff0000)
					.if ((\val) & 0xFFE00000)
						PFX %xhi(\val)
					.endif
					MOVHI \reg,%xlo(\val)
				.endif
			.endif
		.endif

		.endm

	; ADDIP %reg,16-bit-value
		.macro	ADDIP reg,val
		_pfx_op	ADDI,\reg,\val
		.endm

	; SUBIP %reg,16-bit-value
		.macro	SUBIP reg,val
		_pfx_op	SUBI,\reg,\val
		.endm

	; CMPIP %reg,16-bit-value
		.macro	CMPIP reg,val
		_pfx_op	CMPI,\reg,\val
		.endm

	; ANDIP %reg,16-bit-value
		.macro	ANDIP reg,val
		PFX		%hi(\val)
		AND		\reg,%lo(\val)
		.endm

	; ANDNIP %reg,16-bit-value
		.macro	ANDNIP reg,val
		PFX		%hi(\val)
		ANDN		\reg,%lo(\val)
		.endm

	; ORIP %reg,16-bit-value
		.macro	ORIP reg,val
		PFX		%hi(\val)
		OR			\reg,%lo(\val)
		.endm

	; XORIP %reg,16-bit-value
		.macro	XORIP reg,val
		PFX		%hi(\val)
		XOR		\reg,%lo(\val)
		.endm

	; BEQ addr
		.macro	BEQ addr
		IFS		cc_eq
		BR			\addr
		.endm

	; BNE addr
		.macro	BNE addr
		IFS		cc_ne
		BR			\addr
		.endm

	; BLE addr
		.macro	BLE addr
		SKPS		cc_gt
		BR			\addr
		.endm

	; BLT addr
		.macro	BLT addr
		SKPS		cc_ge
		BR			\addr
		.endm

		.macro	digitToChar reg
		ANDIP	\reg,0x000f
		CMPI	\reg,10
		SKPS	cc_lt
		ADDI	\reg,'A'-'0'-10
		PFX		%hi('0')
		ADDI	\reg,%lo('0')
		.endm

; PUSHRET == dec sp, and stash return addr
	.macro	PUSHRET
	SUBI		%sp,2
	ST			[%sp],%o7
	.endm
; POPRET == pop and jump
	.macro	POPRET
	LD			%o7,[%sp]
	JMP		%o7
	ADDI		%sp,2		; branch delay slot
	.endm

; RESTRET = restore & return
	.macro	RESTRET
	JMP		%i7
	RESTORE
	.endm

	;--------------------
	; MOVI16 %reg,Address
	;
	.macro	MOVI16	reg,val
	PFX	%hi(\val)
	MOVI	\reg,%lo(\val)
	.endm

	;--------------------
	; MOVI32 %reg,Address
	;
	.macro	MOVI32	reg,val
	PFX	%hi(\val)
	MOVI	\reg,%lo(\val)
	PFX	%xhi(\val)
	MOVHI	\reg,%xlo(\val)
	.endm

	;--------------------
	; MOVIA %reg,Address
	;
	.macro	MOVIA		reg,val
	.if __nios32__
		MOVI32 \reg,\val
	.else
		MOVI16 \reg,\val
	.endif
	.endm

	;--------------------
	; _BR

	.macro _BR target,viaRegister=%g7
	MOVIA	\viaRegister,\target@h
	JMP	\viaRegister
	.endm

	;--------------------
	; _BSR

	.macro _BSR target,viaRegister=%g7
	MOVIA	\viaRegister,\target@h
	CALL	\viaRegister
	.endm

	;---------------------
	; NM_Print "Your String Here"
	;
	.macro	NM_Print	string

	BR		pastStringData\@
	NOP

stringData\@:
	.asciz	"\string"
	.align 1		; aligns by 2^n
pastStringData\@:
	MOVIA		%o0,stringData\@
	_BSR		NR_TxString
	NOP
	.endm

	.macro	NM_PrintLn string
	NM_Print	"\string"
	_BSR		NR_TxCR
	NOP
	.endm

	.macro	NM_PrintRegister reg	; affects %g0 & %g1 & %g7, but thrashes the CWP a bit
	SAVE		%sp,-16
	NM_Print	"\reg = "
	RESTORE
	MOV		%g0,\reg
	SAVE		%sp,-16
	MOV		%o0,%g0
	_BSR		NR_TxHex
	NOP
	_BSR		NR_TxCR
	NOP
	RESTORE
	.endm

	.macro	NM_PrintChar char
	MOVIP		%o0,\char
	_BSR		NR_TxChar
	NOP
	.endm

	.macro	NM_Print2Chars char1,char2
	MOVIP		%o0,(\char2<<8)+\char1
	_BSR		NR_TxChar
	NOP
	_BSR		NR_TxChar
	LSRI		%o0,8
	.endm



; ---------------------------
; Completely inline UART sends
; Send the char, or %g7 if not there.
; Trashes %g5 and %g6 and %g7...

	.macro	NM_TxChar char=0
;NM_D_Delay 1000
	MOVIA	%g6,NA_UARTBase
txCharLoop\@:
	PFX	2
.if \char
	LD	%g7,[%g6]
	SKP1	%g7,6
.else
	LD	%g5,[%g6]
	SKP1	%g5,6
.endif
	BR	txCharLoop\@
	NOP
.if \char
	MOVIP	%g7,\char
.endif
	PFX	1
	ST	[%g6],%g7
;NM_D_Delay 4
	.endm

		.macro NM_TxCR
		NM_TxChar 13
		NM_TxChar 10
		.endm

		.macro NM_TxHexDigit,reg,shift
		MOV		%g7,\reg
		LSRI		%g7,\shift
		ANDIP		%g7,0x000f
		CMPI		%g7,10
		SKPS		cc_lt
		ADDIP		%g7,'A'-'0'-10
		ADDIP		%g7,'0'
		NM_TxChar
		.endm

		.macro NM_TxHex

	.if __nios32__
		NM_TxHexDigit %g0,28
		NM_TxHexDigit %g0,24
		NM_TxHexDigit %g0,20
		NM_TxHexDigit %g0,16
	.endif

		NM_TxHexDigit %g0,12
		NM_TxHexDigit %g0,8
		NM_TxHexDigit %g0,4
		NM_TxHexDigit %g0,0
		.endm










; ----------------------
; The following macros are
; rather mighty. They expand
; to large inline code for
; printing various things to
; the serial port. They are
; useful for debugging
; trap handlers, where you
; can't just go and call
; NR_TxChar and such, because,
; well, the CWP might be
; off limits!
;
; They do, however, presume
; that the stack is in good
; working order.


.macro NM_D_PushGRegisters
 	SUBIP %sp,16+69				; oddball number so if we accidentally see it, it looks funny.
	STS	[%sp,16+0],%g0
	STS	[%sp,16+1],%g1
	STS	[%sp,16+2],%g2
	STS	[%sp,16+3],%g3
	STS	[%sp,16+4],%g4
	STS	[%sp,16+5],%g5
	STS	[%sp,16+6],%g6
	STS	[%sp,16+7],%g7
	.endm

.macro NM_D_PopGRegisters
	LDS	%g0,[%sp,16+0]
	LDS	%g1,[%sp,16+1]
	LDS	%g2,[%sp,16+2]
	LDS	%g3,[%sp,16+3]
	LDS	%g4,[%sp,16+4]
	LDS	%g5,[%sp,16+5]
	LDS	%g6,[%sp,16+6]
	LDS	%g7,[%sp,16+7]
	ADDIP	%sp,16+69				; must match the push
	.endm


.macro NM_D_TxChar	c
	SUBI	%sp,16+8		; 32 or 16 bit, that's enough space
	STS	[%sp,16+0],%g6
	STS	[%sp,16+0],%g7
	NM_TxChar \c
	LDS	%g6,[%sp,16+0]
	LDS	%g7,[%sp,16+1]
	ADDI	%sp,16+8
	.endm

.macro NM_D_TxChar3 c1,c2,c3
 NM_D_TxChar '<'
 NM_D_TxChar \c1
 NM_D_TxChar \c2
 NM_D_TxChar \c3
 NM_D_TxChar '>'
.endm

.macro NM_D_TxRegister r,n,reg
 NM_D_PushGRegisters
 NM_TxChar '('
 NM_TxChar \r
 NM_TxChar \n
 NM_TxChar ':'
 MOV		%g0,\reg
 NM_TxHex
 NM_TxChar ')'
 NM_D_PopGRegisters
.endm

.macro NM_D_TxReg r,n,reg
	NM_D_TxRegister \r,\n,\reg
.endm

; Do a delay loop, affects no registers.

.macro NM_D_Delay d
	SUBI	%sp,16+4
	STS	[%sp,16+0],%g0
	MOVIP	%g0,\d
NM_D_DelayLoop\@:
	IFRnz	%g0
	 BR	NM_D_DelayLoop\@
	SUBI	%g0,1
	LDS	%g0,[%sp,16+0]
	ADDI	%sp,16+4
.endm