Rizin
unix-like reverse engineering framework and cli tools
asm.c File Reference
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "dcpu16.h"

Go to the source code of this file.

Macros

#define NOTEND   1 /* endian hack */
 

Functions

static ut8 get_register_id (char reg)
 
static void clean_line (char *oline, const char *line)
 
static ut8 decode_parameter (char *param, int *extra_word_needed, ut16 *extra_word_value)
 
int dcpu16_assemble (ut8 *out, const char *unoline)
 

Macro Definition Documentation

◆ NOTEND

#define NOTEND   1 /* endian hack */

Definition at line 40 of file asm.c.

Function Documentation

◆ clean_line()

static void clean_line ( char *  oline,
const char *  line 
)
static

Definition at line 48 of file asm.c.

48  {
49  int cn = 0, n = 0;
50 
51  while (line[cn] != 0 && line[cn] != '\n' && line[cn] != ';') {
52  if (line[cn] >= '!' && line[cn] <= '~') {
53  char current_char = line[cn];
54 
55  /* Convert to upper case */
56  if (current_char >= 'a' && current_char <= 'z')
57  current_char = toupper((unsigned char)current_char);
58 
59  /* Place in cleaned line */
60  oline[n] = current_char;
61  n++;
62  }
63  cn++;
64  }
65  oline[n] = 0;
66 }
int n
Definition: mipsasm.c:19
line
Definition: setup.py:34
#define toupper(c)
Definition: safe-ctype.h:147

References setup::line, n, and toupper.

Referenced by dcpu16_assemble().

◆ dcpu16_assemble()

int dcpu16_assemble ( ut8 out,
const char *  unoline 
)

Definition at line 216 of file asm.c.

216  {
217  ut16 wordA = 0, wordB = 0;
218  int basic_opcode = 0;
219  int non_basic_opcode = 0;
220  char line[256] = { 0 }, *param;
221  int off = 0;
222  // uberflow!
223  clean_line(line, unoline);
224 
225  if (!(*line))
226  return 0;
227  if (strlen(line) < 4)
228  return 0;
229  param = line + 3; /* Cut off first 3 characters */
230 
231  /* Basic instructions */
232  // cmon! use an array
233  if (!strncmp("SET", line, 3))
234  basic_opcode = 0x1;
235  else if (!strncmp("ADD", line, 3))
236  basic_opcode = 0x2;
237  else if (!strncmp("SUB", line, 3))
238  basic_opcode = 0x3;
239  else if (!strncmp("MUL", line, 3))
240  basic_opcode = 0x4;
241  else if (!strncmp("DIV", line, 3))
242  basic_opcode = 0x5;
243  else if (!strncmp("MOD", line, 3))
244  basic_opcode = 0x6;
245  else if (!strncmp("SHL", line, 3))
246  basic_opcode = 0x7;
247  else if (!strncmp("SHR", line, 3))
248  basic_opcode = 0x8;
249  else if (!strncmp("AND", line, 3))
250  basic_opcode = 0x9;
251  else if (!strncmp("BOR", line, 3))
252  basic_opcode = 0xA;
253  else if (!strncmp("XOR", line, 3))
254  basic_opcode = 0xB;
255  else if (!strncmp("IFE", line, 3))
256  basic_opcode = 0xC;
257  else if (!strncmp("IFN", line, 3))
258  basic_opcode = 0xD;
259  else if (!strncmp("IFG", line, 3))
260  basic_opcode = 0xE;
261  else if (!strncmp("IFB", line, 3))
262  basic_opcode = 0xF;
263 
264  /* Non basic instructions */
265  if (basic_opcode == 0) {
266  if (!strncmp("JSR", line, 3)) {
267  non_basic_opcode = 0x1;
268  } else {
269  fprintf(stderr, "Unknown instruction\n");
270  return -1;
271  }
272  }
273 
274  /* Decode basic instructions */
275  if (basic_opcode != 0) {
276  ut8 paramA = 0, paramB = 0;
277 
278  /* Find comma */
279  int cn = 0;
280  while (cn < 256 && param[cn] != ',' && param[cn] != '\n' && param[cn] != 0)
281  cn++;
282 
283  if (param[cn] == ',') {
284  ut16 first_word;
285  int extraA = 0;
286  int extraB = 0;
287  char *pa, *pb;
288  /* Split parameter string to A and B */
289  param[cn] = 0;
290  pa = param;
291  pb = param + cn + 1;
292 
293  /* Increment address for the start word */
294  // current_address++;
295 
296  /* Parameter A */
297  paramA = decode_parameter(pa, &extraA, &wordA);
298  // if (extraA == 1) current_address++;
299 
300  /* Parameter B */
301  paramB = decode_parameter(pb, &extraB, &wordB);
302  // if (extraB == 1) current_address++;
303 
304  /* Put everything together */
305  first_word = ((paramB & 0x3F) << 10) | ((paramA & 0x3F) << 4) | (basic_opcode & 0xF);
306 
307  /* write opcode */
308 #if NOTEND
309  memcpy(out, &first_word, 2);
310  if (extraA == 1) {
311  memcpy(out + 2, &wordA, 2);
312  off = 4;
313  } else
314  off = 2;
315  if (extraB == 1) {
316  memcpy(out + off, &wordB, 2);
317  off += 2;
318  }
319 #else
320  out[0] = (first_word >> 8) & 0xff;
321  out[1] = first_word & 0xff;
322  if (extraA == 1) {
323  out[2] = (wordA >> 8) & 0xff;
324  out[3] = wordA & 0xff;
325  off = 4;
326  } else
327  off = 2;
328  if (extraB == 1) {
329  out[off] = (wordB >> 8) & 0xff;
330  out[off + 1] = wordB & 0xff;
331  off += 2;
332  }
333 #endif
334  } else {
335  fprintf(stderr, "Missing comma\n");
336  return -1;
337  }
338  }
339 
340  /* Non basic instructions */
341  if (non_basic_opcode == 0x1) { /* JSR */
342  int extraX = 0;
343  ut16 first_word, wordX = 0;
344  ut8 p = decode_parameter(param, &extraX, &wordX);
345 
346  first_word = ((p & 0x3F) << 10) | ((non_basic_opcode & 0x3F) << 4) | (basic_opcode & 0xF);
347 #if NOTEND
348  memcpy(out, &first_word, 2);
349  if (extraX == 1) {
350  memcpy(out + 2, &wordX, 2);
351  off = 4;
352  } else
353  off = 2;
354 #else
355  out[0] = (first_word >> 8) & 0xff;
356  out[1] = first_word & 0xff;
357  if (extraX == 1) {
358  out[2] = (wordX >> 8) & 0xff;
359  out[3] = wordX & 0xff;
360  off = 4;
361  } else
362  off = 2;
363 #endif
364  }
365  return off;
366 }
static void clean_line(char *oline, const char *line)
Definition: asm.c:48
static ut8 decode_parameter(char *param, int *extra_word_needed, ut16 *extra_word_value)
Definition: asm.c:71
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
uint16_t ut16
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
int off
Definition: pal.c:13

References clean_line(), decode_parameter(), setup::line, memcpy(), off, out, and p.

Referenced by assemble().

◆ decode_parameter()

static ut8 decode_parameter ( char *  param,
int extra_word_needed,
ut16 extra_word_value 
)
static

Definition at line 71 of file asm.c.

71  {
72  /* Check for square brackets */
73  int square_brackets = 0;
74  int first_sqbracket = 0, last_sqbracket = 0;
75  if (param[0] == '[') {
76  first_sqbracket = 1;
77  param++;
78  }
79  if (param[strlen(param) - 1] == ']') {
80  last_sqbracket = 1;
81  param[strlen(param) - 1] = 0;
82  }
83 
84  /* Check for errors */
85  if (first_sqbracket == 1) {
86  square_brackets = 1;
87  if (last_sqbracket != 1) {
88  fprintf(stderr, "Missing last square bracket\n");
89  return 0;
90  }
91  } else {
92  if (last_sqbracket == 1) {
93  fprintf(stderr, "Missing first square bracket\n");
94  return 0;
95  }
96  }
97 
98  /* Check if this is a hex literal */
99  if (param[0] == '0' && param[1] == 'X') {
100  /* Decode hex */
101  ut16 value = 0;
102  param = param + 2; /* Remove 0x */
103  int digit_count = strlen(param);
104  int digit_num = 0;
105  int reg = -1;
106  for (digit_num = 0; digit_num < digit_count; digit_num++) {
107  /* Get Digit value */
108  int digit_val = -1;
109  char current_digit = param[digit_num];
110  if (current_digit >= '0' && current_digit <= '9')
111  digit_val = current_digit - '0';
112  if (current_digit >= 'A' && current_digit <= 'F')
113  digit_val = current_digit - 'A' + 10;
114 
115  if (current_digit == '+' && square_brackets == 1) {
116  reg = get_register_id(param[digit_num + 1]);
117  digit_num++;
118  } else {
119  /* Check for errors */
120  if (digit_val == -1) {
121  fprintf(stderr, "invalid literal\n");
122  return 0;
123  }
124 
125  /* Merge into final number */
126  value = (value << 4) + digit_val;
127  }
128  }
129 
130  if (value <= 0x1f && square_brackets == 0)
131  return value + 0x20;
132 
133  *extra_word_needed = 1;
134  *extra_word_value = value;
135 
136  if (square_brackets == 1) {
137  if (reg != -1)
138  return 0x10 + reg;
139  return 0x1e;
140  }
141  return 0x1f;
142  }
143 
144  /* Check if this is a decimal literal */
145  if (param[0] >= '0' && param[0] <= '9') {
146  /* Decode decimal */
147  ut16 value = 0;
148  int digit_count = strlen(param);
149  int digit_num = 0;
150  int reg = -1;
151  for (digit_num = 0; digit_num < digit_count; digit_num++) {
152  /* Get Digit value */
153  int digit_val = -1;
154  char current_digit = param[digit_num];
155  if (current_digit >= '0' && current_digit <= '9')
156  digit_val = current_digit - '0';
157 
158  if (current_digit == '+' && square_brackets == 1) {
159  reg = get_register_id(param[digit_num + 1]);
160  digit_num++;
161  } else {
162  /* Check for errors */
163  if (digit_val == -1) {
164  fprintf(stderr, "invalid literal\n");
165  return 0;
166  }
167 
168  /* Merge into final number */
169  value = (value * 10) + digit_val;
170  }
171  }
172  if (value <= 0x1f && square_brackets == 0)
173  return value + 0x20;
174 
175  *extra_word_needed = 1;
176  *extra_word_value = value;
177 
178  if (square_brackets == 1) {
179  if (reg != -1)
180  return 0x10 + reg;
181  return 0x1e;
182  }
183  return 0x1f;
184  }
185 
186  /* Check if this is a register */
187  if (param[1] == 0) { /* This is a quick way to check that this is 1 character long */
188  ut8 reg = get_register_id(param[0]);
189  if (square_brackets == 1)
190  reg += 0x08;
191  return reg;
192  }
193 
194  /* Check if this is a word */
195  if (!strncmp("POP", param, 3))
196  return 0x18;
197  if (!strncmp("PEEK", param, 4))
198  return 0x19;
199  if (!strncmp("PUSH", param, 4))
200  return 0x1a;
201  if (!strncmp("SP", param, 2))
202  return 0x1b;
203  if (!strncmp("PC", param, 2))
204  return 0x1c;
205  if (!strncmp("O", param, 1))
206  return 0x1d;
207 
208  /* Must be a label, store a labelref */
209  *extra_word_needed = 1;
210  /* Allocate blank extra word, this will be where the
211  pointer to the label will be stored at link stage */
212  *extra_word_value = 0;
213  return 0x1f;
214 }
static ut8 get_register_id(char reg)
Definition: asm.c:42
static int value
Definition: cmd_api.c:93
#define reg(n)

References get_register_id(), reg, and value.

Referenced by dcpu16_assemble().

◆ get_register_id()

static ut8 get_register_id ( char  reg)
static

Definition at line 42 of file asm.c.

42  {
43  const char *regs = "ABCXYZIJ";
44  const char *p = strchr(regs, reg);
45  return p ? (int)(size_t)(p - regs) : 0;
46 }
static char * regs[]
Definition: analysis_sh.c:203
static int
Definition: sfsocketcall.h:114

References int, p, reg, and regs.

Referenced by decode_parameter().