Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1126 savelij 1
/* codepps4.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS                                                                        */
6
/*                                                                           */
7
/* Code Generator Rockwell PPS-4                                             */
8
/*                                                                           */
9
/*****************************************************************************/
10
 
11
#include "stdinc.h"
12
 
13
#include <string.h>
14
#include <ctype.h>
15
 
16
#include "bpemu.h"
17
#include "asmdef.h"
18
#include "asmsub.h"
19
#include "asmpars.h"
20
#include "headids.h"
21
#include "asmitree.h"
22
#include "codevars.h"
23
#include "asmerr.h"
24
#include "errmsg.h"
25
#include "fourpseudo.h"
26
 
27
#include "codepps4.h"
28
 
29
/*---------------------------------------------------------------------------*/
30
/* Instruction Decoders */
31
 
32
/*!------------------------------------------------------------------------
33
 * \fn     decode_fixed(Word code)
34
 * \brief  handle instructions with no argument
35
 * \param  code machine code
36
 * ------------------------------------------------------------------------ */
37
 
38
static void decode_fixed(Word code)
39
{
40
  if (ChkArgCnt(0, 0))
41
  {
42
    BAsmCode[0] = code;
43
    CodeLen = 1;
44
  }
45
}
46
 
47
/*!------------------------------------------------------------------------
48
 * \fn     decode_adi(Word code)
49
 * \brief  handle ADI instruction
50
 * \param  code machine code
51
 * ------------------------------------------------------------------------ */
52
 
53
static void decode_adi(Word code)
54
{
55
  if (ChkArgCnt(1, 1))
56
  {
57
    tEvalResult eval_result;
58
    Byte value = EvalStrIntExpressionWithResult(&ArgStr[1], Int4, &eval_result);
59
 
60
    if (eval_result.OK)
61
    {
62
      /* I am not 100% sure I have to insert one's complement of the
63
         value into the instruction.  But this way, it makes most sense: */
64
 
65
      if (mFirstPassUnknownOrQuestionable(eval_result.Flags))
66
        value = 15;
67
      value = ~value & 15;
68
      if ((value == 15) || (value == 5))
69
        WrStrErrorPos(ErrNum_InvArg, &ArgStr[1]);
70
      else
71
      {
72
        BAsmCode[0] = code | value;
73
        CodeLen = 1;
74
      }
75
    }
76
  }
77
}
78
 
79
/*!------------------------------------------------------------------------
80
 * \fn     decode_imm_3(Word code)
81
 * \brief  handle instructions with 3 bit immediate operand
82
 * \param  code machine code
83
 * ------------------------------------------------------------------------ */
84
 
85
static void decode_imm_3(Word code)
86
{
87
  if (ChkArgCnt(1, 1))
88
  {
89
    Boolean ok;
90
 
91
    BAsmCode[0] = EvalStrIntExpression(&ArgStr[1], UInt3, &ok);
92
    if (ok)
93
    {
94
      BAsmCode[0] = code | (BAsmCode[0] & 0x07);
95
      CodeLen = 1;
96
    }
97
  }
98
}
99
 
100
/*!------------------------------------------------------------------------
101
 * \fn     decode_imm_4(Word code)
102
 * \brief  handle instructions with 4 bit immediate operand
103
 * \param  code machine code
104
 * ------------------------------------------------------------------------ */
105
 
106
static void decode_imm_4(Word code)
107
{
108
  if (ChkArgCnt(1, 1))
109
  {
110
    Boolean ok;
111
 
112
    BAsmCode[0] = EvalStrIntExpression(&ArgStr[1], UInt4, &ok);
113
    if (ok)
114
    {
115
      BAsmCode[0] = code | (BAsmCode[0] & 0x0f);
116
      CodeLen = 1;
117
    }
118
  }
119
}
120
 
121
/*!------------------------------------------------------------------------
122
 * \fn     decode_imm_8(Word code)
123
 * \brief  handle instructions with 8 bit immediate operand
124
 * \param  code machine code
125
 * ------------------------------------------------------------------------ */
126
 
127
static void decode_imm_8(Word code)
128
{
129
  if (ChkArgCnt(1, 1))
130
  {
131
    Boolean ok;
132
 
133
    BAsmCode[1] = EvalStrIntExpression(&ArgStr[1], Int8, &ok);
134
    if (ok)
135
    {
136
      BAsmCode[0] = code;
137
      CodeLen = 2;
138
    }
139
  }
140
}
141
 
142
/*!------------------------------------------------------------------------
143
 * \fn     decode_t(Word code)
144
 * \brief  handle T instruction
145
 * \param  code machine code
146
 * ------------------------------------------------------------------------ */
147
 
148
static void decode_t(Word code)
149
{
150
  if (ChkArgCnt(1, 1))
151
  {
152
    tEvalResult eval_result;
153
    Word address = EvalStrIntExpressionWithResult(&ArgStr[1], UInt12, &eval_result);
154
 
155
    if (eval_result.OK
156
     && ChkSamePage(EProgCounter(), address, 6, eval_result.Flags))
157
    {
158
      ChkSpace(SegCode, eval_result.AddrSpaceMask);
159
      BAsmCode[0] = code | (address & 63);
160
      CodeLen = 1;
161
    }
162
  }
163
}
164
 
165
/*!------------------------------------------------------------------------
166
 * \fn     decode_tm(Word code)
167
 * \brief  handle TM instruction
168
 * \param  code machine code
169
 * ------------------------------------------------------------------------ */
170
 
171
static void decode_tm(Word code)
172
{
173
  if (ChkArgCnt(1, 1))
174
  {
175
    tEvalResult eval_result;
176
    Word address = EvalStrIntExpressionWithResult(&ArgStr[1], UInt12, &eval_result);
177
 
178
    /* A lower address byte fron locations 0xd0...0xff is accessed, with
179
       bits 11:8 set to 0x1. We check for a correct vector address: */
180
 
181
    if (eval_result.OK)
182
    {
183
      ChkSpace(SegCode, eval_result.AddrSpaceMask);
184
      if (mFirstPassUnknownOrQuestionable(eval_result.Flags))
185
        address = (address & 0x00f) | 0x0d0;
186
      if (ChkRange(address, 0xd0, 0xff))
187
      {
188
        BAsmCode[0] = code | (address & 0x3f);
189
        CodeLen = 1;
190
      }
191
    }
192
  }
193
}
194
 
195
/*!------------------------------------------------------------------------
196
 * \fn     decode_tl(Word code)
197
 * \brief  handle TL instruction
198
 * \param  code machine code
199
 * ------------------------------------------------------------------------ */
200
 
201
static void decode_tl(Word code)
202
{
203
  if (ChkArgCnt(1, 1))
204
  {
205
    tEvalResult eval_result;
206
    Word address = EvalStrIntExpressionWithResult(&ArgStr[1], UInt12, &eval_result);
207
 
208
    if (eval_result.OK)
209
    {
210
      ChkSpace(SegCode, eval_result.AddrSpaceMask);
211
      BAsmCode[0] = code | (Hi(address) & 15);
212
      BAsmCode[1] = Lo(address);
213
      CodeLen = 2;
214
    }
215
  }
216
}
217
 
218
/*!------------------------------------------------------------------------
219
 * \fn     decode_tml(Word code)
220
 * \brief  handle TML instruction
221
 * \param  code machine code
222
 * ------------------------------------------------------------------------ */
223
 
224
static void decode_tml(Word code)
225
{
226
  if (ChkArgCnt(1, 1))
227
  {
228
    tEvalResult eval_result;
229
    Word address = EvalStrIntExpressionWithResult(&ArgStr[1], UInt12, &eval_result);
230
 
231
    if (eval_result.OK)
232
    {
233
      ChkSpace(SegCode, eval_result.AddrSpaceMask);
234
      if (mFirstPassUnknownOrQuestionable(eval_result.Flags))
235
        address = (address & 0x0ff) | 0x100;
236
      if (ChkRange(address, 0x100, 0x3ff))
237
      {
238
        BAsmCode[0] = code | (Hi(address) & 0x03);
239
        BAsmCode[1] = Lo(address);
240
        CodeLen = 2;
241
      }
242
    }
243
  }
244
}
245
 
246
/*!------------------------------------------------------------------------
247
 * \fn     decode_data_pps4(Word code)
248
 * \brief  handle DATA instruction
249
 * ------------------------------------------------------------------------ */
250
 
251
static void decode_data_pps4(Word code)
252
{
253
  UNUSED(code);
254
 
255
  DecodeDATA(Int8, Int4);
256
}
257
 
258
/*---------------------------------------------------------------------------*/
259
/* Code Table Handling */
260
 
261
/*!------------------------------------------------------------------------
262
 * \fn     init_fields(void)
263
 * \brief  build up instruction hash table
264
 * ------------------------------------------------------------------------ */
265
 
266
static void init_fields(void)
267
{
268
  InstTable = CreateInstTable(101);
269
 
270
  AddInstTable(InstTable, "AD"   , 0x0b, decode_fixed);
271
  AddInstTable(InstTable, "ADC"  , 0x0a, decode_fixed);
272
  AddInstTable(InstTable, "ADSK" , 0x09, decode_fixed);
273
  AddInstTable(InstTable, "ADCSK", 0x08, decode_fixed);
274
  AddInstTable(InstTable, "DC"   , 0x65, decode_fixed);
275
  AddInstTable(InstTable, "AND"  , 0x0d, decode_fixed);
276
  AddInstTable(InstTable, "OR"   , 0x0f, decode_fixed);
277
  AddInstTable(InstTable, "EOR"  , 0x0c, decode_fixed);
278
  AddInstTable(InstTable, "COMP" , 0x0e, decode_fixed);
279
  AddInstTable(InstTable, "SC"   , 0x20, decode_fixed);
280
  AddInstTable(InstTable, "RC"   , 0x24, decode_fixed);
281
  AddInstTable(InstTable, "SF1"  , 0x22, decode_fixed);
282
  AddInstTable(InstTable, "RF1"  , 0x26, decode_fixed);
283
  AddInstTable(InstTable, "SF2"  , 0x21, decode_fixed);
284
  AddInstTable(InstTable, "RF2"  , 0x25, decode_fixed);
285
  AddInstTable(InstTable, "LAX"  , 0x12, decode_fixed);
286
  AddInstTable(InstTable, "LXA"  , 0x1b, decode_fixed);
287
  AddInstTable(InstTable, "LABL" , 0x11, decode_fixed);
288
  AddInstTable(InstTable, "LBMX" , 0x10, decode_fixed);
289
  AddInstTable(InstTable, "LBUA" , 0x04, decode_fixed);
290
  AddInstTable(InstTable, "XABL" , 0x19, decode_fixed);
291
  AddInstTable(InstTable, "XBMX" , 0x18, decode_fixed);
292
  AddInstTable(InstTable, "XAX"  , 0x1a, decode_fixed);
293
  AddInstTable(InstTable, "XS"   , 0x06, decode_fixed);
294
  AddInstTable(InstTable, "CYS"  , 0x6f, decode_fixed);
295
  AddInstTable(InstTable, "INCB" , 0x17, decode_fixed);
296
  AddInstTable(InstTable, "DECB" , 0x1f, decode_fixed);
297
  AddInstTable(InstTable, "SKC"  , 0x15, decode_fixed);
298
  AddInstTable(InstTable, "SKZ"  , 0x1e, decode_fixed);
299
  AddInstTable(InstTable, "SKF1" , 0x16, decode_fixed);
300
  AddInstTable(InstTable, "SKF2" , 0x14, decode_fixed);
301
  AddInstTable(InstTable, "RTN"  , 0x05, decode_fixed);
302
  AddInstTable(InstTable, "RTNSK", 0x07, decode_fixed);
303
  AddInstTable(InstTable, "DIA"  , 0x27, decode_fixed);
304
  AddInstTable(InstTable, "DIB"  , 0x23, decode_fixed);
305
  AddInstTable(InstTable, "DOA"  , 0x1d, decode_fixed);
306
  AddInstTable(InstTable, "SAG"  , 0x13, decode_fixed);
307
 
308
  AddInstTable(InstTable, "ADI"  , 0x60, decode_adi);
309
  AddInstTable(InstTable, "LD"   , 0x30, decode_imm_3);
310
  AddInstTable(InstTable, "EX"   , 0x38, decode_imm_3);
311
  AddInstTable(InstTable, "EXD"  , 0x28, decode_imm_3);
312
  AddInstTable(InstTable, "LDI"  , 0x70, decode_imm_4);
313
  AddInstTable(InstTable, "LB"   , 0xc0, decode_imm_4);
314
  AddInstTable(InstTable, "LBL"  , 0x00, decode_imm_8);
315
  AddInstTable(InstTable, "SKBI" , 0x40, decode_imm_4);
316
  AddInstTable(InstTable, "IOL"  , 0x1c, decode_imm_8);
317
 
318
  AddInstTable(InstTable, "T"    , 0x80, decode_t);
319
  AddInstTable(InstTable, "TM"   , 0xc0, decode_tm);
320
  AddInstTable(InstTable, "TL"   , 0x50, decode_tl);
321
  AddInstTable(InstTable, "TML"  , 0x00, decode_tml);
322
 
323
  AddInstTable(InstTable, "RES",  0, DecodeRES);
324
  AddInstTable(InstTable, "DS",   0, DecodeRES);
325
  AddInstTable(InstTable, "DATA", 0, decode_data_pps4);
326
}
327
 
328
/*!------------------------------------------------------------------------
329
 * \fn     deinit_fields(void)
330
 * \brief  tear down instruction hash table
331
 * ------------------------------------------------------------------------ */
332
 
333
static void deinit_fields(void)
334
{
335
  DestroyInstTable(InstTable);
336
}
337
 
338
/*---------------------------------------------------------------------------*/
339
/* Interface Functions */
340
 
341
/*!------------------------------------------------------------------------
342
 * \fn     make_code_pps4(void)
343
 * \brief  machine instruction dispatcher
344
 * ------------------------------------------------------------------------ */
345
 
346
static void make_code_pps4(void)
347
{
348
  CodeLen = 0; DontPrint = False;
349
 
350
  /* to be ignored */
351
 
352
  if (Memo("")) return;
353
 
354
  /* pseudo instructions */
355
 
356
  if (!LookupInstTable(InstTable, OpPart.str.p_str))
357
    WrStrErrorPos(ErrNum_UnknownInstruction, &OpPart);
358
}
359
 
360
/*!------------------------------------------------------------------------
361
 * \fn     switch_from_pps4(void)
362
 * \brief  cleanups after switch from target
363
 * ------------------------------------------------------------------------ */
364
 
365
static void switch_from_pps4(void)
366
{
367
  deinit_fields();
368
}
369
 
370
/*!------------------------------------------------------------------------
371
 * \fn     is_def_cp_pps4(void)
372
 * \brief  does instruction use label field?
373
 * ------------------------------------------------------------------------ */
374
 
375
static Boolean is_def_pps4(void)
376
{
377
  return False;
378
}
379
 
380
/*!------------------------------------------------------------------------
381
 * \fn     switch_to_pps4(void)
382
 * \brief  prepare to assemble code for this target
383
 * ------------------------------------------------------------------------ */
384
 
385
static void switch_to_pps4(void)
386
{
387
  const TFamilyDescr *p_descr = FindFamilyByName("PPS-4");
388
 
389
  TurnWords = False;
390
  SetIntConstMode(eIntConstModeIntel);
391
 
392
  PCSymbol = "$";
393
  HeaderID = p_descr->Id;
394
  NOPCode = 0x00;
395
  DivideChars = ",";
396
  HasAttrs = False;
397
 
398
  ValidSegs = (1 << SegCode) | (1 << SegData);
399
  Grans[SegCode] = 1; ListGrans[SegCode] = 1; SegLimits[SegCode] = 0xfff;
400
  Grans[SegData] = 1; ListGrans[SegData] = 1; SegLimits[SegData] = 0xfff;
401
 
402
  MakeCode = make_code_pps4;
403
  SwitchFrom = switch_from_pps4;
404
  IsDef = is_def_pps4;
405
  init_fields();
406
}
407
 
408
/*!------------------------------------------------------------------------
409
 * \fn     codepps4_init(void)
410
 * \brief  register PPS-4 target
411
 * ------------------------------------------------------------------------ */
412
 
413
void codepps4_init(void)
414
{
415
  (void)AddCPU("PPS-4"    , switch_to_pps4);
416
}