OpenCores
URL https://opencores.org/ocsvn/System09/System09/trunk

Subversion Repositories System09

[/] [System09/] [trunk/] [Tools/] [as09/] [do09.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 74 davidgb
/*
2
 *      MC6809 specific processing
3
 */
4
 
5
#define PAGE2 0x10
6
#define PAGE3 0x11
7
#define IPBYTE 0x9F /* extended indirect postbyte */
8
#define SWI     0x3F
9
 
10
/* register names */
11
 
12
#define RD 0
13
#define RX 1
14
#define RY 2
15
#define RU 3
16
#define RS 4
17
#define RPC 5
18
#define RA 8
19
#define RB 9
20
#define RCC 10
21
#define RDP 11
22
#define RPCR 12
23
 
24
/* convert tfr/exg reg number into psh/pul format */
25
int     regs[] = { 6,16,32,64,64,128,0,0,2,4,1,8,0};
26
int     rcycl[]= { 2,2, 2, 2, 2, 2,  0,0,1,1,1,1,0};
27
 
28
/* addressing modes */
29
#define IMMED   0       /* immediate */
30
#define IND     1       /* indexed */
31
#define INDIR   2       /* indirect */
32
#define OTHER   3       /* NOTA */
33
 
34
/*
35
 *      localinit --- machine specific initialization
36
 */
37
localinit()
38
{
39
}
40
 
41
/*
42
 *      do_op --- process mnemonic
43
 *
44
 * Called with the base opcode and it's class. Optr points to
45
 * the beginning of the operand field.
46
 */
47
void do_op(opcode,class)
48
int opcode; /* base opcode */
49
int class; /* mnemonic class */
50
{
51
 int     dist;   /* relative branch distance */
52
 int     src,dst;/* source and destination registers */
53
 int     pbyte;  /* postbyte value */
54
 int     amode;  /* indicated addressing mode */
55
 int j;
56
 
57
 amode = set_mode();     /* pickup indicated addressing mode */
58
 
59
 switch(class){
60
  case INH:                       /* inherent addressing */
61
   emit(opcode);
62
   return;
63
  case GEN:                       /* general addressing */
64
   do_gen(opcode,amode);
65
   return;
66
  case IMM:                       /* immediate addressing */
67
   if( amode != IMMED ){
68
    error("Immediate Operand Required");
69
    return;
70
    }
71
   Optr++;
72
   eval();
73
   emit(opcode);
74
   emit(lobyte(Result));
75
   return;
76
  case REL:                       /* short relative branches */
77
   eval();
78
   dist = Result - (Pc+2);
79
   emit(opcode);
80
   if( (dist >127 || dist <-128) && Pass==2){
81
    error("Branch out of Range");
82
    emit(lobyte(-2));
83
    return;
84
    }
85
   emit(lobyte(dist));
86
   return;
87
  case P2REL:                     /* long relative branches */
88
   eval();
89
   dist = Result - (Pc+4);
90
   emit(PAGE2);
91
   emit(opcode);
92
   eword(dist);
93
   return;
94
  case P1REL:                     /* lbra and lbsr */
95
   if( amode == IMMED)
96
    Optr++; /* kludge for C compiler */
97
   eval();
98
   dist = Result - (Pc+3);
99
   emit(opcode);
100
   eword(dist);
101
   return;
102
  case NOIMM:
103
   if( amode == IMMED ){
104
    error("Immediate Addressing Illegal");
105
    return;
106
    }
107
   do_gen(opcode,amode);
108
   return;
109
  case P2GEN:
110
   emit(PAGE2);
111
   if( amode == IMMED ){
112
    emit(opcode);
113
    Optr++;
114
    eval();
115
    eword(Result);
116
    return;
117
    }
118
   do_gen(opcode,amode);
119
   return;
120
  case P3GEN:
121
   emit(PAGE3);
122
   if( amode == IMMED ){
123
    emit(opcode);
124
    Optr++;
125
    eval();
126
    eword(Result);
127
    return;
128
    }
129
   do_gen(opcode,amode);
130
   return;
131
  case RTOR:                      /* tfr and exg */
132
   emit(opcode);
133
   src = regnum();
134
   while(alpha(*Optr))Optr++;
135
   if(src==ERR){
136
    error("Register Name Required");
137
    emit(0);
138
    return;
139
    }
140
   if(*Optr++ != ','){
141
    error("Missing ,");
142
    emit(0);
143
    return;
144
    }
145
   dst = regnum();
146
   while(alpha(*Optr))Optr++;
147
   if(dst==ERR){
148
    error("Register Name Required");
149
    emit(0);
150
    return;
151
    }
152
   if( src==RPCR || dst==RPCR){
153
    error("PCR illegal here");
154
    emit(0);
155
    return;
156
    }
157
   if( (src <=5 && dst >=8) ||
158
       (src >=8 && dst <=5)){
159
    error("Register Size Mismatch");
160
    emit(0);
161
    return;
162
    }
163
   emit( (src<<4)+dst );
164
   return;
165
  case INDEXED:                   /* indexed addressing only */
166
   if( *Optr == '#'){
167
    Optr++;         /* kludge city */
168
    amode = IND;
169
    }
170
   if( amode != IND ){
171
    error("Indexed Addressing Required");
172
    return;
173
    }
174
   do_indexed(opcode);
175
   return;
176
  case RLIST:                     /* pushes and pulls */
177
   if(*Operand == EOS){
178
    error("Register List Required");
179
    return;
180
    }
181
   emit(opcode);
182
   pbyte = 0;
183
   do{
184
    j = regnum();
185
    if( j == ERR || j==RPCR)
186
     error("Illegal Register Name");
187
    else if(j==RS && (opcode==52))
188
     error("Can't Push S on S");
189
    else if(j==RU && (opcode==54))
190
     error("Can't Push U on U");
191
    else if(j==RS && (opcode==53))
192
     error("Can't Pull S from S");
193
    else if(j==RU && (opcode==55))
194
     error("Can't Pull U from U");
195
    else{
196
     pbyte |= regs[j];
197
     Cycles += rcycl[j];
198
     }
199
    while(*Optr != EOS && alpha(*Optr))Optr++;
200
   }while( *Optr++ == ',' );
201
   emit(lobyte(pbyte));
202
   return;
203
  case P2NOIMM:
204
   if( amode == IMMED )
205
    error("Immediate Addressing Illegal");
206
   else{
207
    emit(PAGE2);
208
    do_gen(opcode,amode);
209
    }
210
   return;
211
  case P2INH:                     /* Page 2 inherent */
212
   emit(PAGE2);
213
   emit(opcode);
214
   return;
215
  case P3INH:                     /* Page 3 inherent */
216
   emit(PAGE3);
217
   emit(opcode);
218
   return;
219
  case LONGIMM:
220
   if( amode == IMMED ){
221
    emit(opcode);
222
    Optr++;
223
    eval();
224
    eword(Result);
225
    }
226
   else
227
    do_gen(opcode,amode);
228
   return;
229
  case GRP2:
230
   if( amode == IND ){
231
    do_indexed(opcode+0x60);
232
    return;
233
    }
234
   else if( amode == INDIR){
235
    Optr++;
236
    emit(opcode + 0x60);
237
    emit(IPBYTE);
238
    eval();
239
    eword(Result);
240
    Cycles += 7;
241
    if(*Optr == ']'){
242
     Optr++;
243
     return;
244
     }
245
    error("Missing ']'");
246
    return;
247
    }
248
   eval();
249
   if(Force_word){
250
    emit(opcode+0x70);
251
    eword(Result);
252
    Cycles += 3;
253
    return;
254
    }
255
   if(Force_byte){
256
    emit(opcode);
257
    emit(lobyte(Result));
258
    Cycles += 2;
259
    return;
260
    }
261
   if(Result>=0 && Result <=0xFF){
262
    emit(opcode);
263
    emit(lobyte(Result));
264
    Cycles += 2;
265
    return;
266
    }
267
   else {
268
    emit(opcode+0x70);
269
    eword(Result);
270
    Cycles += 3;
271
    return;
272
    }
273
  case SYS:                       /* system call */
274
   emit(SWI);
275
   eval();
276
   emit(lobyte(Result));
277
   return;
278
  default:
279
   fatal("Error in Mnemonic table");
280
  }
281
}
282
 
283
 
284
/*
285
 *      do_gen --- process general addressing mode stuff
286
 */
287
do_gen(op,mode)
288
int     op;
289
int     mode;
290
{
291
 if( mode == IMMED){
292
  Optr++;
293
  emit(op);
294
  eval();
295
  emit(lobyte(Result));
296
        return(0);
297
  }
298
 else if( mode == IND ){
299
  do_indexed(op+0x20);
300
        return(0);
301
  }
302
 else if( mode == INDIR){
303
  Optr++;
304
  emit(op+0x20);
305
  emit(IPBYTE);
306
  eval();
307
  eword(Result);
308
  Cycles += 7;
309
  if(*Optr == ']'){
310
   Optr++;
311
         return(0);
312
   }
313
  error("Missing ']'");
314
        return(0);
315
  }
316
 else if( mode == OTHER){
317
  eval();
318
  if(Force_word){
319
   emit(op+0x30);
320
   eword(Result);
321
   Cycles += 3;
322
         return(0);
323
   }
324
  if(Force_byte){
325
   emit(op+0x10);
326
   emit(lobyte(Result));
327
   Cycles += 2;
328
         return(0);
329
   }
330
  if(Result>=0 && Result <=0xFF){
331
   emit(op+0x10);
332
   emit(lobyte(Result));
333
   Cycles += 2;
334
         return(0);
335
   }
336
  else {
337
   emit(op+0x30);
338
   eword(Result);
339
   Cycles += 3;
340
         return(0);
341
   }
342
  }
343
 else {
344
  error("Unknown Addressing Mode");
345
        return(0);
346
  }
347
}
348
 
349
/*
350
 *      do_indexed --- handle all wierd stuff for indexed addressing
351
 */
352
do_indexed(op)
353
int op;
354
{
355
 int     pbyte;
356
 int     j,k;
357
 int     predec,pstinc;
358
 
359
 Cycles += 2;    /* indexed is always 2+ base cycle count */
360
 predec=0;
361
 pstinc=0;
362
 pbyte=128;
363
 emit(op);
364
 if(*Optr=='['){
365
  pbyte |= 0x10;    /* set indirect bit */
366
  Optr++;
367
  if( !any((char)']',Optr))
368
   error("Missing ']'");
369
  Cycles += 3;    /* indirection takes this much longer */
370
  }
371
 j=regnum();
372
 if(j==RA){
373
  Cycles++;
374
  abd_index(pbyte+6);
375
        return(0);
376
  }
377
 if(j==RB){
378
  Cycles++;
379
  abd_index(pbyte+5);
380
        return(0);
381
  }
382
 if(j==RD){
383
  Cycles += 4;
384
  abd_index(pbyte+11);
385
        return(0);
386
  }
387
 eval();
388
 Optr++;
389
 while(*Optr=='-'){
390
  predec++;
391
  Optr++;
392
  }
393
 j=regnum();
394
 while( alpha(*Optr) )Optr++;
395
 while(*Optr=='+'){
396
  pstinc++;
397
  Optr++;
398
  }
399
 if(j==RPC || j==RPCR){
400
  if( pstinc || predec ){
401
   error("Auto Inc/Dec Illegal on PC");
402
         return(0);
403
   }
404
  if(j==RPC){
405
   if(Force_word){
406
    emit(pbyte+13);
407
    eword(Result);
408
    Cycles += 5;
409
                return(0);
410
    }
411
   if(Force_byte){
412
    emit(pbyte+12);
413
    emit(lobyte(Result));
414
    Cycles++;
415
                return(0);
416
    }
417
   if(Result>=-128 && Result <=127){
418
    emit(pbyte+12);
419
    emit(lobyte(Result));
420
    Cycles++;
421
                return(0);
422
    }
423
   else {
424
    emit(pbyte+13);
425
    eword(Result);
426
    Cycles += 5;
427
                return(0);
428
    }
429
   }
430
  /* PCR addressing */
431
  if(Force_word){
432
   emit(pbyte+13);
433
   eword(Result-(Pc+2));
434
   Cycles += 5;
435
         return(0);
436
   }
437
  if(Force_byte){
438
   emit(pbyte+12);
439
   emit(lobyte(Result-(Pc+1)));
440
   Cycles++;
441
         return(0);
442
   }
443
  k=Result-(Pc+2);
444
  if( k >= -128 && k <= 127){
445
   emit(pbyte+12);
446
   emit(lobyte(Result-(Pc+1)));
447
   Cycles++;
448
         return(0);
449
   }
450
  else{
451
   emit(pbyte+13);
452
   eword(Result-(Pc+2));
453
   Cycles += 5;
454
         return(0);
455
   }
456
  }
457
 if(predec || pstinc){
458
  if(Result != 0){
459
   error("Offset must be Zero");
460
         return(0);
461
   }
462
  if(predec>2 || pstinc>2){
463
   error("Auto Inc/Dec by 1 or 2 only");
464
         return(0);
465
   }
466
  if((predec==1 && (pbyte&0x10) != 0) ||
467
     (pstinc==1 && (pbyte&0x10) != 0)){
468
   error("No Auto Inc/Dec by 1 for Indirect");
469
         return(0);
470
   }
471
  if(predec && pstinc){
472
   error("Can't do both!");
473
         return(0);
474
   }
475
  if(predec)
476
   pbyte += predec+1;
477
  if(pstinc)
478
   pbyte += pstinc-1;
479
  pbyte += rtype(j);
480
  emit(pbyte);
481
  Cycles += 1 + predec + pstinc;
482
        return(0);
483
  }
484
 pbyte += rtype(j);
485
 if(Force_word){
486
  emit(pbyte+0x09);
487
  eword(Result);
488
  Cycles += 4;
489
        return(0);
490
  }
491
 if(Force_byte){
492
  emit(pbyte+0x08);
493
  emit(lobyte(Result));
494
  Cycles++;
495
        return(0);
496
  }
497
 if(Result==0){
498
  emit(pbyte+0x04);
499
        return(0);
500
  }
501
 if((Result >= -16) && (Result <= 15) && ((pbyte&16)==0)){
502
  pbyte &= 127;
503
  pbyte += Result&31;
504
  emit(pbyte);
505
  Cycles++;
506
        return(0);
507
  }
508
 if(Result >= -128 && Result <= 127){
509
  emit(pbyte+0x08);
510
  emit(lobyte(Result));
511
  Cycles++;
512
        return(0);
513
  }
514
 emit(pbyte+0x09);
515
 eword(Result);
516
 Cycles += 4;
517
 return(0);
518
}
519
 
520
 
521
/*
522
 *      abd_index --- a,b or d indexed
523
 */
524
 
525
abd_index(pbyte)
526
int pbyte;
527
{
528
 int     k;
529
 
530
 Optr += 2;
531
 k=regnum();
532
 pbyte += rtype(k);
533
 emit(pbyte);
534
 return(0);
535
}
536
 
537
/*
538
 *      rtype --- return register type in post-byte format
539
 */
540
rtype(r)
541
int r;
542
{
543
 switch(r){
544
 case RX:        return(0x00);
545
 case RY:        return(0x20);
546
 case RU:        return(0x40);
547
 case RS:        return(0x60);
548
  }
549
 error("Illegal Register for Indexed");
550
 return(0);
551
}
552
 
553
/*
554
 *      set_mode --- determine addressing mode from operand field
555
 */
556
set_mode()
557
{
558
 register char *p;
559
 
560
 if( *Operand == '#' )
561
  return(IMMED);          /* immediate addressing */
562
 p = Operand;
563
 while( *p != EOS && *p != BLANK && *p != TAB){/* any , before break */
564
  if( *p == ',')
565
   return(IND);    /* indexed addressing */
566
  p++;
567
  }
568
 if( *Operand == '[')
569
  return(INDIR);          /* indirect addressing */
570
 return(OTHER);                  /* NOTA */
571
}
572
 
573
/*
574
 *      regnum --- return register number of *Optr
575
 */
576
regnum()
577
{
578
 if( head(Optr,"D" ))return(RD);
579
 if( head(Optr,"d" ))return(RD);
580
 if( head(Optr,"X" ))return(RX);
581
 if( head(Optr,"x" ))return(RX);
582
 if( head(Optr,"Y" ))return(RY);
583
 if( head(Optr,"y" ))return(RY);
584
 if( head(Optr,"U" ))return(RU);
585
 if( head(Optr,"u" ))return(RU);
586
 if( head(Optr,"S" ))return(RS);
587
 if( head(Optr,"s" ))return(RS);
588
 if( head(Optr,"PC" ))return(RPC);
589
 if( head(Optr,"pc" ))return(RPC);
590
 if( head(Optr,"PCR" ))return(RPCR);
591
 if( head(Optr,"pcr" ))return(RPCR);
592
 if( head(Optr,"A" ))return(RA);
593
 if( head(Optr,"a" ))return(RA);
594
 if( head(Optr,"B" ))return(RB);
595
 if( head(Optr,"b" ))return(RB);
596
 if( head(Optr,"CC" ))return(RCC);
597
 if( head(Optr,"cc" ))return(RCC);
598
 if( head(Optr,"DP" ))return(RDP);
599
 if( head(Optr,"dp" ))return(RDP);
600
 return(ERR);
601
}
602
 
603
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.