Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1126 savelij 1
/* code3201x.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS-Portierung                                                             */
6
/*                                                                           */
7
/* Codegenerator TMS3201x-Familie                                            */
8
/*                                                                           */
9
/*****************************************************************************/
10
 
11
#include "stdinc.h"
12
#include <string.h>
13
#include <ctype.h>
14
 
15
#include "bpemu.h"
16
#include "strutil.h"
17
#include "chunks.h"
18
#include "asmdef.h"
19
#include "asmsub.h"
20
#include "asmpars.h"
21
#include "asmitree.h"
22
#include "codepseudo.h"
23
#include "fourpseudo.h"
24
#include "codevars.h"
25
#include "errmsg.h"
26
 
27
#include "code3201x.h"
28
 
29
typedef struct
30
{
31
  Word Code;
32
  Word AllowShifts;
33
} AdrShiftOrder;
34
 
35
typedef struct
36
{
37
  Word Code;
38
  Integer Min, Max;
39
  Word Mask;
40
} ImmOrder;
41
 
42
 
43
static Word AdrMode;
44
static Boolean AdrOK;
45
 
46
static CPUVar CPU32010, CPU32015;
47
 
48
static AdrShiftOrder *AdrShiftOrders;
49
static ImmOrder *ImmOrders;
50
 
51
/*----------------------------------------------------------------------------*/
52
 
53
static Word EvalARExpression(const tStrComp *pArg, Boolean *OK)
54
{
55
  *OK = True;
56
  if (!as_strcasecmp(pArg->str.p_str, "AR0"))
57
    return 0;
58
  if (!as_strcasecmp(pArg->str.p_str, "AR1"))
59
    return 1;
60
  return EvalStrIntExpression(pArg, UInt1, OK);
61
}
62
 
63
static void DecodeAdr(const tStrComp *pArg, int Aux, Boolean Must1)
64
{
65
  Byte h;
66
  char *p;
67
  char *Arg = pArg->str.p_str;
68
 
69
  AdrOK = False;
70
 
71
  if ((!strcmp(pArg->str.p_str, "*")) || (!strcmp(pArg->str.p_str, "*-")) || (!strcmp(pArg->str.p_str, "*+")))
72
  {
73
    AdrMode = 0x88;
74
    if (strlen(Arg) == 2)
75
      AdrMode += (pArg->str.p_str[1] == '+') ? 0x20 : 0x10;
76
    if (Aux <= ArgCnt)
77
    {
78
      h = EvalARExpression(&ArgStr[Aux], &AdrOK);
79
      if (AdrOK)
80
      {
81
        AdrMode &= 0xf7;
82
        AdrMode += h;
83
      }
84
    }
85
    else
86
      AdrOK = True;
87
  }
88
  else if (ChkArgCnt(1, Aux - 1))
89
  {
90
    tEvalResult EvalResult;
91
 
92
    h = 0;
93
    if ((strlen(pArg->str.p_str) > 3) && (!as_strncasecmp(pArg->str.p_str, "DAT", 3)))
94
    {
95
      AdrOK = True;
96
      for (p = pArg->str.p_str + 3; *p != '\0'; p++)
97
        if ((*p > '9') || (*p < '0'))
98
          AdrOK = False;
99
      if (AdrOK)
100
      {
101
        h = EvalStrIntExpressionOffsWithResult(pArg, 3, UInt8, &EvalResult);
102
        AdrOK = EvalResult.OK;
103
      }
104
    }
105
    if (!AdrOK)
106
    {
107
      h = EvalStrIntExpressionWithResult(pArg, Int8, &EvalResult);
108
      AdrOK = EvalResult.OK;
109
    }
110
    if (AdrOK)
111
    {
112
      if (Must1 && (h < 0x80) && !mFirstPassUnknown(EvalResult.Flags))
113
      {
114
        WrError(ErrNum_UnderRange);
115
        AdrOK = False;
116
      }
117
      else
118
      {
119
        AdrMode = h & 0x7f;
120
        ChkSpace(SegData, EvalResult.AddrSpaceMask);
121
      }
122
    }
123
  }
124
}
125
 
126
/*----------------------------------------------------------------------------*/
127
 
128
/* kein Argument */
129
 
130
static void DecodeFixed(Word Code)
131
{
132
  if (ChkArgCnt(0, 0))
133
  {
134
    CodeLen = 1;
135
    WAsmCode[0] = Code;
136
  }
137
}
138
 
139
/* Spruenge */
140
 
141
static void DecodeJmp(Word Code)
142
{
143
  if (ChkArgCnt(1, 1))
144
  {
145
    Boolean OK;
146
 
147
    WAsmCode[1] = EvalStrIntExpression(&ArgStr[1], UInt12, &OK);
148
    if (OK)
149
    {
150
      CodeLen = 2;
151
      WAsmCode[0] = Code;
152
    }
153
  }
154
}
155
 
156
/* nur Adresse */
157
 
158
static void DecodeAdrInst(Word Code)
159
{
160
  if (ChkArgCnt(1, 2))
161
  {
162
    DecodeAdr(&ArgStr[1], 2, Code & 1);
163
    if (AdrOK)
164
    {
165
      CodeLen = 1;
166
      WAsmCode[0] = (Code & 0xfffe) + AdrMode;
167
    }
168
  }
169
}
170
 
171
/* Adresse & schieben */
172
 
173
static void DecodeAdrShift(Word Index)
174
{
175
  Boolean HasSh;
176
  int AuxArgIndex;
177
  const AdrShiftOrder *pOrder = AdrShiftOrders + Index;
178
 
179
  if (ChkArgCnt(1, 3))
180
  {
181
    if (*ArgStr[1].str.p_str == '*')
182
    {
183
      switch (ArgCnt)
184
      {
185
        case 1:
186
          HasSh = False;
187
          AuxArgIndex = 3;
188
          break;
189
        case 2:
190
          if (!as_strncasecmp(ArgStr[2].str.p_str, "AR", 2))
191
          {
192
            HasSh = False;
193
            AuxArgIndex = 2;
194
          }
195
          else
196
          {
197
            HasSh = True;
198
            AuxArgIndex = 3;
199
          }
200
          break;
201
        default: /* 3 */
202
          HasSh = True;
203
          AuxArgIndex = 3;
204
      }
205
    }
206
    else
207
    {
208
      AuxArgIndex = 3;
209
      HasSh = (ArgCnt == 2);
210
    }
211
    DecodeAdr(&ArgStr[1], AuxArgIndex, False);
212
    if (AdrOK)
213
    {
214
      Boolean OK;
215
      Word AdrWord;
216
 
217
      if (!HasSh)
218
      {
219
        OK = True;
220
        AdrWord = 0;
221
      }
222
      else
223
      {
224
        tSymbolFlags Flags;
225
 
226
        AdrWord = EvalStrIntExpressionWithFlags(&ArgStr[2], Int4, &OK, &Flags);
227
        if (OK && mFirstPassUnknown(Flags))
228
          AdrWord = 0;
229
      }
230
      if (OK)
231
      {
232
        if ((pOrder->AllowShifts & (1 << AdrWord)) == 0) WrError(ErrNum_InvShiftArg);
233
        else
234
        {
235
          CodeLen = 1;
236
          WAsmCode[0] = pOrder->Code + AdrMode + (AdrWord << 8);
237
        }
238
      }
239
    }
240
  }
241
}
242
 
243
/* Ein/Ausgabe */
244
 
245
static void DecodeIN_OUT(Word Code)
246
{
247
  if (ChkArgCnt(2, 3))
248
  {
249
    DecodeAdr(&ArgStr[1], 3, False);
250
    if (AdrOK)
251
    {
252
      tEvalResult EvalResult;
253
      Word AdrWord = EvalStrIntExpressionWithResult(&ArgStr[2], UInt3, &EvalResult);
254
      if (EvalResult.OK)
255
      {
256
        ChkSpace(SegIO, EvalResult.AddrSpaceMask);
257
        CodeLen = 1;
258
        WAsmCode[0] = Code + AdrMode + (AdrWord << 8);
259
      }
260
    }
261
  }
262
}
263
 
264
/* konstantes Argument */
265
 
266
static void DecodeImm(Word Index)
267
{
268
  const ImmOrder *pOrder = ImmOrders + Index;
269
 
270
  if (ChkArgCnt(1, 1))
271
  {
272
    Boolean OK;
273
    tSymbolFlags Flags;
274
    LongInt AdrLong = EvalStrIntExpressionWithFlags(&ArgStr[1], Int32, &OK, &Flags);
275
 
276
    if (OK)
277
    {
278
      if (mFirstPassUnknown(Flags))
279
        AdrLong &= pOrder->Mask;
280
      if (AdrLong < pOrder->Min) WrError(ErrNum_UnderRange);
281
      else if (AdrLong > pOrder->Max) WrError(ErrNum_OverRange);
282
      else
283
      {
284
        CodeLen = 1;
285
        WAsmCode[0] = pOrder->Code + (AdrLong & pOrder->Mask);
286
      }
287
    }
288
  }
289
}
290
 
291
/* mit Hilfsregistern */
292
 
293
static void DecodeLARP(Word Code)
294
{
295
  UNUSED(Code);
296
 
297
  if (ChkArgCnt(1, 1))
298
  {
299
    Boolean OK;
300
    Word AdrWord = EvalARExpression(&ArgStr[1], &OK);
301
    if (OK)
302
    {
303
      CodeLen = 1;
304
      WAsmCode[0] = 0x6880 + AdrWord;
305
    }
306
  }
307
}
308
 
309
static void DecodeLAR_SAR(Word Code)
310
{
311
  if (ChkArgCnt(2, 3))
312
  {
313
    Boolean OK;
314
    Word AdrWord = EvalARExpression(&ArgStr[1], &OK);
315
    if (OK)
316
    {
317
      DecodeAdr(&ArgStr[2], 3, False);
318
      if (AdrOK)
319
      {
320
        CodeLen = 1;
321
        WAsmCode[0] = Code + AdrMode + (AdrWord << 8);
322
      }
323
    }
324
  }
325
}
326
 
327
static void DecodeLARK(Word Code)
328
{
329
  UNUSED(Code);
330
 
331
  if (ChkArgCnt(2, 2))
332
  {
333
    Boolean OK;
334
    Word AdrWord = EvalARExpression(&ArgStr[1], &OK);
335
    if (OK)
336
    {
337
      WAsmCode[0] = EvalStrIntExpression(&ArgStr[2], Int8, &OK);
338
      if (OK)
339
      {
340
        CodeLen = 1;
341
        WAsmCode[0] = Lo(WAsmCode[0]) + 0x7000 + (AdrWord << 8);
342
      }
343
    }
344
  }
345
}
346
 
347
static void DecodePORT(Word Code)
348
{
349
  UNUSED(Code);
350
 
351
  CodeEquate(SegIO, 0, 7);
352
}
353
 
354
static void DecodeDATA_3201x(Word Code)
355
{
356
  UNUSED(Code);
357
 
358
  DecodeDATA(Int16, Int16);
359
}
360
 
361
/*----------------------------------------------------------------------------*/
362
 
363
static void AddFixed(const char *NName, Word NCode)
364
{
365
  AddInstTable(InstTable, NName, NCode, DecodeFixed);
366
}
367
 
368
static void AddJmp(const char *NName, Word NCode)
369
{
370
  AddInstTable(InstTable, NName, NCode, DecodeJmp);
371
}
372
 
373
static void AddAdr(const char *NName, Word NCode, Word NMust1)
374
{
375
  AddInstTable(InstTable, NName, NCode | NMust1, DecodeAdrInst);
376
}
377
 
378
static void AddAdrShift(const char *NName, Word NCode, Word NAllow)
379
{
380
  order_array_rsv_end(AdrShiftOrders, AdrShiftOrder);
381
  AdrShiftOrders[InstrZ].Code = NCode;
382
  AdrShiftOrders[InstrZ].AllowShifts = NAllow;
383
  AddInstTable(InstTable, NName, InstrZ++, DecodeAdrShift);
384
}
385
 
386
static void AddImm(const char *NName, Word NCode, Integer NMin, Integer NMax, Word NMask)
387
{
388
  order_array_rsv_end(ImmOrders, ImmOrder);
389
  ImmOrders[InstrZ].Code = NCode;
390
  ImmOrders[InstrZ].Min = NMin;
391
  ImmOrders[InstrZ].Max = NMax;
392
  ImmOrders[InstrZ].Mask = NMask;
393
  AddInstTable(InstTable, NName, InstrZ++, DecodeImm);
394
}
395
 
396
static void InitFields(void)
397
{
398
  InstTable = CreateInstTable(203);
399
  AddInstTable(InstTable, "IN", 0x4000, DecodeIN_OUT);
400
  AddInstTable(InstTable, "OUT", 0x4800, DecodeIN_OUT);
401
  AddInstTable(InstTable, "LARP", 0, DecodeLARP);
402
  AddInstTable(InstTable, "LAR", 0x3800, DecodeLAR_SAR);
403
  AddInstTable(InstTable, "SAR", 0x3000, DecodeLAR_SAR);
404
  AddInstTable(InstTable, "LARK", 0, DecodeLARK);
405
  AddInstTable(InstTable, "PORT", 0, DecodePORT);
406
  AddInstTable(InstTable, "RES", 0, DecodeRES);
407
  AddInstTable(InstTable, "DATA", 0, DecodeDATA_3201x);
408
 
409
  AddFixed("ABS"   , 0x7f88);  AddFixed("APAC"  , 0x7f8f);
410
  AddFixed("CALA"  , 0x7f8c);  AddFixed("DINT"  , 0x7f81);
411
  AddFixed("EINT"  , 0x7f82);  AddFixed("NOP"   , 0x7f80);
412
  AddFixed("PAC"   , 0x7f8e);  AddFixed("POP"   , 0x7f9d);
413
  AddFixed("PUSH"  , 0x7f9c);  AddFixed("RET"   , 0x7f8d);
414
  AddFixed("ROVM"  , 0x7f8a);  AddFixed("SOVM"  , 0x7f8b);
415
  AddFixed("SPAC"  , 0x7f90);  AddFixed("ZAC"   , 0x7f89);
416
 
417
  AddJmp("B"     , 0xf900);  AddJmp("BANZ"  , 0xf400);
418
  AddJmp("BGEZ"  , 0xfd00);  AddJmp("BGZ"   , 0xfc00);
419
  AddJmp("BIOZ"  , 0xf600);  AddJmp("BLEZ"  , 0xfb00);
420
  AddJmp("BLZ"   , 0xfa00);  AddJmp("BNZ"   , 0xfe00);
421
  AddJmp("BV"    , 0xf500);  AddJmp("BZ"    , 0xff00);
422
  AddJmp("CALL"  , 0xf800);
423
 
424
  AddAdr("ADDH"  , 0x6000, False);  AddAdr("ADDS"  , 0x6100, False);
425
  AddAdr("AND"   , 0x7900, False);  AddAdr("DMOV"  , 0x6900, False);
426
  AddAdr("LDP"   , 0x6f00, False);  AddAdr("LST"   , 0x7b00, False);
427
  AddAdr("LT"    , 0x6a00, False);  AddAdr("LTA"   , 0x6c00, False);
428
  AddAdr("LTD"   , 0x6b00, False);  AddAdr("MAR"   , 0x6800, False);
429
  AddAdr("MPY"   , 0x6d00, False);  AddAdr("OR"    , 0x7a00, False);
430
  AddAdr("SST"   , 0x7c00, True );  AddAdr("SUBC"  , 0x6400, False);
431
  AddAdr("SUBH"  , 0x6200, False);  AddAdr("SUBS"  , 0x6300, False);
432
  AddAdr("TBLR"  , 0x6700, False);  AddAdr("TBLW"  , 0x7d00, False);
433
  AddAdr("XOR"   , 0x7800, False);  AddAdr("ZALH"  , 0x6500, False);
434
  AddAdr("ZALS"  , 0x6600, False);
435
 
436
  InstrZ = 0;
437
  AddAdrShift("ADD"   , 0x0000, 0xffff);
438
  AddAdrShift("LAC"   , 0x2000, 0xffff);
439
  AddAdrShift("SACH"  , 0x5800, 0x0013);
440
  AddAdrShift("SACL"  , 0x5000, 0x0001);
441
  AddAdrShift("SUB"   , 0x1000, 0xffff);
442
 
443
  InstrZ = 0;
444
  AddImm("LACK", 0x7e00,     0,  255,   0xff);
445
  AddImm("LDPK", 0x6e00,     0,    1,    0x1);
446
  AddImm("MPYK", 0x8000, -4096, 4095, 0x1fff);
447
}
448
 
449
static void DeinitFields(void)
450
{
451
  DestroyInstTable(InstTable);
452
 
453
  order_array_free(AdrShiftOrders);
454
  order_array_free(ImmOrders);
455
}
456
 
457
/*----------------------------------------------------------------------------*/
458
 
459
/*!------------------------------------------------------------------------
460
 * \fn     InternSymbol_3201X(char *pArg, TempResult *pResult)
461
 * \brief  parse for built-in symbols
462
 * \param  pArg source argument
463
 * \param  pResult possible result
464
 * ------------------------------------------------------------------------ */
465
 
466
static void InternSymbol_3201X(char *pArg, TempResult *pResult)
467
{
468
  if ((strlen(pArg) == 3)
469
   && (as_toupper(pArg[0]) == 'P')
470
   && (as_toupper(pArg[1]) == 'A')
471
   && ((pArg[2] >= '0') && (pArg[2] <= '7')))
472
  {
473
    as_tempres_set_int(pResult, pArg[2] - '0');
474
    pResult->AddrSpaceMask |= 1 << SegIO;
475
  }
476
}
477
 
478
static void MakeCode_3201X(void)
479
{
480
  CodeLen = 0;
481
  DontPrint = False;
482
 
483
  /* zu ignorierendes */
484
 
485
  if (Memo(""))
486
    return;
487
 
488
  if (!LookupInstTable(InstTable, OpPart.str.p_str))
489
    WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
490
}
491
 
492
static Boolean IsDef_3201X(void)
493
{
494
  return (Memo("PORT"));
495
}
496
 
497
static void SwitchFrom_3201X(void)
498
{
499
  DeinitFields();
500
}
501
 
502
static void SwitchTo_3201X(void)
503
{
504
  TurnWords = False;
505
  SetIntConstMode(eIntConstModeIntel);
506
 
507
  PCSymbol = "$";
508
  HeaderID = 0x74;
509
  NOPCode = 0x7f80;
510
  DivideChars = ",";
511
  HasAttrs = False;
512
 
513
  ValidSegs = (1 << SegCode)|(1 << SegData)|(1 << SegIO);
514
  Grans[SegCode] = 2; ListGrans[SegCode] = 2; SegInits[SegCode] = 0;
515
  SegLimits[SegCode] = 0xfff;
516
  Grans[SegData] = 2; ListGrans[SegData] = 2; SegInits[SegData] = 0;
517
  SegLimits[SegData] = (MomCPU == CPU32010) ? 0x8f : 0xff;
518
  Grans[SegIO  ] = 2; ListGrans[SegIO  ] = 2; SegInits[SegIO  ] = 0;
519
  SegLimits[SegIO  ] = 7;
520
 
521
  MakeCode = MakeCode_3201X;
522
  IsDef = IsDef_3201X;
523
  InternSymbol = InternSymbol_3201X;
524
  SwitchFrom = SwitchFrom_3201X;
525
  InitFields();
526
}
527
 
528
void code3201x_init(void)
529
{
530
  CPU32010 = AddCPU("32010", SwitchTo_3201X);
531
  CPU32015 = AddCPU("32015", SwitchTo_3201X);
532
}