1 /* cpu.c example cpu-description file */
2 /* (c) in 2013 by Volker Barthelmann */
3
4 #include "vasm.h"
5
6 char *cpu_copyright="VideoCore IV cpu backend 0.1 (c) in 2013 Volker Barthelmann";
7 char *cpuname="vidcore";
8
9 mnemonic mnemonics[]={
10 #include "opcodes.h"
11 };
12
13 int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]);
14
15 int bitsperbyte=8;
16 int bytespertaddr=4;
17
18 static char *ccs[]={"eq","ne","cs","cc","mi","pl","vs","vc",
19 "hi","ls","ge","lt","gt","le","???","f"};
20
21 static char *vflags[]={"all","none","ifz","ifnz","ifn","ifnn","ifc","ifnc"};
22
23 static char *accs[]={
24 "???", "sub", "wba", "???", "clra", "???", "???", "???",
25 "sign", "???", "???", "???", "???", "???", "???", "???",
26 "high", "???", "???", "???", "???", "???", "???", "???",
27 "???", "???", "???", "???", "???", "???", "???", "???",
28 "uadd", "usub", "uacc", "udec", "???", "???", "???", "???",
29 "sadd", "ssub", "sacc", "sdec", "???", "???", "???", "???",
30 "uaddh", "usubh", "uacch", "udech", "???", "???", "???", "???",
31 "saddh", "ssubh", "sacch", "sdech", "???", "???", "???", "???"};
32
33 static char *sru[]={
34 "sumu", "sums", "???", "imin", "???", "imax", "???", "max"};
35
oplen(int op)36 static size_t oplen(int op)
37 {
38 if(op<=EN_MEMDISP16)
39 return 2;
40 else if(op<=EN_ARITHI32)
41 return 4;
42 else if(op<=EN_VARITHI48)
43 return 6;
44 else if(op<=EN_ADDCMPB64)
45 return 8;
46 else if(op<=EN_VARITHI80)
47 return 10;
48 ierror(0);
49 }
50
skip_reg(char * s,int * reg)51 static char *skip_reg(char *s,int *reg)
52 {
53 int r=-1;
54 char* orig=s;
55 if(s[0]=='p'&&s[1]=='c'){
56 *reg=31;
57 return s+2;
58 }
59 if(s[0]=='s'&&s[1]=='r'){
60 *reg=30;
61 return s+2;
62 }
63 if(s[0]=='l'&&s[1]=='r'){
64 *reg=26;
65 return s+2;
66 }
67 if(s[0]=='s'&&s[1]=='p'){
68 *reg=25;
69 return s+2;
70 }
71 if(*s!='r'){
72 return s;
73 }
74 s++;
75 if(*s<'0'||*s>'9'){
76 return orig;
77 }
78 r=*s++-'0';
79 if(*s>='0'&&*s<='9')
80 r=10*r+*s++-'0';
81 if(isalnum(*s)||*s=='_'){
82 return orig;
83 }
84 *reg=r;
85 return s;
86 }
87
parse_operand(char * p,int len,operand * op,int req)88 int parse_operand(char *p,int len,operand *op,int req)
89 {
90 int r;
91 char *s,*start=p;
92
93 op->type=-1;
94 p=skip(p);
95
96 if(req>=OP_REG&&req<=OP_LR){
97 int reg;
98 s=skip_reg(p,&r);
99 if(s!=p){
100 if((req==OP_REG&&r<=31)||
101 (req==OP_SREG&&r<=15)||
102 (req==OP_PC&&r==31)||
103 (req==OP_LR&&r==26)||
104 (req==OP_MREG&&(r==0||r==6||r==16||r==24))){
105 op->type=OP_REG;
106 op->reg=r;
107 }else
108 return 0;
109 }else
110 return 0;
111 p=skip(s);
112 }else if(req==OP_MREG){
113 int first;
114 s=skip_reg(p,&r);
115 if(s==p)
116 return 0;
117 if(r==0)
118 op->dreg=0;
119 else if(r==6)
120 op->dreg=1;
121 else if(r==16)
122 op->dreg=2;
123 else if(r==24)
124 op->dreg=3;
125 else
126 return 0;
127 s=skip(s);
128 if(*s!='-')
129 return 0;
130 p=skip(s+1);
131 first=r;
132 s=skip_reg(p,&r);
133 if(s==p)
134 return 0;
135 p=skip(s);
136 op->reg=(r-first)&31;
137 }else if(req==OP_IND){
138 p=skip(p);
139 if(*p!='(') return 0;
140 p=skip(p+1);
141 s=skip_reg(p,&r);
142 if(s==p) return 0;
143 if(r>15) return 0;
144 p=skip(s);
145 op->reg=r;
146 if(*p!=')') return 0;
147 p=skip(p+1);
148 op->type=OP_IND;
149 }else if(req==OP_VIND){
150 int nodisp=0;
151 p=skip(p);
152 if(*p=='('){
153 char *m;
154 m=s=skip(p+1);
155 s=skip_reg(s,&r);
156 if((m!=s)||(*s=='0')) nodisp=1;
157 }
158 if(!nodisp){
159 op->offset=parse_expr(&p);
160 if(!op->offset) return 0;
161 }else
162 op->offset=0;
163 if(*p!='(') return 0;
164 p=skip(p+1);
165 s=skip_reg(p,&r);
166 if (s==p){
167 /* Special case: Allow '0' instead of a register */
168 if (*p=='0'){
169 p=skip(p+1);
170 op->reg=15;
171 }
172 else return 0;
173 }else{
174 if(r>14) return 0;
175 p=skip(s);
176 op->reg=r;
177 }
178 op->dreg=15;
179 if(*p=='+'&&p[1]=='='){
180 p=skip(p+2);
181 s=skip_reg(p,&r);
182 if(s==p) return 0;
183 if(r>14) return 0;
184 p=skip(s);
185 op->dreg=r;
186 }
187 if(*p!=')') return 0;
188 p=skip(p+1);
189 op->type=OP_IND;
190 }else if(req==OP_PREDEC){
191 p=skip(p);
192 if(p[0]!='-'||p[1]!='-') return 0;
193 p=skip(p+2);
194 if(*p!='(') return 0;
195 p=skip(p+1);
196 s=skip_reg(p,&r);
197 if(s==p) return 0;
198 p=skip(s);
199 if(*p!=')') return 0;
200 p=skip(p+1);
201 op->reg=r;
202 op->type=OP_PREDEC;
203 }else if(req==OP_POSTINC){
204 p=skip(p);
205 if(*p!='(') return 0;
206 p=skip(p+1);
207 s=skip_reg(p,&r);
208 if(s==p) return 0;
209 p=skip(s);
210 if(*p!=')') return 0;
211 p=skip(p+1);
212 if(*p++!='+') return 0;
213 if(*p!='+') return 0;
214 p=skip(p+1);
215 op->reg=r;
216 op->type=OP_POSTINC;
217 }else if(req==OP_REGIND){
218 p=skip(p);
219 if(*p!='(') return 0;
220 p=skip(p+1);
221 s=skip_reg(p,&op->reg);
222 if(s==p) return 0;
223 p=skip(s);
224 if(*p!=',') return 0;
225 p=skip(p+1);
226 s=skip_reg(p,&op->dreg);
227 if(s==p) return 0;
228 p=skip(s);
229 if(*p!=')') return 0;
230 op->type=OP_REGIND;
231 p=skip(p+1);
232 }else if(req==OP_IMMIND||
233 req==OP_IMMINDSP||
234 req==OP_IMMINDSD||
235 req==OP_IMMINDR0||
236 req==OP_IMMINDS||
237 req==OP_IMMINDPC){
238 op->offset=0;
239 if(*p=='('){
240 char *p2;
241 p2=skip(p+1);
242 s=skip_reg(p2,&r);
243 if(s!=p2){
244 p=skip(s);
245 if(*p==')'){
246 p=skip(p+1);
247 op->offset=number_expr(0);
248 }
249 }
250 }
251 if(!op->offset){
252 op->offset=parse_expr(&p);
253 if(!op->offset) return 0;
254 p=skip(p);
255 if(*p!='(') return 0;
256 p=skip(p+1);
257 s=skip_reg(p,&r);
258 if(s==p) return 0;
259 p=skip(s);
260 if(*p!=')') return 0;
261 }
262 if(req==OP_IMMINDSP&&r!=25) return 0;
263 if(req==OP_IMMINDPC&&r!=31) return 0;
264 if(req==OP_IMMINDSD&&r!=24) return 0;
265 if(req==OP_IMMINDR0&&r!=0) return 0;
266 if(req==OP_IMMINDS&&r>15) return 0;
267 op->reg=r;
268 op->type=OP_IMMIND;
269 p=skip(p+1);
270 }else if(req>=OP_IMM4&&req<=OP_IMM32&&skip_reg(p,&r)==p){
271 op->type=OP_IMM32;
272 op->offset=parse_expr(&p);
273 simplify_expr(op->offset);
274 p=skip(p);
275 }else if((req==OP_ABS||req==OP_REL)&&skip_reg(p,&r)==p){
276 op->type=req;
277 op->offset=parse_expr(&p);
278 simplify_expr(op->offset);
279 p=skip(p);
280 }else if(req==OP_VREG||req==OP_VREGM||req==OP_VREGMM||req==OP_VREGA80){
281 s=skip_reg(p,&r);
282 op->offset=0;
283 if(s!=p){
284 if (*s=='+'||*s=='-'){
285 if(req==OP_VREG) return 0;
286 op->offset=parse_expr(&s);
287 }
288 p=skip(s);
289 op->type=OP_VREG;
290 if(req==OP_VREG){
291 op->reg=(0xE<<6)|r;
292 op->dreg=0x3c;
293 }else{
294 op->reg=(0xE<<6);
295 op->dreg=r<<2;
296 }
297 }else if(*p=='-'){
298 p=skip(p+1);
299 op->type=OP_VREG;
300 op->reg=(0xF<<6);
301 op->dreg=0x3c;
302 }else{
303 int size,vert,x,y,inc=15<<2;
304 expr *e;
305 if(*p=='H'||*p=='h')
306 vert=0;
307 // Disable vertical registers in 48-bit instructions for now
308 else if((req!=OP_VREG)&&(*p=='V'||*p=='v'))
309 vert=1;
310 else
311 return 0;
312 p=skip(p+1);
313 if(*p=='X'||*p=='x'){
314 size=2;
315 p=skip(p+1);
316 }else if(*p=='1'&&p[1]=='6'){
317 size=2;
318 p=skip(p+2);
319 }else if(*p=='Y'||*p=='y'){
320 size=4;
321 p=skip(p+1);
322 }else if(*p=='3'&&p[1]=='2'){
323 size=4;
324 p=skip(p+2);
325 }else if(*p=='8'){
326 size=1;
327 p=skip(p+1);
328 }else{
329 size=1;
330 p=skip(p);
331 }
332 if(*p!='(') return 0;
333 p=skip(p+1);
334 e=parse_expr(&p);
335 if(e->type!=NUM) return 0;
336 y=e->c.val;
337 p=skip(p);
338 #if 1
339 if(req!=OP_VREG&&*p=='+'){
340 p++;
341 if(*p!='+') return 0;
342 if(vert) {
343 cpu_error(4);
344 return 0;
345 }
346 p=skip(p+1);
347 inc|=2;
348 }
349 #endif
350 if(*p!=',') return 0;
351 p=skip(p+1);
352 if((*p=='c')||(*p=='C'))
353 {
354 p++;
355 if (*p!='b'&&*p!='B') return 0;
356 p++;
357 if (*p!='+') return 0;
358 inc|=1;
359 }
360 e=parse_expr(&p);
361 if(e->type!=NUM) return 0;
362 x=e->c.val;
363 p=skip(p);
364 #if 1
365 if(req!=OP_VREG&&*p=='+'){
366 p++;
367 if(*p!='+') return 0;
368 if(!vert) {
369 cpu_error(4);
370 return 0;
371 }
372 p=skip(p+1);
373 inc|=2;
374 }
375 #endif
376 if(*p!=')') return 0;
377 p=skip(p+1);
378 if(req!=OP_VREG&&*p=='*'){
379 p=skip(p+1);
380 inc|=1;
381 }
382 if(req!=OP_VREG&&*p=='+'){
383 p=skip(p+1);
384 s=skip_reg(p,&r);
385 if(s==p) return 0;
386 p=skip(s);
387 inc&=~0x3c;
388 inc|=(r<<2);
389 }
390 if(req==OP_VREGA80){
391 if(size==1){
392 op->reg=(vert<<6)|((x&48)<<3);
393 }else if(size==2){
394 if(x&16) return 0;
395 op->reg=(vert<<6)|(8<<6)|((x&32)<<2);
396 }else{
397 if(x&48) return 0;
398 op->reg=(vert<<6)|(12<<6);
399 }
400 if(y<0||y>63) return 0;
401 op->reg|=y&63;
402 inc|=(x&15)<<6;
403 }else{
404 if(vert){
405 if(size==1){
406 op->reg=(1<<6)|((x&48)<<3);
407 }else if(size==2){
408 if(x&16) return 0;
409 op->reg=(9<<6)|((x&32)<<2);
410 }else{
411 if(x&48) return 0;
412 op->reg=13<<6;
413 }
414 if(y<0||y>63||(y&15)) return 0;
415 op->reg|=(y&48)|(x&15);
416 }
417 else{
418 if(size==1){
419 if(x&15) return 0;
420 op->reg=(x&48)<<3;
421 }else if(size==2){
422 if(x&31) return 0;
423 op->reg=(8<<6)|((x&32)<<2);
424 }else{
425 if(x) return 0;
426 op->reg=12<<6;
427 }
428 if(y<0||y>63) return 0;
429 op->reg|=y&63;
430 }
431 }
432 op->dreg=inc;
433 op->type=OP_VREG;
434 }
435 }else
436 return 0;
437
438 if(req==OP_VREGMM||req==OP_IMM32M||req==OP_VIND){
439 int vecmod=0,i;
440 while(1){
441 if(!strncasecmp(p,"rep",3)&&isspace((unsigned char)p[3])){
442 expr *e;
443 taddr x;
444 p=skip(p+3);
445 if((*p=='r')&&(p[1]=='0')&&!isdigit(p[2])){
446 p=skip(p+2);
447 vecmod|=7<<16;
448 i=0;
449 }else{
450 e=parse_expr(&p);
451 if(e->type!=NUM) return 0;
452 x=e->c.val;
453 for(i=0;i<8;i++){
454 if((1<<i)==x){
455 vecmod|=i<<16;
456 break;
457 }
458 }
459 }
460 if(i>=8) return 0;
461 p=skip(p);
462 continue;
463 }
464 for(i=0;i<sizeof(vflags)/sizeof(vflags[0]);i++){
465 if((!strncasecmp(p,vflags[i],strlen(vflags[i])))&&
466 (!isalpha(p[strlen(vflags[i])]))){
467 if(vecmod&0x380) return 0;
468 vecmod|=i<<7;
469 p=skip(p+strlen(vflags[i]));
470 continue;
471 }
472 }
473 for (i=0;i<sizeof(sru)/sizeof(sru[0]);i++){
474 if(!strncasecmp(p,sru[i],strlen(sru[i]))){
475 p=skip(p+strlen(sru[i]));
476 p=skip_reg(p,&r);
477 if((r<0)||(r>7)) return 0;
478 vecmod|=(1<<6)|(i<<3)|r;
479 continue;
480 }
481 }
482 for (i=0;i<sizeof(accs)/sizeof(accs[0]);i++){
483 if((!strncasecmp(p,accs[i],strlen(accs[i])))&&
484 (!isalpha(p[strlen(accs[i])]))){
485 if(vecmod&0x40) return 0;
486 vecmod|=i;
487 p=skip(p+strlen(accs[i]));
488 continue;
489 }
490 }
491 if(!strncasecmp(p,"ena",3)){
492 if(vecmod&0x40) return 0;
493 p=skip(p+3);
494 vecmod|=32;
495 }
496 if(!strncasecmp(p,"setf",4)){
497 p=skip(p+4);
498 vecmod|=1<<20;
499 continue;
500 }
501 break;
502 }
503
504 op->vecmod=vecmod;
505 }
506
507 if(p>=start+len)
508 return 1;
509 else
510 return 0;
511 }
512
dooffset(int rel,expr * tree,section * sec,taddr pc,rlist ** relocs,int roffset,int size,taddr mask)513 static taddr dooffset(int rel,expr *tree,section *sec,taddr pc,rlist **relocs,int roffset,int size,taddr mask)
514 {
515 taddr val;
516 if(!eval_expr(tree,&val,sec,pc)){
517 taddr addend=val;
518 symbol *base;
519 if(find_base(tree,&base,sec,pc)!=BASE_OK){
520 general_error(38);
521 return val;
522 }
523 if(rel==REL_PC){
524 val-=pc;
525 addend+=roffset/8;
526 }
527 if(rel!=REL_PC||!LOCREF(base)||base->sec!=sec){
528 add_nreloc_masked(relocs,base,addend,rel,size,roffset,mask);
529 return 0;
530 }
531 }
532 #if 0
533 if(val<-(1<<(size-1))||val>((1<<(size-1))-1))
534 cpu_error(1,size);
535 #endif
536 return val&mask;
537 }
538
reloffset(expr * tree,section * sec,taddr pc,rlist ** relocs,int roffset,int size,taddr mask)539 static taddr reloffset(expr *tree,section *sec,taddr pc,rlist **relocs,int roffset,int size,taddr mask)
540 {
541 /* taddr mask=size==32?0xffffffff:((((taddr)1)<<size)-1);*/
542 return dooffset(REL_PC,tree,sec,pc,relocs,roffset,size,mask);
543 }
544
absoffset(expr * tree,section * sec,taddr pc,rlist ** relocs,int roffset,int size)545 static taddr absoffset(expr *tree,section *sec,taddr pc,rlist **relocs,int roffset,int size)
546 {
547 /* taddr mask=size==32?0xffffffff:((((taddr)1)<<size)-1);*/
548 return dooffset(REL_ABS,tree,sec,pc,relocs,roffset,size,0xffffffff);
549 }
550
absval(expr * tree,section * sec,taddr pc,int bits,int sgn)551 static taddr absval(expr *tree,section *sec,taddr pc,int bits,int sgn)
552 {
553 taddr val;
554 if(!eval_expr(tree,&val,sec,pc))
555 cpu_error(0);
556 if(!sgn){
557 if(val<0||val>=(1<<bits))
558 cpu_error(1,bits);
559 }else{
560 if(val<-(1<<(bits-1))||val>=(1<<(bits-1)))
561 cpu_error(1,bits);
562 }
563 return val&((1<<bits)-1);
564 }
565
chkval(expr * tree,section * sec,taddr pc,int bits,int sgn)566 static int chkval(expr *tree,section *sec,taddr pc,int bits,int sgn)
567 {
568 taddr val;
569 if(!eval_expr(tree,&val,sec,pc))
570 cpu_error(0);
571 if(!sgn){
572 if(val<0||val>=(1<<bits))
573 return 0;
574 }else{
575 if(val<-(1<<(bits-1))||val>=(1<<(bits-1)))
576 return 0;
577 }
578 return 1;
579 }
580
581 /* replace instruction by one with encoding enc */
replace(int c,int enc)582 static int replace(int c,int enc)
583 {
584 int i=c+1;
585 while(!strcmp(mnemonics[c].name,mnemonics[i].name)){
586 if(mnemonics[i].ext.encoding==enc){
587 c=i;
588 break;
589 }
590 i++;
591 }
592 if(c!=i) ierror(0);
593 return c;
594 }
translate(instruction * p,section * sec,taddr pc)595 static int translate(instruction *p,section *sec,taddr pc)
596 {
597 int c=p->code,e=mnemonics[c].ext.encoding;
598 taddr val;
599
600 if(p->qualifiers[0]){
601 /* extend to larger variants if ccs are required */
602 if(e==EN_MEMDISP16)
603 c=replace(c,EN_MEMDISP32);
604 if(e==EN_ARITHR16)
605 c=replace(c,EN_ARITHR32);
606 if(e==EN_ARITHI16)
607 c=replace(c,EN_ARITHI32);
608 }
609 if(e==EN_ARITHI32){
610 if(p->op[2]){
611 if(!chkval(p->op[2]->offset,sec,pc,6,1)&&(!strcmp("add",mnemonics[c].name)||!strcmp("sub",mnemonics[c].name)))
612 c=replace(c,EN_ADD48);
613 }else{
614 if((mnemonics[c].ext.code<32)&&(!chkval(p->op[1]->offset,sec,pc,6,1)))
615 c=replace(c,EN_ARITHI48);
616 }
617 }
618 if(e==EN_ARITHI16){
619 if(!chkval(p->op[1]->offset,sec,pc,5,0))
620 c=replace(c,EN_ARITHI48);
621 }
622 if(e==EN_RBRANCH16){
623 symbol *base;
624 if(find_base(p->op[0]->offset,&base,sec,pc)!=BASE_OK||!LOCREF(base)||base->sec!=sec)
625 c=replace(c,EN_RBRANCH32);
626 else{
627 int i;
628 i=eval_expr(p->op[0]->offset,&val,sec,pc);
629 val-=pc;
630 if(val>126||val<-128)
631 c=replace(c,EN_RBRANCH32);
632 }
633 }
634 if(e==EN_ADDCMPB32){
635 int i;
636 i=eval_expr(p->op[3]->offset,&val,sec,pc);
637 val-=pc;
638 if(val>1022||val<-1024)
639 c+=4;
640 else if(p->op[2]->type!=OP_REG&&(val>254||val<-256))
641 c+=4;
642 }
643 if((e==EN_MEMDISP16||e==EN_MEMDISP32||e==EN_MEM12DISP32||e==EN_MEM16DISP32)){
644 if(!eval_expr(p->op[1]->offset,&val,sec,pc)){
645 c=replace(c,EN_MEM48);
646 }else{
647 if(e==EN_MEMDISP16&&(val<0||val>54||(val&3))){
648 if(val<=4095&&val>=-4096)
649 c=replace(c,EN_MEM12DISP32);
650 else
651 c=replace(c,EN_MEM48);
652 }
653 }
654 }
655 /* todo */
656 return c;
657 }
658
659 /* Convert an instruction into a DATA atom including relocations,
660 if necessary. */
eval_instruction(instruction * p,section * sec,taddr pc)661 dblock *eval_instruction(instruction *p,section *sec,taddr pc)
662 {
663 dblock *db=new_dblock();
664 int c,sz,enc,cc,ww,m=0;
665 unsigned long code,code2,code3;
666 rlist *relocs=0;
667
668 if(p->qualifiers[0]){
669 int i;
670 for(i=0;i<15;i++){
671 if(!strcmp(p->qualifiers[0],ccs[i])){
672 cc=i;
673 break;
674 }
675 }
676 if(i>15) ierror(0);
677 }else
678 cc=14;
679
680 c=translate(p,sec,pc);
681 enc=mnemonics[c].ext.encoding;
682
683 db->size=sz=oplen(enc);
684 db->data=mymalloc(db->size);
685
686 code=mnemonics[c].ext.code;
687
688 switch(enc){
689 case EN_ARITHR16:
690 if(cc!=14) cpu_error(3);
691 code=0x40000000|(code<<24);
692 code|=(p->op[0]->reg<<16)|(p->op[1]->reg<<20);
693 break;
694 case EN_ARITHI16:
695 if(cc!=14) cpu_error(3);
696 code=0x60000000|((code>>1)<<25);
697 code|=(p->op[0]->reg<<16)|(absval(p->op[1]->offset,sec,pc,5,0)<<20);
698 break;
699 case EN_FIX16:
700 if(cc!=14) cpu_error(3);
701 break;
702 case EN_IBRANCH16:
703 if(cc!=14) cpu_error(3);
704 code|=(p->op[0]->reg<<16);
705 break;
706 case EN_RBRANCH16:
707 code=0x18000000;
708 code|=cc<<23;
709 code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,0,7,0xfe)>>1)&127)<<16;
710 break;
711 case EN_MREG16:
712 if(cc!=14) cpu_error(3);
713 code|=(p->op[0]->dreg<<21)|(p->op[0]->reg<<16);
714 break;
715 case EN_RBRANCH32:
716 if(code==0x90000000)
717 code|=cc<<24;
718 else
719 code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,8,4,0xF000000)>>24)&0xf)<<24;
720 code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,16,16,0x1fffe)>>1)&0x7fffff);
721 code|=((reloffset(p->op[0]->offset,sec,pc,&relocs,0,7,0xfe0000)>>17)&0x7f)<<16;
722 break;
723 case EN_FUNARY32:
724 code=0xC0000040|(code<<21);
725 code|=p->op[0]->reg<<16;
726 code|=p->op[1]->reg<<11;
727 code|=cc<<7;
728 break;
729 case EN_ARITHR32:
730 code=0xC0000000|(code<<21);
731 code|=p->op[0]->reg<<16;
732 if(p->op[2]){
733 code|=p->op[1]->reg<<11;
734 code|=p->op[2]->reg;
735 }else{
736 code|=p->op[0]->reg<<11;
737 code|=p->op[1]->reg;
738 }
739 code|=cc<<7;
740 break;
741 case EN_ARITHI32:
742 code=0xC0000040|(code<<21);
743 code|=p->op[0]->reg<<16;
744 if(p->op[2]){
745 code|=p->op[1]->reg<<11;
746 code|=absval(p->op[2]->offset,sec,pc,6,1);
747 }else{
748 code|=p->op[0]->reg<<11;
749 code|=absval(p->op[1]->offset,sec,pc,6,1);
750 }
751 code|=cc<<7;
752 break;
753 case EN_ADDCMPB64:
754 // Large offset: invert CC, place a long branch after
755 // so we really generate the following:
756 // addcmpb<~cc> d, a, b, skip
757 // b <destination>
758 // skip:
759 // <rest of code>
760 m=1;
761 if(cc&1) cc--; else cc++;
762 case EN_ADDCMPB32:
763 code=0x80000000|(code<<14);
764 code|=cc<<24;
765 code|=p->op[0]->reg<<16;
766 if(code&0x4000){
767 code|=absval(p->op[1]->offset,sec,pc,4,1)<<20;
768 }else{
769 code|=p->op[1]->reg<<20;
770 }
771 if(code&0x8000){
772 code|=absval(p->op[2]->offset,sec,pc,6,0)<<8;
773 if(m)
774 code|=4;
775 else
776 code|=((reloffset(p->op[3]->offset,sec,pc,&relocs,16,9,0x1ff)>>1)&0xff);
777 }else{
778 code|=p->op[2]->reg<<10;
779 if(m)
780 code|=4;
781 else
782 code|=((reloffset(p->op[3]->offset,sec,pc,&relocs,16,11,0x7ff)>>1)&0x3ff);
783 }
784 if(m){
785 code2=0x90000000|(14<<24);
786 code2|=((reloffset(p->op[3]->offset,sec,pc+4,&relocs,48,16,0x1fffe)>>1)&0x7fffff);
787 code2|=((reloffset(p->op[3]->offset,sec,pc+4,&relocs,32,7,0xfe0000)>>17)&0x7f)<<16;
788 }
789 break;
790 case EN_ARITHI48:
791 if(cc!=14) cpu_error(3);
792 code=0xE8000000|(code<<21);
793 code|=p->op[0]->reg<<16;
794 code2=absoffset(p->op[1]->offset,sec,pc,&relocs,16,32);
795 break;
796 case EN_ADD48:
797 if(cc!=14) cpu_error(3);
798 if(p->op[2])
799 code2=absoffset(p->op[2]->offset,sec,pc,&relocs,16,32);
800 else
801 code2=absoffset(p->op[1]->offset,sec,pc,&relocs,16,32);
802 /* pseudo sub */
803 if(code==6)
804 code2=-code2;
805 code=0xEC000000;
806 code|=p->op[0]->reg<<16;
807 if(p->op[2])
808 code|=p->op[1]->reg<<21;
809 else
810 code|=p->op[0]->reg<<21;
811 break;
812 case EN_MEMREG16:
813 if(cc!=14) cpu_error(3);
814 code=0x08000000|(code<<24);
815 code|=p->op[0]->reg<<16;
816 code|=p->op[1]->reg<<20;
817 ww=0; /*FIXME*/
818 code|=ww<<25;
819 break;
820 case EN_MEMSTACK16:
821 if(cc!=14) cpu_error(3);
822 code=0x04000000|(code<<25);
823 code|=p->op[0]->reg<<16;
824 code|=(absval(p->op[1]->offset,sec,pc,7,1)>>2)<<20;
825 break;
826 case EN_MEMDISP16:
827 if(cc!=14) cpu_error(3);
828 code=0x20000000|(code<<28);
829 code|=p->op[0]->reg<<16;
830 code|=(absval(p->op[1]->offset,sec,pc,6,0)>>2)<<24;
831 code|=p->op[1]->reg<<20;
832 break;
833 case EN_LEA16:
834 if(cc!=14) cpu_error(3);
835 code=0x10000000;
836 code|=p->op[0]->reg<<16;
837 code|=(absval(p->op[1]->offset,sec,pc,8,1)>>2)<<21;
838 break;
839 case EN_LEA48:
840 if(cc!=14) cpu_error(3);
841 code=0xE5000000|(p->op[0]->reg<<16);
842 code2=reloffset(p->op[1]->offset,sec,pc,&relocs,16,32,0xffffffff);
843 break;
844 case EN_MEM48:
845 if(cc!=14) cpu_error(3);
846 code=0xE6000000|(code<<21);
847 code|=p->op[0]->reg<<16;
848 if(p->op[1]->reg==31)
849 code2=reloffset(p->op[1]->offset,sec,pc,&relocs,16,27,0xffffffff)&0x7ffffff;
850 else
851 /* TODO: other relocs */
852 code2=absoffset(p->op[1]->offset,sec,pc,&relocs,16,27)&0x7ffffff;
853 code2|=p->op[1]->reg<<27;
854 break;
855 case EN_MEMREG32:
856 code=0xA0000000|(code<<21);
857 code|=p->op[0]->reg<<16;
858 code|=p->op[1]->reg<<11;
859 code|=p->op[1]->dreg;
860 code|=cc<<7;
861 break;
862 case EN_MEMDISP32:
863 code=0xA0000040|(code<<21);
864 code|=p->op[0]->reg<<16;
865 code|=p->op[1]->reg<<11;
866 code|=absval(p->op[1]->offset,sec,pc,5,1);
867 code|=cc<<7;
868 break;
869 case EN_MEMPREDEC:
870 case EN_MEMPOSTINC:
871 code<<=21;
872 if(p->op[1]->type==OP_POSTINC)
873 code|=0xA5000000;
874 else
875 code|=0xA4000000;
876 code|=p->op[0]->reg<<16;
877 code|=p->op[1]->reg<<11;
878 code|=cc<<7;
879 break;
880 case EN_MEM12DISP32:
881 if(cc!=14) cpu_error(3);
882 code=0xA2000000|(code<<21);
883 code|=p->op[0]->reg<<16;
884 code|=p->op[1]->reg<<11;
885 code|=absval(p->op[1]->offset,sec,pc,12,1)&0x7ff;
886 code|=(absval(p->op[1]->offset,sec,pc,12,1)&0x800)<<13;
887 break;
888 case EN_MEM16DISP32:
889 if(cc!=14) cpu_error(3);
890 code|=p->op[0]->reg<<16;
891 if((code&0xff000000)==0xaa000000)
892 code|=reloffset(p->op[1]->offset,sec,pc,&relocs,16,16,0xffff)&0xffff;
893 else
894 code|=absval(p->op[1]->offset,sec,pc,16,1);
895 break;
896 case EN_VLOAD48:
897 code=0xF0000000|(code<<19);
898 code2=(p->op[0]->reg<<22)|(7<<7)|p->op[1]->reg;
899 break;
900 case EN_VSTORE48:
901 code=0xF0000000|(code<<19);
902 code2=(p->op[0]->reg<<12)|(7<<7)|p->op[1]->reg;
903 break;
904 case EN_VREAD48:
905 code=0xF0000000|(code<<19);
906 code2=(p->op[0]->reg<<22)|p->op[1]->reg;
907 break;
908 case EN_VWRITE48:
909 code=0xF0000000|(code<<19);
910 code2=(p->op[0]->reg<<12)|p->op[1]->reg;
911 break;
912 case EN_VREADI48:
913 code=0xF0000000|(code<<19);
914 code2=(p->op[0]->reg<<22)|absval(p->op[1]->offset,sec,pc,6,0)|(1<<10);
915 break;
916 case EN_VWRITEI48:
917 code=0xF0000000|(code<<19);
918 code2=(p->op[0]->reg<<12)|absval(p->op[1]->offset,sec,pc,6,0)|(1<<10);
919 break;
920 case EN_VARITHR48:
921 if(code<48) code|=64;
922 code=0xF4000000|(code<<19);
923 if(p->op[2]){
924 code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|p->op[2]->reg;
925 }else{
926 code2=(p->op[0]->reg<<22)|p->op[1]->reg;
927 }
928 break;
929 case EN_VARITHI48:
930 if(code<48) code|=64;
931 code=0xF4000000|(code<<19);
932 if(p->op[2]){
933 code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|absval(p->op[2]->offset,sec,pc,6,0)|(1<<10);
934 }else{
935 code2=(p->op[0]->reg<<22)|absval(p->op[1]->offset,sec,pc,6,0)|(1<<10);
936 }
937 break;
938 // TODO: Check these!
939 case EN_VLOAD80:
940 code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
941 code2=(p->op[0]->reg<<22);
942 code3=(p->op[1]->reg<<2)|(p->op[0]->dreg<<26)|((p->op[1]->dreg)<<22);
943 if(p->op[1]->offset){
944 code2|=(absval(p->op[1]->offset,sec,pc,16,1)&0x7f);
945 code3|=(absval(p->op[1]->offset,sec,pc,16,1)>>7)&3;
946 code3|=((absval(p->op[1]->offset,sec,pc,16,1)>>9)&0x7f)<<6;
947 }
948 break;
949 case EN_VSTORE80:
950 code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
951 code2=(p->op[0]->reg<<12);
952 code3=(p->op[1]->reg<<2)|(p->op[0]->dreg<<20)|((p->op[1]->dreg)<<28);
953 if(p->op[1]->offset){
954 code2|=(absval(p->op[1]->offset,sec,pc,16,1)&0x7f);
955 code3|=(absval(p->op[1]->offset,sec,pc,16,1)>>7)&3;
956 code3|=((absval(p->op[1]->offset,sec,pc,16,1)>>9)&0x7f)<<6;
957 }
958 break;
959 case EN_VREAD80:
960 if(p->op[1]->offset){
961 p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
962 p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
963 }
964 code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
965 code2=(p->op[0]->reg<<22)|(p->op[1]->reg);
966 if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
967 code3=(p->op[0]->dreg<<26)|(p->op[1]->dreg);
968 code3|=(p->op[1]->vecmod&0x3fff)<<6;
969 break;
970 case EN_VWRITE80:
971 if(p->op[1]->offset){
972 p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
973 p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
974 }
975 code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
976 code2=(p->op[0]->reg<<12)|(p->op[1]->reg);
977 if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
978 code3=((p->op[0]->dreg&0x3f)<<20)|((p->op[0]->dreg&0x3c0)<<10)|(p->op[1]->dreg);
979 code3|=(p->op[1]->vecmod&0x3fff)<<6;
980 break;
981 case EN_VREADI80:
982 if(p->op[1]->offset){
983 p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
984 p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
985 }
986 code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
987 if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
988 code2=(p->op[0]->reg<<22)|(1<<10)|(absval(p->op[1]->offset,sec,pc,16,0)&0x3ff);
989 code3=(p->op[0]->dreg<<26)|((absval(p->op[1]->offset,sec,pc,16,0)>>10)&0x3f);
990 code3|=(p->op[1]->vecmod&0x3fff)<<6;
991 break;
992 case EN_VWRITEI80:
993 if(p->op[1]->offset){
994 p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
995 p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
996 }
997 code=0xF8000000|(code<<19)|(p->op[1]->vecmod&0x70000);
998 if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
999 code2=(p->op[0]->reg<<12)|(1<<10)|(absval(p->op[1]->offset,sec,pc,16,0)&0x3ff);
1000 code3=((p->op[0]->dreg&0x3f)<<20)|((p->op[0]->dreg&0x3c0)<<10)|((absval(p->op[1]->offset,sec,pc,16,0)>>10)&0x3f);
1001 code3|=(p->op[1]->vecmod&0x3fff)<<6;
1002 break;
1003 case EN_VARITHR80:
1004 if(code<48) code|=64;
1005 if(p->op[2]){
1006 if(p->op[2]->offset){
1007 p->op[2]->reg|=(absval(p->op[2]->offset,sec,pc,9,1)&0x7f);
1008 p->op[2]->dreg|=(absval(p->op[2]->offset,sec,pc,9,1)>>7)&3;
1009 }
1010 code=0xFC000000|(code<<19)|(p->op[2]->vecmod&0x70000);
1011 code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|(p->op[2]->reg);
1012 if(p->op[2]->vecmod&(1<<20)) code2|=(1<<11);
1013 code3=(p->op[0]->dreg<<26)|((p->op[1]->dreg&0x3f)<<20)|((p->op[1]->dreg&0x3c0)<<10)|(p->op[2]->dreg);
1014 code3|=(p->op[2]->vecmod&0x3fff)<<6;
1015 }else{
1016 if(p->op[1]->offset){
1017 p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
1018 p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7)&3;
1019 }
1020 code=0xFC000000|(code<<19)|(p->op[1]->vecmod&0x70000);
1021 code2=(p->op[0]->reg<<22)|(p->op[1]->reg);
1022 if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
1023 code3=(p->op[0]->dreg<<26)|(p->op[1]->dreg);
1024 code3|=(p->op[1]->vecmod&0x3fff)<<6;
1025 }
1026 break;
1027 case EN_VARITHI80:
1028 if(code<48) code|=64;
1029 if(p->op[2]){
1030 if(p->op[2]->offset){
1031 p->op[2]->reg|=(absval(p->op[2]->offset,sec,pc,9,1)&0x7f);
1032 p->op[2]->dreg|=(absval(p->op[2]->offset,sec,pc,9,1)>>7);
1033 }
1034 code=0xFC000000|(code<<19)|(p->op[2]->vecmod&0x70000);
1035 if(p->op[2]->vecmod&(1<<20)) code2|=(1<<11);
1036 code2=(p->op[0]->reg<<22)|(p->op[1]->reg<<12)|(1<<10)|(absval(p->op[2]->offset,sec,pc,16,0)&0x3ff);
1037 code3=(p->op[0]->dreg<<26)|((p->op[1]->dreg&0x3f)<<20)|((p->op[1]->dreg&0x3c0)<<10)|((absval(p->op[2]->offset,sec,pc,16,0)>>10)&0x3f);
1038 code3|=(p->op[2]->vecmod&0x3fff)<<6;
1039 }else{
1040 if(p->op[1]->offset){
1041 p->op[1]->reg|=(absval(p->op[1]->offset,sec,pc,9,1)&0x7f);
1042 p->op[1]->dreg|=(absval(p->op[1]->offset,sec,pc,9,1)>>7);
1043 }
1044 code=0xFC000000|(code<<19)|(p->op[1]->vecmod&0x70000);
1045 if(p->op[1]->vecmod&(1<<20)) code2|=(1<<11);
1046 code2=(p->op[0]->reg<<22)|(1<<10)|(absval(p->op[1]->offset,sec,pc,16,0)&0x3ff);
1047 code3=(p->op[0]->dreg<<26)|((absval(p->op[1]->offset,sec,pc,16,0)>>10)&0x3f);
1048 code3|=(p->op[1]->vecmod&0x3fff)<<6;
1049 }
1050 break;
1051 default:
1052 ierror(0);
1053 }
1054
1055 if(enc>=EN_VLOAD48&&enc<=EN_VARITHI48){
1056 db->data[0]=(code>>16)&0xff;
1057 db->data[1]=(code>>24)&0xff;
1058 db->data[3]=(code2>>24)&0xff;
1059 db->data[2]=(code2>>16)&0xff;
1060 db->data[5]=(code2>>8)&0xff;
1061 db->data[4]=(code2>>0)&0xff;
1062 }else if(sz==2){
1063 db->data[0]=(code>>16)&0xff;
1064 db->data[1]=(code>>24)&0xff;
1065 }else if(sz==4){
1066 db->data[1]=(code>>24)&0xff;
1067 db->data[0]=(code>>16)&0xff;
1068 db->data[3]=(code>>8)&0xff;
1069 db->data[2]=(code)&0xff;
1070 }else if(sz==6){
1071 db->data[0]=(code>>16)&0xff;
1072 db->data[1]=(code>>24)&0xff;
1073 db->data[5]=(code2>>24)&0xff;
1074 db->data[4]=(code2>>16)&0xff;
1075 db->data[3]=(code2>>8)&0xff;
1076 db->data[2]=(code2>>0)&0xff;
1077 }
1078 else if(sz==8){
1079 db->data[1]=(code>>24)&0xff;
1080 db->data[0]=(code>>16)&0xff;
1081 db->data[3]=(code>>8)&0xff;
1082 db->data[2]=(code)&0xff;
1083 db->data[5]=(code2>>24)&0xff;
1084 db->data[4]=(code2>>16)&0xff;
1085 db->data[7]=(code2>>8)&0xff;
1086 db->data[6]=(code2)&0xff;
1087 }else if(sz==10){
1088 db->data[0]=(code>>16)&0xff;
1089 db->data[1]=(code>>24)&0xff;
1090 db->data[3]=(code2>>24)&0xff;
1091 db->data[2]=(code2>>16)&0xff;
1092 db->data[5]=(code2>>8)&0xff;
1093 db->data[4]=(code2>>0)&0xff;
1094 db->data[7]=(code3>>24)&0xff;
1095 db->data[6]=(code3>>16)&0xff;
1096 db->data[9]=(code3>>8)&0xff;
1097 db->data[8]=(code3>>0)&0xff;
1098 }
1099 db->relocs=relocs;
1100 return db;
1101 }
1102
1103 /* Create a dblock (with relocs, if necessary) for size bits of data. */
eval_data(operand * op,size_t bitsize,section * sec,taddr pc)1104 dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
1105 {
1106 dblock *new=new_dblock();
1107 taddr val;
1108 new->size=(bitsize+7)/8;
1109 new->data=mymalloc(new->size);
1110 if(op->type!=OP_ABS)
1111 ierror(0);
1112 if(bitsize!=8&&bitsize!=16&&bitsize!=32)
1113 cpu_error(2);
1114 val=absoffset(op->offset,sec,pc,&new->relocs,0,bitsize);
1115 if(bitsize==32){
1116 new->data[3]=val>>24;
1117 new->data[2]=val>>16;
1118 new->data[1]=val>>8;
1119 new->data[0]=val;
1120 }else if(bitsize==16){
1121 new->data[1]=val>>8;
1122 new->data[0]=val;
1123 }else
1124 new->data[0]=val;
1125 return new;
1126 }
1127
1128
1129 /* Calculate the size of the current instruction; must be identical
1130 to the data created by eval_instruction. */
instruction_size(instruction * p,section * sec,taddr pc)1131 size_t instruction_size(instruction *p,section *sec,taddr pc)
1132 {
1133 int c;
1134 c=translate(p,sec,pc);
1135 return oplen(mnemonics[c].ext.encoding);
1136 }
1137
new_operand()1138 operand *new_operand()
1139 {
1140 operand *new=mymalloc(sizeof(*new));
1141 new->type=-1;
1142 return new;
1143 }
1144
1145 /* return true, if initialization was successfull */
init_cpu()1146 int init_cpu()
1147 {
1148 return 1;
1149 }
1150
1151 /* return true, if the passed argument is understood */
cpu_args(char * p)1152 int cpu_args(char *p)
1153 {
1154 return 0;
1155 }
1156
1157 /* parse cpu-specific directives; return pointer to end of
1158 cpu-specific text */
parse_cpu_special(char * s)1159 char *parse_cpu_special(char *s)
1160 {
1161 char *name=s,*merk=s;
1162
1163 return merk;
1164 }
1165
set_default_qualifiers(char ** q,int * q_len)1166 int set_default_qualifiers(char **q,int *q_len)
1167 /* fill in pointers to default qualifiers, return number of qualifiers */
1168 {
1169 q[0]="u32";
1170 q_len[0]=3;
1171 q[1]="";
1172 q_len[1]=0;
1173 return 2;
1174 }
1175
parse_instruction(char * s,int * inst_len,char ** ext,int * ext_len,int * ext_cnt)1176 char *parse_instruction(char *s,int *inst_len,char **ext,int *ext_len,
1177 int *ext_cnt)
1178 /* parse instruction and save extension locations */
1179 {
1180 char *inst = s, l, i;
1181 int cnt = 0;
1182
1183 while (*s && *s!='.' && !isspace((unsigned char)*s))
1184 s++;
1185 l = s - inst;
1186
1187 if(strncasecmp("divs",inst,l)&&strncmp("vreadacc",inst,l)&&
1188 strncasecmp("vcmpge",inst,l)){
1189 for(i=0;i<16;i++){
1190 int cl=strlen(ccs[i]);
1191 if(l>cl&&!strncasecmp(s-cl,ccs[i],cl)){
1192 ext[0]=s-cl;
1193 ext_len[0]=cl;
1194 cnt=1;
1195 l-=cl;
1196 break;
1197 }
1198 }
1199 }
1200
1201 *ext_cnt = cnt;
1202
1203 *inst_len=l;
1204
1205 return s;
1206 }
1207