Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1186 savelij 1
/* operator.c */
2
/*****************************************************************************/
3
/* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only                     */
4
/*                                                                           */
5
/* AS-Portierung                                                             */
6
/*                                                                           */
7
/* defintion of operators                                                    */
8
/*                                                                           */
9
/*****************************************************************************/
10
 
11
#include <stdio.h>
12
#include <math.h>
13
 
14
#include "stdinc.h"
15
#include "errmsg.h"
16
#include "asmdef.h"
17
#include "asmerr.h"
18
#include "asmpars.h"
19
#include "asmrelocs.h"
20
#include "operator.h"
21
 
22
#define PromoteLValFlags() \
23
        do \
24
        { \
25
          if (pErg->Typ != TempNone) \
26
          { \
27
            pErg->Flags |= (pLVal->Flags & eSymbolFlags_Promotable); \
28
            pErg->AddrSpaceMask |= pLVal->AddrSpaceMask; \
29
            if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = pLVal->DataSize; \
30
          } \
31
        } \
32
        while (0)
33
 
34
#define PromoteRValFlags() \
35
        do \
36
        { \
37
          if (pErg->Typ != TempNone) \
38
          { \
39
            pErg->Flags |= (pRVal->Flags & eSymbolFlags_Promotable); \
40
            pErg->AddrSpaceMask |= pRVal->AddrSpaceMask; \
41
            if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = pRVal->DataSize; \
42
          } \
43
        } \
44
        while (0)
45
 
46
#define PromoteLRValFlags() \
47
        do \
48
        { \
49
          if (pErg->Typ != TempNone) \
50
          { \
51
            pErg->Flags |= ((pLVal->Flags | pRVal->Flags) & eSymbolFlags_Promotable); \
52
            pErg->AddrSpaceMask |= pLVal->AddrSpaceMask | pRVal->AddrSpaceMask; \
53
            if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = pLVal->DataSize; \
54
            if (pErg->DataSize == eSymbolSizeUnknown) pErg->DataSize = pRVal->DataSize; \
55
          } \
56
        } \
57
        while (0)
58
 
59
/*!------------------------------------------------------------------------
60
 * \fn     reg_cmp(const tRegDescr *p_reg1, tSymbolSize data_size1,
61
                   const tRegDescr *p_reg2, tSymbolSize data_size2)
62
 * \brief  compare two register symbols
63
 * \param  p_reg1, p_reg2 registers to compare
64
 * \return -1 : reg1 < reg2
65
 *          0 : reg1 = reg2
66
 *         +1 : reg1 > reg2
67
 *         -2 : unequal, but no smaller/greater relation can be given
68
 * ------------------------------------------------------------------------ */
69
 
70
static int reg_cmp(const TempResult *p_val1, const TempResult *p_val2)
71
{
72
  tRegInt num1, num2;
73
 
74
  /* If the two symbols are for different target architectures,
75
     they are for sure unequal, but no ordering criteria can be given: */
76
 
77
  if ((p_val1->Contents.RegDescr.Dissect != p_val2->Contents.RegDescr.Dissect)
78
   || (p_val1->Contents.RegDescr.compare != p_val2->Contents.RegDescr.compare))
79
    return -2;
80
 
81
  /* architecture-specific comparison function? */
82
 
83
  if (p_val1->Contents.RegDescr.compare)
84
    return p_val1->Contents.RegDescr.compare(p_val1->Contents.RegDescr.Reg, p_val1->DataSize,
85
                                             p_val2->Contents.RegDescr.Reg, p_val2->DataSize);
86
 
87
  /* The generic comparison: If operand sizes differ, they are 'just unequal',
88
     otherwise compare register numbers: */
89
 
90
  if (p_val1->DataSize != p_val2->DataSize)
91
    return -2;
92
  num1 = p_val1->Contents.RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
93
  num2 = p_val2->Contents.RegDescr.Reg & ~REGSYM_FLAG_ALIAS;
94
  if (num1 < num2)
95
    return -1;
96
  else if (num1 > num2)
97
    return 1;
98
  else
99
    return 0;
100
}
101
 
102
static Boolean OneComplOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
103
{
104
  UNUSED(pLVal);
105
  if (!pRVal)
106
    return False;
107
 
108
  as_tempres_set_int(pErg, ~(pRVal->Contents.Int));
109
  PromoteLValFlags();
110
  return True;
111
}
112
 
113
static Boolean ShLeftOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
114
{
115
  if (!pLVal || !pRVal)
116
    return False;
117
 
118
  as_tempres_set_int(pErg, pLVal->Contents.Int << pRVal->Contents.Int);
119
  PromoteLRValFlags();
120
  return True;
121
}
122
 
123
static Boolean ShRightOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
124
{
125
  if (!pLVal || !pRVal)
126
    return False;
127
 
128
  as_tempres_set_int(pErg, pLVal->Contents.Int >> pRVal->Contents.Int);
129
  PromoteLRValFlags();
130
  return True;
131
}
132
 
133
static Boolean BitMirrorOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
134
{
135
  int z;
136
 
137
  if (!pLVal || !pRVal)
138
    return False;
139
 
140
  if ((pRVal->Contents.Int < 1) || (pRVal->Contents.Int > 32)) WrError(ErrNum_OverRange);
141
  else
142
  {
143
    LargeInt Result = (pLVal->Contents.Int >> pRVal->Contents.Int) << pRVal->Contents.Int;
144
 
145
    for (z = 0; z < pRVal->Contents.Int; z++)
146
    {
147
      if ((pLVal->Contents.Int & (1 << (pRVal->Contents.Int - 1 - z))) != 0)
148
        Result |= (1 << z);
149
    }
150
    as_tempres_set_int(pErg, Result);
151
  }
152
  PromoteLRValFlags();
153
  return True;
154
}
155
 
156
static Boolean BinAndOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
157
{
158
  if (!pLVal || !pRVal)
159
    return False;
160
 
161
  as_tempres_set_int(pErg, pLVal->Contents.Int & pRVal->Contents.Int);
162
  PromoteLRValFlags();
163
  return True;
164
}
165
 
166
static Boolean BinOrOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
167
{
168
  if (!pLVal || !pRVal)
169
    return False;
170
 
171
  as_tempres_set_int(pErg, pLVal->Contents.Int | pRVal->Contents.Int);
172
  PromoteLRValFlags();
173
  return True;
174
}
175
 
176
static Boolean BinXorOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
177
{
178
  if (!pLVal || !pRVal)
179
    return False;
180
 
181
  as_tempres_set_int(pErg, pLVal->Contents.Int ^ pRVal->Contents.Int);
182
  PromoteLRValFlags();
183
  return True;
184
}
185
 
186
static Boolean PotOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
187
{
188
  LargeInt HVal;
189
 
190
  if (!pLVal || !pRVal)
191
    return False;
192
 
193
  switch (pLVal->Typ)
194
  {
195
    case TempInt:
196
      if (pRVal->Contents.Int < 0) as_tempres_set_int(pErg, 0);
197
      else
198
      {
199
        LargeInt l = pLVal->Contents.Int, r = pRVal->Contents.Int;
200
 
201
        HVal = 1;
202
        while (r > 0)
203
        {
204
          if (r & 1)
205
            HVal *= l;
206
          r >>= 1;
207
          if (r)
208
            l *= l;
209
        }
210
        as_tempres_set_int(pErg, HVal);
211
      }
212
      break;
213
    case TempFloat:
214
      if (pRVal->Contents.Float == 0.0)
215
        as_tempres_set_float(pErg, 1.0);
216
      else if (pLVal->Contents.Float == 0.0)
217
        as_tempres_set_float(pErg, 0.0);
218
      else if (pLVal->Contents.Float > 0)
219
        as_tempres_set_float(pErg, pow(pLVal->Contents.Float, pRVal->Contents.Float));
220
      else if ((as_fabs(pRVal->Contents.Float) <= ((as_float_t)MaxLongInt)) && (floor(pRVal->Contents.Float) == pRVal->Contents.Float))
221
      {
222
        as_float_t Base = pLVal->Contents.Float, Result;
223
 
224
        HVal = (LongInt) floor(pRVal->Contents.Float + 0.5);
225
        if (HVal < 0)
226
        {
227
          Base = 1 / Base;
228
          HVal = -HVal;
229
        }
230
        Result = 1.0;
231
        while (HVal > 0)
232
        {
233
          if (HVal & 1)
234
            Result *= Base;
235
          Base *= Base;
236
          HVal >>= 1;
237
        }
238
        as_tempres_set_float(pErg, Result);
239
      }
240
      else
241
      {
242
        WrError(ErrNum_InvArgPair);
243
        pErg->Typ = TempNone;
244
      }
245
      break;
246
    default:
247
      break;
248
  }
249
  PromoteLRValFlags();
250
  return True;
251
}
252
 
253
static Boolean MultOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
254
{
255
  if (!pLVal || !pRVal)
256
    return False;
257
 
258
  switch (pLVal->Typ)
259
  {
260
    case TempInt:
261
      as_tempres_set_int(pErg, pLVal->Contents.Int * pRVal->Contents.Int);
262
      break;
263
    case TempFloat:
264
      as_tempres_set_float(pErg, pLVal->Contents.Float * pRVal->Contents.Float);
265
      break;
266
    default:
267
      break;
268
  }
269
  PromoteLRValFlags();
270
  return True;
271
}
272
 
273
static Boolean DivOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
274
{
275
  if (!pLVal || !pRVal)
276
    return False;
277
 
278
  switch (pLVal->Typ)
279
  {
280
    case TempInt:
281
      if (pRVal->Contents.Int == 0) WrError(ErrNum_DivByZero);
282
      else
283
        as_tempres_set_int(pErg, pLVal->Contents.Int / pRVal->Contents.Int);
284
      break;
285
    case TempFloat:
286
      if (pRVal->Contents.Float == 0.0) WrError(ErrNum_DivByZero);
287
      else
288
        as_tempres_set_float(pErg, pLVal->Contents.Float / pRVal->Contents.Float);
289
    default:
290
      break;
291
  }
292
  PromoteLRValFlags();
293
  return True;
294
}
295
 
296
static Boolean ModOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
297
{
298
  if (!pLVal || !pRVal)
299
    return False;
300
 
301
  if (pRVal->Contents.Int == 0) WrError(ErrNum_DivByZero);
302
  else
303
    as_tempres_set_int(pErg, pLVal->Contents.Int % pRVal->Contents.Int);
304
  PromoteLRValFlags();
305
  return True;
306
}
307
 
308
/* TODO: handle return code of NonZString2Int() better */
309
 
310
static Boolean AddOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
311
{
312
  if (!pLVal || !pRVal)
313
    return False;
314
 
315
  as_tempres_set_none(pErg);
316
  switch (pLVal->Typ)
317
  {
318
    case TempInt:
319
      switch (pRVal->Typ)
320
      {
321
        case TempInt:
322
          as_tempres_set_int(pErg, pLVal->Contents.Int + pRVal->Contents.Int);
323
          pErg->Relocs = MergeRelocs(&(pLVal->Relocs), &(pRVal->Relocs), TRUE);
324
          break;
325
        case TempString:
326
        {
327
          LargeInt RIntVal;
328
          tErrorNum error_num = NonZString2Int(&pRVal->Contents.str, &RIntVal);
329
 
330
          RIntVal += pLVal->Contents.Int;
331
          if (ErrNum_None == error_num)
332
          {
333
            if (RIntVal >= 0)
334
            {
335
              as_tempres_set_c_str(pErg, "");
336
              Int2NonZString(&pErg->Contents.str, RIntVal);
337
            }
338
            else
339
              as_tempres_set_int(pErg, RIntVal);
340
          }
341
          else
342
            WrError(error_num);
343
          break;
344
        }
345
        default:
346
          break;
347
      }
348
      break;
349
    case TempFloat:
350
      if (TempFloat == pRVal->Typ)
351
        as_tempres_set_float(pErg, pLVal->Contents.Float + pRVal->Contents.Float);
352
      break;
353
    case TempString:
354
    {
355
      switch (pRVal->Typ)
356
      {
357
        case TempString:
358
          as_tempres_set_str(pErg, &pLVal->Contents.str);
359
          as_nonz_dynstr_append(&pErg->Contents.str, &pRVal->Contents.str);
360
          break;
361
        case TempInt:
362
        {
363
          LargeInt LIntVal;
364
          tErrorNum error_num = NonZString2Int(&pLVal->Contents.str, &LIntVal);
365
 
366
          if (ErrNum_None == error_num)
367
          {
368
            LIntVal += pRVal->Contents.Int;
369
            if (LIntVal >= 0)
370
            {
371
              as_tempres_set_c_str(pErg, "");
372
              Int2NonZString(&pErg->Contents.str, LIntVal);
373
            }
374
            else
375
              as_tempres_set_int(pErg, LIntVal);
376
          }
377
          else
378
            WrError(error_num);
379
          break;
380
        }
381
        default:
382
          break;
383
      }
384
      break;
385
    }
386
    default:
387
      break;
388
  }
389
  PromoteLRValFlags();
390
  return True;
391
}
392
 
393
static Boolean SubOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
394
{
395
  if (!pLVal || !pRVal)
396
    return False;
397
 
398
  switch (pLVal->Typ)
399
  {
400
    case TempInt:
401
      as_tempres_set_int(pErg, pLVal->Contents.Int - pRVal->Contents.Int);
402
      break;
403
    case TempFloat:
404
      as_tempres_set_float(pErg, pLVal->Contents.Float - pRVal->Contents.Float);
405
      break;
406
    default:
407
      break;
408
  }
409
  PromoteLRValFlags();
410
  return True;
411
}
412
 
413
static Boolean SubSglOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
414
{
415
  UNUSED(pLVal);
416
  if (!pRVal)
417
    return False;
418
 
419
  switch (pLVal->Typ)
420
  {
421
    case TempInt:
422
      as_tempres_set_int(pErg, -pRVal->Contents.Int);
423
      break;
424
    case TempFloat:
425
      as_tempres_set_float(pErg, -pRVal->Contents.Float);
426
      break;
427
    default:
428
      break;
429
  }
430
  PromoteRValFlags();
431
  return True;
432
}
433
 
434
static Boolean LogNotOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
435
{
436
  UNUSED(pLVal);
437
  if (!pRVal)
438
    return False;
439
 
440
  as_tempres_set_int(pErg, pRVal->Contents.Int ? 0 : 1);
441
  PromoteLValFlags();
442
  return True;
443
}
444
 
445
static Boolean LogAndOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
446
{
447
  if (!pLVal)
448
    return False;
449
 
450
  /* short circuit evaluation: 0 && ... -> 0 */
451
 
452
  if (!pRVal)
453
  {
454
    if (!pLVal->Contents.Int)
455
    {
456
      as_tempres_set_int(pErg, 0);
457
      PromoteLValFlags();
458
      return True;
459
    }
460
    return False;
461
  }
462
 
463
  as_tempres_set_int(pErg, (pLVal->Contents.Int && pRVal->Contents.Int) ? 1 : 0);
464
  PromoteLRValFlags();
465
  return True;
466
}
467
 
468
static Boolean LogOrOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
469
{
470
  if (!pLVal)
471
    return False;
472
 
473
  /* short circuit evaluation: 1 ||  ... -> 1 */
474
 
475
  if (!pRVal)
476
  {
477
    if (pLVal->Contents.Int)
478
    {
479
      as_tempres_set_int(pErg, 1);
480
      PromoteLValFlags();
481
      return True;
482
    }
483
    return False;
484
  }
485
 
486
  as_tempres_set_int(pErg, (pLVal->Contents.Int || pRVal->Contents.Int) ? 1 : 0);
487
  PromoteLRValFlags();
488
  return True;
489
}
490
 
491
static Boolean LogXorOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
492
{
493
  if (!pLVal || !pRVal)
494
    return False;
495
 
496
  as_tempres_set_int(pErg, ((pLVal->Contents.Int != 0) != (pRVal->Contents.Int != 0)) ? 1 : 0);
497
  PromoteLRValFlags();
498
  return True;
499
}
500
 
501
static Boolean EqOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
502
{
503
  if (!pLVal || !pRVal)
504
    return False;
505
 
506
  switch (pLVal->Typ)
507
  {
508
    case TempInt:
509
      as_tempres_set_int(pErg, (pLVal->Contents.Int == pRVal->Contents.Int) ? 1 : 0);
510
      break;
511
    case TempFloat:
512
      as_tempres_set_int(pErg, (pLVal->Contents.Float == pRVal->Contents.Float) ? 1 : 0);
513
      break;
514
    case TempString:
515
      as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) == 0) ? 1 : 0);
516
      break;
517
    case TempReg:
518
      as_tempres_set_int(pErg, 0 == reg_cmp(pLVal, pRVal));
519
      break;
520
    default:
521
      break;
522
  }
523
  PromoteLRValFlags();
524
  return True;
525
}
526
 
527
static Boolean GtOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
528
{
529
  if (!pLVal || !pRVal)
530
    return False;
531
 
532
  switch (pLVal->Typ)
533
  {
534
    case TempInt:
535
      as_tempres_set_int(pErg, (pLVal->Contents.Int > pRVal->Contents.Int) ? 1 : 0);
536
      break;
537
    case TempFloat:
538
      as_tempres_set_int(pErg, (pLVal->Contents.Float > pRVal->Contents.Float) ? 1 : 0);
539
      break;
540
    case TempString:
541
      as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) > 0) ? 1 : 0);
542
      break;
543
    case TempReg:
544
      as_tempres_set_int(pErg, reg_cmp(pLVal, pRVal) == 1);
545
      break;
546
    default:
547
      break;
548
  }
549
  PromoteLRValFlags();
550
  return True;
551
}
552
 
553
static Boolean LtOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
554
{
555
  if (!pLVal || !pRVal)
556
    return False;
557
 
558
  switch (pLVal->Typ)
559
  {
560
    case TempInt:
561
      as_tempres_set_int(pErg, (pLVal->Contents.Int < pRVal->Contents.Int) ? 1 : 0);
562
      break;
563
    case TempFloat:
564
      as_tempres_set_int(pErg, (pLVal->Contents.Float < pRVal->Contents.Float) ? 1 : 0);
565
      break;
566
    case TempString:
567
      as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) < 0) ? 1 : 0);
568
      break;
569
    case TempReg:
570
      as_tempres_set_int(pErg, reg_cmp(pLVal, pRVal) == -1);
571
      break;
572
    default:
573
      break;
574
  }
575
  PromoteLRValFlags();
576
  return True;
577
}
578
 
579
static Boolean LeOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
580
{
581
  if (!pLVal || !pRVal)
582
    return False;
583
 
584
  switch (pLVal->Typ)
585
  {
586
    case TempInt:
587
      as_tempres_set_int(pErg, (pLVal->Contents.Int <= pRVal->Contents.Int) ? 1 : 0);
588
      break;
589
    case TempFloat:
590
      as_tempres_set_int(pErg, (pLVal->Contents.Float <= pRVal->Contents.Float) ? 1 : 0);
591
      break;
592
    case TempString:
593
      as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) <= 0) ? 1 : 0);
594
      break;
595
    case TempReg:
596
    {
597
      int cmp_res = reg_cmp(pLVal, pRVal);
598
      as_tempres_set_int(pErg, (cmp_res == -1) || (cmp_res == 0));
599
      break;
600
    }
601
    default:
602
      break;
603
  }
604
  PromoteLRValFlags();
605
  return True;
606
}
607
 
608
static Boolean GeOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
609
{
610
  if (!pLVal || !pRVal)
611
    return False;
612
 
613
  switch (pLVal->Typ)
614
  {
615
    case TempInt:
616
      as_tempres_set_int(pErg, (pLVal->Contents.Int >= pRVal->Contents.Int) ? 1 : 0);
617
      break;
618
    case TempFloat:
619
      as_tempres_set_int(pErg, (pLVal->Contents.Float >= pRVal->Contents.Float) ? 1 : 0);
620
      break;
621
    case TempString:
622
      as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) >= 0) ? 1 : 0);
623
      break;
624
    case TempReg:
625
    {
626
      int cmp_res = reg_cmp(pLVal, pRVal);
627
      as_tempres_set_int(pErg, (cmp_res == 1) || (cmp_res == 0));
628
      break;
629
    }
630
    default:
631
      break;
632
  }
633
  PromoteLRValFlags();
634
  return True;
635
}
636
 
637
static Boolean UneqOp(TempResult *pErg, TempResult *pLVal, TempResult *pRVal)
638
{
639
  if (!pLVal || !pRVal)
640
    return False;
641
 
642
  switch (pLVal->Typ)
643
  {
644
    case TempInt:
645
      as_tempres_set_int(pErg, (pLVal->Contents.Int != pRVal->Contents.Int) ? 1 : 0);
646
      break;
647
    case TempFloat:
648
      as_tempres_set_int(pErg, (pLVal->Contents.Float != pRVal->Contents.Float) ? 1 : 0);
649
      break;
650
    case TempString:
651
      as_tempres_set_int(pErg, (as_nonz_dynstr_cmp(&pLVal->Contents.str, &pRVal->Contents.str) != 0) ? 1 : 0);
652
      break;
653
    case TempReg:
654
      as_tempres_set_int(pErg, reg_cmp(pLVal, pRVal) != 0);
655
      break;
656
    default:
657
      break;
658
  }
659
  PromoteLRValFlags();
660
  return True;
661
}
662
 
663
#define Int2Int       (TempInt    | (TempInt << 4)   )
664
#define Float2Float   (TempFloat  | (TempFloat << 4) )
665
#define String2String (TempString | (TempString << 4))
666
#define Reg2Reg       (TempReg    | (TempReg << 4)   )
667
#define Int2String    (TempInt    | (TempString << 4))
668
#define String2Int    (TempString | (TempInt << 4)   )
669
 
670
const as_operator_t operators[] =
671
{
672
  {"~" , 1 , e_op_monadic,  1, { TempInt << 4, 0, 0, 0, 0 }, OneComplOp},
673
  {"<<", 2 , e_op_dyadic ,  3, { Int2Int, 0, 0, 0, 0 }, ShLeftOp},
674
  {">>", 2 , e_op_dyadic ,  3, { Int2Int, 0, 0, 0, 0 }, ShRightOp},
675
  {"><", 2 , e_op_dyadic ,  4, { Int2Int, 0, 0, 0, 0 }, BitMirrorOp},
676
  {"&" , 1 , e_op_dyadic ,  5, { Int2Int, 0, 0, 0, 0 }, BinAndOp},
677
  {"|" , 1 , e_op_dyadic ,  6, { Int2Int, 0, 0, 0, 0 }, BinOrOp},
678
  {"!" , 1 , e_op_dyadic ,  7, { Int2Int, 0, 0, 0, 0 }, BinXorOp},
679
  {"^" , 1 , e_op_dyadic ,  8, { Int2Int, Float2Float, 0, 0, 0 }, PotOp},
680
  {"*" , 1 , e_op_dyadic , 11, { Int2Int, Float2Float, 0, 0, 0 }, MultOp},
681
  {"/" , 1 , e_op_dyadic , 11, { Int2Int, Float2Float, 0, 0, 0 }, DivOp},
682
  {"#" , 1 , e_op_dyadic , 11, { Int2Int, 0, 0, 0, 0 }, ModOp},
683
  {"+" , 1 , e_op_dyadic , 13, { Int2Int, Float2Float, String2String, Int2String, String2Int }, AddOp},
684
  /* minus may have one or two operands */
685
  {"-" , 1 , e_op_dyadic , 13, { Int2Int, Float2Float, 0, 0, 0 }, SubOp},
686
  {"-" , 1 , e_op_monadic, 13, { TempInt << 4, TempFloat << 4, 0, 0, 0 }, SubSglOp},
687
  {"~~", 2 , e_op_monadic,  2, { TempInt << 4, 0, 0, 0, 0 }, LogNotOp},
688
  {"&&", 2 , e_op_dyadic_short , 15, { Int2Int, 0, 0, 0, 0 }, LogAndOp},
689
  {"||", 2 , e_op_dyadic_short , 16, { Int2Int, 0, 0, 0, 0 }, LogOrOp},
690
  {"!!", 2 , e_op_dyadic , 17, { Int2Int, 0, 0, 0, 0 }, LogXorOp},
691
  {"=" , 1 , e_op_dyadic , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, EqOp},
692
  {"==", 2 , e_op_dyadic , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, EqOp},
693
  {">" , 1 , e_op_dyadic , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, GtOp},
694
  {"<" , 1 , e_op_dyadic , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, LtOp},
695
  {"<=", 2 , e_op_dyadic , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, LeOp},
696
  {">=", 2 , e_op_dyadic , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, GeOp},
697
  {"<>", 2 , e_op_dyadic , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, UneqOp},
698
  {"!=", 2 , e_op_dyadic , 23, { Int2Int, Float2Float, String2String, Reg2Reg, 0 }, UneqOp},
699
  /* termination marker */
700
  {NULL, 0 , e_op_monadic,  0, { 0, 0, 0, 0, 0 }, NULL}
701
};
702
 
703
const as_operator_t no_operators[] =
704
{
705
  {NULL, 0 , e_op_monadic,  0, { 0, 0, 0, 0, 0 }, NULL}
706
};
707
 
708
const as_operator_t *target_operators = no_operators;