Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

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