1 /* cpu.c example cpu-description file */
2 /* (c) in 2002 by Volker Barthelmann */
3
4 #include "vasm.h"
5
6 char *cpu_copyright="vasm c16x/st10 cpu backend 0.2c (c) in 2002-2005 Volker Barthelmann";
7 char *cpuname="c16x";
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 int JMPA,JMPR,JMPS,JNB,JB,JBC,JNBS,JMP;
19 static int notrans,tojmpa;
20
21 #define JMPCONV 256
22 #define INVCC(c) (((c)&1)?(c)-1:(c)+1)
23
24 #define ISBIT 1
25
26 typedef struct sfr {
27 struct sfr *next;
28 int flags;
29 unsigned int laddr,saddr,boffset;
30 } sfr;
31
32
33 sfr *first_sfr;
34 #define SFRHTSIZE 1024
35 hashtable *sfrhash;
36
skip_reg(char * s,int * reg)37 static char *skip_reg(char *s,int *reg)
38 {
39 int r=-1;
40 if(*s!='r'&&*s!='R'){
41 cpu_error(1);
42 return s;
43 }
44 s++;
45 if(*s<'0'||*s>'9'){
46 cpu_error(1);
47 return s;
48 }
49 r=*s++-'0';
50 if(*s>='0'&&*s<='5')
51 r=10*r+*s++-'0';
52 *reg=r;
53 return s;
54 }
55
parse_operand(char * p,int len,operand * op,int requires)56 int parse_operand(char *p,int len,operand *op,int requires)
57 {
58 op->type=-1;
59 op->mod=-1;
60 p=skip(p);
61 if(requires==OP_REL){
62 char *s=p;
63 op->type=OP_REL;
64 op->offset=parse_expr(&s);
65 simplify_expr(op->offset);
66 if(s==p)
67 return 0;
68 else
69 return 1;
70 }
71 if(requires==OP_CC){
72 op->type=OP_CC;
73 if(len<4||len>6||p[0]!='c'||p[1]!='c'||p[2]!='_')
74 return 0;
75 if(len==4){
76 if(p[3]=='z')
77 op->cc=2;
78 else if(p[3]=='v')
79 op->cc=4;
80 else if(p[3]=='n')
81 op->cc=6;
82 else if(p[3]=='c')
83 op->cc=8;
84 else
85 return 0;
86 }else if(len==5){
87 if(p[3]=='u'&&p[4]=='c')
88 op->cc=0;
89 else if(p[3]=='n'&&p[4]=='z')
90 op->cc=3;
91 else if(p[3]=='n'&&p[4]=='v')
92 op->cc=5;
93 else if(p[3]=='n'&&p[4]=='n')
94 op->cc=7;
95 else if(p[3]=='n'&&p[4]=='c')
96 op->cc=0;
97 else if(p[3]=='e'&&p[4]=='q')
98 op->cc=2;
99 else if(p[3]=='n'&&p[4]=='e')
100 op->cc=3;
101 else
102 return 0;
103 }else if(len==6){
104 if(!strncmp(p+3,"ult",3))
105 op->cc=8;
106 else if(!strncmp(p+3,"ule",3))
107 op->cc=0xf;
108 else if(!strncmp(p+3,"uge",3))
109 op->cc=0x9;
110 else if(!strncmp(p+3,"ugt",3))
111 op->cc=0xe;
112 else if(!strncmp(p+3,"slt",3))
113 op->cc=0xc;
114 else if(!strncmp(p+3,"sle",3))
115 op->cc=0xb;
116 else if(!strncmp(p+3,"sge",3))
117 op->cc=0xd;
118 else if(!strncmp(p+3,"sgt",3))
119 op->cc=0xa;
120 else if(!strncmp(p+3,"net",3))
121 op->cc=0x1;
122 else
123 return 0;
124 }
125 return 1;
126 }
127 if((p[0]=='r'||p[0]=='R')&&p[1]>='0'&&p[1]<='9'&&(len==2||p[2]=='.')){
128 op->type=OP_GPR;
129 op->reg=p[1]-'0';
130 op->regsfr=op->reg+0xf0;
131 if(len>2){
132 op->type=OP_BADDR;
133 if(requires==OP_BADDR){
134 p=skip(p+3);
135 op->boffset=parse_expr(&p);
136 op->offset=number_expr(op->regsfr);
137 }
138 }
139 }else if((p[0]=='r'||p[0]=='R')&&p[1]=='1'&&p[2]>='0'&&p[2]<='5'&&(len==3||p[3]=='.')){
140 op->type=OP_GPR;
141 op->reg=(p[1]-'0')*10+p[2]-'0';
142 op->regsfr=op->reg+0xf0;
143 if(len>3){
144 op->type=OP_BADDR;
145 if(requires==OP_BADDR){
146 p=skip(p+4);
147 op->boffset=parse_expr(&p);
148 op->offset=number_expr(op->regsfr);
149 }
150 }
151 }else if(len==3&&(p[0]=='r'||p[0]=='R')&&(p[1]=='l'||p[1]=='L')&&p[2]>='0'&&p[2]<='7'){
152 op->type=OP_BGPR;
153 op->reg=(p[2]-'0')*2;
154 op->regsfr=op->reg+0xf0;
155 }else if(len==3&&(p[0]=='r'||p[0]=='R')&&(p[1]=='h'||p[1]=='H')&&p[2]>='0'&&p[2]<='7'){
156 op->type=OP_BGPR;
157 op->reg=(p[2]-'0')*2+1;
158 op->regsfr=op->reg+0xf0;
159 }else if(p[0]=='#'){
160 op->type=OP_IMM16;
161 p=skip(p+1);
162 if((!strncmp("SOF",p,3)||!strncmp("sof",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SOF;p=skip(p+3);}
163 if((!strncmp("SEG",p,3)||!strncmp("seg",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SEG;p=skip(p+3);}
164 if((!strncmp("DPP0:",p,5)||!strncmp("dpp0:",p,5))){op->mod=MOD_DPP0;p=skip(p+5);}
165 if((!strncmp("DPP1:",p,5)||!strncmp("dpp1:",p,5))){op->mod=MOD_DPP1;p=skip(p+5);}
166 if((!strncmp("DPP2:",p,5)||!strncmp("dpp2:",p,5))){op->mod=MOD_DPP2;p=skip(p+5);}
167 if((!strncmp("DPP3:",p,5)||!strncmp("dpp3:",p,5))){op->mod=MOD_DPP3;p=skip(p+5);}
168 if((!strncmp("DPPX:",p,5)||!strncmp("dppx:",p,5))){op->mod=MOD_DPPX;p=skip(p+5);}
169 op->offset=parse_expr(&p);
170 simplify_expr(op->offset);
171 #if 0
172 if(op->offset->type==NUM){
173 taddr val=op->offset->c.val;
174 if(val>=0&&val<=7)
175 op->type=OP_IMM3;
176 else if(val>=0&&val<=15)
177 op->type=OP_IMM4;
178 else if(val>=0&&val<=127)
179 op->type=OP_IMM7;
180 else if(val>=0&&val<=255)
181 op->type=OP_IMM8;
182 }
183 #endif
184 }else if(*p=='['){
185 p=skip(p+1);
186 if(*p=='-'){
187 p=skip(p+1);
188 p=skip_reg(p,&op->reg);
189 p=skip(p);
190 if(*p!=']')
191 cpu_error(0);
192 if(op->reg<=3)
193 op->type=OP_PREDEC03;
194 else
195 op->type=OP_PREDEC;
196 }else{
197 p=skip_reg(p,&op->reg);
198 p=skip(p);
199 if(*p=='+'){
200 p=skip(p+1);
201 if(*p==']'){
202 if(op->reg<=3)
203 op->type=OP_POSTINC03;
204 else
205 op->type=OP_POSTINC;
206 }else{
207 if(*p!='#')
208 cpu_error(0);
209 p=skip(p+1);
210 op->offset=parse_expr(&p);
211 p=skip(p);
212 op->type=OP_REGDISP;
213 }
214 }else{
215 if(op->reg<=3)
216 op->type=OP_REG03IND;
217 else
218 op->type=OP_REGIND;
219 }
220 if(*p!=']')
221 cpu_error(0);
222 }
223 }else{
224 if(ISIDSTART(*p)){
225 char *name=p;
226 hashdata data;
227 while((p==name||ISIDCHAR(*p))&&*p!='.')
228 p++;
229 if(find_namelen(sfrhash,name,p-name,&data)){
230 sfr *sfr;
231 sfr=data.ptr;
232 if(sfr->flags&ISBIT){
233 op->offset=number_expr(sfr->saddr);
234 op->type=OP_BADDR;
235 op->boffset=number_expr(sfr->boffset);
236 }else{
237 if(requires==OP_SFR||requires==OP_BSFR||requires==OP_BWORD){
238 op->offset=number_expr(sfr->saddr);
239 op->type=requires;
240 }else if(requires==OP_BADDR&&*p=='.'){
241 op->offset=number_expr(sfr->saddr);
242 p=skip(p+1);
243 op->boffset=parse_expr(&p);
244 op->type=OP_BADDR;
245 }else if(requires==OP_ABS||requires==OP_BABS){
246 op->type=requires;
247 op->offset=number_expr((2*sfr->saddr)+(sfr->laddr<<8));
248 }
249 }
250 }
251 if(op->type==-1)
252 p=name;
253 }
254 if(op->type==-1){
255 if((!strncmp("SOF",p,3)||!strncmp("sof",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SOF;p=skip(p+3);}
256 if((!strncmp("SEG",p,3)||!strncmp("seg",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SEG;p=skip(p+3);}
257 if((!strncmp("DPP0:",p,5)||!strncmp("dpp0:",p,5))){op->mod=MOD_DPP0;p=skip(p+5);}
258 if((!strncmp("DPP1:",p,5)||!strncmp("dpp1:",p,5))){op->mod=MOD_DPP1;p=skip(p+5);}
259 if((!strncmp("DPP2:",p,5)||!strncmp("dpp2:",p,5))){op->mod=MOD_DPP2;p=skip(p+5);}
260 if((!strncmp("DPP3:",p,5)||!strncmp("dpp3:",p,5))){op->mod=MOD_DPP3;p=skip(p+5);}
261 if((!strncmp("DPPX:",p,5)||!strncmp("dppx:",p,5))){op->mod=MOD_DPPX;p=skip(p+5);}
262 op->offset=parse_expr(&p);
263 op->type=OP_ABS;
264 }
265 }
266 if(requires==op->type)
267 return 1;
268 if(requires==OP_BWORD&&op->type==OP_SFR)
269 return 1;
270 if(op->type==OP_IMM16&&(requires>=OP_IMM2&&requires<=OP_IMM16))
271 return 1;
272 if(op->type==OP_PREDEC03&&requires==OP_PREDEC)
273 return 1;
274 if(op->type==OP_POSTINC03&&requires==OP_POSTINC)
275 return 1;
276 if(op->type==OP_REG03IND&&requires==OP_REGIND)
277 return 1;
278 if((requires==OP_SFR&&op->type==OP_GPR)||
279 (requires==OP_BWORD&&op->type==OP_GPR)||
280 (requires==OP_BWORD&&op->type==OP_BGPR)||
281 (requires==OP_BSFR&&op->type==OP_BGPR)){
282 op->offset=number_expr(op->regsfr);
283 return 1;
284 }
285 if(requires==OP_BSFR&&op->type==OP_BGPR)
286 return 1;
287 if(requires==OP_JADDR&&op->type==OP_ABS)
288 return 1;
289 if(requires==OP_BABS&&op->type==OP_ABS)
290 return 1;
291 /*FIXME*/
292 return 0;
293 }
294
reloffset(expr * tree,section * sec,taddr pc)295 static taddr reloffset(expr *tree,section *sec,taddr pc)
296 {
297 symbol *sym;
298 int btype;
299 taddr val;
300 simplify_expr(tree);
301 if(tree->type==NUM){
302 /* should we do it like this?? */
303 val=tree->c.val;
304 }else{
305 btype=find_base(tree,&sym,sec,pc);
306 if(btype!=BASE_OK||!LOCREF(sym)||sym->sec!=sec)
307 val=0xffff;
308 else{
309 eval_expr(tree,&val,sec,pc);
310 val=val-pc;
311 }
312 }
313 return val;
314 }
315
absoffset2(expr * tree,int mod,section * sec,taddr pc,rlist ** relocs,int roffset,int size,taddr mask)316 static taddr absoffset2(expr *tree,int mod,section *sec,taddr pc,rlist **relocs,int roffset,int size,taddr mask)
317 {
318 taddr val;
319 if(mod==MOD_SOF){
320 if(mask!=0xffffffff&&mask!=0xffff) cpu_error(5);
321 mask=0xffff;
322 }
323 if(mod==MOD_SEG){
324 if(mask!=0xff&&mask!=0xffff&&mask!=0xffffffff) cpu_error(6);
325 mask<<=16;
326 }
327 if(mod==MOD_DPP0||mod==MOD_DPP1||mod==MOD_DPP2||mod==MOD_DPP3||mod==MOD_DPPX){
328 if(mask!=0xffffffff&&mask!=0xffff) cpu_error(7);
329 mask=0x3fff;
330 }
331 if(!eval_expr(tree,&val,sec,pc)){
332 taddr addend=val;
333 symbol *base;
334 if(find_base(tree,&base,sec,pc)!=BASE_OK){
335 general_error(38);
336 return val;
337 }
338 if(mod==MOD_DPP1) val|=0x4000;
339 if(mod==MOD_DPP2) val|=0x8000;
340 if(mod==MOD_DPP3) val|=0xc000;
341 if(mod==MOD_DPPX){
342 static int dpplen;
343 static char *dppname;
344 char *id=base->name;
345 symbol *dppsym;
346 size-=2;
347 if(strlen(id)+9>dpplen){
348 myfree(dppname);
349 dppname=mymalloc(dpplen=strlen(id)+9);
350 }
351 strcpy(dppname,"___DPP_");
352 strcat(dppname,id);
353 dppsym=new_import(dppname);
354 if(dppsym->type==EXPRESSION){
355 if(!eval_expr(dppsym->expr,&val,0,0))
356 ierror(0);
357 val<<=14;
358 }else{
359 add_nreloc_masked(relocs,dppsym,0,REL_ABS,2,roffset+14,0x3);
360 }
361 }
362 add_nreloc_masked(relocs,base,addend,REL_ABS,size,roffset,mask);
363 return val;
364 }
365 val&=mask;
366 if(mod==MOD_DPPX) cpu_error(7);
367 if(mod==MOD_DPP1) val|=0x4000;
368 if(mod==MOD_DPP2) val|=0x8000;
369 if(mod==MOD_DPP3) val|=0xc000;
370 if(mod==MOD_SEG) val>>=16;
371 /*FIXME: range check */
372 #if 1
373 if(size==16)
374 return val&0xffff;
375 else
376 return val&((1<<size)-1);
377 #else
378 return val;
379 #endif
380 }
381
absoffset(expr * tree,int mod,section * sec,taddr pc,rlist ** relocs,int roffset,int size)382 static taddr absoffset(expr *tree,int mod,section *sec,taddr pc,rlist **relocs,int roffset,int size)
383 {
384 /* taddr mask=size==32?0xffffffff:((((taddr)1)<<size)-1);*/
385 return absoffset2(tree,mod,sec,pc,relocs,roffset,size,0xffffffff);
386 }
387
absval(expr * tree,section * sec,taddr pc,int bits)388 static taddr absval(expr *tree,section *sec,taddr pc,int bits)
389 {
390 taddr val;
391 if(!eval_expr(tree,&val,sec,pc))
392 cpu_error(0);
393 if(bits==2){
394 /* ext instructions */
395 if(val<1||val>4)
396 cpu_error(3,2);
397 return val;
398 }else if(val<0||val>=(1<<bits))
399 cpu_error(3,bits);
400 return val&((1<<bits)-1);
401 }
402
translate(instruction * p,section * sec,taddr pc)403 static int translate(instruction *p,section *sec,taddr pc)
404 {
405 int c=p->code;
406 taddr val;
407 /* choose one of jmpr/jmpa */
408 if(c==JMP||(!notrans&&(c==JMPA||c==JMPR||c==JB||c==JNB))){
409 val=reloffset(p->op[1]->offset,sec,pc);
410 if(val<-256||val>254||val%2){
411 if(c==JB) return JNB|JMPCONV;
412 if(c==JNB) return JB|JMPCONV;
413 if(c==JMPA) return JMPA;
414 if(tojmpa) return JMPA;
415 if(p->op[0]->cc==0)
416 return JMPS;
417 else
418 return JMPR|JMPCONV;
419 }else{
420 if(c==JB||c==JNB)
421 return c;
422 return JMPR;
423 }
424 }
425 /* choose between gpr,#imm3 and reg,#imm16 */
426 if(mnemonics[c].operand_type[1]==OP_IMM3){
427 if(!eval_expr(p->op[1]->offset,&val,sec,pc)||val<0||val>7){
428 if(!strcmp(mnemonics[c].name,mnemonics[c+1].name))
429 return c+1;
430 }
431 }
432 /* choose between gpr,#imm4 and reg,#imm16 */
433 if(mnemonics[c].operand_type[1]==OP_IMM4){
434 if(!eval_expr(p->op[1]->offset,&val,sec,pc)||val<0||val>7){
435 if(!strcmp(mnemonics[c].name,mnemonics[c+1].name))
436 return c+1;
437 }
438 }
439 return c;
440 }
441
442 /* Convert an instruction into a DATA atom including relocations,
443 if necessary. */
eval_instruction(instruction * p,section * sec,taddr pc)444 dblock *eval_instruction(instruction *p,section *sec,taddr pc)
445 {
446 dblock *db=new_dblock();
447 int opcode,c,jmpconv=0,osize;
448 unsigned long code;
449 char *d;
450 taddr val;
451 rlist *relocs=0;
452 operand *jmpaddr;
453
454 c=translate(p,sec,pc);
455 if(c&JMPCONV){ jmpconv=1;c&=~JMPCONV;}
456 if((mnemonics[p->code].operand_type[0]==OP_GPR&&mnemonics[c].operand_type[0]==OP_SFR)||
457 (mnemonics[p->code].operand_type[0]==OP_BGPR&&mnemonics[c].operand_type[0]==OP_BSFR))
458 p->op[0]->offset=number_expr(p->op[0]->regsfr);
459
460
461 db->size=osize=mnemonics[c].ext.len*2;
462 if(jmpconv) db->size+=4;
463 db->data=mymalloc(db->size);
464
465 opcode=mnemonics[c].ext.opcode;
466 switch(mnemonics[c].ext.encoding){
467 case 0:
468 code=opcode<<16|(opcode>>8)<<8|opcode>>8;
469 break;
470 case 1:
471 code=opcode;
472 break;
473 case 2:
474 code=opcode|p->op[0]->reg<<4|p->op[1]->reg;
475 break;
476 case 3:
477 code=opcode|p->op[0]->reg|p->op[1]->reg<<4;
478 break;
479 case 4:
480 code=opcode|p->op[0]->reg<<4|p->op[1]->reg|8;
481 break;
482 case 5:
483 code=opcode|p->op[0]->reg<<4|p->op[1]->reg|12;
484 break;
485 case 6:
486 code=opcode|p->op[0]->reg<<4|absval(p->op[1]->offset,sec,pc,3);
487 break;
488 case 7:
489 /* fall through */
490 case 8:
491 code=opcode<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,20,8)<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
492 break;
493 case 9:
494 code=opcode|p->op[0]->reg|absval(p->op[1]->offset,sec,pc,4)<<4;
495 break;
496 case 10:
497 /* rfi: reorder bmov operands */
498 code=opcode<<16|
499 absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,8,8)<<16|
500 absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,8)<<0|
501 absoffset(p->op[1]->boffset,0,sec,pc,&relocs,24,4)<<12|
502 absoffset(p->op[0]->boffset,0,sec,pc,&relocs,28,4)<<8;
503 break;
504 case 11:
505 code=opcode|absoffset(p->op[0]->boffset,0,sec,pc,&relocs,0,4)<<12|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8);
506 break;
507 case 12:
508 code=opcode<<16|
509 absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
510 absoffset(p->op[2]->offset,p->op[2]->mod,sec,pc,&relocs,16,8)<<8|
511 absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,24,8);
512 break;
513 case 13:
514 code=opcode<<16|
515 absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
516 absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,8)<<8|
517 absoffset(p->op[2]->offset,p->op[2]->mod,sec,pc,&relocs,24,8);
518 break;
519 case 14:
520 code=opcode<<16|p->op[0]->cc<<20|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
521 break;
522 case 15:
523 code=opcode|p->op[0]->cc<<4|p->op[1]->reg;
524 break;
525 case 16:
526 val=((reloffset(p->op[0]->offset,sec,pc)-2)>>1)&255;
527 code=opcode|val;
528 break;
529 case 17:
530 if(p->op[0]->type==OP_CC){
531 /* jmp cc_uc was converted to jmps */
532 code=opcode<<16|absoffset2(p->op[1]->offset,0,sec,pc,&relocs,8,8,0xffff0000)<<16|absoffset2(p->op[1]->offset,0,sec,pc,&relocs,16,16,0xffff);
533 }else{
534 code=opcode<<16|absoffset2(p->op[0]->offset,0,sec,pc,&relocs,8,8,0xffff0000)<<16|absoffset2(p->op[0]->offset,0,sec,pc,&relocs,16,16,0xffff);
535 }
536 break;
537 case 18:
538 /* fall through */
539 case 19:
540 code=opcode<<16|0xf<<20|p->op[0]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
541 break;
542 case 20:
543 code=opcode|p->op[0]->reg<<4;
544 break;
545 case 21:
546 code=opcode|p->op[0]->reg<<4|p->op[0]->reg;
547 break;
548 case 22:
549 if(!jmpconv){
550 val=((reloffset(p->op[1]->offset,sec,pc)-4)>>1)&255;
551 code=opcode<<16|
552 absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
553 absoffset(p->op[0]->boffset,0,sec,pc,&relocs,24,4)<<12|
554 val;
555 }else{
556 code=opcode<<16|
557 absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
558 absoffset(p->op[0]->boffset,0,sec,pc,&relocs,24,4)<<12|
559 2;
560 jmpaddr=p->op[1];
561 }
562 break;
563 case 23:
564 if(!jmpconv){
565 val=((reloffset(p->op[1]->offset,sec,pc)-2)>>1)&255;
566 code=opcode|p->op[0]->cc<<12|val;
567 }else{
568 code=opcode|INVCC(p->op[0]->cc)<<12|2;
569 jmpaddr=p->op[1];
570 }
571 break;
572 case 24:
573 code=opcode<<16|p->op[0]->reg<<20|p->op[1]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
574 break;
575 case 25:
576 code=opcode<<16|p->op[0]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
577 break;
578 case 26:
579 code=opcode|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8);
580 break;
581 case 27:
582 code=opcode|absval(p->op[0]->offset,sec,pc,7)<<1;
583 break;
584 case 28:
585 code=opcode<<16|p->op[0]->reg<<16|p->op[1]->reg<<20|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16);
586 break;
587 case 29:
588 code=opcode<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,8,8)<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16);
589 break;
590 case 30:
591 code=opcode<<16|p->op[1]->reg<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16);
592 break;
593 case 31:
594 code=opcode|((absval(p->op[0]->offset,sec,pc,2)-1)<<4);
595 break;
596 case 32:
597 code=opcode|p->op[0]->reg|((absval(p->op[1]->offset,sec,pc,2)-1)<<4);
598 break;
599 case 34:
600 code=opcode<<16|((absval(p->op[1]->offset,sec,pc,2)-1)<<20)|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,8);
601 break;
602 case 33:
603 default:
604 ierror(mnemonics[c].ext.encoding);
605 }
606
607 d=db->data;
608 if(osize==4){
609 *d++=code>>24;
610 *d++=code>>16;
611 *d++=code;
612 *d++=code>>8;
613 }else{
614 *d++=code>>8;
615 *d++=code;
616 }
617 if(jmpconv){
618 *d++=0xfa;
619 *d++=absoffset2(jmpaddr->offset,0,sec,pc,&relocs,8+8*osize,8,0xffff0000);
620 val=absoffset2(jmpaddr->offset,0,sec,pc,&relocs,16+8*osize,16,0xffff);
621 *d++=val>>8;
622 *d++=val;
623 }
624 db->relocs=relocs;
625 return db;
626 }
627
628 /* Create a dblock (with relocs, if necessary) for size bits of data. */
eval_data(operand * op,size_t bitsize,section * sec,taddr pc)629 dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
630 {
631 dblock *new=new_dblock();
632 taddr val;
633 new->size=(bitsize+7)/8;
634 new->data=mymalloc(new->size);
635 if(op->type!=OP_ABS)
636 ierror(0);
637 if(bitsize!=8&&bitsize!=16&&bitsize!=32)
638 cpu_error(4);
639 val=absoffset(op->offset,op->mod,sec,pc,&new->relocs,0,bitsize);
640 if(bitsize==32){
641 new->data[3]=val>>24;
642 new->data[2]=val>>16;
643 new->data[1]=val>>8;
644 new->data[0]=val;
645 }else if(bitsize==16){
646 new->data[1]=val>>8;
647 new->data[0]=val;
648 }else
649 new->data[0]=val;
650 return new;
651 }
652
653
654 /* Calculate the size of the current instruction; must be identical
655 to the data created by eval_instruction. */
instruction_size(instruction * p,section * sec,taddr pc)656 size_t instruction_size(instruction *p,section *sec,taddr pc)
657 {
658 int c=translate(p,sec,pc),add=0;
659 if(c&JMPCONV){ add=4;c&=~JMPCONV;}
660 return mnemonics[c].ext.len*2+add;
661 }
662
new_operand()663 operand *new_operand()
664 {
665 operand *new=mymalloc(sizeof(*new));
666 new->type=-1;
667 return new;
668 }
669
670 /* return true, if initialization was successfull */
init_cpu()671 int init_cpu()
672 {
673 int i;
674 for(i=0;i<mnemonic_cnt;i++){
675 if(!strcmp(mnemonics[i].name,"jmp"))
676 JMP=i;
677 if(!strcmp(mnemonics[i].name,"jmpr"))
678 JMPR=i;
679 if(!strcmp(mnemonics[i].name,"jmpa"))
680 JMPA=i;
681 if(!strcmp(mnemonics[i].name,"jmps"))
682 JMPS=i;
683 if(!strcmp(mnemonics[i].name,"jb"))
684 JB=i;
685 if(!strcmp(mnemonics[i].name,"jbc"))
686 JBC=i;
687 if(!strcmp(mnemonics[i].name,"jnb"))
688 JNB=i;
689 if(!strcmp(mnemonics[i].name,"jnbs"))
690 JNBS=i;
691 }
692 sfrhash=new_hashtable(SFRHTSIZE);
693 return 1;
694 }
695
696 /* return true, if the passed argument is understood */
cpu_args(char * p)697 int cpu_args(char *p)
698 {
699 if(!strcmp(p,"-no-translations")){
700 notrans=1;
701 return 1;
702 }
703 if(!strcmp(p,"-jmpa")){
704 tojmpa=1;
705 return 1;
706 }
707 return 0;
708 }
709
710 /* parse cpu-specific directives; return pointer to end of
711 cpu-specific text */
parse_cpu_special(char * s)712 char *parse_cpu_special(char *s)
713 {
714 char *name=s,*merk=s;
715 if(ISIDSTART(*s)){
716 s++;
717 while(ISIDCHAR(*s))
718 s++;
719 if(s-name==4&&!strncmp(name,".sfr",4)){
720 sfr *new;
721 hashdata data;
722 expr *tree;
723 s=skip(s);
724 if(!ISIDSTART(*s))
725 cpu_error(0);
726 name=s++;
727 while(ISIDCHAR(*s))
728 s++;
729 if(find_namelen(sfrhash,name,s-name,&data))
730 new=data.ptr;
731 else{
732 data.ptr=new=mymalloc(sizeof(*new));
733 add_hashentry(sfrhash,cnvstr(name,s-name),data);
734 new->next=first_sfr;
735 first_sfr=new;
736 }
737 new->flags=new->laddr=new->saddr=0;
738 new->boffset=0;
739 s=skip(s);
740 if(*s!=',')
741 cpu_error(0);
742 else
743 s=skip(s+1);
744 tree=parse_expr(&s);
745 simplify_expr(tree);
746 if(!tree||tree->type!=NUM)
747 cpu_error(0);
748 else
749 new->laddr=tree->c.val;
750 s=skip(s);
751 if(tree->c.val==0xfe||tree->c.val==0xf0){
752 if(*s!=',')
753 cpu_error(0);
754 else
755 s=skip(s+1);
756 free_expr(tree);
757 tree=parse_expr(&s);
758 simplify_expr(tree);
759 if(!tree||tree->type!=NUM)
760 cpu_error(0);
761 else
762 new->saddr=tree->c.val;
763 free_expr(tree);
764 s=skip(s);
765 }else{
766 if(tree->c.val>=0xfe00)
767 new->laddr=0xfe;
768 else
769 new->laddr=0xf0;
770 new->saddr=(tree->c.val-(new->laddr<<8))/2;
771 if((new->laddr<<8)+2*new->saddr!=tree->c.val) ierror(0);
772 free_expr(tree);
773 }
774 if(*s==','){
775 s=skip(s+1);
776 tree=parse_expr(&s);
777 simplify_expr(tree);
778 new->boffset=tree->c.val;
779 new->flags|=ISBIT;
780 free_expr(tree);
781 }
782 return skip(s);
783 }
784 }
785 return merk;
786 }
787