1 /*
2  *  TMS320C67xx code generator for TCC
3  *
4  *  Copyright (c) 2001, 2002 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 
21 #ifdef TARGET_DEFS_ONLY
22 
23 /* #define ASSEMBLY_LISTING_C67 */
24 
25 /* number of available registers */
26 #define NB_REGS            24
27 
28 /* a register can belong to several classes. The classes must be
29    sorted from more general to more precise (see gv2() code which does
30    assumptions on it). */
31 #define RC_INT     0x0001	/* generic integer register */
32 #define RC_FLOAT   0x0002	/* generic float register */
33 #define RC_EAX     0x0004
34 #define RC_ST0     0x0008
35 #define RC_ECX     0x0010
36 #define RC_EDX     0x0020
37 #define RC_INT_BSIDE  0x00000040	/* generic integer register  on b side */
38 #define RC_C67_A4     0x00000100
39 #define RC_C67_A5     0x00000200
40 #define RC_C67_B4     0x00000400
41 #define RC_C67_B5     0x00000800
42 #define RC_C67_A6     0x00001000
43 #define RC_C67_A7     0x00002000
44 #define RC_C67_B6     0x00004000
45 #define RC_C67_B7     0x00008000
46 #define RC_C67_A8     0x00010000
47 #define RC_C67_A9     0x00020000
48 #define RC_C67_B8     0x00040000
49 #define RC_C67_B9     0x00080000
50 #define RC_C67_A10    0x00100000
51 #define RC_C67_A11    0x00200000
52 #define RC_C67_B10    0x00400000
53 #define RC_C67_B11    0x00800000
54 #define RC_C67_A12    0x01000000
55 #define RC_C67_A13    0x02000000
56 #define RC_C67_B12    0x04000000
57 #define RC_C67_B13    0x08000000
58 #define RC_IRET    RC_C67_A4	/* function return: integer register */
59 #define RC_IRE2    RC_C67_A5	/* function return: second integer register */
60 #define RC_FRET    RC_C67_A4	/* function return: float register */
61 
62 /* pretty names for the registers */
63 enum {
64     TREG_EAX = 0,		// really A2
65     TREG_ECX,			// really A3
66     TREG_EDX,			// really B0
67     TREG_ST0,			// really B1
68     TREG_C67_A4,
69     TREG_C67_A5,
70     TREG_C67_B4,
71     TREG_C67_B5,
72     TREG_C67_A6,
73     TREG_C67_A7,
74     TREG_C67_B6,
75     TREG_C67_B7,
76     TREG_C67_A8,
77     TREG_C67_A9,
78     TREG_C67_B8,
79     TREG_C67_B9,
80     TREG_C67_A10,
81     TREG_C67_A11,
82     TREG_C67_B10,
83     TREG_C67_B11,
84     TREG_C67_A12,
85     TREG_C67_A13,
86     TREG_C67_B12,
87     TREG_C67_B13,
88 };
89 
90 /* return registers for function */
91 #define REG_IRET TREG_C67_A4	/* single word int return register */
92 #define REG_IRE2 TREG_C67_A5    /* second word return register (for long long) */
93 #define REG_FRET TREG_C67_A4	/* float return register */
94 
95 /* defined if function parameters must be evaluated in reverse order */
96 /* #define INVERT_FUNC_PARAMS */
97 
98 /* defined if structures are passed as pointers. Otherwise structures
99    are directly pushed on stack. */
100 /* #define FUNC_STRUCT_PARAM_AS_PTR */
101 
102 /* pointer size, in bytes */
103 #define PTR_SIZE 4
104 
105 /* long double size and alignment, in bytes */
106 #define LDOUBLE_SIZE  12
107 #define LDOUBLE_ALIGN 4
108 /* maximum alignment (for aligned attribute support) */
109 #define MAX_ALIGN     8
110 
111 /******************************************************/
112 #else /* ! TARGET_DEFS_ONLY */
113 /******************************************************/
114 #define USING_GLOBALS
115 #include "tcc.h"
116 
117 ST_DATA const int reg_classes[NB_REGS] = {
118     /* eax */ RC_INT | RC_FLOAT | RC_EAX,
119     // only allow even regs for floats (allow for doubles)
120     /* ecx */ RC_INT | RC_ECX,
121     /* edx */ RC_INT | RC_INT_BSIDE | RC_FLOAT | RC_EDX,
122     // only allow even regs for floats (allow for doubles)
123     /* st0 */ RC_INT | RC_INT_BSIDE | RC_ST0,
124     /* A4  */ RC_C67_A4,
125     /* A5  */ RC_C67_A5,
126     /* B4  */ RC_C67_B4,
127     /* B5  */ RC_C67_B5,
128     /* A6  */ RC_C67_A6,
129     /* A7  */ RC_C67_A7,
130     /* B6  */ RC_C67_B6,
131     /* B7  */ RC_C67_B7,
132     /* A8  */ RC_C67_A8,
133     /* A9  */ RC_C67_A9,
134     /* B8  */ RC_C67_B8,
135     /* B9  */ RC_C67_B9,
136     /* A10  */ RC_C67_A10,
137     /* A11  */ RC_C67_A11,
138     /* B10  */ RC_C67_B10,
139     /* B11  */ RC_C67_B11,
140     /* A12  */ RC_C67_A10,
141     /* A13  */ RC_C67_A11,
142     /* B12  */ RC_C67_B10,
143     /* B13  */ RC_C67_B11
144 };
145 
146 // although tcc thinks it is passing parameters on the stack,
147 // the C67 really passes up to the first 10 params in special
148 // regs or regs pairs (for 64 bit params).  So keep track of
149 // the stack offsets so we can translate to the appropriate
150 // reg (pair)
151 
152 #define NoCallArgsPassedOnStack 10
153 int NoOfCurFuncArgs;
154 int TranslateStackToReg[NoCallArgsPassedOnStack];
155 int ParamLocOnStack[NoCallArgsPassedOnStack];
156 int TotalBytesPushedOnStack;
157 
158 #ifndef FALSE
159 # define FALSE 0
160 # define TRUE 1
161 #endif
162 
163 #undef BOOL
164 #define BOOL int
165 
166 #define ALWAYS_ASSERT(x) \
167 do {\
168    if (!(x))\
169        tcc_error("internal compiler error file at %s:%d", __FILE__, __LINE__);\
170 } while (0)
171 
172 /******************************************************/
173 static unsigned long func_sub_sp_offset;
174 static int func_ret_sub;
175 
176 static BOOL C67_invert_test;
177 static int C67_compare_reg;
178 
179 #ifdef ASSEMBLY_LISTING_C67
180 FILE *f = NULL;
181 #endif
182 
C67_g(int c)183 void C67_g(int c)
184 {
185     int ind1;
186     if (nocode_wanted)
187         return;
188 #ifdef ASSEMBLY_LISTING_C67
189     fprintf(f, " %08X", c);
190 #endif
191     ind1 = ind + 4;
192     if (ind1 > (int) cur_text_section->data_allocated)
193 	section_realloc(cur_text_section, ind1);
194     cur_text_section->data[ind] = c & 0xff;
195     cur_text_section->data[ind + 1] = (c >> 8) & 0xff;
196     cur_text_section->data[ind + 2] = (c >> 16) & 0xff;
197     cur_text_section->data[ind + 3] = (c >> 24) & 0xff;
198     ind = ind1;
199 }
200 
201 
202 /* output a symbol and patch all calls to it */
gsym_addr(int t, int a)203 void gsym_addr(int t, int a)
204 {
205     int n, *ptr;
206     while (t) {
207 	ptr = (int *) (cur_text_section->data + t);
208 	{
209 	    Sym *sym;
210 
211 	    // extract 32 bit address from MVKH/MVKL
212 	    n = ((*ptr >> 7) & 0xffff);
213 	    n |= ((*(ptr + 1) >> 7) & 0xffff) << 16;
214 
215 	    // define a label that will be relocated
216 
217 	    sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
218 	    greloc(cur_text_section, sym, t, R_C60LO16);
219 	    greloc(cur_text_section, sym, t + 4, R_C60HI16);
220 
221 	    // clear out where the pointer was
222 
223 	    *ptr &= ~(0xffff << 7);
224 	    *(ptr + 1) &= ~(0xffff << 7);
225 	}
226 	t = n;
227     }
228 }
229 
230 // these are regs that tcc doesn't really know about,
231 // but assign them unique values so the mapping routines
232 // can distinguish them
233 
234 #define C67_A0 105
235 #define C67_SP 106
236 #define C67_B3 107
237 #define C67_FP 108
238 #define C67_B2 109
239 #define C67_CREG_ZERO -1	/* Special code for no condition reg test */
240 
241 
ConvertRegToRegClass(int r)242 int ConvertRegToRegClass(int r)
243 {
244     // only works for A4-B13
245 
246     return RC_C67_A4 << (r - TREG_C67_A4);
247 }
248 
249 
250 // map TCC reg to C67 reg number
251 
C67_map_regn(int r)252 int C67_map_regn(int r)
253 {
254     if (r == 0)			// normal tcc regs
255 	return 0x2;		// A2
256     else if (r == 1)		// normal tcc regs
257 	return 3;		// A3
258     else if (r == 2)		// normal tcc regs
259 	return 0;		// B0
260     else if (r == 3)		// normal tcc regs
261 	return 1;		// B1
262     else if (r >= TREG_C67_A4 && r <= TREG_C67_B13)	// these form a pattern of alt pairs
263 	return (((r & 0xfffffffc) >> 1) | (r & 1)) + 2;
264     else if (r == C67_A0)
265 	return 0;		// set to A0 (offset reg)
266     else if (r == C67_B2)
267 	return 2;		// set to B2 (offset reg)
268     else if (r == C67_B3)
269 	return 3;		// set to B3 (return address reg)
270     else if (r == C67_SP)
271 	return 15;		// set to SP (B15) (offset reg)
272     else if (r == C67_FP)
273 	return 15;		// set to FP (A15) (offset reg)
274     else if (r == C67_CREG_ZERO)
275 	return 0;		// Special code for no condition reg test
276     else
277 	ALWAYS_ASSERT(FALSE);
278 
279     return 0;
280 }
281 
282 // mapping from tcc reg number to
283 // C67 register to condition code field
284 //
285 // valid condition code regs are:
286 //
287 // tcc reg 2 ->B0 -> 1
288 // tcc reg 3 ->B1 -> 2
289 // tcc reg 0 -> A2 -> 5
290 // tcc reg 1 -> A3 -> X
291 // tcc reg      B2 -> 3
292 
C67_map_regc(int r)293 int C67_map_regc(int r)
294 {
295     if (r == 0)			// normal tcc regs
296 	return 0x5;
297     else if (r == 2)		// normal tcc regs
298 	return 0x1;
299     else if (r == 3)		// normal tcc regs
300 	return 0x2;
301     else if (r == C67_B2)	// normal tcc regs
302 	return 0x3;
303     else if (r == C67_CREG_ZERO)
304 	return 0;		// Special code for no condition reg test
305     else
306 	ALWAYS_ASSERT(FALSE);
307 
308     return 0;
309 }
310 
311 
312 // map TCC reg to C67 reg side A or B
313 
C67_map_regs(int r)314 int C67_map_regs(int r)
315 {
316     if (r == 0)			// normal tcc regs
317 	return 0x0;
318     else if (r == 1)		// normal tcc regs
319 	return 0x0;
320     else if (r == 2)		// normal tcc regs
321 	return 0x1;
322     else if (r == 3)		// normal tcc regs
323 	return 0x1;
324     else if (r >= TREG_C67_A4 && r <= TREG_C67_B13)	// these form a pattern of alt pairs
325 	return (r & 2) >> 1;
326     else if (r == C67_A0)
327 	return 0;		// set to A side
328     else if (r == C67_B2)
329 	return 1;		// set to B side
330     else if (r == C67_B3)
331 	return 1;		// set to B side
332     else if (r == C67_SP)
333 	return 0x1;		// set to SP (B15) B side
334     else if (r == C67_FP)
335 	return 0x0;		// set to FP (A15) A side
336     else
337 	ALWAYS_ASSERT(FALSE);
338 
339     return 0;
340 }
341 
C67_map_S12(char *s)342 int C67_map_S12(char *s)
343 {
344     if (strstr(s, ".S1") != NULL)
345 	return 0;
346     else if (strcmp(s, ".S2"))
347 	return 1;
348     else
349 	ALWAYS_ASSERT(FALSE);
350 
351     return 0;
352 }
353 
C67_map_D12(char *s)354 int C67_map_D12(char *s)
355 {
356     if (strstr(s, ".D1") != NULL)
357 	return 0;
358     else if (strcmp(s, ".D2"))
359 	return 1;
360     else
361 	ALWAYS_ASSERT(FALSE);
362 
363     return 0;
364 }
365 
366 
367 
C67_asm(char *s, int a, int b, int c)368 void C67_asm(char *s, int a, int b, int c)
369 {
370     BOOL xpath;
371 
372 #ifdef ASSEMBLY_LISTING_C67
373     if (!f) {
374 	f = fopen("TCC67_out.txt", "wt");
375     }
376     fprintf(f, "%04X ", ind);
377 #endif
378 
379     if (strstr(s, "MVKL") == s) {
380 	C67_g((C67_map_regn(b) << 23) |
381 	      ((a & 0xffff) << 7) | (0x0a << 2) | (C67_map_regs(b) << 1));
382     } else if (strstr(s, "MVKH") == s) {
383 	C67_g((C67_map_regn(b) << 23) |
384 	      (((a >> 16) & 0xffff) << 7) |
385 	      (0x1a << 2) | (C67_map_regs(b) << 1));
386     } else if (strstr(s, "STW.D SP POST DEC") == s) {
387 	C67_g((C67_map_regn(a) << 23) |	//src
388 	      (15 << 18) |	//SP B15
389 	      (2 << 13) |	//ucst5 (must keep 8 byte boundary !!)
390 	      (0xa << 9) |	//mode a = post dec ucst
391 	      (0 << 8) |	//r (LDDW bit 0)
392 	      (1 << 7) |	//y D1/D2 use B side
393 	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
394 	      (1 << 2) |	//opcode
395 	      (C67_map_regs(a) << 1) |	//side of src
396 	      (0 << 0));	//parallel
397     } else if (strstr(s, "STB.D *+SP[A0]") == s) {
398 	C67_g((C67_map_regn(a) << 23) |	//src
399 	      (15 << 18) |	//base reg A15
400 	      (0 << 13) |	//offset reg A0
401 	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
402 	      (0 << 8) |	//r (LDDW bit 0)
403 	      (0 << 7) |	//y D1/D2 A side
404 	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
405 	      (1 << 2) |	//opcode
406 	      (C67_map_regs(a) << 1) |	//side of src
407 	      (0 << 0));	//parallel
408     } else if (strstr(s, "STH.D *+SP[A0]") == s) {
409 	C67_g((C67_map_regn(a) << 23) |	//src
410 	      (15 << 18) |	//base reg A15
411 	      (0 << 13) |	//offset reg A0
412 	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
413 	      (0 << 8) |	//r (LDDW bit 0)
414 	      (0 << 7) |	//y D1/D2 A side
415 	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
416 	      (1 << 2) |	//opcode
417 	      (C67_map_regs(a) << 1) |	//side of src
418 	      (0 << 0));	//parallel
419     } else if (strstr(s, "STB.D *+SP[A0]") == s) {
420 	C67_g((C67_map_regn(a) << 23) |	//src
421 	      (15 << 18) |	//base reg A15
422 	      (0 << 13) |	//offset reg A0
423 	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
424 	      (0 << 8) |	//r (LDDW bit 0)
425 	      (0 << 7) |	//y D1/D2 A side
426 	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
427 	      (1 << 2) |	//opcode
428 	      (C67_map_regs(a) << 1) |	//side of src
429 	      (0 << 0));	//parallel
430     } else if (strstr(s, "STH.D *+SP[A0]") == s) {
431 	C67_g((C67_map_regn(a) << 23) |	//src
432 	      (15 << 18) |	//base reg A15
433 	      (0 << 13) |	//offset reg A0
434 	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
435 	      (0 << 8) |	//r (LDDW bit 0)
436 	      (0 << 7) |	//y D1/D2 A side
437 	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
438 	      (1 << 2) |	//opcode
439 	      (C67_map_regs(a) << 1) |	//side of src
440 	      (0 << 0));	//parallel
441     } else if (strstr(s, "STW.D *+SP[A0]") == s) {
442 	C67_g((C67_map_regn(a) << 23) |	//src
443 	      (15 << 18) |	//base reg A15
444 	      (0 << 13) |	//offset reg A0
445 	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
446 	      (0 << 8) |	//r (LDDW bit 0)
447 	      (0 << 7) |	//y D1/D2 A side
448 	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
449 	      (1 << 2) |	//opcode
450 	      (C67_map_regs(a) << 1) |	//side of src
451 	      (0 << 0));	//parallel
452     } else if (strstr(s, "STW.D *") == s) {
453 	C67_g((C67_map_regn(a) << 23) |	//src
454 	      (C67_map_regn(b) << 18) |	//base reg A0
455 	      (0 << 13) |	//cst5
456 	      (1 << 9) |	//mode 1 = pos cst offset
457 	      (0 << 8) |	//r (LDDW bit 0)
458 	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
459 	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
460 	      (1 << 2) |	//opcode
461 	      (C67_map_regs(a) << 1) |	//side of src
462 	      (0 << 0));	//parallel
463     } else if (strstr(s, "STH.D *") == s) {
464 	C67_g((C67_map_regn(a) << 23) |	//src
465 	      (C67_map_regn(b) << 18) |	//base reg A0
466 	      (0 << 13) |	//cst5
467 	      (1 << 9) |	//mode 1 = pos cst offset
468 	      (0 << 8) |	//r (LDDW bit 0)
469 	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
470 	      (5 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
471 	      (1 << 2) |	//opcode
472 	      (C67_map_regs(a) << 1) |	//side of src
473 	      (0 << 0));	//parallel
474     } else if (strstr(s, "STB.D *") == s) {
475 	C67_g((C67_map_regn(a) << 23) |	//src
476 	      (C67_map_regn(b) << 18) |	//base reg A0
477 	      (0 << 13) |	//cst5
478 	      (1 << 9) |	//mode 1 = pos cst offset
479 	      (0 << 8) |	//r (LDDW bit 0)
480 	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
481 	      (3 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
482 	      (1 << 2) |	//opcode
483 	      (C67_map_regs(a) << 1) |	//side of src
484 	      (0 << 0));	//parallel
485     } else if (strstr(s, "STW.D +*") == s) {
486 	ALWAYS_ASSERT(c < 32);
487 	C67_g((C67_map_regn(a) << 23) |	//src
488 	      (C67_map_regn(b) << 18) |	//base reg A0
489 	      (c << 13) |	//cst5
490 	      (1 << 9) |	//mode 1 = pos cst offset
491 	      (0 << 8) |	//r (LDDW bit 0)
492 	      (C67_map_regs(b) << 7) |	//y D1/D2 base reg side
493 	      (7 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
494 	      (1 << 2) |	//opcode
495 	      (C67_map_regs(a) << 1) |	//side of src
496 	      (0 << 0));	//parallel
497     } else if (strstr(s, "LDW.D SP PRE INC") == s) {
498 	C67_g((C67_map_regn(a) << 23) |	//dst
499 	      (15 << 18) |	//base reg B15
500 	      (2 << 13) |	//ucst5 (must keep 8 byte boundary)
501 	      (9 << 9) |	//mode 9 = pre inc ucst5
502 	      (0 << 8) |	//r (LDDW bit 0)
503 	      (1 << 7) |	//y D1/D2  B side
504 	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
505 	      (1 << 2) |	//opcode
506 	      (C67_map_regs(a) << 1) |	//side of dst
507 	      (0 << 0));	//parallel
508     } else if (strstr(s, "LDDW.D SP PRE INC") == s) {
509 	C67_g((C67_map_regn(a) << 23) |	//dst
510 	      (15 << 18) |	//base reg B15
511 	      (1 << 13) |	//ucst5 (must keep 8 byte boundary)
512 	      (9 << 9) |	//mode 9 = pre inc ucst5
513 	      (1 << 8) |	//r (LDDW bit 1)
514 	      (1 << 7) |	//y D1/D2  B side
515 	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
516 	      (1 << 2) |	//opcode
517 	      (C67_map_regs(a) << 1) |	//side of dst
518 	      (0 << 0));	//parallel
519     } else if (strstr(s, "LDW.D *+SP[A0]") == s) {
520 	C67_g((C67_map_regn(a) << 23) |	//dst
521 	      (15 << 18) |	//base reg A15
522 	      (0 << 13) |	//offset reg A0
523 	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
524 	      (0 << 8) |	//r (LDDW bit 0)
525 	      (0 << 7) |	//y D1/D2  A side
526 	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
527 	      (1 << 2) |	//opcode
528 	      (C67_map_regs(a) << 1) |	//side of dst
529 	      (0 << 0));	//parallel
530     } else if (strstr(s, "LDDW.D *+SP[A0]") == s) {
531 	C67_g((C67_map_regn(a) << 23) |	//dst
532 	      (15 << 18) |	//base reg A15
533 	      (0 << 13) |	//offset reg A0
534 	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
535 	      (1 << 8) |	//r (LDDW bit 1)
536 	      (0 << 7) |	//y D1/D2  A side
537 	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
538 	      (1 << 2) |	//opcode
539 	      (C67_map_regs(a) << 1) |	//side of dst
540 	      (0 << 0));	//parallel
541     } else if (strstr(s, "LDH.D *+SP[A0]") == s) {
542 	C67_g((C67_map_regn(a) << 23) |	//dst
543 	      (15 << 18) |	//base reg A15
544 	      (0 << 13) |	//offset reg A0
545 	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
546 	      (0 << 8) |	//r (LDDW bit 0)
547 	      (0 << 7) |	//y D1/D2  A side
548 	      (4 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
549 	      (1 << 2) |	//opcode
550 	      (C67_map_regs(a) << 1) |	//side of dst
551 	      (0 << 0));	//parallel
552     } else if (strstr(s, "LDB.D *+SP[A0]") == s) {
553 	C67_g((C67_map_regn(a) << 23) |	//dst
554 	      (15 << 18) |	//base reg A15
555 	      (0 << 13) |	//offset reg A0
556 	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
557 	      (0 << 8) |	//r (LDDW bit 0)
558 	      (0 << 7) |	//y D1/D2  A side
559 	      (2 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
560 	      (1 << 2) |	//opcode
561 	      (C67_map_regs(a) << 1) |	//side of dst
562 	      (0 << 0));	//parallel
563     } else if (strstr(s, "LDHU.D *+SP[A0]") == s) {
564 	C67_g((C67_map_regn(a) << 23) |	//dst
565 	      (15 << 18) |	//base reg A15
566 	      (0 << 13) |	//offset reg A0
567 	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
568 	      (0 << 8) |	//r (LDDW bit 0)
569 	      (0 << 7) |	//y D1/D2  A side
570 	      (0 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
571 	      (1 << 2) |	//opcode
572 	      (C67_map_regs(a) << 1) |	//side of dst
573 	      (0 << 0));	//parallel
574     } else if (strstr(s, "LDBU.D *+SP[A0]") == s) {
575 	C67_g((C67_map_regn(a) << 23) |	//dst
576 	      (15 << 18) |	//base reg A15
577 	      (0 << 13) |	//offset reg A0
578 	      (5 << 9) |	//mode 5 = pos offset, base reg + off reg
579 	      (0 << 8) |	//r (LDDW bit 0)
580 	      (0 << 7) |	//y D1/D2  A side
581 	      (1 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
582 	      (1 << 2) |	//opcode
583 	      (C67_map_regs(a) << 1) |	//side of dst
584 	      (0 << 0));	//parallel
585     } else if (strstr(s, "LDW.D *") == s) {
586 	C67_g((C67_map_regn(b) << 23) |	//dst
587 	      (C67_map_regn(a) << 18) |	//base reg A15
588 	      (0 << 13) |	//cst5
589 	      (1 << 9) |	//mode 1 = pos cst offset
590 	      (0 << 8) |	//r (LDDW bit 0)
591 	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
592 	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
593 	      (1 << 2) |	//opcode
594 	      (C67_map_regs(b) << 1) |	//side of dst
595 	      (0 << 0));	//parallel
596     } else if (strstr(s, "LDDW.D *") == s) {
597 	C67_g((C67_map_regn(b) << 23) |	//dst
598 	      (C67_map_regn(a) << 18) |	//base reg A15
599 	      (0 << 13) |	//cst5
600 	      (1 << 9) |	//mode 1 = pos cst offset
601 	      (1 << 8) |	//r (LDDW bit 1)
602 	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
603 	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
604 	      (1 << 2) |	//opcode
605 	      (C67_map_regs(b) << 1) |	//side of dst
606 	      (0 << 0));	//parallel
607     } else if (strstr(s, "LDH.D *") == s) {
608 	C67_g((C67_map_regn(b) << 23) |	//dst
609 	      (C67_map_regn(a) << 18) |	//base reg A15
610 	      (0 << 13) |	//cst5
611 	      (1 << 9) |	//mode 1 = pos cst offset
612 	      (0 << 8) |	//r (LDDW bit 0)
613 	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
614 	      (4 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
615 	      (1 << 2) |	//opcode
616 	      (C67_map_regs(b) << 1) |	//side of dst
617 	      (0 << 0));	//parallel
618     } else if (strstr(s, "LDB.D *") == s) {
619 	C67_g((C67_map_regn(b) << 23) |	//dst
620 	      (C67_map_regn(a) << 18) |	//base reg A15
621 	      (0 << 13) |	//cst5
622 	      (1 << 9) |	//mode 1 = pos cst offset
623 	      (0 << 8) |	//r (LDDW bit 0)
624 	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
625 	      (2 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
626 	      (1 << 2) |	//opcode
627 	      (C67_map_regs(b) << 1) |	//side of dst
628 	      (0 << 0));	//parallel
629     } else if (strstr(s, "LDHU.D *") == s) {
630 	C67_g((C67_map_regn(b) << 23) |	//dst
631 	      (C67_map_regn(a) << 18) |	//base reg A15
632 	      (0 << 13) |	//cst5
633 	      (1 << 9) |	//mode 1 = pos cst offset
634 	      (0 << 8) |	//r (LDDW bit 0)
635 	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
636 	      (0 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
637 	      (1 << 2) |	//opcode
638 	      (C67_map_regs(b) << 1) |	//side of dst
639 	      (0 << 0));	//parallel
640     } else if (strstr(s, "LDBU.D *") == s) {
641 	C67_g((C67_map_regn(b) << 23) |	//dst
642 	      (C67_map_regn(a) << 18) |	//base reg A15
643 	      (0 << 13) |	//cst5
644 	      (1 << 9) |	//mode 1 = pos cst offset
645 	      (0 << 8) |	//r (LDDW bit 0)
646 	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
647 	      (1 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
648 	      (1 << 2) |	//opcode
649 	      (C67_map_regs(b) << 1) |	//side of dst
650 	      (0 << 0));	//parallel
651     } else if (strstr(s, "LDW.D +*") == s) {
652 	C67_g((C67_map_regn(b) << 23) |	//dst
653 	      (C67_map_regn(a) << 18) |	//base reg A15
654 	      (1 << 13) |	//cst5
655 	      (1 << 9) |	//mode 1 = pos cst offset
656 	      (0 << 8) |	//r (LDDW bit 0)
657 	      (C67_map_regs(a) << 7) |	//y D1/D2  src side
658 	      (6 << 4) |	//ldst 3=STB, 5=STH 5, 7=STW, 6=LDW 4=LDH 2=LDB 0=LDHU 1=LDBU
659 	      (1 << 2) |	//opcode
660 	      (C67_map_regs(b) << 1) |	//side of dst
661 	      (0 << 0));	//parallel
662     } else if (strstr(s, "CMPLTSP") == s) {
663 	xpath = C67_map_regs(a) ^ C67_map_regs(b);
664 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
665 
666 	C67_g((C67_map_regn(c) << 23) |	//dst
667 	      (C67_map_regn(b) << 18) |	//src2
668 	      (C67_map_regn(a) << 13) |	//src1
669 	      (xpath << 12) |	//x use cross path for src2
670 	      (0x3a << 6) |	//opcode
671 	      (0x8 << 2) |	//opcode fixed
672 	      (C67_map_regs(c) << 1) |	//side for reg c
673 	      (0 << 0));	//parallel
674     } else if (strstr(s, "CMPGTSP") == s) {
675 	xpath = C67_map_regs(a) ^ C67_map_regs(b);
676 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
677 
678 	C67_g((C67_map_regn(c) << 23) |	//dst
679 	      (C67_map_regn(b) << 18) |	//src2
680 	      (C67_map_regn(a) << 13) |	//src1
681 	      (xpath << 12) |	//x use cross path for src2
682 	      (0x39 << 6) |	//opcode
683 	      (0x8 << 2) |	//opcode fixed
684 	      (C67_map_regs(c) << 1) |	//side for reg c
685 	      (0 << 0));	//parallel
686     } else if (strstr(s, "CMPEQSP") == s) {
687 	xpath = C67_map_regs(a) ^ C67_map_regs(b);
688 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
689 
690 	C67_g((C67_map_regn(c) << 23) |	//dst
691 	      (C67_map_regn(b) << 18) |	//src2
692 	      (C67_map_regn(a) << 13) |	//src1
693 	      (xpath << 12) |	//x use cross path for src2
694 	      (0x38 << 6) |	//opcode
695 	      (0x8 << 2) |	//opcode fixed
696 	      (C67_map_regs(c) << 1) |	//side for reg c
697 	      (0 << 0));	//parallel
698     }
699 
700     else if (strstr(s, "CMPLTDP") == s) {
701 	xpath = C67_map_regs(a) ^ C67_map_regs(b);
702 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
703 
704 	C67_g((C67_map_regn(c) << 23) |	//dst
705 	      (C67_map_regn(b) << 18) |	//src2
706 	      (C67_map_regn(a) << 13) |	//src1
707 	      (xpath << 12) |	//x use cross path for src2
708 	      (0x2a << 6) |	//opcode
709 	      (0x8 << 2) |	//opcode fixed
710 	      (C67_map_regs(c) << 1) |	//side for reg c
711 	      (0 << 0));	//parallel
712     } else if (strstr(s, "CMPGTDP") == s) {
713 	xpath = C67_map_regs(a) ^ C67_map_regs(b);
714 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
715 
716 	C67_g((C67_map_regn(c) << 23) |	//dst
717 	      (C67_map_regn(b) << 18) |	//src2
718 	      (C67_map_regn(a) << 13) |	//src1
719 	      (xpath << 12) |	//x use cross path for src2
720 	      (0x29 << 6) |	//opcode
721 	      (0x8 << 2) |	//opcode fixed
722 	      (C67_map_regs(c) << 1) |	//side for reg c
723 	      (0 << 0));	//parallel
724     } else if (strstr(s, "CMPEQDP") == s) {
725 	xpath = C67_map_regs(a) ^ C67_map_regs(b);
726 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
727 
728 	C67_g((C67_map_regn(c) << 23) |	//dst
729 	      (C67_map_regn(b) << 18) |	//src2
730 	      (C67_map_regn(a) << 13) |	//src1
731 	      (xpath << 12) |	//x use cross path for src2
732 	      (0x28 << 6) |	//opcode
733 	      (0x8 << 2) |	//opcode fixed
734 	      (C67_map_regs(c) << 1) |	//side for reg c
735 	      (0 << 0));	//parallel
736     } else if (strstr(s, "CMPLT") == s) {
737 	xpath = C67_map_regs(a) ^ C67_map_regs(b);
738 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
739 
740 	C67_g((C67_map_regn(c) << 23) |	//dst
741 	      (C67_map_regn(b) << 18) |	//src2
742 	      (C67_map_regn(a) << 13) |	//src1
743 	      (xpath << 12) |	//x use cross path for src2
744 	      (0x57 << 5) |	//opcode
745 	      (0x6 << 2) |	//opcode fixed
746 	      (C67_map_regs(c) << 1) |	//side for reg c
747 	      (0 << 0));	//parallel
748     } else if (strstr(s, "CMPGT") == s) {
749 	xpath = C67_map_regs(a) ^ C67_map_regs(b);
750 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
751 
752 	C67_g((C67_map_regn(c) << 23) |	//dst
753 	      (C67_map_regn(b) << 18) |	//src2
754 	      (C67_map_regn(a) << 13) |	//src1
755 	      (xpath << 12) |	//x use cross path for src2
756 	      (0x47 << 5) |	//opcode
757 	      (0x6 << 2) |	//opcode fixed
758 	      (C67_map_regs(c) << 1) |	//side for reg c
759 	      (0 << 0));	//parallel
760     } else if (strstr(s, "CMPEQ") == s) {
761 	xpath = C67_map_regs(a) ^ C67_map_regs(b);
762 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
763 
764 	C67_g((C67_map_regn(c) << 23) |	//dst
765 	      (C67_map_regn(b) << 18) |	//src2
766 	      (C67_map_regn(a) << 13) |	//src1
767 	      (xpath << 12) |	//x use cross path for src2
768 	      (0x53 << 5) |	//opcode
769 	      (0x6 << 2) |	//opcode fixed
770 	      (C67_map_regs(c) << 1) |	//side for reg c
771 	      (0 << 0));	//parallel
772     } else if (strstr(s, "CMPLTU") == s) {
773 	xpath = C67_map_regs(a) ^ C67_map_regs(b);
774 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
775 
776 	C67_g((C67_map_regn(c) << 23) |	//dst
777 	      (C67_map_regn(b) << 18) |	//src2
778 	      (C67_map_regn(a) << 13) |	//src1
779 	      (xpath << 12) |	//x use cross path for src2
780 	      (0x5f << 5) |	//opcode
781 	      (0x6 << 2) |	//opcode fixed
782 	      (C67_map_regs(c) << 1) |	//side for reg c
783 	      (0 << 0));	//parallel
784     } else if (strstr(s, "CMPGTU") == s) {
785 	xpath = C67_map_regs(a) ^ C67_map_regs(b);
786 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
787 
788 	C67_g((C67_map_regn(c) << 23) |	//dst
789 	      (C67_map_regn(b) << 18) |	//src2
790 	      (C67_map_regn(a) << 13) |	//src1
791 	      (xpath << 12) |	//x use cross path for src2
792 	      (0x4f << 5) |	//opcode
793 	      (0x6 << 2) |	//opcode fixed
794 	      (C67_map_regs(c) << 1) |	//side for reg c
795 	      (0 << 0));	//parallel
796     } else if (strstr(s, "B DISP") == s) {
797 	C67_g((0 << 29) |	//creg
798 	      (0 << 28) |	//z
799 	      (a << 7) |	//cnst
800 	      (0x4 << 2) |	//opcode fixed
801 	      (0 << 1) |	//S0/S1
802 	      (0 << 0));	//parallel
803     } else if (strstr(s, "B.") == s) {
804 	xpath = C67_map_regs(c) ^ 1;
805 
806 	C67_g((C67_map_regc(b) << 29) |	//creg
807 	      (a << 28) |	//inv
808 	      (0 << 23) |	//dst
809 	      (C67_map_regn(c) << 18) |	//src2
810 	      (0 << 13) |	//
811 	      (xpath << 12) |	//x cross path if !B side
812 	      (0xd << 6) |	//opcode
813 	      (0x8 << 2) |	//opcode fixed
814 	      (1 << 1) |	//must be S2
815 	      (0 << 0));	//parallel
816     } else if (strstr(s, "MV.L") == s) {
817 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
818 
819 	C67_g((0 << 29) |	//creg
820 	      (0 << 28) |	//inv
821 	      (C67_map_regn(c) << 23) |	//dst
822 	      (C67_map_regn(b) << 18) |	//src2
823 	      (0 << 13) |	//src1 (cst5)
824 	      (xpath << 12) |	//x cross path if opposite sides
825 	      (0x2 << 5) |	//opcode
826 	      (0x6 << 2) |	//opcode fixed
827 	      (C67_map_regs(c) << 1) |	//side of dest
828 	      (0 << 0));	//parallel
829     } else if (strstr(s, "SPTRUNC.L") == s) {
830 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
831 
832 	C67_g((0 << 29) |	//creg
833 	      (0 << 28) |	//inv
834 	      (C67_map_regn(c) << 23) |	//dst
835 	      (C67_map_regn(b) << 18) |	//src2
836 	      (0 << 13) |	//src1 NA
837 	      (xpath << 12) |	//x cross path if opposite sides
838 	      (0xb << 5) |	//opcode
839 	      (0x6 << 2) |	//opcode fixed
840 	      (C67_map_regs(c) << 1) |	//side of dest
841 	      (0 << 0));	//parallel
842     } else if (strstr(s, "DPTRUNC.L") == s) {
843 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
844 
845 	C67_g((0 << 29) |	//creg
846 	      (0 << 28) |	//inv
847 	      (C67_map_regn(c) << 23) |	//dst
848 	      ((C67_map_regn(b) + 1) << 18) |	//src2   WEIRD CPU must specify odd reg for some reason
849 	      (0 << 13) |	//src1 NA
850 	      (xpath << 12) |	//x cross path if opposite sides
851 	      (0x1 << 5) |	//opcode
852 	      (0x6 << 2) |	//opcode fixed
853 	      (C67_map_regs(c) << 1) |	//side of dest
854 	      (0 << 0));	//parallel
855     } else if (strstr(s, "INTSP.L") == s) {
856 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
857 
858 	C67_g((0 << 29) |	//creg
859 	      (0 << 28) |	//inv
860 	      (C67_map_regn(c) << 23) |	//dst
861 	      (C67_map_regn(b) << 18) |	//src2
862 	      (0 << 13) |	//src1 NA
863 	      (xpath << 12) |	//x cross path if opposite sides
864 	      (0x4a << 5) |	//opcode
865 	      (0x6 << 2) |	//opcode fixed
866 	      (C67_map_regs(c) << 1) |	//side of dest
867 	      (0 << 0));	//parallel
868     } else if (strstr(s, "INTSPU.L") == s) {
869 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
870 
871 	C67_g((0 << 29) |	//creg
872 	      (0 << 28) |	//inv
873 	      (C67_map_regn(c) << 23) |	//dst
874 	      (C67_map_regn(b) << 18) |	//src2
875 	      (0 << 13) |	//src1 NA
876 	      (xpath << 12) |	//x cross path if opposite sides
877 	      (0x49 << 5) |	//opcode
878 	      (0x6 << 2) |	//opcode fixed
879 	      (C67_map_regs(c) << 1) |	//side of dest
880 	      (0 << 0));	//parallel
881     } else if (strstr(s, "INTDP.L") == s) {
882 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
883 
884 	C67_g((0 << 29) |	//creg
885 	      (0 << 28) |	//inv
886 	      (C67_map_regn(c) << 23) |	//dst
887 	      (C67_map_regn(b) << 18) |	//src2
888 	      (0 << 13) |	//src1 NA
889 	      (xpath << 12) |	//x cross path if opposite sides
890 	      (0x39 << 5) |	//opcode
891 	      (0x6 << 2) |	//opcode fixed
892 	      (C67_map_regs(c) << 1) |	//side of dest
893 	      (0 << 0));	//parallel
894     } else if (strstr(s, "INTDPU.L") == s) {
895 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
896 
897 	C67_g((0 << 29) |	//creg
898 	      (0 << 28) |	//inv
899 	      (C67_map_regn(c) << 23) |	//dst
900 	      ((C67_map_regn(b) + 1) << 18) |	//src2   WEIRD CPU must specify odd reg for some reason
901 	      (0 << 13) |	//src1 NA
902 	      (xpath << 12) |	//x cross path if opposite sides
903 	      (0x3b << 5) |	//opcode
904 	      (0x6 << 2) |	//opcode fixed
905 	      (C67_map_regs(c) << 1) |	//side of dest
906 	      (0 << 0));	//parallel
907     } else if (strstr(s, "SPDP.L") == s) {
908 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
909 
910 	C67_g((0 << 29) |	//creg
911 	      (0 << 28) |	//inv
912 	      (C67_map_regn(c) << 23) |	//dst
913 	      (C67_map_regn(b) << 18) |	//src2
914 	      (0 << 13) |	//src1 NA
915 	      (xpath << 12) |	//x cross path if opposite sides
916 	      (0x2 << 6) |	//opcode
917 	      (0x8 << 2) |	//opcode fixed
918 	      (C67_map_regs(c) << 1) |	//side of dest
919 	      (0 << 0));	//parallel
920     } else if (strstr(s, "DPSP.L") == s) {
921 	ALWAYS_ASSERT(C67_map_regs(b) == C67_map_regs(c));
922 
923 	C67_g((0 << 29) |	//creg
924 	      (0 << 28) |	//inv
925 	      (C67_map_regn(c) << 23) |	//dst
926 	      ((C67_map_regn(b) + 1) << 18) |	//src2 WEIRD CPU must specify odd reg for some reason
927 	      (0 << 13) |	//src1 NA
928 	      (0 << 12) |	//x cross path if opposite sides
929 	      (0x9 << 5) |	//opcode
930 	      (0x6 << 2) |	//opcode fixed
931 	      (C67_map_regs(c) << 1) |	//side of dest
932 	      (0 << 0));	//parallel
933     } else if (strstr(s, "ADD.L") == s) {
934 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
935 
936 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
937 
938 	C67_g((0 << 29) |	//creg
939 	      (0 << 28) |	//inv
940 	      (C67_map_regn(c) << 23) |	//dst
941 	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
942 	      (C67_map_regn(a) << 13) |	//src1
943 	      (xpath << 12) |	//x cross path if opposite sides
944 	      (0x3 << 5) |	//opcode
945 	      (0x6 << 2) |	//opcode fixed
946 	      (C67_map_regs(c) << 1) |	//side of dest
947 	      (0 << 0));	//parallel
948     } else if (strstr(s, "SUB.L") == s) {
949 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
950 
951 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
952 
953 	C67_g((0 << 29) |	//creg
954 	      (0 << 28) |	//inv
955 	      (C67_map_regn(c) << 23) |	//dst
956 	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
957 	      (C67_map_regn(a) << 13) |	//src1
958 	      (xpath << 12) |	//x cross path if opposite sides
959 	      (0x7 << 5) |	//opcode
960 	      (0x6 << 2) |	//opcode fixed
961 	      (C67_map_regs(c) << 1) |	//side of dest
962 	      (0 << 0));	//parallel
963     } else if (strstr(s, "OR.L") == s) {
964 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
965 
966 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
967 
968 	C67_g((0 << 29) |	//creg
969 	      (0 << 28) |	//inv
970 	      (C67_map_regn(c) << 23) |	//dst
971 	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
972 	      (C67_map_regn(a) << 13) |	//src1
973 	      (xpath << 12) |	//x cross path if opposite sides
974 	      (0x7f << 5) |	//opcode
975 	      (0x6 << 2) |	//opcode fixed
976 	      (C67_map_regs(c) << 1) |	//side of dest
977 	      (0 << 0));	//parallel
978     } else if (strstr(s, "AND.L") == s) {
979 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
980 
981 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
982 
983 	C67_g((0 << 29) |	//creg
984 	      (0 << 28) |	//inv
985 	      (C67_map_regn(c) << 23) |	//dst
986 	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
987 	      (C67_map_regn(a) << 13) |	//src1
988 	      (xpath << 12) |	//x cross path if opposite sides
989 	      (0x7b << 5) |	//opcode
990 	      (0x6 << 2) |	//opcode fixed
991 	      (C67_map_regs(c) << 1) |	//side of dest
992 	      (0 << 0));	//parallel
993     } else if (strstr(s, "XOR.L") == s) {
994 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
995 
996 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
997 
998 	C67_g((0 << 29) |	//creg
999 	      (0 << 28) |	//inv
1000 	      (C67_map_regn(c) << 23) |	//dst
1001 	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1002 	      (C67_map_regn(a) << 13) |	//src1
1003 	      (xpath << 12) |	//x cross path if opposite sides
1004 	      (0x6f << 5) |	//opcode
1005 	      (0x6 << 2) |	//opcode fixed
1006 	      (C67_map_regs(c) << 1) |	//side of dest
1007 	      (0 << 0));	//parallel
1008     } else if (strstr(s, "ADDSP.L") == s) {
1009 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1010 
1011 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1012 
1013 	C67_g((0 << 29) |	//creg
1014 	      (0 << 28) |	//inv
1015 	      (C67_map_regn(c) << 23) |	//dst
1016 	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1017 	      (C67_map_regn(a) << 13) |	//src1
1018 	      (xpath << 12) |	//x cross path if opposite sides
1019 	      (0x10 << 5) |	//opcode
1020 	      (0x6 << 2) |	//opcode fixed
1021 	      (C67_map_regs(c) << 1) |	//side of dest
1022 	      (0 << 0));	//parallel
1023     } else if (strstr(s, "ADDDP.L") == s) {
1024 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1025 
1026 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1027 
1028 	C67_g((0 << 29) |	//creg
1029 	      (0 << 28) |	//inv
1030 	      (C67_map_regn(c) << 23) |	//dst
1031 	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1032 	      (C67_map_regn(a) << 13) |	//src1
1033 	      (xpath << 12) |	//x cross path if opposite sides
1034 	      (0x18 << 5) |	//opcode
1035 	      (0x6 << 2) |	//opcode fixed
1036 	      (C67_map_regs(c) << 1) |	//side of dest
1037 	      (0 << 0));	//parallel
1038     } else if (strstr(s, "SUBSP.L") == s) {
1039 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1040 
1041 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1042 
1043 	C67_g((0 << 29) |	//creg
1044 	      (0 << 28) |	//inv
1045 	      (C67_map_regn(c) << 23) |	//dst
1046 	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1047 	      (C67_map_regn(a) << 13) |	//src1
1048 	      (xpath << 12) |	//x cross path if opposite sides
1049 	      (0x11 << 5) |	//opcode
1050 	      (0x6 << 2) |	//opcode fixed
1051 	      (C67_map_regs(c) << 1) |	//side of dest
1052 	      (0 << 0));	//parallel
1053     } else if (strstr(s, "SUBDP.L") == s) {
1054 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1055 
1056 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1057 
1058 	C67_g((0 << 29) |	//creg
1059 	      (0 << 28) |	//inv
1060 	      (C67_map_regn(c) << 23) |	//dst
1061 	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1062 	      (C67_map_regn(a) << 13) |	//src1
1063 	      (xpath << 12) |	//x cross path if opposite sides
1064 	      (0x19 << 5) |	//opcode
1065 	      (0x6 << 2) |	//opcode fixed
1066 	      (C67_map_regs(c) << 1) |	//side of dest
1067 	      (0 << 0));	//parallel
1068     } else if (strstr(s, "MPYSP.M") == s) {
1069 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1070 
1071 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1072 
1073 	C67_g((0 << 29) |	//creg
1074 	      (0 << 28) |	//inv
1075 	      (C67_map_regn(c) << 23) |	//dst
1076 	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1077 	      (C67_map_regn(a) << 13) |	//src1
1078 	      (xpath << 12) |	//x cross path if opposite sides
1079 	      (0x1c << 7) |	//opcode
1080 	      (0x0 << 2) |	//opcode fixed
1081 	      (C67_map_regs(c) << 1) |	//side of dest
1082 	      (0 << 0));	//parallel
1083     } else if (strstr(s, "MPYDP.M") == s) {
1084 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1085 
1086 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1087 
1088 	C67_g((0 << 29) |	//creg
1089 	      (0 << 28) |	//inv
1090 	      (C67_map_regn(c) << 23) |	//dst
1091 	      (C67_map_regn(b) << 18) |	//src2 (possible x path)
1092 	      (C67_map_regn(a) << 13) |	//src1
1093 	      (xpath << 12) |	//x cross path if opposite sides
1094 	      (0x0e << 7) |	//opcode
1095 	      (0x0 << 2) |	//opcode fixed
1096 	      (C67_map_regs(c) << 1) |	//side of dest
1097 	      (0 << 0));	//parallel
1098     } else if (strstr(s, "MPYI.M") == s) {
1099 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1100 
1101 	ALWAYS_ASSERT(C67_map_regs(a) == C67_map_regs(c));
1102 
1103 	C67_g((0 << 29) |	//creg
1104 	      (0 << 28) |	//inv
1105 	      (C67_map_regn(c) << 23) |	//dst
1106 	      (C67_map_regn(b) << 18) |	//src2
1107 	      (C67_map_regn(a) << 13) |	//src1 (cst5)
1108 	      (xpath << 12) |	//x cross path if opposite sides
1109 	      (0x4 << 7) |	//opcode
1110 	      (0x0 << 2) |	//opcode fixed
1111 	      (C67_map_regs(c) << 1) |	//side of dest
1112 	      (0 << 0));	//parallel
1113     } else if (strstr(s, "SHR.S") == s) {
1114 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1115 
1116 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1117 
1118 	C67_g((0 << 29) |	//creg
1119 	      (0 << 28) |	//inv
1120 	      (C67_map_regn(c) << 23) |	//dst
1121 	      (C67_map_regn(b) << 18) |	//src2
1122 	      (C67_map_regn(a) << 13) |	//src1
1123 	      (xpath << 12) |	//x cross path if opposite sides
1124 	      (0x37 << 6) |	//opcode
1125 	      (0x8 << 2) |	//opcode fixed
1126 	      (C67_map_regs(c) << 1) |	//side of dest
1127 	      (0 << 0));	//parallel
1128     } else if (strstr(s, "SHRU.S") == s) {
1129 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1130 
1131 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1132 
1133 	C67_g((0 << 29) |	//creg
1134 	      (0 << 28) |	//inv
1135 	      (C67_map_regn(c) << 23) |	//dst
1136 	      (C67_map_regn(b) << 18) |	//src2
1137 	      (C67_map_regn(a) << 13) |	//src1
1138 	      (xpath << 12) |	//x cross path if opposite sides
1139 	      (0x27 << 6) |	//opcode
1140 	      (0x8 << 2) |	//opcode fixed
1141 	      (C67_map_regs(c) << 1) |	//side of dest
1142 	      (0 << 0));	//parallel
1143     } else if (strstr(s, "SHL.S") == s) {
1144 	xpath = C67_map_regs(b) ^ C67_map_regs(c);
1145 
1146 	ALWAYS_ASSERT(C67_map_regs(c) == C67_map_regs(a));
1147 
1148 	C67_g((0 << 29) |	//creg
1149 	      (0 << 28) |	//inv
1150 	      (C67_map_regn(c) << 23) |	//dst
1151 	      (C67_map_regn(b) << 18) |	//src2
1152 	      (C67_map_regn(a) << 13) |	//src1
1153 	      (xpath << 12) |	//x cross path if opposite sides
1154 	      (0x33 << 6) |	//opcode
1155 	      (0x8 << 2) |	//opcode fixed
1156 	      (C67_map_regs(c) << 1) |	//side of dest
1157 	      (0 << 0));	//parallel
1158     } else if (strstr(s, "||ADDK") == s) {
1159 	xpath = 0;		// no xpath required just use the side of the src/dst
1160 
1161 	C67_g((0 << 29) |	//creg
1162 	      (0 << 28) |	//inv
1163 	      (C67_map_regn(b) << 23) |	//dst
1164 	      (a << 07) |	//scst16
1165 	      (0x14 << 2) |	//opcode fixed
1166 	      (C67_map_regs(b) << 1) |	//side of dst
1167 	      (1 << 0));	//parallel
1168     } else if (strstr(s, "ADDK") == s) {
1169 	xpath = 0;		// no xpath required just use the side of the src/dst
1170 
1171 	C67_g((0 << 29) |	//creg
1172 	      (0 << 28) |	//inv
1173 	      (C67_map_regn(b) << 23) |	//dst
1174 	      (a << 07) |	//scst16
1175 	      (0x14 << 2) |	//opcode fixed
1176 	      (C67_map_regs(b) << 1) |	//side of dst
1177 	      (0 << 0));	//parallel
1178     } else if (strstr(s, "NOP") == s) {
1179 	C67_g(((a - 1) << 13) |	//no of cycles
1180 	      (0 << 0));	//parallel
1181     } else
1182 	ALWAYS_ASSERT(FALSE);
1183 
1184 #ifdef ASSEMBLY_LISTING_C67
1185     fprintf(f, " %s %d %d %d\n", s, a, b, c);
1186 #endif
1187 
1188 }
1189 
1190 //r=reg to load, fr=from reg, symbol for relocation, constant
1191 
C67_MVKL(int r, int fc)1192 void C67_MVKL(int r, int fc)
1193 {
1194     C67_asm("MVKL.", fc, r, 0);
1195 }
1196 
C67_MVKH(int r, int fc)1197 void C67_MVKH(int r, int fc)
1198 {
1199     C67_asm("MVKH.", fc, r, 0);
1200 }
1201 
C67_STB_SP_A0(int r)1202 void C67_STB_SP_A0(int r)
1203 {
1204     C67_asm("STB.D *+SP[A0]", r, 0, 0);	// STB  r,*+SP[A0]
1205 }
1206 
C67_STH_SP_A0(int r)1207 void C67_STH_SP_A0(int r)
1208 {
1209     C67_asm("STH.D *+SP[A0]", r, 0, 0);	// STH  r,*+SP[A0]
1210 }
1211 
C67_STW_SP_A0(int r)1212 void C67_STW_SP_A0(int r)
1213 {
1214     C67_asm("STW.D *+SP[A0]", r, 0, 0);	// STW  r,*+SP[A0]
1215 }
1216 
C67_STB_PTR(int r, int r2)1217 void C67_STB_PTR(int r, int r2)
1218 {
1219     C67_asm("STB.D *", r, r2, 0);	// STB  r, *r2
1220 }
1221 
C67_STH_PTR(int r, int r2)1222 void C67_STH_PTR(int r, int r2)
1223 {
1224     C67_asm("STH.D *", r, r2, 0);	// STH  r, *r2
1225 }
1226 
C67_STW_PTR(int r, int r2)1227 void C67_STW_PTR(int r, int r2)
1228 {
1229     C67_asm("STW.D *", r, r2, 0);	// STW  r, *r2
1230 }
1231 
C67_STW_PTR_PRE_INC(int r, int r2, int n)1232 void C67_STW_PTR_PRE_INC(int r, int r2, int n)
1233 {
1234     C67_asm("STW.D +*", r, r2, n);	// STW  r, *+r2
1235 }
1236 
C67_PUSH(int r)1237 void C67_PUSH(int r)
1238 {
1239     C67_asm("STW.D SP POST DEC", r, 0, 0);	// STW  r,*SP--
1240 }
1241 
C67_LDW_SP_A0(int r)1242 void C67_LDW_SP_A0(int r)
1243 {
1244     C67_asm("LDW.D *+SP[A0]", r, 0, 0);	// LDW  *+SP[A0],r
1245 }
1246 
C67_LDDW_SP_A0(int r)1247 void C67_LDDW_SP_A0(int r)
1248 {
1249     C67_asm("LDDW.D *+SP[A0]", r, 0, 0);	// LDDW  *+SP[A0],r
1250 }
1251 
C67_LDH_SP_A0(int r)1252 void C67_LDH_SP_A0(int r)
1253 {
1254     C67_asm("LDH.D *+SP[A0]", r, 0, 0);	// LDH  *+SP[A0],r
1255 }
1256 
C67_LDB_SP_A0(int r)1257 void C67_LDB_SP_A0(int r)
1258 {
1259     C67_asm("LDB.D *+SP[A0]", r, 0, 0);	// LDB  *+SP[A0],r
1260 }
1261 
C67_LDHU_SP_A0(int r)1262 void C67_LDHU_SP_A0(int r)
1263 {
1264     C67_asm("LDHU.D *+SP[A0]", r, 0, 0);	// LDHU  *+SP[A0],r
1265 }
1266 
C67_LDBU_SP_A0(int r)1267 void C67_LDBU_SP_A0(int r)
1268 {
1269     C67_asm("LDBU.D *+SP[A0]", r, 0, 0);	// LDBU  *+SP[A0],r
1270 }
1271 
C67_LDW_PTR(int r, int r2)1272 void C67_LDW_PTR(int r, int r2)
1273 {
1274     C67_asm("LDW.D *", r, r2, 0);	// LDW  *r,r2
1275 }
1276 
C67_LDDW_PTR(int r, int r2)1277 void C67_LDDW_PTR(int r, int r2)
1278 {
1279     C67_asm("LDDW.D *", r, r2, 0);	// LDDW  *r,r2
1280 }
1281 
C67_LDH_PTR(int r, int r2)1282 void C67_LDH_PTR(int r, int r2)
1283 {
1284     C67_asm("LDH.D *", r, r2, 0);	// LDH  *r,r2
1285 }
1286 
C67_LDB_PTR(int r, int r2)1287 void C67_LDB_PTR(int r, int r2)
1288 {
1289     C67_asm("LDB.D *", r, r2, 0);	// LDB  *r,r2
1290 }
1291 
C67_LDHU_PTR(int r, int r2)1292 void C67_LDHU_PTR(int r, int r2)
1293 {
1294     C67_asm("LDHU.D *", r, r2, 0);	// LDHU  *r,r2
1295 }
1296 
C67_LDBU_PTR(int r, int r2)1297 void C67_LDBU_PTR(int r, int r2)
1298 {
1299     C67_asm("LDBU.D *", r, r2, 0);	// LDBU  *r,r2
1300 }
1301 
C67_LDW_PTR_PRE_INC(int r, int r2)1302 void C67_LDW_PTR_PRE_INC(int r, int r2)
1303 {
1304     C67_asm("LDW.D +*", r, r2, 0);	// LDW  *+r,r2
1305 }
1306 
C67_POP(int r)1307 void C67_POP(int r)
1308 {
1309     C67_asm("LDW.D SP PRE INC", r, 0, 0);	// LDW  *++SP,r
1310 }
1311 
C67_POP_DW(int r)1312 void C67_POP_DW(int r)
1313 {
1314     C67_asm("LDDW.D SP PRE INC", r, 0, 0);	// LDDW  *++SP,r
1315 }
1316 
C67_CMPLT(int s1, int s2, int dst)1317 void C67_CMPLT(int s1, int s2, int dst)
1318 {
1319     C67_asm("CMPLT.L1", s1, s2, dst);
1320 }
1321 
C67_CMPGT(int s1, int s2, int dst)1322 void C67_CMPGT(int s1, int s2, int dst)
1323 {
1324     C67_asm("CMPGT.L1", s1, s2, dst);
1325 }
1326 
C67_CMPEQ(int s1, int s2, int dst)1327 void C67_CMPEQ(int s1, int s2, int dst)
1328 {
1329     C67_asm("CMPEQ.L1", s1, s2, dst);
1330 }
1331 
C67_CMPLTU(int s1, int s2, int dst)1332 void C67_CMPLTU(int s1, int s2, int dst)
1333 {
1334     C67_asm("CMPLTU.L1", s1, s2, dst);
1335 }
1336 
C67_CMPGTU(int s1, int s2, int dst)1337 void C67_CMPGTU(int s1, int s2, int dst)
1338 {
1339     C67_asm("CMPGTU.L1", s1, s2, dst);
1340 }
1341 
1342 
C67_CMPLTSP(int s1, int s2, int dst)1343 void C67_CMPLTSP(int s1, int s2, int dst)
1344 {
1345     C67_asm("CMPLTSP.S1", s1, s2, dst);
1346 }
1347 
C67_CMPGTSP(int s1, int s2, int dst)1348 void C67_CMPGTSP(int s1, int s2, int dst)
1349 {
1350     C67_asm("CMPGTSP.S1", s1, s2, dst);
1351 }
1352 
C67_CMPEQSP(int s1, int s2, int dst)1353 void C67_CMPEQSP(int s1, int s2, int dst)
1354 {
1355     C67_asm("CMPEQSP.S1", s1, s2, dst);
1356 }
1357 
C67_CMPLTDP(int s1, int s2, int dst)1358 void C67_CMPLTDP(int s1, int s2, int dst)
1359 {
1360     C67_asm("CMPLTDP.S1", s1, s2, dst);
1361 }
1362 
C67_CMPGTDP(int s1, int s2, int dst)1363 void C67_CMPGTDP(int s1, int s2, int dst)
1364 {
1365     C67_asm("CMPGTDP.S1", s1, s2, dst);
1366 }
1367 
C67_CMPEQDP(int s1, int s2, int dst)1368 void C67_CMPEQDP(int s1, int s2, int dst)
1369 {
1370     C67_asm("CMPEQDP.S1", s1, s2, dst);
1371 }
1372 
1373 
C67_IREG_B_REG(int inv, int r1, int r2)1374 void C67_IREG_B_REG(int inv, int r1, int r2)	// [!R] B  r2
1375 {
1376     C67_asm("B.S2", inv, r1, r2);
1377 }
1378 
1379 
1380 // call with how many 32 bit words to skip
1381 // (0 would branch to the branch instruction)
1382 
C67_B_DISP(int disp)1383 void C67_B_DISP(int disp)	//  B  +2  Branch with constant displacement
1384 {
1385     // Branch point is relative to the 8 word fetch packet
1386     //
1387     // we will assume the text section always starts on an 8 word (32 byte boundary)
1388     //
1389     // so add in how many words into the fetch packet the branch is
1390 
1391 
1392     C67_asm("B DISP", disp + ((ind & 31) >> 2), 0, 0);
1393 }
1394 
C67_NOP(int n)1395 void C67_NOP(int n)
1396 {
1397     C67_asm("NOP", n, 0, 0);
1398 }
1399 
C67_ADDK(int n, int r)1400 void C67_ADDK(int n, int r)
1401 {
1402     ALWAYS_ASSERT(abs(n) < 32767);
1403 
1404     C67_asm("ADDK", n, r, 0);
1405 }
1406 
C67_ADDK_PARALLEL(int n, int r)1407 void C67_ADDK_PARALLEL(int n, int r)
1408 {
1409     ALWAYS_ASSERT(abs(n) < 32767);
1410 
1411     C67_asm("||ADDK", n, r, 0);
1412 }
1413 
C67_Adjust_ADDK(int *inst, int n)1414 void C67_Adjust_ADDK(int *inst, int n)
1415 {
1416     ALWAYS_ASSERT(abs(n) < 32767);
1417 
1418     *inst = (*inst & (~(0xffff << 7))) | ((n & 0xffff) << 7);
1419 }
1420 
C67_MV(int r, int v)1421 void C67_MV(int r, int v)
1422 {
1423     C67_asm("MV.L", 0, r, v);
1424 }
1425 
1426 
C67_DPTRUNC(int r, int v)1427 void C67_DPTRUNC(int r, int v)
1428 {
1429     C67_asm("DPTRUNC.L", 0, r, v);
1430 }
1431 
C67_SPTRUNC(int r, int v)1432 void C67_SPTRUNC(int r, int v)
1433 {
1434     C67_asm("SPTRUNC.L", 0, r, v);
1435 }
1436 
C67_INTSP(int r, int v)1437 void C67_INTSP(int r, int v)
1438 {
1439     C67_asm("INTSP.L", 0, r, v);
1440 }
1441 
C67_INTDP(int r, int v)1442 void C67_INTDP(int r, int v)
1443 {
1444     C67_asm("INTDP.L", 0, r, v);
1445 }
1446 
C67_INTSPU(int r, int v)1447 void C67_INTSPU(int r, int v)
1448 {
1449     C67_asm("INTSPU.L", 0, r, v);
1450 }
1451 
C67_INTDPU(int r, int v)1452 void C67_INTDPU(int r, int v)
1453 {
1454     C67_asm("INTDPU.L", 0, r, v);
1455 }
1456 
C67_SPDP(int r, int v)1457 void C67_SPDP(int r, int v)
1458 {
1459     C67_asm("SPDP.L", 0, r, v);
1460 }
1461 
C67_DPSP(int r, int v)1462 void C67_DPSP(int r, int v)	// note regs must be on the same side
1463 {
1464     C67_asm("DPSP.L", 0, r, v);
1465 }
1466 
C67_ADD(int r, int v)1467 void C67_ADD(int r, int v)
1468 {
1469     C67_asm("ADD.L", v, r, v);
1470 }
1471 
C67_SUB(int r, int v)1472 void C67_SUB(int r, int v)
1473 {
1474     C67_asm("SUB.L", v, r, v);
1475 }
1476 
C67_AND(int r, int v)1477 void C67_AND(int r, int v)
1478 {
1479     C67_asm("AND.L", v, r, v);
1480 }
1481 
C67_OR(int r, int v)1482 void C67_OR(int r, int v)
1483 {
1484     C67_asm("OR.L", v, r, v);
1485 }
1486 
C67_XOR(int r, int v)1487 void C67_XOR(int r, int v)
1488 {
1489     C67_asm("XOR.L", v, r, v);
1490 }
1491 
C67_ADDSP(int r, int v)1492 void C67_ADDSP(int r, int v)
1493 {
1494     C67_asm("ADDSP.L", v, r, v);
1495 }
1496 
C67_SUBSP(int r, int v)1497 void C67_SUBSP(int r, int v)
1498 {
1499     C67_asm("SUBSP.L", v, r, v);
1500 }
1501 
C67_MPYSP(int r, int v)1502 void C67_MPYSP(int r, int v)
1503 {
1504     C67_asm("MPYSP.M", v, r, v);
1505 }
1506 
C67_ADDDP(int r, int v)1507 void C67_ADDDP(int r, int v)
1508 {
1509     C67_asm("ADDDP.L", v, r, v);
1510 }
1511 
C67_SUBDP(int r, int v)1512 void C67_SUBDP(int r, int v)
1513 {
1514     C67_asm("SUBDP.L", v, r, v);
1515 }
1516 
C67_MPYDP(int r, int v)1517 void C67_MPYDP(int r, int v)
1518 {
1519     C67_asm("MPYDP.M", v, r, v);
1520 }
1521 
C67_MPYI(int r, int v)1522 void C67_MPYI(int r, int v)
1523 {
1524     C67_asm("MPYI.M", v, r, v);
1525 }
1526 
C67_SHL(int r, int v)1527 void C67_SHL(int r, int v)
1528 {
1529     C67_asm("SHL.S", r, v, v);
1530 }
1531 
C67_SHRU(int r, int v)1532 void C67_SHRU(int r, int v)
1533 {
1534     C67_asm("SHRU.S", r, v, v);
1535 }
1536 
C67_SHR(int r, int v)1537 void C67_SHR(int r, int v)
1538 {
1539     C67_asm("SHR.S", r, v, v);
1540 }
1541 
1542 
1543 
1544 /* load 'r' from value 'sv' */
load(int r, SValue * sv)1545 void load(int r, SValue * sv)
1546 {
1547     int v, t, ft, fc, fr, size = 0, element;
1548     BOOL Unsigned = FALSE;
1549     SValue v1;
1550 
1551     fr = sv->r;
1552     ft = sv->type.t;
1553     fc = sv->c.i;
1554 
1555     v = fr & VT_VALMASK;
1556     if (fr & VT_LVAL) {
1557 	if (v == VT_LLOCAL) {
1558 	    v1.type.t = VT_INT;
1559 	    v1.r = VT_LOCAL | VT_LVAL;
1560 	    v1.c.i = fc;
1561 	    load(r, &v1);
1562 	    fr = r;
1563 	} else if ((ft & VT_BTYPE) == VT_LDOUBLE) {
1564 	    tcc_error("long double not supported");
1565 	} else if ((ft & VT_TYPE) == VT_BYTE) {
1566 	    size = 1;
1567 	} else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED)) {
1568 	    size = 1;
1569 	    Unsigned = TRUE;
1570 	} else if ((ft & VT_TYPE) == VT_SHORT) {
1571 	    size = 2;
1572 	} else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED)) {
1573 	    size = 2;
1574 	    Unsigned = TRUE;
1575 	} else if ((ft & VT_BTYPE) == VT_DOUBLE) {
1576 	    size = 8;
1577 	} else {
1578 	    size = 4;
1579 	}
1580 
1581 	// check if fc is a positive reference on the stack,
1582 	// if it is tcc is referencing what it thinks is a parameter
1583 	// on the stack, so check if it is really in a register.
1584 
1585 
1586 	if (v == VT_LOCAL && fc > 0) {
1587 	    int stack_pos = 8;
1588 
1589 	    for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1590 		if (fc == stack_pos)
1591 		    break;
1592 
1593 		stack_pos += TranslateStackToReg[t];
1594 	    }
1595 
1596 	    // param has been pushed on stack, get it like a local var
1597 
1598 	    fc = ParamLocOnStack[t] - 8;
1599 	}
1600 
1601 	if ((fr & VT_VALMASK) < VT_CONST)	// check for pure indirect
1602 	{
1603 	    if (size == 1) {
1604 		if (Unsigned)
1605 		    C67_LDBU_PTR(v, r);	// LDBU  *v,r
1606 		else
1607 		    C67_LDB_PTR(v, r);	// LDB  *v,r
1608 	    } else if (size == 2) {
1609 		if (Unsigned)
1610 		    C67_LDHU_PTR(v, r);	// LDHU  *v,r
1611 		else
1612 		    C67_LDH_PTR(v, r);	// LDH  *v,r
1613 	    } else if (size == 4) {
1614 		C67_LDW_PTR(v, r);	// LDW  *v,r
1615 	    } else if (size == 8) {
1616 		C67_LDDW_PTR(v, r);	// LDDW  *v,r
1617 	    }
1618 
1619 	    C67_NOP(4);		// NOP 4
1620 	    return;
1621 	} else if (fr & VT_SYM) {
1622 	    greloc(cur_text_section, sv->sym, ind, R_C60LO16);	// rem the inst need to be patched
1623 	    greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1624 
1625 
1626 	    C67_MVKL(C67_A0, fc);	//r=reg to load,  constant
1627 	    C67_MVKH(C67_A0, fc);	//r=reg to load,  constant
1628 
1629 
1630 	    if (size == 1) {
1631 		if (Unsigned)
1632 		    C67_LDBU_PTR(C67_A0, r);	// LDBU  *A0,r
1633 		else
1634 		    C67_LDB_PTR(C67_A0, r);	// LDB  *A0,r
1635 	    } else if (size == 2) {
1636 		if (Unsigned)
1637 		    C67_LDHU_PTR(C67_A0, r);	// LDHU  *A0,r
1638 		else
1639 		    C67_LDH_PTR(C67_A0, r);	// LDH  *A0,r
1640 	    } else if (size == 4) {
1641 		C67_LDW_PTR(C67_A0, r);	// LDW  *A0,r
1642 	    } else if (size == 8) {
1643 		C67_LDDW_PTR(C67_A0, r);	// LDDW  *A0,r
1644 	    }
1645 
1646 	    C67_NOP(4);		// NOP 4
1647 	    return;
1648 	} else {
1649 	    element = size;
1650 
1651 	    // divide offset in bytes to create element index
1652 	    C67_MVKL(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
1653 	    C67_MVKH(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
1654 
1655 	    if (size == 1) {
1656 		if (Unsigned)
1657 		    C67_LDBU_SP_A0(r);	// LDBU  r, SP[A0]
1658 		else
1659 		    C67_LDB_SP_A0(r);	// LDB  r, SP[A0]
1660 	    } else if (size == 2) {
1661 		if (Unsigned)
1662 		    C67_LDHU_SP_A0(r);	// LDHU  r, SP[A0]
1663 		else
1664 		    C67_LDH_SP_A0(r);	// LDH  r, SP[A0]
1665 	    } else if (size == 4) {
1666 		C67_LDW_SP_A0(r);	// LDW  r, SP[A0]
1667 	    } else if (size == 8) {
1668 		C67_LDDW_SP_A0(r);	// LDDW  r, SP[A0]
1669 	    }
1670 
1671 
1672 	    C67_NOP(4);		// NOP 4
1673 	    return;
1674 	}
1675     } else {
1676 	if (v == VT_CONST) {
1677 	    if (fr & VT_SYM) {
1678 		greloc(cur_text_section, sv->sym, ind, R_C60LO16);	// rem the inst need to be patched
1679 		greloc(cur_text_section, sv->sym, ind + 4, R_C60HI16);
1680 	    }
1681 	    C67_MVKL(r, fc);	//r=reg to load, constant
1682 	    C67_MVKH(r, fc);	//r=reg to load, constant
1683 	} else if (v == VT_LOCAL) {
1684 	    C67_MVKL(r, fc + 8);	//r=reg to load, constant C67 stack points to next free
1685 	    C67_MVKH(r, fc + 8);	//r=reg to load, constant
1686 	    C67_ADD(C67_FP, r);	// MV v,r   v -> r
1687 	} else if (v == VT_CMP) {
1688 	    C67_MV(C67_compare_reg, r);	// MV v,r   v -> r
1689 	} else if (v == VT_JMP || v == VT_JMPI) {
1690 	    t = v & 1;
1691 	    C67_B_DISP(4);	//  Branch with constant displacement, skip over this branch, load, nop, load
1692 	    C67_MVKL(r, t);	//  r=reg to load, 0 or 1 (do this while branching)
1693 	    C67_NOP(4);		//  NOP 4
1694 	    gsym(fc);		//  modifies other branches to branch here
1695 	    C67_MVKL(r, t ^ 1);	//  r=reg to load, 0 or 1
1696 	} else if (v != r) {
1697 	    C67_MV(v, r);	// MV v,r   v -> r
1698 
1699 	    if ((ft & VT_BTYPE) == VT_DOUBLE)
1700 		C67_MV(v + 1, r + 1);	// MV v,r   v -> r
1701 	}
1702     }
1703 }
1704 
1705 
1706 /* store register 'r' in lvalue 'v' */
store(int r, SValue * v)1707 void store(int r, SValue * v)
1708 {
1709     int fr, bt, ft, fc, size, t, element;
1710 
1711     ft = v->type.t;
1712     fc = v->c.i;
1713     fr = v->r & VT_VALMASK;
1714     bt = ft & VT_BTYPE;
1715     /* XXX: incorrect if float reg to reg */
1716 
1717     if (bt == VT_LDOUBLE) {
1718 	tcc_error("long double not supported");
1719     } else {
1720 	if (bt == VT_SHORT)
1721 	    size = 2;
1722 	else if (bt == VT_BYTE)
1723 	    size = 1;
1724 	else if (bt == VT_DOUBLE)
1725 	    size = 8;
1726 	else
1727 	    size = 4;
1728 
1729 	if ((v->r & VT_VALMASK) == VT_CONST) {
1730 	    /* constant memory reference */
1731 
1732 	    if (v->r & VT_SYM) {
1733 		greloc(cur_text_section, v->sym, ind, R_C60LO16);	// rem the inst need to be patched
1734 		greloc(cur_text_section, v->sym, ind + 4, R_C60HI16);
1735 	    }
1736 	    C67_MVKL(C67_A0, fc);	//r=reg to load,  constant
1737 	    C67_MVKH(C67_A0, fc);	//r=reg to load,  constant
1738 
1739 	    if (size == 1)
1740 		C67_STB_PTR(r, C67_A0);	// STB  r, *A0
1741 	    else if (size == 2)
1742 		C67_STH_PTR(r, C67_A0);	// STH  r, *A0
1743 	    else if (size == 4 || size == 8)
1744 		C67_STW_PTR(r, C67_A0);	// STW  r, *A0
1745 
1746 	    if (size == 8)
1747 		C67_STW_PTR_PRE_INC(r + 1, C67_A0, 1);	// STW  r, *+A0[1]
1748 	} else if ((v->r & VT_VALMASK) == VT_LOCAL) {
1749 	    // check case of storing to passed argument that
1750 	    // tcc thinks is on the stack but for C67 is
1751 	    // passed as a reg.  However it may have been
1752 	    // saved to the stack, if that reg was required
1753 	    // for a call to a child function
1754 
1755 	    if (fc > 0)		// argument ??
1756 	    {
1757 		// walk through sizes and figure which param
1758 
1759 		int stack_pos = 8;
1760 
1761 		for (t = 0; t < NoCallArgsPassedOnStack; t++) {
1762 		    if (fc == stack_pos)
1763 			break;
1764 
1765 		    stack_pos += TranslateStackToReg[t];
1766 		}
1767 
1768 		// param has been pushed on stack, get it like a local var
1769 		fc = ParamLocOnStack[t] - 8;
1770 	    }
1771 
1772 	    if (size == 8)
1773 		element = 4;
1774 	    else
1775 		element = size;
1776 
1777 	    // divide offset in bytes to create word index
1778 	    C67_MVKL(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
1779 	    C67_MVKH(C67_A0, (fc / element) + 8 / element);	//r=reg to load,  constant
1780 
1781 
1782 
1783 	    if (size == 1)
1784 		C67_STB_SP_A0(r);	// STB  r, SP[A0]
1785 	    else if (size == 2)
1786 		C67_STH_SP_A0(r);	// STH  r, SP[A0]
1787 	    else if (size == 4 || size == 8)
1788 		C67_STW_SP_A0(r);	// STW  r, SP[A0]
1789 
1790 	    if (size == 8) {
1791 		C67_ADDK(1, C67_A0);	//  ADDK 1,A0
1792 		C67_STW_SP_A0(r + 1);	//  STW  r, SP[A0]
1793 	    }
1794 	} else {
1795 	    if (size == 1)
1796 		C67_STB_PTR(r, fr);	// STB  r, *fr
1797 	    else if (size == 2)
1798 		C67_STH_PTR(r, fr);	// STH  r, *fr
1799 	    else if (size == 4 || size == 8)
1800 		C67_STW_PTR(r, fr);	// STW  r, *fr
1801 
1802 	    if (size == 8) {
1803 		C67_STW_PTR_PRE_INC(r + 1, fr, 1);	// STW  r, *+fr[1]
1804 	    }
1805 	}
1806     }
1807 }
1808 
1809 /* 'is_jmp' is '1' if it is a jump */
gcall_or_jmp(int is_jmp)1810 static void gcall_or_jmp(int is_jmp)
1811 {
1812     int r;
1813     Sym *sym;
1814 
1815     if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
1816 	/* constant case */
1817 	if (vtop->r & VT_SYM) {
1818 	    /* relocation case */
1819 
1820 	    // get add into A0, then start the jump B3
1821 
1822 	    greloc(cur_text_section, vtop->sym, ind, R_C60LO16);	// rem the inst need to be patched
1823 	    greloc(cur_text_section, vtop->sym, ind + 4, R_C60HI16);
1824 
1825 	    C67_MVKL(C67_A0, 0);	//r=reg to load, constant
1826 	    C67_MVKH(C67_A0, 0);	//r=reg to load, constant
1827 	    C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0);	//  B.S2x  A0
1828 
1829 	    if (is_jmp) {
1830 		C67_NOP(5);	// simple jump, just put NOP
1831 	    } else {
1832 		// Call, must load return address into B3 during delay slots
1833 
1834 		sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0);	// symbol for return address
1835 		greloc(cur_text_section, sym, ind, R_C60LO16);	// rem the inst need to be patched
1836 		greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1837 		C67_MVKL(C67_B3, 0);	//r=reg to load, constant
1838 		C67_MVKH(C67_B3, 0);	//r=reg to load, constant
1839 		C67_NOP(3);	// put remaining NOPs
1840 	    }
1841 	} else {
1842 	    /* put an empty PC32 relocation */
1843 	    ALWAYS_ASSERT(FALSE);
1844 	}
1845     } else {
1846 	/* otherwise, indirect call */
1847 	r = gv(RC_INT);
1848 	C67_IREG_B_REG(0, C67_CREG_ZERO, r);	//  B.S2x  r
1849 
1850 	if (is_jmp) {
1851 	    C67_NOP(5);		// simple jump, just put NOP
1852 	} else {
1853 	    // Call, must load return address into B3 during delay slots
1854 
1855 	    sym = get_sym_ref(&char_pointer_type, cur_text_section, ind + 12, 0);	// symbol for return address
1856 	    greloc(cur_text_section, sym, ind, R_C60LO16);	// rem the inst need to be patched
1857 	    greloc(cur_text_section, sym, ind + 4, R_C60HI16);
1858 	    C67_MVKL(C67_B3, 0);	//r=reg to load, constant
1859 	    C67_MVKH(C67_B3, 0);	//r=reg to load, constant
1860 	    C67_NOP(3);		// put remaining NOPs
1861 	}
1862     }
1863 }
1864 
1865 /* Return the number of registers needed to return the struct, or 0 if
1866    returning via struct pointer. */
gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize)1867 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, int *ret_align, int *regsize) {
1868     *ret_align = 1; // Never have to re-align return values for x86-64
1869     return 0;
1870 }
1871 
1872 /* generate function call with address in (vtop->t, vtop->c) and free function
1873    context. Stack entry is popped */
gfunc_call(int nb_args)1874 void gfunc_call(int nb_args)
1875 {
1876     int i, r, size = 0;
1877     int args_sizes[NoCallArgsPassedOnStack];
1878 
1879     if (nb_args > NoCallArgsPassedOnStack) {
1880 	tcc_error("more than 10 function params not currently supported");
1881 	// handle more than 10, put some on the stack
1882     }
1883 
1884     for (i = 0; i < nb_args; i++) {
1885 	if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
1886 	    ALWAYS_ASSERT(FALSE);
1887 	} else {
1888 	    /* simple type (currently always same size) */
1889 	    /* XXX: implicit cast ? */
1890 
1891 
1892 	    if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
1893 		tcc_error("long long not supported");
1894 	    } else if ((vtop->type.t & VT_BTYPE) == VT_LDOUBLE) {
1895 		tcc_error("long double not supported");
1896 	    } else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
1897 		size = 8;
1898 	    } else {
1899 		size = 4;
1900 	    }
1901 
1902 	    // put the parameter into the corresponding reg (pair)
1903 
1904 	    r = gv(RC_C67_A4 << (2 * i));
1905 
1906 	    // must put on stack because with 1 pass compiler , no way to tell
1907 	    // if an up coming nested call might overwrite these regs
1908 
1909 	    C67_PUSH(r);
1910 
1911 	    if (size == 8) {
1912 		C67_STW_PTR_PRE_INC(r + 1, C67_SP, 3);	// STW  r, *+SP[3] (go back and put the other)
1913 	    }
1914 	    args_sizes[i] = size;
1915 	}
1916 	vtop--;
1917     }
1918     // POP all the params on the stack into registers for the
1919     // immediate call (in reverse order)
1920 
1921     for (i = nb_args - 1; i >= 0; i--) {
1922 
1923 	if (args_sizes[i] == 8)
1924 	    C67_POP_DW(TREG_C67_A4 + i * 2);
1925 	else
1926 	    C67_POP(TREG_C67_A4 + i * 2);
1927     }
1928     gcall_or_jmp(0);
1929     vtop--;
1930 }
1931 
1932 
1933 // to be compatible with Code Composer for the C67
1934 // the first 10 parameters must be passed in registers
1935 // (pairs for 64 bits) starting wit; A4:A5, then B4:B5 and
1936 // ending with B12:B13.
1937 //
1938 // When a call is made, if the caller has its parameters
1939 // in regs A4-B13 these must be saved before/as the call
1940 // parameters are loaded and restored upon return (or if/when needed).
1941 
1942 /* generate function prolog of type 't' */
gfunc_prolog(Sym *func_sym)1943 void gfunc_prolog(Sym *func_sym)
1944 {
1945     CType *func_type = &func_sym->type;
1946     int addr, align, size, func_call, i;
1947     Sym *sym;
1948     CType *type;
1949 
1950     sym = func_type->ref;
1951     func_call = sym->f.func_call;
1952     addr = 8;
1953     /* if the function returns a structure, then add an
1954        implicit pointer parameter */
1955     if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
1956 	func_vc = addr;
1957 	addr += 4;
1958     }
1959 
1960     NoOfCurFuncArgs = 0;
1961 
1962     /* define parameters */
1963     while ((sym = sym->next) != NULL) {
1964 	type = &sym->type;
1965 	sym_push(sym->v & ~SYM_FIELD, type, VT_LOCAL | VT_LVAL, addr);
1966 	size = type_size(type, &align);
1967 	size = (size + 3) & ~3;
1968 
1969 	// keep track of size of arguments so
1970 	// we can translate where tcc thinks they
1971 	// are on the stack into the appropriate reg
1972 
1973 	TranslateStackToReg[NoOfCurFuncArgs] = size;
1974 	NoOfCurFuncArgs++;
1975 
1976 #ifdef FUNC_STRUCT_PARAM_AS_PTR
1977 	/* structs are passed as pointer */
1978 	if ((type->t & VT_BTYPE) == VT_STRUCT) {
1979 	    size = 4;
1980 	}
1981 #endif
1982 	addr += size;
1983     }
1984     func_ret_sub = 0;
1985     /* pascal type call ? */
1986     if (func_call == FUNC_STDCALL)
1987 	func_ret_sub = addr - 8;
1988 
1989     C67_MV(C67_FP, C67_A0);	//  move FP -> A0
1990     C67_MV(C67_SP, C67_FP);	//  move SP -> FP
1991 
1992     // place all the args passed in regs onto the stack
1993 
1994     loc = 0;
1995     for (i = 0; i < NoOfCurFuncArgs; i++) {
1996 
1997 	ParamLocOnStack[i] = loc;	// remember where the param is
1998 	loc += -8;
1999 
2000 	C67_PUSH(TREG_C67_A4 + i * 2);
2001 
2002 	if (TranslateStackToReg[i] == 8) {
2003 	    C67_STW_PTR_PRE_INC(TREG_C67_A4 + i * 2 + 1, C67_SP, 3);	// STW  r, *+SP[1] (go back and put the other)
2004 	}
2005     }
2006 
2007     TotalBytesPushedOnStack = -loc;
2008 
2009     func_sub_sp_offset = ind;	// remember where we put the stack instruction
2010     C67_ADDK(0, C67_SP);	//  ADDK.L2 loc,SP  (just put zero temporarily)
2011 
2012     C67_PUSH(C67_A0);
2013     C67_PUSH(C67_B3);
2014 }
2015 
2016 /* generate function epilog */
gfunc_epilog(void)2017 void gfunc_epilog(void)
2018 {
2019     {
2020 	int local = (-loc + 7) & -8;	// stack must stay aligned to 8 bytes for LDDW instr
2021 	C67_POP(C67_B3);
2022 	C67_NOP(4);		// NOP wait for load
2023 	C67_IREG_B_REG(0, C67_CREG_ZERO, C67_B3);	//  B.S2  B3
2024 	C67_POP(C67_FP);
2025 	C67_ADDK(local, C67_SP);	//  ADDK.L2 loc,SP
2026 	C67_Adjust_ADDK((int *) (cur_text_section->data +
2027 				 func_sub_sp_offset),
2028 			-local + TotalBytesPushedOnStack);
2029 	C67_NOP(3);		// NOP
2030     }
2031 }
2032 
gen_fill_nops(int bytes)2033 ST_FUNC void gen_fill_nops(int bytes)
2034 {
2035     if ((bytes & 3))
2036       tcc_error("alignment of code section not multiple of 4");
2037     while (bytes > 0) {
2038 	C67_NOP(4);
2039 	bytes -= 4;
2040     }
2041 }
2042 
2043 /* generate a jump to a label */
gjmp(int t)2044 int gjmp(int t)
2045 {
2046     int ind1 = ind;
2047     if (nocode_wanted)
2048         return t;
2049 
2050     C67_MVKL(C67_A0, t);	//r=reg to load,  constant
2051     C67_MVKH(C67_A0, t);	//r=reg to load,  constant
2052     C67_IREG_B_REG(0, C67_CREG_ZERO, C67_A0);	// [!R] B.S2x  A0
2053     C67_NOP(5);
2054     return ind1;
2055 }
2056 
2057 /* generate a jump to a fixed address */
gjmp_addr(int a)2058 void gjmp_addr(int a)
2059 {
2060     Sym *sym;
2061     // I guess this routine is used for relative short
2062     // local jumps, for now just handle it as the general
2063     // case
2064 
2065     // define a label that will be relocated
2066 
2067     sym = get_sym_ref(&char_pointer_type, cur_text_section, a, 0);
2068     greloc(cur_text_section, sym, ind, R_C60LO16);
2069     greloc(cur_text_section, sym, ind + 4, R_C60HI16);
2070 
2071     gjmp(0);			// place a zero there later the symbol will be added to it
2072 }
2073 
2074 /* generate a test. set 'inv' to invert test. Stack entry is popped */
gjmp_cond(int op, int t)2075 ST_FUNC int gjmp_cond(int op, int t)
2076 {
2077         int ind1;
2078         int inv = op & 1;
2079         if (nocode_wanted)
2080             return t;
2081 
2082 	/* fast case : can jump directly since flags are set */
2083 	// C67 uses B2 sort of as flags register
2084 	ind1 = ind;
2085 	C67_MVKL(C67_A0, t);	//r=reg to load, constant
2086 	C67_MVKH(C67_A0, t);	//r=reg to load, constant
2087 
2088 	if (C67_compare_reg != TREG_EAX &&	// check if not already in a conditional test reg
2089 	    C67_compare_reg != TREG_EDX &&
2090 	    C67_compare_reg != TREG_ST0 && C67_compare_reg != C67_B2) {
2091 	    C67_MV(C67_compare_reg, C67_B2);
2092 	    C67_compare_reg = C67_B2;
2093 	}
2094 
2095 	C67_IREG_B_REG(C67_invert_test ^ inv, C67_compare_reg, C67_A0);	// [!R] B.S2x  A0
2096 	C67_NOP(5);
2097 	t = ind1;		//return where we need to patch
2098 
2099         return t;
2100 }
2101 
gjmp_append(int n0, int t)2102 ST_FUNC int gjmp_append(int n0, int t)
2103 {
2104     if (n0) {
2105             int n = n0, *p;
2106 	    /* insert vtop->c jump list in t */
2107 
2108 	    // I guess the idea is to traverse to the
2109 	    // null at the end of the list and store t
2110 	    // there
2111 	    while (n != 0) {
2112 		p = (int *) (cur_text_section->data + n);
2113 
2114 		// extract 32 bit address from MVKH/MVKL
2115 		n = ((*p >> 7) & 0xffff);
2116 		n |= ((*(p + 1) >> 7) & 0xffff) << 16;
2117 	    }
2118 	    *p |= (t & 0xffff) << 7;
2119 	    *(p + 1) |= ((t >> 16) & 0xffff) << 7;
2120 	    t = n0;
2121     }
2122     return t;
2123 }
2124 
2125 /* generate an integer binary operation */
gen_opi(int op)2126 void gen_opi(int op)
2127 {
2128     int r, fr, opc, t;
2129 
2130     switch (op) {
2131     case '+':
2132     case TOK_ADDC1:		/* add with carry generation */
2133 	opc = 0;
2134       gen_op8:
2135 
2136 
2137 // C67 can't do const compares, must load into a reg
2138 // so just go to gv2 directly - tktk
2139 
2140 
2141 
2142 	if (op >= TOK_ULT && op <= TOK_GT)
2143 	    gv2(RC_INT_BSIDE, RC_INT);	// make sure r (src1) is on the B Side of CPU
2144 	else
2145 	    gv2(RC_INT, RC_INT);
2146 
2147 	r = vtop[-1].r;
2148 	fr = vtop[0].r;
2149 
2150 	C67_compare_reg = C67_B2;
2151 
2152 
2153 	if (op == TOK_LT) {
2154 	    C67_CMPLT(r, fr, C67_B2);
2155 	    C67_invert_test = FALSE;
2156 	} else if (op == TOK_GE) {
2157 	    C67_CMPLT(r, fr, C67_B2);
2158 	    C67_invert_test = TRUE;
2159 	} else if (op == TOK_GT) {
2160 	    C67_CMPGT(r, fr, C67_B2);
2161 	    C67_invert_test = FALSE;
2162 	} else if (op == TOK_LE) {
2163 	    C67_CMPGT(r, fr, C67_B2);
2164 	    C67_invert_test = TRUE;
2165 	} else if (op == TOK_EQ) {
2166 	    C67_CMPEQ(r, fr, C67_B2);
2167 	    C67_invert_test = FALSE;
2168 	} else if (op == TOK_NE) {
2169 	    C67_CMPEQ(r, fr, C67_B2);
2170 	    C67_invert_test = TRUE;
2171 	} else if (op == TOK_ULT) {
2172 	    C67_CMPLTU(r, fr, C67_B2);
2173 	    C67_invert_test = FALSE;
2174 	} else if (op == TOK_UGE) {
2175 	    C67_CMPLTU(r, fr, C67_B2);
2176 	    C67_invert_test = TRUE;
2177 	} else if (op == TOK_UGT) {
2178 	    C67_CMPGTU(r, fr, C67_B2);
2179 	    C67_invert_test = FALSE;
2180 	} else if (op == TOK_ULE) {
2181 	    C67_CMPGTU(r, fr, C67_B2);
2182 	    C67_invert_test = TRUE;
2183 	} else if (op == '+')
2184 	    C67_ADD(fr, r);	// ADD  r,fr,r
2185 	else if (op == '-')
2186 	    C67_SUB(fr, r);	// SUB  r,fr,r
2187 	else if (op == '&')
2188 	    C67_AND(fr, r);	// AND  r,fr,r
2189 	else if (op == '|')
2190 	    C67_OR(fr, r);	// OR  r,fr,r
2191 	else if (op == '^')
2192 	    C67_XOR(fr, r);	// XOR  r,fr,r
2193 	else
2194 	    ALWAYS_ASSERT(FALSE);
2195 
2196 	vtop--;
2197 	if (op >= TOK_ULT && op <= TOK_GT)
2198             vset_VT_CMP(0x80);
2199 	break;
2200     case '-':
2201     case TOK_SUBC1:		/* sub with carry generation */
2202 	opc = 5;
2203 	goto gen_op8;
2204     case TOK_ADDC2:		/* add with carry use */
2205 	opc = 2;
2206 	goto gen_op8;
2207     case TOK_SUBC2:		/* sub with carry use */
2208 	opc = 3;
2209 	goto gen_op8;
2210     case '&':
2211 	opc = 4;
2212 	goto gen_op8;
2213     case '^':
2214 	opc = 6;
2215 	goto gen_op8;
2216     case '|':
2217 	opc = 1;
2218 	goto gen_op8;
2219     case '*':
2220     case TOK_UMULL:
2221 	gv2(RC_INT, RC_INT);
2222 	r = vtop[-1].r;
2223 	fr = vtop[0].r;
2224 	vtop--;
2225 	C67_MPYI(fr, r);	// 32 bit multiply  fr,r,fr
2226 	C67_NOP(8);		// NOP 8 for worst case
2227 	break;
2228     case TOK_SHL:
2229 	gv2(RC_INT_BSIDE, RC_INT_BSIDE);	// shift amount must be on same side as dst
2230 	r = vtop[-1].r;
2231 	fr = vtop[0].r;
2232 	vtop--;
2233 	C67_SHL(fr, r);		// arithmetic/logical shift
2234 	break;
2235 
2236     case TOK_SHR:
2237 	gv2(RC_INT_BSIDE, RC_INT_BSIDE);	// shift amount must be on same side as dst
2238 	r = vtop[-1].r;
2239 	fr = vtop[0].r;
2240 	vtop--;
2241 	C67_SHRU(fr, r);	// logical shift
2242 	break;
2243 
2244     case TOK_SAR:
2245 	gv2(RC_INT_BSIDE, RC_INT_BSIDE);	// shift amount must be on same side as dst
2246 	r = vtop[-1].r;
2247 	fr = vtop[0].r;
2248 	vtop--;
2249 	C67_SHR(fr, r);		// arithmetic shift
2250 	break;
2251 
2252     case '/':
2253 	t = TOK__divi;
2254       call_func:
2255 	vswap();
2256 	/* call generic idiv function */
2257 	vpush_global_sym(&func_old_type, t);
2258 	vrott(3);
2259 	gfunc_call(2);
2260 	vpushi(0);
2261 	vtop->r = REG_IRET;
2262 	vtop->r2 = VT_CONST;
2263 	break;
2264     case TOK_UDIV:
2265     case TOK_PDIV:
2266 	t = TOK__divu;
2267 	goto call_func;
2268     case '%':
2269 	t = TOK__remi;
2270 	goto call_func;
2271     case TOK_UMOD:
2272 	t = TOK__remu;
2273 	goto call_func;
2274 
2275     default:
2276 	opc = 7;
2277 	goto gen_op8;
2278     }
2279 }
2280 
2281 /* generate a floating point operation 'v = t1 op t2' instruction. The
2282    two operands are guaranteed to have the same floating point type */
2283 /* XXX: need to use ST1 too */
gen_opf(int op)2284 void gen_opf(int op)
2285 {
2286     int ft, fc, fr, r;
2287 
2288     if (op >= TOK_ULT && op <= TOK_GT)
2289 	gv2(RC_EDX, RC_EAX);	// make sure src2 is on b side
2290     else
2291 	gv2(RC_FLOAT, RC_FLOAT);	// make sure src2 is on b side
2292 
2293     ft = vtop->type.t;
2294     fc = vtop->c.i;
2295     r = vtop->r;
2296     fr = vtop[-1].r;
2297 
2298 
2299     if ((ft & VT_BTYPE) == VT_LDOUBLE)
2300 	tcc_error("long doubles not supported");
2301 
2302     if (op >= TOK_ULT && op <= TOK_GT) {
2303 
2304 	r = vtop[-1].r;
2305 	fr = vtop[0].r;
2306 
2307 	C67_compare_reg = C67_B2;
2308 
2309 	if (op == TOK_LT) {
2310 	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2311 		C67_CMPLTDP(r, fr, C67_B2);
2312 	    else
2313 		C67_CMPLTSP(r, fr, C67_B2);
2314 
2315 	    C67_invert_test = FALSE;
2316 	} else if (op == TOK_GE) {
2317 	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2318 		C67_CMPLTDP(r, fr, C67_B2);
2319 	    else
2320 		C67_CMPLTSP(r, fr, C67_B2);
2321 
2322 	    C67_invert_test = TRUE;
2323 	} else if (op == TOK_GT) {
2324 	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2325 		C67_CMPGTDP(r, fr, C67_B2);
2326 	    else
2327 		C67_CMPGTSP(r, fr, C67_B2);
2328 
2329 	    C67_invert_test = FALSE;
2330 	} else if (op == TOK_LE) {
2331 	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2332 		C67_CMPGTDP(r, fr, C67_B2);
2333 	    else
2334 		C67_CMPGTSP(r, fr, C67_B2);
2335 
2336 	    C67_invert_test = TRUE;
2337 	} else if (op == TOK_EQ) {
2338 	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2339 		C67_CMPEQDP(r, fr, C67_B2);
2340 	    else
2341 		C67_CMPEQSP(r, fr, C67_B2);
2342 
2343 	    C67_invert_test = FALSE;
2344 	} else if (op == TOK_NE) {
2345 	    if ((ft & VT_BTYPE) == VT_DOUBLE)
2346 		C67_CMPEQDP(r, fr, C67_B2);
2347 	    else
2348 		C67_CMPEQSP(r, fr, C67_B2);
2349 
2350 	    C67_invert_test = TRUE;
2351 	} else {
2352 	    ALWAYS_ASSERT(FALSE);
2353 	}
2354         vset_VT_CMP(0x80);
2355     } else {
2356 	if (op == '+') {
2357 	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
2358 		C67_ADDDP(r, fr);	// ADD  fr,r,fr
2359 		C67_NOP(6);
2360 	    } else {
2361 		C67_ADDSP(r, fr);	// ADD  fr,r,fr
2362 		C67_NOP(3);
2363 	    }
2364 	    vtop--;
2365 	} else if (op == '-') {
2366 	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
2367 		C67_SUBDP(r, fr);	// SUB  fr,r,fr
2368 		C67_NOP(6);
2369 	    } else {
2370 		C67_SUBSP(r, fr);	// SUB  fr,r,fr
2371 		C67_NOP(3);
2372 	    }
2373 	    vtop--;
2374 	} else if (op == '*') {
2375 	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
2376 		C67_MPYDP(r, fr);	// MPY  fr,r,fr
2377 		C67_NOP(9);
2378 	    } else {
2379 		C67_MPYSP(r, fr);	// MPY  fr,r,fr
2380 		C67_NOP(3);
2381 	    }
2382 	    vtop--;
2383 	} else if (op == '/') {
2384 	    if ((ft & VT_BTYPE) == VT_DOUBLE) {
2385 		// must call intrinsic DP floating point divide
2386 		vswap();
2387 		/* call generic idiv function */
2388 		vpush_global_sym(&func_old_type, TOK__divd);
2389 		vrott(3);
2390 		gfunc_call(2);
2391 		vpushi(0);
2392 		vtop->r = REG_FRET;
2393 		vtop->r2 = REG_IRE2;
2394 
2395 	    } else {
2396 		// must call intrinsic SP floating point divide
2397 		vswap();
2398 		/* call generic idiv function */
2399 		vpush_global_sym(&func_old_type, TOK__divf);
2400 		vrott(3);
2401 		gfunc_call(2);
2402 		vpushi(0);
2403 		vtop->r = REG_FRET;
2404 		vtop->r2 = VT_CONST;
2405 	    }
2406 	} else
2407 	    ALWAYS_ASSERT(FALSE);
2408 
2409 
2410     }
2411 }
2412 
2413 
2414 /* convert integers to fp 't' type. Must handle 'int', 'unsigned int'
2415    and 'long long' cases. */
gen_cvt_itof(int t)2416 void gen_cvt_itof(int t)
2417 {
2418     int r;
2419 
2420     gv(RC_INT);
2421     r = vtop->r;
2422 
2423     if ((t & VT_BTYPE) == VT_DOUBLE) {
2424 	if (t & VT_UNSIGNED)
2425 	    C67_INTDPU(r, r);
2426 	else
2427 	    C67_INTDP(r, r);
2428 
2429 	C67_NOP(4);
2430 	vtop->type.t = VT_DOUBLE;
2431     } else {
2432 	if (t & VT_UNSIGNED)
2433 	    C67_INTSPU(r, r);
2434 	else
2435 	    C67_INTSP(r, r);
2436 	C67_NOP(3);
2437 	vtop->type.t = VT_FLOAT;
2438     }
2439 
2440 }
2441 
2442 /* convert fp to int 't' type */
2443 /* XXX: handle long long case */
gen_cvt_ftoi(int t)2444 void gen_cvt_ftoi(int t)
2445 {
2446     int r;
2447 
2448     gv(RC_FLOAT);
2449     r = vtop->r;
2450 
2451     if (t != VT_INT)
2452 	tcc_error("long long not supported");
2453     else {
2454 	if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE) {
2455 	    C67_DPTRUNC(r, r);
2456 	    C67_NOP(3);
2457 	} else {
2458 	    C67_SPTRUNC(r, r);
2459 	    C67_NOP(3);
2460 	}
2461 
2462 	vtop->type.t = VT_INT;
2463 
2464     }
2465 }
2466 
2467 /* convert from one floating point type to another */
gen_cvt_ftof(int t)2468 void gen_cvt_ftof(int t)
2469 {
2470     int r, r2;
2471 
2472     if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE &&
2473 	(t & VT_BTYPE) == VT_FLOAT) {
2474 	// convert double to float
2475 
2476 	gv(RC_FLOAT);		// get it in a register pair
2477 
2478 	r = vtop->r;
2479 
2480 	C67_DPSP(r, r);		// convert it to SP same register
2481 	C67_NOP(3);
2482 
2483 	vtop->type.t = VT_FLOAT;
2484 	vtop->r2 = VT_CONST;	// set this as unused
2485     } else if ((vtop->type.t & VT_BTYPE) == VT_FLOAT &&
2486 	       (t & VT_BTYPE) == VT_DOUBLE) {
2487 	// convert float to double
2488 
2489 	gv(RC_FLOAT);		// get it in a register
2490 
2491 	r = vtop->r;
2492 
2493 	if (r == TREG_EAX) {	// make sure the paired reg is avail
2494 	    r2 = get_reg(RC_ECX);
2495 	} else if (r == TREG_EDX) {
2496 	    r2 = get_reg(RC_ST0);
2497 	} else {
2498 	    ALWAYS_ASSERT(FALSE);
2499             r2 = 0; /* avoid warning */
2500         }
2501 
2502 	C67_SPDP(r, r);		// convert it to DP same register
2503 	C67_NOP(1);
2504 
2505 	vtop->type.t = VT_DOUBLE;
2506 	vtop->r2 = r2;		// set this as unused
2507     } else {
2508 	ALWAYS_ASSERT(FALSE);
2509     }
2510 }
2511 
2512 /* computed goto support */
ggoto(void)2513 void ggoto(void)
2514 {
2515     gcall_or_jmp(1);
2516     vtop--;
2517 }
2518 
2519 /* Save the stack pointer onto the stack and return the location of its address */
gen_vla_sp_save(int addr)2520 ST_FUNC void gen_vla_sp_save(int addr) {
2521     tcc_error("variable length arrays unsupported for this target");
2522 }
2523 
2524 /* Restore the SP from a location on the stack */
gen_vla_sp_restore(int addr)2525 ST_FUNC void gen_vla_sp_restore(int addr) {
2526     tcc_error("variable length arrays unsupported for this target");
2527 }
2528 
2529 /* Subtract from the stack pointer, and push the resulting value onto the stack */
gen_vla_alloc(CType *type, int align)2530 ST_FUNC void gen_vla_alloc(CType *type, int align) {
2531     tcc_error("variable length arrays unsupported for this target");
2532 }
2533 
2534 /* end of C67 code generator */
2535 /*************************************************************/
2536 #endif
2537 /*************************************************************/
2538