1# r0, r4-r6 are used as tmps, consider them call clobbered by these macros.
2
3	.macro start
4	.data
5failmsg:
6	.ascii "fail\n"
7passmsg:
8	.ascii "pass\n"
9	.text
10	.global _start
11_start:
12	ldi32 0x7fffc,sp	; TODO -- what's a good value for this?
13	ldi32 0xffc00,r0
14	mov   r0,tbr		; defined in manual
15	mov   sp,usp
16	mov   sp,ssp
17	.endm
18
19; Exit with return code
20	.macro exit rc
21	ldi32 \rc,r4
22	ldi32 #1,r0
23	int   #10
24	.endm
25
26; Pass the test case
27	.macro pass
28	ldi32 #5,r6
29	ldi32 #passmsg,r5
30	ldi32 #1,r4
31	ldi32 #5,r0
32	int   #10
33	exit  #0
34	.endm
35
36; Fail the testcase
37	.macro fail
38	ldi32 #5,r6
39	ldi32 #failmsg,r5
40	ldi32 #1,r4
41	ldi32 #5,r0
42	int   #10
43	exit  #1
44	.endm
45
46; Load an immediate value into a general register
47; TODO: use minimal sized insn
48	.macro mvi_h_gr val reg
49	ldi32 \val,\reg
50	.endm
51
52; Load an immediate value into a dedicated register
53	.macro mvi_h_dr val reg
54	ldi32 \val,r0
55	mov r0,\reg
56	.endm
57
58; Load a general register into another general register
59	.macro mvr_h_gr src targ
60	mov \src,\targ
61	.endm
62
63; Store an immediate into a word in memory
64	.macro mvi_h_mem val addr
65	mvi_h_gr  \val r4
66	mvr_h_mem r4,\addr
67	.endm
68
69; Store a register into a word in memory
70	.macro mvr_h_mem reg addr
71	st \reg,@\addr
72	.endm
73
74; Store the current ps on the stack
75	.macro save_ps
76	st ps,@-r15
77	.endm
78
79; Load a word value from memory
80	.macro ldmem_h_gr addr reg
81	ld @\addr,\reg
82	.endm
83
84; Add 2 general registers
85	.macro add_h_gr reg1 reg2
86	add \reg1,\reg2
87	.endm
88
89; Increment a register by and immediate
90	.macro inci_h_gr inc reg
91	mvi_h_gr \inc,r4
92	add r4,\reg
93	.endm
94
95; Test the value of an immediate against a general register
96	.macro test_h_gr val reg
97	.if (\val >= 0) && (\val <= 15)
98	cmp \val,\reg
99	.else
100	.if (\val < 0) && (\val >= -16)
101	cmp2 \val,\reg
102	.else
103	ldi32 \val,r4
104	cmp r4,\reg
105	.endif
106	.endif
107	beq test_gr\@
108	fail
109test_gr\@:
110	.endm
111
112; compare two general registers
113	.macro testr_h_gr reg1 reg2
114	cmp \reg1,\reg2
115	beq testr_gr\@
116	fail
117testr_gr\@:
118	.endm
119
120; Test the value of an immediate against a dedicated register
121	.macro test_h_dr val reg
122	mov \reg,r5
123	test_h_gr \val r5
124	.endm
125
126; Test the value of an general register against a dedicated register
127	.macro testr_h_dr gr dr
128	mov \dr,r5
129	testr_h_gr \gr r5
130	.endm
131
132; Compare an immediate with word in memory
133	.macro test_h_mem val addr
134	ldmem_h_gr \addr r5
135	test_h_gr \val r5
136	.endm
137
138; Compare a general register with word in memory
139	.macro testr_h_mem reg addr
140	ldmem_h_gr \addr r5
141	testr_h_gr \reg r5
142	.endm
143
144; Set the condition codes
145	.macro set_cc mask
146	andccr	0xf0
147	orccr	\mask
148	.endm
149
150; Set the stack mode
151	.macro set_s_user
152	orccr	0x20
153	.endm
154
155	.macro set_s_system
156	andccr	0x1f
157	.endm
158
159; Test the stack mode
160	.macro test_s_user
161	mvr_h_gr ps,r0
162	mvi_h_gr 0x20,r4
163	and      r4,r0
164	test_h_gr 0x20,r0
165	.endm
166
167	.macro test_s_system
168	mvr_h_gr ps,r0
169	mvi_h_gr 0x20,r4
170	and      r4,r0
171	test_h_gr 0x0,r0
172	.endm
173
174; Set the interrupt bit
175	.macro set_i val
176	.if (\val == 1)
177	orccr	0x10
178	.else
179	andccr	0x2f
180	.endif
181	.endm
182
183; Test the stack mode
184	.macro test_i val
185	mvr_h_gr  ps,r0
186	mvi_h_gr  0x10,r4
187	and       r4,r0
188	.if (\val == 1)
189	test_h_gr 0x10,r0
190	.else
191	test_h_gr 0x0,r0
192	.endif
193	.endm
194
195; Set the ilm
196	.macro set_ilm val
197	stilm \val
198	.endm
199
200; Test the ilm
201	.macro test_ilm val
202	mvr_h_gr   ps,r0
203	mvi_h_gr   0x1f0000,r4
204	and        r4,r0
205	mvi_h_gr   \val,r5
206	mvi_h_gr   0x1f,r4
207	and	   r4,r5
208	lsl        15,r5
209	lsl        1,r5
210	testr_h_gr r0,r5
211	.endm
212
213; Test the condition codes
214	.macro test_cc N Z V C
215	.if (\N == 1)
216	bp fail\@
217	.else
218	bn fail\@
219	.endif
220	.if (\Z == 1)
221	bne fail\@
222	.else
223	beq fail\@
224	.endif
225	.if (\V == 1)
226	bnv fail\@
227	.else
228	bv fail\@
229	.endif
230	.if (\C == 1)
231	bnc fail\@
232	.else
233	bc fail\@
234	.endif
235	bra test_cc\@
236fail\@:
237	fail
238test_cc\@:
239	.endm
240
241; Set the division bits
242	.macro set_dbits val
243	mvr_h_gr ps,r5
244	mvi_h_gr 0xfffff8ff,r4
245	and r4,r5
246	mvi_h_gr \val,r0
247	mvi_h_gr 3,r4
248	and r4,r0
249	lsl 9,r0
250	or r0,r5
251	mvr_h_gr r5,ps
252	.endm
253
254; Test the division bits
255	.macro test_dbits val
256	mvr_h_gr ps,r0
257	lsr 9,r0
258	mvi_h_gr 3,r4
259	and r4,r0
260	test_h_gr \val,r0
261	.endm
262
263; Save the return pointer
264	.macro save_rp
265	st rp,@-R15
266	.ENDM
267
268; restore the return pointer
269	.macro restore_rp
270	ld @R15+,rp
271	.endm
272
273; Ensure branch taken
274	.macro take_branch opcode
275	\opcode take_br\@
276	fail
277take_br\@:
278	.endm
279
280	.macro take_branch_d opcode val
281	\opcode take_brd\@
282	ldi:8 \val,r0
283	fail
284take_brd\@:
285	test_h_gr \val,r0
286	.endm
287
288; Ensure branch not taken
289	.macro no_branch opcode
290	\opcode no_brf\@
291	bra	no_brs\@
292no_brf\@:
293	fail
294no_brs\@:
295	.endm
296
297	.macro no_branch_d opcode val
298	\opcode no_brdf\@
299	ldi:8   \val,r0
300	bra	no_brds\@
301no_brdf\@:
302	fail
303no_brds\@:
304	test_h_gr \val,r0
305	.endm
306
307