1
2 #include "config.h"
3
4 #include <stdio.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdarg.h>
8
9 #include <orc/orcprogram.h>
10 #include <orc/orcdebug.h>
11 #include <orc/orcinternal.h>
12
13 /**
14 * SECTION:orcprogram
15 * @title: OrcProgram
16 * @short_description: Creating and manipulating Orc programs
17 */
18
19
20 /**
21 * orc_program_new:
22 *
23 * Create a new OrcProgram. The program should be freed using
24 * @orc_program_free().
25 *
26 * Returns: a pointer to an OrcProgram structure
27 */
28 OrcProgram *
orc_program_new(void)29 orc_program_new (void)
30 {
31 OrcProgram *p;
32
33 orc_init ();
34
35 p = malloc(sizeof(OrcProgram));
36 memset (p, 0, sizeof(OrcProgram));
37
38 p->name = malloc (40);
39 sprintf(p->name, "func_%p", p);
40
41 return p;
42 }
43
44 /**
45 * orc_program_new_dss:
46 * @size1: size of destination array members
47 * @size2: size of first source array members
48 * @size3: size of second source array members
49 *
50 * Create a new OrcProgram, with a destination named "d1" and
51 * two sources named "s1" and "s2".
52 *
53 * Returns: a pointer to an OrcProgram structure
54 */
55 OrcProgram *
orc_program_new_dss(int size1,int size2,int size3)56 orc_program_new_dss (int size1, int size2, int size3)
57 {
58 OrcProgram *p;
59
60 p = orc_program_new ();
61
62 orc_program_add_destination (p, size1, "d1");
63 orc_program_add_source (p, size2, "s1");
64 orc_program_add_source (p, size3, "s2");
65
66 return p;
67 }
68
69 /**
70 * orc_program_new_ds:
71 * @size1: size of destination array members
72 * @size2: size of source array members
73 *
74 * Create a new OrcProgram, with a destination named "d1" and
75 * one source named "s1".
76 *
77 * Returns: a pointer to an OrcProgram structure
78 */
79 OrcProgram *
orc_program_new_ds(int size1,int size2)80 orc_program_new_ds (int size1, int size2)
81 {
82 OrcProgram *p;
83
84 p = orc_program_new ();
85
86 orc_program_add_destination (p, size1, "d1");
87 orc_program_add_source (p, size2, "s1");
88
89 return p;
90 }
91
92 /**
93 * orc_program_new_ass:
94 * @size1: size of destination array members
95 * @size2: size of first source array members
96 * @size3: size of second source array members
97 *
98 * Create a new OrcProgram, with an accumulator named "a1" and
99 * two source named "s1" and "s2".
100 *
101 * Returns: a pointer to an OrcProgram structure
102 */
103 OrcProgram *
orc_program_new_ass(int size1,int size2,int size3)104 orc_program_new_ass (int size1, int size2, int size3)
105 {
106 OrcProgram *p;
107
108 p = orc_program_new ();
109
110 orc_program_add_accumulator (p, size1, "a1");
111 orc_program_add_source (p, size2, "s1");
112 orc_program_add_source (p, size3, "s2");
113
114 return p;
115 }
116
117 /**
118 * orc_program_new_as:
119 * @size1: size of destination array members
120 * @size2: size of source array members
121 *
122 * Create a new OrcProgram, with an accumulator named "a1" and
123 * one source named "s1".
124 *
125 * Returns: a pointer to an OrcProgram structure
126 */
127 OrcProgram *
orc_program_new_as(int size1,int size2)128 orc_program_new_as (int size1, int size2)
129 {
130 OrcProgram *p;
131
132 p = orc_program_new ();
133
134 orc_program_add_accumulator (p, size1, "a1");
135 orc_program_add_source (p, size2, "s1");
136
137 return p;
138 }
139
140 OrcProgram *
orc_program_new_from_static_bytecode(const orc_uint8 * bytecode)141 orc_program_new_from_static_bytecode (const orc_uint8 *bytecode)
142 {
143 OrcProgram *p;
144
145 p = orc_program_new ();
146 orc_bytecode_parse_function (p, bytecode);
147
148 return p;
149 }
150
151 /**
152 * orc_program_free:
153 * @program: a pointer to an OrcProgram structure
154 *
155 * Frees an OrcProgram.
156 */
157 void
orc_program_free(OrcProgram * program)158 orc_program_free (OrcProgram *program)
159 {
160 int i;
161 for(i=0;i<ORC_N_VARIABLES;i++){
162 if (program->vars[i].name) {
163 free (program->vars[i].name);
164 program->vars[i].name = NULL;
165 }
166 if (program->vars[i].type_name) {
167 free (program->vars[i].type_name);
168 program->vars[i].type_name = NULL;
169 }
170 }
171 if (program->asm_code) {
172 free (program->asm_code);
173 program->asm_code = NULL;
174 }
175 if (program->orccode) {
176 orc_code_free (program->orccode);
177 program->orccode = NULL;
178 }
179 if (program->init_function) {
180 free (program->init_function);
181 program->init_function = NULL;
182 }
183 if (program->backup_name) {
184 free (program->backup_name);
185 program->backup_name = NULL;
186 }
187 if (program->name) {
188 free (program->name);
189 program->name = NULL;
190 }
191 if (program->error_msg) {
192 free (program->error_msg);
193 program->error_msg = NULL;
194 }
195 free (program);
196 }
197
198 /**
199 * orc_program_set_name:
200 * @program: a pointer to an OrcProgram structure
201 * @name: string to set the name to
202 *
203 * Sets the name of the program. The string is copied.
204 */
205 void
orc_program_set_name(OrcProgram * program,const char * name)206 orc_program_set_name (OrcProgram *program, const char *name)
207 {
208 if (program->name) {
209 free (program->name);
210 }
211 program->name = strdup (name);
212 }
213
214 /**
215 * orc_program_set_line:
216 * @program: a pointer to an OrcProgram structure
217 * @name: define where we are in the source
218 *
219 * Sets the current line of the program.
220 */
221 void
orc_program_set_line(OrcProgram * program,unsigned int line)222 orc_program_set_line (OrcProgram *program, unsigned int line)
223 {
224 program->current_line = line;
225 }
226
227 /**
228 * orc_program_set_2d:
229 * @program: a pointer to an OrcProgram structure
230 *
231 * Sets a flag on the program indicating that arrays are two
232 * dimensional. This causes the compiler to generate code for
233 * an OrcExec2D executor.
234 */
235 void
orc_program_set_2d(OrcProgram * program)236 orc_program_set_2d (OrcProgram *program)
237 {
238 program->is_2d = TRUE;
239 }
240
orc_program_set_constant_n(OrcProgram * program,int n)241 void orc_program_set_constant_n (OrcProgram *program, int n)
242 {
243 program->constant_n = n;
244 }
245
orc_program_set_n_multiple(OrcProgram * program,int n)246 void orc_program_set_n_multiple (OrcProgram *program, int n)
247 {
248 program->n_multiple = n;
249 }
250
orc_program_set_n_minimum(OrcProgram * program,int n)251 void orc_program_set_n_minimum (OrcProgram *program, int n)
252 {
253 program->n_minimum = n;
254 }
255
orc_program_set_n_maximum(OrcProgram * program,int n)256 void orc_program_set_n_maximum (OrcProgram *program, int n)
257 {
258 program->n_maximum = n;
259 }
260
orc_program_set_constant_m(OrcProgram * program,int m)261 void orc_program_set_constant_m (OrcProgram *program, int m)
262 {
263 program->constant_m = m;
264 }
265
266 /**
267 * orc_program_set_backup_function:
268 * @program: a pointer to an OrcProgram structure
269 * @func: a function that performs the operations in the program
270 *
271 * Normally, if a program cannot be compiled for a particular CPU,
272 * Orc will emulate the function, which is typically very slow. This
273 * function allows the developer to provide a function that is called
274 * instead of resorting to emulation.
275 */
276 void
orc_program_set_backup_function(OrcProgram * program,OrcExecutorFunc func)277 orc_program_set_backup_function (OrcProgram *program, OrcExecutorFunc func)
278 {
279 program->backup_func = func;
280 if (program->code_exec == NULL) {
281 program->code_exec = func;
282 }
283 }
284
285 /**
286 * orc_program_set_backup_name:
287 * @program: a pointer to an OrcProgram structure
288 * @name: a function name that performs the operations in the program
289 */
290 void
orc_program_set_backup_name(OrcProgram * program,const char * name)291 orc_program_set_backup_name (OrcProgram *program, const char *name)
292 {
293 if (program->backup_name)
294 free (program->backup_name);
295 program->backup_name = strdup (name);
296 }
297
298 /**
299 * orc_program_get_name:
300 * @program: a pointer to an OrcProgram structure
301 *
302 * Gets the name of the program. The string is valid until the name
303 * is changed or the program is freed.
304 *
305 * Returns: a character string
306 */
307 const char *
orc_program_get_name(OrcProgram * program)308 orc_program_get_name (OrcProgram *program)
309 {
310 return program->name;
311 }
312
313 /**
314 * orc_program_add_temporary:
315 * @program: a pointer to an OrcProgram structure
316 * @size: size of data values
317 * @name: name of variable
318 *
319 * Creates a new variable holding temporary values.
320 *
321 * Returns: the index of the new variable
322 */
323 int
orc_program_add_temporary(OrcProgram * program,int size,const char * name)324 orc_program_add_temporary (OrcProgram *program, int size, const char *name)
325 {
326 int i = ORC_VAR_T1 + program->n_temp_vars;
327
328 if (program->n_temp_vars >= ORC_MAX_TEMP_VARS) {
329 orc_program_set_error (program, "too many temporary variables allocated");
330 return 0;
331 }
332
333 program->vars[i].vartype = ORC_VAR_TYPE_TEMP;
334 program->vars[i].size = size;
335 program->vars[i].name = strdup(name);
336 program->n_temp_vars++;
337
338 return i;
339 }
340
341 /**
342 * orc_program_dup_temporary:
343 * @program: a pointer to an OrcProgram structure
344 * @var: variable to duplicate
345 * @j: index
346 *
347 * Internal function.
348 *
349 * Returns: the index of the new variable
350 */
351 int
orc_program_dup_temporary(OrcProgram * program,int var,int j)352 orc_program_dup_temporary (OrcProgram *program, int var, int j)
353 {
354 int i = ORC_VAR_T1 + program->n_temp_vars;
355
356 if (program->n_temp_vars >= ORC_MAX_TEMP_VARS) {
357 orc_program_set_error (program, "too many temporary variables allocated");
358 return 0;
359 }
360
361 program->vars[i].vartype = ORC_VAR_TYPE_TEMP;
362 program->vars[i].size = program->vars[var].size;
363 program->vars[i].name = malloc (strlen(program->vars[var].name) + 10);
364 sprintf(program->vars[i].name, "%s.dup%d", program->vars[var].name, j);
365 program->n_temp_vars++;
366
367 return i;
368 }
369
370 /**
371 * orc_program_add_source_full:
372 * @program: a pointer to an OrcProgram structure
373 * @size: size of data values
374 * @name: name of variable
375 * @type_name: name of type, or NULL
376 * @alignment: alignment in bytes, or 0
377 *
378 * Creates a new variable representing a source array.
379 *
380 * Returns: the index of the new variable
381 */
382 int
orc_program_add_source_full(OrcProgram * program,int size,const char * name,const char * type_name,int alignment)383 orc_program_add_source_full (OrcProgram *program, int size, const char *name,
384 const char *type_name, int alignment)
385 {
386 int i = ORC_VAR_S1 + program->n_src_vars;
387
388 if (program->n_src_vars >= ORC_MAX_SRC_VARS) {
389 orc_program_set_error (program, "too many source variables allocated");
390 return 0;
391 }
392
393 program->vars[i].vartype = ORC_VAR_TYPE_SRC;
394 program->vars[i].size = size;
395 if (alignment == 0) alignment = size;
396 program->vars[i].alignment = alignment;
397 program->vars[i].name = strdup(name);
398 if (type_name) {
399 program->vars[i].type_name = strdup(type_name);
400 }
401 program->n_src_vars++;
402
403 return i;
404 }
405
406 /**
407 * orc_program_add_source:
408 * @program: a pointer to an OrcProgram structure
409 * @size: size of data values
410 * @name: name of variable
411 *
412 * Creates a new variable representing a source array.
413 *
414 * Returns: the index of the new variable
415 */
416 int
orc_program_add_source(OrcProgram * program,int size,const char * name)417 orc_program_add_source (OrcProgram *program, int size, const char *name)
418 {
419 return orc_program_add_source_full (program, size, name, NULL, 0);
420 }
421
422 /**
423 * orc_program_add_destination_full:
424 * @program: a pointer to an OrcProgram structure
425 * @size: size of data values
426 * @name: name of variable
427 *
428 * Creates a new variable representing a destination array.
429 *
430 * Returns: the index of the new variable
431 */
432 int
orc_program_add_destination_full(OrcProgram * program,int size,const char * name,const char * type_name,int alignment)433 orc_program_add_destination_full (OrcProgram *program, int size, const char *name,
434 const char *type_name, int alignment)
435 {
436 int i = ORC_VAR_D1 + program->n_dest_vars;
437
438 if (program->n_dest_vars >= ORC_MAX_DEST_VARS) {
439 orc_program_set_error (program, "too many destination variables allocated");
440 return 0;
441 }
442
443 program->vars[i].vartype = ORC_VAR_TYPE_DEST;
444 program->vars[i].size = size;
445 if (alignment == 0) alignment = size;
446 program->vars[i].alignment = alignment;
447 program->vars[i].name = strdup(name);
448 if (type_name) {
449 program->vars[i].type_name = strdup(type_name);
450 }
451 program->n_dest_vars++;
452
453 return i;
454 }
455
456 /**
457 * orc_program_add_destination:
458 * @program: a pointer to an OrcProgram structure
459 * @size: size of data values
460 * @name: name of variable
461 *
462 * Creates a new variable representing a destination array.
463 *
464 * Returns: the index of the new variable
465 */
466 int
orc_program_add_destination(OrcProgram * program,int size,const char * name)467 orc_program_add_destination (OrcProgram *program, int size, const char *name)
468 {
469 return orc_program_add_destination_full (program, size, name, NULL, 0);
470 }
471
472 /**
473 * orc_program_add_constant:
474 * @program: a pointer to an OrcProgram structure
475 * @size: size of data value
476 * @value: the value
477 * @name: name of variable
478 *
479 * Creates a new variable representing a constant value.
480 *
481 * Returns: the index of the new variable
482 */
483 int
orc_program_add_constant(OrcProgram * program,int size,int value,const char * name)484 orc_program_add_constant (OrcProgram *program, int size, int value, const char *name)
485 {
486 int i;
487
488 i = ORC_VAR_C1 + program->n_const_vars;
489
490 if (program->n_const_vars >= ORC_MAX_CONST_VARS) {
491 orc_program_set_error (program, "too many constants allocated");
492 return 0;
493 }
494
495 program->vars[i].vartype = ORC_VAR_TYPE_CONST;
496 program->vars[i].size = size;
497 program->vars[i].value.i = value;
498 program->vars[i].name = strdup(name);
499 program->n_const_vars++;
500
501 return i;
502 }
503
504 int
orc_program_add_constant_int64(OrcProgram * program,int size,orc_int64 value,const char * name)505 orc_program_add_constant_int64 (OrcProgram *program, int size,
506 orc_int64 value, const char *name)
507 {
508 int i;
509
510 i = ORC_VAR_C1 + program->n_const_vars;
511
512 if (program->n_const_vars >= ORC_MAX_CONST_VARS) {
513 orc_program_set_error (program, "too many constants allocated");
514 return 0;
515 }
516
517 program->vars[i].vartype = ORC_VAR_TYPE_CONST;
518 program->vars[i].size = size;
519 program->vars[i].value.i = value;
520 program->vars[i].name = strdup(name);
521 program->n_const_vars++;
522
523 return i;
524 }
525
526 int
orc_program_add_constant_float(OrcProgram * program,int size,float value,const char * name)527 orc_program_add_constant_float (OrcProgram *program, int size,
528 float value, const char *name)
529 {
530 orc_union32 u;
531 u.f = value;
532 return orc_program_add_constant (program, size, u.i, name);
533 }
534
535 int
orc_program_add_constant_double(OrcProgram * program,int size,double value,const char * name)536 orc_program_add_constant_double (OrcProgram *program, int size,
537 double value, const char *name)
538 {
539 orc_union64 u;
540 u.f = value;
541 return orc_program_add_constant_int64 (program, size, u.i, name);
542 }
543
544 int
orc_program_add_constant_str(OrcProgram * program,int size,const char * value,const char * name)545 orc_program_add_constant_str (OrcProgram *program, int size,
546 const char *value, const char *name)
547 {
548 int i;
549 char *end;
550 orc_int64 val_i;
551 double val_d;
552 int j;
553
554 i = ORC_VAR_C1 + program->n_const_vars;
555
556 if (program->n_const_vars >= ORC_MAX_CONST_VARS) {
557 orc_program_set_error (program, "too many constants allocated");
558 return 0;
559 }
560
561 val_i = _strtoll (value, &end, 0);
562 if (end[0] == 0) {
563 program->vars[i].value.i = val_i;
564 if (size == 0)
565 size = 4;
566 } else if ((end[0] == 'l' || end[0] == 'L') && end[1] == 0) {
567 program->vars[i].value.i = val_i;
568 if (size == 0)
569 size = 8;
570 } else {
571 val_d = strtod (value, &end);
572
573 if (end[0] == 0) {
574 orc_union32 u;
575 u.f = val_d;
576 program->vars[i].value.i = u.i;
577 if (size == 0)
578 size = 4;
579 } else if ((end[0] == 'l' || end[0] == 'L') && end[1] == 0) {
580 program->vars[i].value.f = val_d;
581 if (size == 0)
582 size = 8;
583 } else {
584 return -1;
585 }
586 }
587
588 for(j=0;j<program->n_const_vars;j++){
589 if (program->vars[ORC_VAR_C1 + j].value.i == program->vars[i].value.i &&
590 program->vars[ORC_VAR_C1 + j].size == size) {
591 return ORC_VAR_C1 + j;
592 }
593 }
594
595 program->vars[i].vartype = ORC_VAR_TYPE_CONST;
596 program->vars[i].size = size;
597 program->vars[i].name = strdup(name);
598 program->n_const_vars++;
599
600 return i;
601 }
602
603 /**
604 * orc_program_add_parameter:
605 * @program: a pointer to an OrcProgram structure
606 * @size: size of data value
607 * @name: name of variable
608 *
609 * Creates a new variable representing a scalar parameter.
610 *
611 * Returns: the index of the new variable
612 */
613 int
orc_program_add_parameter(OrcProgram * program,int size,const char * name)614 orc_program_add_parameter (OrcProgram *program, int size, const char *name)
615 {
616 int i = ORC_VAR_P1 + program->n_param_vars;
617
618 if (program->n_param_vars >= ORC_MAX_PARAM_VARS) {
619 orc_program_set_error (program, "too many parameter variables allocated");
620 return 0;
621 }
622
623 program->vars[i].vartype = ORC_VAR_TYPE_PARAM;
624 program->vars[i].param_type = ORC_PARAM_TYPE_INT;
625 program->vars[i].size = size;
626 program->vars[i].name = strdup(name);
627 program->n_param_vars++;
628
629 return i;
630 }
631
632 /**
633 * orc_program_add_parameter_float:
634 * @program: a pointer to an OrcProgram structure
635 * @size: size of data value
636 * @name: name of variable
637 *
638 * Creates a new variable representing a scalar parameter.
639 *
640 * Returns: the index of the new variable
641 */
642 int
orc_program_add_parameter_float(OrcProgram * program,int size,const char * name)643 orc_program_add_parameter_float (OrcProgram *program, int size, const char *name)
644 {
645 int i = ORC_VAR_P1 + program->n_param_vars;
646
647 if (program->n_param_vars >= ORC_MAX_PARAM_VARS) {
648 orc_program_set_error (program, "too many parameter variables allocated");
649 return 0;
650 }
651
652 program->vars[i].vartype = ORC_VAR_TYPE_PARAM;
653 program->vars[i].param_type = ORC_PARAM_TYPE_FLOAT;
654 program->vars[i].size = size;
655 program->vars[i].name = strdup(name);
656 program->n_param_vars++;
657
658 return i;
659 }
660
661 int
orc_program_add_parameter_double(OrcProgram * program,int size,const char * name)662 orc_program_add_parameter_double (OrcProgram *program, int size,
663 const char *name)
664 {
665 int i = ORC_VAR_P1 + program->n_param_vars;
666
667 if (program->n_param_vars >= ORC_MAX_PARAM_VARS) {
668 orc_program_set_error (program, "too many parameter variables allocated");
669 return 0;
670 }
671
672 program->vars[i].vartype = ORC_VAR_TYPE_PARAM;
673 program->vars[i].param_type = ORC_PARAM_TYPE_DOUBLE;
674 program->vars[i].size = size;
675 program->vars[i].name = strdup(name);
676 program->n_param_vars++;
677
678 return i;
679 }
680
681 int
orc_program_add_parameter_int64(OrcProgram * program,int size,const char * name)682 orc_program_add_parameter_int64 (OrcProgram *program, int size,
683 const char *name)
684 {
685 int i = ORC_VAR_P1 + program->n_param_vars;
686
687 if (program->n_param_vars >= ORC_MAX_PARAM_VARS) {
688 orc_program_set_error (program, "too many parameter variables allocated");
689 return 0;
690 }
691
692 program->vars[i].vartype = ORC_VAR_TYPE_PARAM;
693 program->vars[i].param_type = ORC_PARAM_TYPE_INT64;
694 program->vars[i].size = size;
695 program->vars[i].name = strdup(name);
696 program->n_param_vars++;
697
698 return i;
699 }
700
701 /**
702 * orc_program_add_accumulator:
703 * @program: a pointer to an OrcProgram structure
704 * @size: size of data value
705 * @name: name of variable
706 *
707 * Creates a new variable representing an accumulator.
708 *
709 * Returns: the index of the new variable
710 */
711 int
orc_program_add_accumulator(OrcProgram * program,int size,const char * name)712 orc_program_add_accumulator (OrcProgram *program, int size, const char *name)
713 {
714 int i = ORC_VAR_A1 + program->n_accum_vars;
715
716 if (program->n_accum_vars >= ORC_MAX_ACCUM_VARS) {
717 orc_program_set_error (program, "too many accumulator variables allocated");
718 return 0;
719 }
720
721 program->vars[i].vartype = ORC_VAR_TYPE_ACCUMULATOR;
722 program->vars[i].size = size;
723 program->vars[i].name = strdup(name);
724 program->n_accum_vars++;
725
726 return i;
727 }
728
729 void
orc_program_set_type_name(OrcProgram * program,int var,const char * type_name)730 orc_program_set_type_name (OrcProgram *program, int var, const char *type_name)
731 {
732 program->vars[var].type_name = strdup(type_name);
733 }
734
735 void
orc_program_set_var_alignment(OrcProgram * program,int var,int alignment)736 orc_program_set_var_alignment (OrcProgram *program, int var, int alignment)
737 {
738 program->vars[var].alignment = alignment;
739 if (alignment >= 16) {
740 program->vars[var].is_aligned = TRUE;
741 }
742 }
743
744 void
orc_program_set_sampling_type(OrcProgram * program,int var,int sampling_type)745 orc_program_set_sampling_type (OrcProgram *program, int var,
746 int sampling_type)
747 {
748 /* This doesn't do anything yet */
749 }
750
751 /**
752 * orc_program_append_ds:
753 * @program: a pointer to an OrcProgram structure
754 * @name: name of instruction
755 * @arg0: index of first variable
756 * @arg1: index of second variable
757 *
758 * Appends an instruction to the program, with arguments @arg0 and
759 * @arg1. The instruction must take 2 operands.
760 */
761 void
orc_program_append_ds(OrcProgram * program,const char * name,int arg0,int arg1)762 orc_program_append_ds (OrcProgram *program, const char *name, int arg0,
763 int arg1)
764 {
765 OrcInstruction *insn;
766
767 insn = program->insns + program->n_insns;
768
769 insn->opcode = orc_opcode_find_by_name (name);
770 if (!insn->opcode) {
771 ORC_ERROR ("unknown opcode: %s", name);
772 }
773 insn->dest_args[0] = arg0;
774 insn->src_args[0] = arg1;
775
776 program->n_insns++;
777 }
778
779 /**
780 * orc_program_append_ds:
781 * @program: a pointer to an OrcProgram structure
782 * @name: name of instruction
783 * @arg0: index of first variable
784 * @arg1: index of second variable
785 * @arg2: index of second variable
786 *
787 * Appends an instruction to the program, with arguments @arg0,
788 * @arg1, and @arg2. The instruction must take 3 operands.
789 */
790 void
orc_program_append(OrcProgram * program,const char * name,int arg0,int arg1,int arg2)791 orc_program_append (OrcProgram *program, const char *name, int arg0,
792 int arg1, int arg2)
793 {
794 OrcInstruction *insn;
795
796 insn = program->insns + program->n_insns;
797
798 insn->opcode = orc_opcode_find_by_name (name);
799 if (!insn->opcode) {
800 ORC_ERROR ("unknown opcode: %s", name);
801 }
802 insn->dest_args[0] = arg0;
803 insn->src_args[0] = arg1;
804 insn->src_args[1] = arg2;
805
806 program->n_insns++;
807 }
808
809 /**
810 * orc_program_append_ds_2:
811 * @program: a pointer to an OrcProgram structure
812 * @name: name of instruction
813 * @arg0: index of first variable
814 * @arg1: index of second variable
815 * @arg2: index of third variable
816 * @arg3: index of fourth variable
817 *
818 * Appends an instruction to the program, with arguments @arg0,
819 * @arg1, @arg2, and @arg3.
820 */
821 void
orc_program_append_2(OrcProgram * program,const char * name,unsigned int flags,int arg0,int arg1,int arg2,int arg3)822 orc_program_append_2 (OrcProgram *program, const char *name, unsigned int flags,
823 int arg0, int arg1, int arg2, int arg3)
824 {
825 OrcInstruction *insn;
826 int args[4];
827 int i;
828
829 insn = program->insns + program->n_insns;
830
831 insn->opcode = orc_opcode_find_by_name (name);
832 if (!insn->opcode) {
833 ORC_ERROR ("unknown opcode: %s", name);
834 }
835 insn->flags = flags;
836 args[0] = arg0;
837 args[1] = arg1;
838 args[2] = arg2;
839 args[3] = arg3;
840 insn->flags = flags;
841 i = 0;
842 insn->dest_args[0] = args[i++];
843 if (insn->opcode) {
844 if (insn->opcode->dest_size[1] != 0) {
845 insn->dest_args[1] = args[i++];
846 }
847 if (insn->opcode->src_size[0] != 0) {
848 insn->src_args[0] = args[i++];
849 }
850 if (insn->opcode->src_size[1] != 0) {
851 insn->src_args[1] = args[i++];
852 }
853 if (insn->opcode->src_size[2] != 0) {
854 insn->src_args[2] = args[i++];
855 }
856 }
857 program->n_insns++;
858 }
859
860 /**
861 * orc_program_find_var_by_name:
862 * @program: a pointer to an OrcProgram structure
863 * @name: name of instruction
864 *
865 * Finds the variable with the name @name. If no variable with the
866 * given name exists in the program, -1 is returned.
867 *
868 * Returns: the index of the variable
869 */
870 int
orc_program_find_var_by_name(OrcProgram * program,const char * name)871 orc_program_find_var_by_name (OrcProgram *program, const char *name)
872 {
873 int i;
874
875 if (name == NULL) return -1;
876
877 for(i=0;i<ORC_N_VARIABLES;i++){
878 if (program->vars[i].name && strcmp (program->vars[i].name, name) == 0) {
879 return i;
880 }
881 }
882
883 return -1;
884 }
885
886 /**
887 * orc_program_append_str:
888 * @program: a pointer to an OrcProgram structure
889 * @name: name of instruction
890 * @arg0: name of first variable
891 * @arg1: name of second variable
892 * @arg2: name of third variable
893 *
894 * Appends an instruction to the program, with arguments @arg0,
895 * @arg1, and @arg2. The instruction must take 3 operands.
896 */
897 void
orc_program_append_str(OrcProgram * program,const char * name,const char * arg1,const char * arg2,const char * arg3)898 orc_program_append_str (OrcProgram *program, const char *name,
899 const char *arg1, const char *arg2, const char *arg3)
900 {
901 OrcInstruction *insn;
902
903 insn = program->insns + program->n_insns;
904
905 insn->opcode = orc_opcode_find_by_name (name);
906 if (!insn->opcode) {
907 ORC_ERROR ("unknown opcode: %s", name);
908 return;
909 }
910 insn->dest_args[0] = orc_program_find_var_by_name (program, arg1);
911 if (insn->opcode->dest_size[1] != 0) {
912 insn->dest_args[1] = orc_program_find_var_by_name (program, arg2);
913 insn->src_args[0] = orc_program_find_var_by_name (program, arg3);
914 } else {
915 insn->src_args[0] = orc_program_find_var_by_name (program, arg2);
916 insn->src_args[1] = orc_program_find_var_by_name (program, arg3);
917 }
918
919 program->n_insns++;
920 }
921
922 /**
923 * orc_program_append_str_2:
924 * @program: a pointer to an OrcProgram structure
925 * @name: name of instruction
926 * @flags: flags
927 * @arg0: name of first variable
928 * @arg1: name of second variable
929 * @arg2: name of third variable
930 * @arg3: name of fourth variable
931 *
932 * Appends an instruction to the program, with arguments @arg0,
933 * @arg1, @arg2, and @arg3.
934 */
935 void
orc_program_append_str_2(OrcProgram * program,const char * name,unsigned int flags,const char * arg1,const char * arg2,const char * arg3,const char * arg4)936 orc_program_append_str_2 (OrcProgram *program, const char *name,
937 unsigned int flags, const char *arg1, const char *arg2, const char *arg3,
938 const char *arg4)
939 {
940 OrcInstruction *insn;
941 int args[4];
942 int i;
943
944 insn = program->insns + program->n_insns;
945
946 insn->line = program->current_line;
947 insn->opcode = orc_opcode_find_by_name (name);
948 if (!insn->opcode) {
949 ORC_ERROR ("unknown opcode: %s at line %d", name, insn->line);
950 }
951 args[0] = orc_program_find_var_by_name (program, arg1);
952 args[1] = orc_program_find_var_by_name (program, arg2);
953 args[2] = orc_program_find_var_by_name (program, arg3);
954 args[3] = orc_program_find_var_by_name (program, arg4);
955 insn->flags = flags;
956 i = 0;
957 insn->dest_args[0] = args[i++];
958 if (insn->opcode) {
959 if (insn->opcode->dest_size[1] != 0) {
960 insn->dest_args[1] = args[i++];
961 }
962 if (insn->opcode->src_size[0] != 0) {
963 insn->src_args[0] = args[i++];
964 }
965 if (insn->opcode->src_size[1] != 0) {
966 insn->src_args[1] = args[i++];
967 }
968 if (insn->opcode->src_size[2] != 0) {
969 insn->src_args[2] = args[i++];
970 }
971 }
972 program->n_insns++;
973 }
974
975 /**
976 * orc_program_append_ds_str:
977 * @program: a pointer to an OrcProgram structure
978 * @name: name of instruction
979 * @arg0: name of first variable
980 * @arg1: name of second variable
981 *
982 * Appends an instruction to the program, with arguments @arg0 and
983 * @arg2. The instruction must take 2 operands.
984 */
985 void
orc_program_append_ds_str(OrcProgram * program,const char * name,const char * arg1,const char * arg2)986 orc_program_append_ds_str (OrcProgram *program, const char *name,
987 const char *arg1, const char *arg2)
988 {
989 OrcInstruction *insn;
990
991 insn = program->insns + program->n_insns;
992
993 insn->opcode = orc_opcode_find_by_name (name);
994 if (!insn->opcode) {
995 ORC_ERROR ("unknown opcode: %s", name);
996 }
997 insn->dest_args[0] = orc_program_find_var_by_name (program, arg1);
998 insn->src_args[0] = orc_program_find_var_by_name (program, arg2);
999
1000 program->n_insns++;
1001 }
1002
1003 void
orc_program_append_dds_str(OrcProgram * program,const char * name,const char * arg1,const char * arg2,const char * arg3)1004 orc_program_append_dds_str (OrcProgram *program, const char *name,
1005 const char *arg1, const char *arg2, const char *arg3)
1006 {
1007 OrcInstruction *insn;
1008
1009 insn = program->insns + program->n_insns;
1010
1011 insn->opcode = orc_opcode_find_by_name (name);
1012 if (!insn->opcode) {
1013 ORC_ERROR ("unknown opcode: %s", name);
1014 }
1015 insn->dest_args[0] = orc_program_find_var_by_name (program, arg1);
1016 insn->dest_args[1] = orc_program_find_var_by_name (program, arg2);
1017 insn->src_args[0] = orc_program_find_var_by_name (program, arg3);
1018
1019 program->n_insns++;
1020 }
1021
1022 /**
1023 * orc_program_get_asm_code:
1024 * @program: a pointer to an OrcProgram structure
1025 *
1026 * Returns a character string containing the assembly code created
1027 * by compiling the program. This string is valid until the program
1028 * is compiled again or the program is freed.
1029 *
1030 * Returns: a character string
1031 */
1032 const char *
orc_program_get_asm_code(OrcProgram * program)1033 orc_program_get_asm_code (OrcProgram *program)
1034 {
1035 return program->asm_code;
1036 }
1037
1038 /**
1039 * orc_program_get_error:
1040 * @program: a pointer to an OrcProgram structure
1041 *
1042 * Returns a character string containing the error message from
1043 * compilation. This string is valid until the program
1044 * is compiled again, the program is freed, or another error
1045 * is set.
1046 *
1047 * Returns: a character string
1048 */
1049 const char *
orc_program_get_error(OrcProgram * program)1050 orc_program_get_error (OrcProgram *program)
1051 {
1052 if (program->error_msg) return program->error_msg;
1053 return "";
1054 }
1055
1056 /**
1057 * orc_program_set_error:
1058 * @program: a pointer to an OrcProgram structure
1059 * @error: an error string
1060 *
1061 * Stores the error in the program. This string is duplicated.
1062 * If an error has already been set, this new error is ignored.
1063 * An error will stay till the next call to _reset, if any.
1064 */
1065 void
orc_program_set_error(OrcProgram * program,const char * error)1066 orc_program_set_error (OrcProgram *program, const char *error)
1067 {
1068 if (!program->error_msg && error) {
1069 program->error_msg = strdup (error);
1070 }
1071 }
1072
1073 /**
1074 * orc_program_get_max_array_size:
1075 * @program: a pointer to an OrcProgram structure
1076 *
1077 * Returns the size of the largest array used in the program.
1078 *
1079 * Returns: the number of bytes
1080 */
1081 int
orc_program_get_max_array_size(OrcProgram * program)1082 orc_program_get_max_array_size (OrcProgram *program)
1083 {
1084 int i;
1085 int max;
1086
1087 max = 0;
1088 for(i=0;i<ORC_N_VARIABLES;i++){
1089 if (program->vars[i].size) {
1090 if (program->vars[i].vartype == ORC_VAR_TYPE_SRC ||
1091 program->vars[i].vartype == ORC_VAR_TYPE_DEST) {
1092 max = MAX(max, program->vars[i].size);
1093 }
1094 }
1095 }
1096
1097 return max;
1098 }
1099
1100 /**
1101 * orc_program_get_max_accumulator_size:
1102 * @program: a pointer to an OrcProgram structure
1103 *
1104 * Returns the size of the largest array used in the program.
1105 *
1106 * Returns: the number of bytes
1107 */
1108 int
orc_program_get_max_accumulator_size(OrcProgram * program)1109 orc_program_get_max_accumulator_size (OrcProgram *program)
1110 {
1111 int i;
1112 int max;
1113
1114 max = 0;
1115 for(i=0;i<ORC_N_VARIABLES;i++){
1116 if (program->vars[i].size) {
1117 if (program->vars[i].vartype == ORC_VAR_TYPE_ACCUMULATOR) {
1118 max = MAX(max, program->vars[i].size);
1119 }
1120 }
1121 }
1122
1123 return max;
1124 }
1125
1126 int _orc_data_cache_size_level1;
1127 int _orc_data_cache_size_level2;
1128 int _orc_data_cache_size_level3;
1129 int _orc_cpu_family;
1130 int _orc_cpu_model;
1131 int _orc_cpu_stepping;
1132 const char *_orc_cpu_name = "unknown";
1133
1134 void
orc_get_data_cache_sizes(int * level1,int * level2,int * level3)1135 orc_get_data_cache_sizes (int *level1, int *level2, int *level3)
1136 {
1137 if (level1) {
1138 *level1 = _orc_data_cache_size_level1;
1139 }
1140 if (level2) {
1141 *level2 = _orc_data_cache_size_level2;
1142 }
1143 if (level3) {
1144 *level3 = _orc_data_cache_size_level3;
1145 }
1146
1147 }
1148
1149 void
orc_get_cpu_family_model_stepping(int * family,int * model,int * stepping)1150 orc_get_cpu_family_model_stepping (int *family, int *model, int *stepping)
1151 {
1152 if (family) {
1153 *family = _orc_cpu_family;
1154 }
1155 if (model) {
1156 *model = _orc_cpu_model;
1157 }
1158 if (stepping) {
1159 *stepping = _orc_cpu_stepping;
1160 }
1161 }
1162
1163 const char *
orc_get_cpu_name(void)1164 orc_get_cpu_name (void)
1165 {
1166 return _orc_cpu_name;
1167 }
1168
1169 void
orc_program_reset(OrcProgram * program)1170 orc_program_reset (OrcProgram *program)
1171 {
1172 if (program->orccode) {
1173 orc_code_free (program->orccode);
1174 program->orccode = NULL;
1175 }
1176 if (program->asm_code) {
1177 free(program->asm_code);
1178 program->asm_code = NULL;
1179 }
1180 if (program->error_msg) {
1181 free(program->error_msg);
1182 program->error_msg = NULL;
1183 }
1184 }
1185
1186 OrcCode *
orc_program_take_code(OrcProgram * program)1187 orc_program_take_code (OrcProgram *program)
1188 {
1189 OrcCode *code = program->orccode;
1190 program->orccode = NULL;
1191 return code;
1192 }
1193
1194 int
orc_program_has_float(OrcCompiler * compiler)1195 orc_program_has_float (OrcCompiler *compiler)
1196 {
1197 int j;
1198 for(j=0;j<compiler->n_insns;j++){
1199 OrcInstruction *insn = compiler->insns + j;
1200 OrcStaticOpcode *opcode = insn->opcode;
1201 if (opcode->flags & ORC_STATIC_OPCODE_FLOAT) return TRUE;
1202 }
1203 return FALSE;
1204 }
1205