Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1186 | savelij | 1 | /* decpseudo.c */ |
2 | /*****************************************************************************/ |
||
3 | /* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only */ |
||
4 | /* */ |
||
5 | /* AS */ |
||
6 | /* */ |
||
7 | /* Commonly Used VAX/PDP-11 Pseudo Instructions */ |
||
8 | /* */ |
||
9 | /*****************************************************************************/ |
||
10 | |||
11 | /***************************************************************************** |
||
12 | * Includes |
||
13 | *****************************************************************************/ |
||
14 | |||
15 | #include "stdinc.h" |
||
16 | #include <string.h> |
||
17 | |||
18 | #include "strutil.h" |
||
19 | #include "asmdef.h" |
||
20 | #include "asmpars.h" |
||
21 | #include "asmerr.h" |
||
22 | #include "errmsg.h" |
||
23 | |||
24 | #include "decpseudo.h" |
||
25 | |||
26 | /***************************************************************************** |
||
27 | * Global Types |
||
28 | *****************************************************************************/ |
||
29 | |||
30 | /*!------------------------------------------------------------------------ |
||
31 | * \fn decode_dec_packed(Word index) |
||
32 | * \brief encode number or decimal string in packed decimal format |
||
33 | * ------------------------------------------------------------------------ */ |
||
34 | |||
35 | static void append_digit(Byte digit, Boolean *p_half) |
||
36 | { |
||
37 | if (*p_half) |
||
38 | { |
||
39 | BAsmCode[CodeLen] |= (digit & 15); |
||
40 | CodeLen++; |
||
41 | switch (ListGrans[ActPC]) |
||
42 | { |
||
43 | case 1: |
||
44 | break; |
||
45 | case 2: |
||
46 | if (!(CodeLen & 1)) |
||
47 | WAsmCode[(CodeLen / 2) - 1] = ((Word)BAsmCode[CodeLen - 1]) << 8 | BAsmCode[CodeLen - 2]; |
||
48 | break; |
||
49 | } |
||
50 | } |
||
51 | else |
||
52 | { |
||
53 | SetMaxCodeLen(CodeLen + 1); |
||
54 | BAsmCode[CodeLen] = (digit & 15) << 4; |
||
55 | } |
||
56 | *p_half = !*p_half; |
||
57 | } |
||
58 | |||
59 | void decode_dec_packed(Word index) |
||
60 | { |
||
61 | TempResult value; |
||
62 | const char *p_str = NULL; |
||
63 | char tmp_dec_str[33]; |
||
64 | |||
65 | UNUSED(index); |
||
66 | |||
67 | if (!ChkArgCnt(1, 2)) |
||
68 | return; |
||
69 | |||
70 | as_tempres_ini(&value); |
||
71 | EvalStrExpression(&ArgStr[1], &value); |
||
72 | switch (value.Typ) |
||
73 | { |
||
74 | case TempNone: |
||
75 | break; |
||
76 | case TempInt: |
||
77 | as_snprintf(tmp_dec_str, sizeof(tmp_dec_str), "%lld", value.Contents.Int); |
||
78 | p_str = tmp_dec_str; |
||
79 | goto writeout; |
||
80 | case TempString: |
||
81 | p_str = value.Contents.str.p_str; |
||
82 | goto writeout; |
||
83 | case TempFloat: |
||
84 | WrStrErrorPos(ErrNum_StringOrIntButFloat, &ArgStr[1]); |
||
85 | break; |
||
86 | default: |
||
87 | WrStrErrorPos(ErrNum_ExpectIntOrString, &ArgStr[1]); |
||
88 | break; |
||
89 | writeout: |
||
90 | { |
||
91 | size_t num_digits = 0, l; |
||
92 | Boolean half, negative; |
||
93 | |||
94 | switch (*p_str) |
||
95 | { |
||
96 | case '-': |
||
97 | negative = True; |
||
98 | p_str++; |
||
99 | break; |
||
100 | case '+': |
||
101 | negative = False; |
||
102 | p_str++; |
||
103 | break; |
||
104 | default: |
||
105 | negative = False; |
||
106 | } |
||
107 | |||
108 | l = strlen(p_str); |
||
109 | half = False; |
||
110 | /* leading zero padding digit is not counted into num_digits: */ |
||
111 | if (!(l & 1)) |
||
112 | append_digit(0, &half); |
||
113 | for (; *p_str; p_str++) |
||
114 | { |
||
115 | if (!isdigit(*p_str)) |
||
116 | { |
||
117 | WrStrErrorPos(ErrNum_InvalidDecDigit, &ArgStr[1]); |
||
118 | CodeLen = 0; half = False; |
||
119 | break; |
||
120 | } |
||
121 | append_digit(*p_str - '0', &half); |
||
122 | if (++num_digits > 31) |
||
123 | { |
||
124 | WrStrErrorPos(ErrNum_DecStringTooLong, &ArgStr[1]); |
||
125 | CodeLen = 0; half = False; |
||
126 | break; |
||
127 | } |
||
128 | } |
||
129 | if (CodeLen || half) |
||
130 | { |
||
131 | append_digit(negative ? 13 : 12, &half); |
||
132 | if (2 == ArgCnt) |
||
133 | EnterIntSymbol(&ArgStr[2], num_digits, SegNone, False); |
||
134 | } |
||
135 | } |
||
136 | } |
||
137 | |||
138 | as_tempres_free(&value); |
||
139 | } |