Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

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