1/* -*- c -*- */
2/* Copyright (C) 2013-2017 Free Software Foundation, Inc.
3   Contributed by Red Hat.
4   Written by DJ Delorie.
5
6   This file is part of the GNU opcodes library.
7
8   This library is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3, or (at your option)
11   any later version.
12
13   It is distributed in the hope that it will be useful, but WITHOUT
14   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16   License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21   MA 02110-1301, USA.  */
22
23#include "sysdep.h"
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include "ansidecl.h"
28#include "opcode/msp430-decode.h"
29
30static int trace = 0;
31
32typedef struct
33{
34  MSP430_Opcode_Decoded *msp430;
35  int (*getbyte)(void *);
36  void *ptr;
37  unsigned char *op;
38  int op_ptr;
39  int pc;
40} LocalData;
41
42#define AU ATTRIBUTE_UNUSED
43#define GETBYTE() getbyte_swapped (ld)
44#define B ((unsigned long) GETBYTE ())
45
46static int
47getbyte_swapped (LocalData *ld)
48{
49  int b;
50
51  if (ld->op_ptr == ld->msp430->n_bytes)
52    {
53      do
54	{
55	  b = ld->getbyte (ld->ptr);
56	  ld->op [(ld->msp430->n_bytes++)^1] = b;
57	}
58      while (ld->msp430->n_bytes & 1);
59    }
60  return ld->op[ld->op_ptr++];
61}
62
63#define ID(x)		msp430->id = x
64
65#define OP(n, t, r, a) (msp430->op[n].type = t,	     \
66		        msp430->op[n].reg = r,	     \
67		        msp430->op[n].addend = a)
68
69#define OPX(n, t, r1, r2, a)	 \
70  (msp430->op[n].type = t,	 \
71   msp430->op[n].reg = r1,	 \
72   msp430->op[n].reg2 = r2,	 \
73   msp430->op[n].addend = a)
74
75#define SYNTAX(x)	msp430->syntax = x
76#define UNSUPPORTED()	msp430->syntax = "*unknown*"
77
78#define DC(c)		OP (0, MSP430_Operand_Immediate, 0, c)
79#define DR(r)		OP (0, MSP430_Operand_Register, r, 0)
80#define DM(r, a)	OP (0, MSP430_Operand_Indirect, r, a)
81#define DA(a)		OP (0, MSP430_Operand_Indirect, MSR_None, a)
82#define AD(r, ad)	encode_ad (r, ad, ld, 0)
83#define ADX(r, ad, x)	encode_ad (r, ad, ld, x)
84
85#define SC(c)		OP (1, MSP430_Operand_Immediate, 0, c)
86#define SR(r)		OP (1, MSP430_Operand_Register, r, 0)
87#define SM(r, a)	OP (1, MSP430_Operand_Indirect, r, a)
88#define SA(a)		OP (1, MSP430_Operand_Indirect, MSR_None, a)
89#define SI(r)		OP (1, MSP430_Operand_Indirect_Postinc, r, 0)
90#define AS(r, as)	encode_as (r, as, ld, 0)
91#define ASX(r, as, x)	encode_as (r, as, ld, x)
92
93#define BW(x)		msp430->size = (x ? 8 : 16)
94/* The last 20 is for SWPBX.Z and SXTX.A.  */
95#define ABW(a,x)	msp430->size = (a ? ((x ? 8 : 16)) : (x ? 20 : 20))
96
97#define IMMU(bytes)	immediate (bytes, 0, ld)
98#define IMMS(bytes)	immediate (bytes, 1, ld)
99
100/* Helper macros for known status bits settings.  */
101#define	F_____		msp430->flags_1 = msp430->flags_0 = 0; msp430->flags_set = 0
102#define	F_VNZC		msp430->flags_1 = msp430->flags_0 = 0; msp430->flags_set = 0x87
103#define	F_0NZC		msp430->flags_1 = 0; msp430->flags_0 = 0x80; msp430->flags_set = 0x07
104
105
106/* The chip is little-endian, but GETBYTE byte-swaps words because the
107   decoder is based on 16-bit "words" so *this* logic is big-endian.  */
108
109static int
110immediate (int bytes, int sign_extend, LocalData *ld)
111{
112  unsigned long i = 0;
113
114  switch (bytes)
115    {
116    case 1:
117      i |= B;
118      if (sign_extend && (i & 0x80))
119	i -= 0x100;
120      break;
121    case 2:
122      i |= B << 8;
123      i |= B;
124      if (sign_extend && (i & 0x8000))
125	i -= 0x10000;
126      break;
127    case 3:
128      i |= B << 16;
129      i |= B << 8;
130      i |= B;
131      if (sign_extend && (i & 0x800000))
132	i -= 0x1000000;
133      break;
134    case 4:
135      i |= B << 24;
136      i |= B << 16;
137      i |= B << 8;
138      i |= B;
139      if (sign_extend && (i & 0x80000000ULL))
140	i -= 0x100000000ULL;
141      break;
142    default:
143      fprintf (stderr,
144	       "Programmer error: immediate() called with invalid byte count %d\n",
145	       bytes);
146      abort ();
147    }
148  return i;
149}
150
151/*
152		PC	SP	SR	CG
153  As
154  00	Rn	-	-	R2	#0
155  01	X(Rn)	Sym	-	X(abs)	#1
156  10	(Rn)	-	-	#4	#2
157  11	(Rn++)	#imm	-	#8	#-1
158
159  Ad
160  0	Rn	-	-	-	-
161  1	X(Rn)	Sym	-	X(abs)	-   */
162
163static void
164encode_ad (int reg, int ad, LocalData *ld, int ext)
165{
166  MSP430_Opcode_Decoded *msp430 = ld->msp430;
167
168  if (ad)
169    {
170      int x = IMMU(2) | (ext << 16);
171      switch (reg)
172	{
173	case 0: /* (PC) -> Symbolic.  */
174	  DA (x + ld->pc + ld->op_ptr - 2);
175	  break;
176	case 2: /* (SR) -> Absolute.  */
177	  DA (x);
178	  break;
179	default:
180	  DM (reg, x);
181	  break;
182	}
183    }
184  else
185    {
186      DR (reg);
187    }
188}
189
190static void
191encode_as (int reg, int as, LocalData *ld, int ext)
192{
193  MSP430_Opcode_Decoded *msp430 = ld->msp430;
194  int x;
195
196  switch (as)
197    {
198    case 0:
199      switch (reg)
200	{
201	case 3:
202	  SC (0);
203	  break;
204	default:
205	  SR (reg);
206	  break;
207	}
208      break;
209    case 1:
210      switch (reg)
211	{
212	case 0: /* PC -> Symbolic.  */
213	  x = IMMU(2) | (ext << 16);
214	  SA (x + ld->pc + ld->op_ptr - 2);
215	  break;
216	case 2: /* SR -> Absolute.  */
217	  x = IMMU(2) | (ext << 16);
218	  SA (x);
219	  break;
220	case 3:
221	  SC (1);
222	  break;
223	default:
224	  x = IMMU(2) | (ext << 16);
225	  SM (reg, x);
226	  break;
227	}
228      break;
229    case 2:
230      switch (reg)
231	{
232	case 2:
233	  SC (4);
234	  break;
235	case 3:
236	  SC (2);
237	  break;
238	case MSR_None:
239	  SA (0);
240	  break;
241	default:
242	  SM (reg, 0);
243	  break;
244	}
245      break;
246    case 3:
247      switch (reg)
248	{
249	case 0:
250	  {
251	    /* This fetch *is* the *PC++ that the opcode encodes :-)  */
252	    x = IMMU(2) | (ext << 16);
253	    SC (x);
254	  }
255	  break;
256	case 2:
257	  SC (8);
258	  break;
259	case 3:
260	  SC (-1);
261	  break;
262	default:
263	  SI (reg);
264	  break;
265	}
266      break;
267    }
268}
269
270static void
271encode_rep_zc (int srxt, int dsxt, LocalData *ld)
272{
273  MSP430_Opcode_Decoded *msp430 = ld->msp430;
274
275  msp430->repeat_reg = srxt & 1;
276  msp430->repeats = dsxt;
277  msp430->zc = (srxt & 2) ? 1 : 0;
278}
279
280#define REPZC(s,d) encode_rep_zc (s, d, ld)
281
282static int
283dopc_to_id (int dopc)
284{
285  switch (dopc)
286    {
287    case 4: return MSO_mov;
288    case 5: return MSO_add;
289    case 6: return MSO_addc;
290    case 7: return MSO_subc;
291    case 8: return MSO_sub;
292    case 9: return MSO_cmp;
293    case 10: return MSO_dadd;
294    case 11: return MSO_bit;
295    case 12: return MSO_bic;
296    case 13: return MSO_bis;
297    case 14: return MSO_xor;
298    case 15: return MSO_and;
299    default: return MSO_unknown;
300    }
301}
302
303static int
304sopc_to_id (int sop, int c)
305{
306  switch (sop * 2 + c)
307    {
308    case 0: return MSO_rrc;
309    case 1: return MSO_swpb;
310    case 2: return MSO_rra;
311    case 3: return MSO_sxt;
312    case 4: return MSO_push;
313    case 5: return MSO_call;
314    case 6: return MSO_reti;
315    default: return MSO_unknown;
316    }
317}
318
319int
320msp430_decode_opcode (unsigned long pc,
321		      MSP430_Opcode_Decoded *msp430,
322		      int (*getbyte)(void *),
323		      void *ptr)
324{
325  LocalData lds, *ld = &lds;
326  unsigned char op_buf[20] = {0};
327  unsigned char *op = op_buf;
328  int raddr;
329  int al_bit;
330  int srxt_bits, dsxt_bits;
331
332  lds.msp430 = msp430;
333  lds.getbyte = getbyte;
334  lds.ptr = ptr;
335  lds.op = op;
336  lds.op_ptr = 0;
337  lds.pc = pc;
338
339  memset (msp430, 0, sizeof (*msp430));
340
341  /* These are overridden by an extension word.  */
342  al_bit = 1;
343  srxt_bits = 0;
344  dsxt_bits = 0;
345
346 post_extension_word:
347  ;
348
349  /* 430X extention word.  */
350/** 0001 1srx t l 00 dsxt 	430x */
351
352  al_bit = l;
353  srxt_bits = srx * 2 + t;
354  dsxt_bits = dsxt;
355  op = op_buf + lds.op_ptr;
356  msp430->ofs_430x = 1;
357  goto post_extension_word;
358
359/* double-op insns:
360   opcode:4 sreg:4 Ad:1 BW:1 As:2 Dreg:4
361
362   single-op insn:
363   opcode:9 BW:1 Ad:2 DSreg:4
364
365   jumps:
366   opcode:3 Cond:3  pcrel:10. */
367
368/* Double-Operand "opcode" fields.  */
369/** VARY dopc 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 */
370
371/** dopc sreg a b as dreg	%D%b	%1,%0				*/
372
373  ID (dopc_to_id (dopc)); ASX (sreg, as, srxt_bits); ADX (dreg, a, dsxt_bits); ABW (al_bit, b);
374  if (a == 0 && as == 0)
375    REPZC (srxt_bits, dsxt_bits);
376
377  switch (msp430->id)
378    {
379    case MSO_mov:	F_____; break;
380    case MSO_add:	F_VNZC; break;
381    case MSO_addc:	F_VNZC; break;
382    case MSO_subc:	F_VNZC; break;
383    case MSO_sub:	F_VNZC; break;
384    case MSO_cmp:	F_VNZC; break;
385    case MSO_dadd:	F_VNZC; break;
386    case MSO_bit:	F_0NZC; break;
387    case MSO_bic:	F_____; break;
388    case MSO_bis:	F_____; break;
389    case MSO_xor:	F_VNZC; break;
390    case MSO_and:	F_0NZC; break;
391    default: break;
392    }
393
394/** 0001 00so c b ad dreg	%S%b	%1				*/
395
396  ID (sopc_to_id (so,c)); ASX (dreg, ad, srxt_bits); ABW (al_bit, b);
397
398  if (ad == 0)
399    REPZC (srxt_bits, dsxt_bits);
400
401  /* The helper functions encode for source, but it's
402     both source and dest, with a few documented exceptions.  */
403  msp430->op[0] = msp430->op[1];
404
405  /* RETI ignores the operand.  */
406  if (msp430->id == MSO_reti)
407    msp430->syntax = "%S";
408
409  switch (msp430->id)
410    {
411    case MSO_rrc:	F_VNZC; break;
412    case MSO_swpb:	F_____; break;
413    case MSO_rra:	F_0NZC; break;
414    case MSO_sxt:	F_0NZC; break;
415    case MSO_push:	F_____; break;
416    case MSO_call:	F_____; break;
417    case MSO_reti:	F_VNZC; break;
418    default: break;
419    }
420
421  /* 20xx 0010 0000 ---- ----
422     3cxx 0011 1100 ---- ----
423          001j mp-- ---- ----.  */
424/** 001jmp aa addrlsbs		%J	%1				*/
425
426  raddr = (aa << 9) | (addrlsbs << 1);
427  if (raddr & 0x400)
428    raddr = raddr - 0x800;
429  /* This is a pc-relative jump, but we don't use SM because that
430     would load the target address from the memory at X(PC), not use
431     PC+X *as* the address.  So we use SC to use the address, not the
432     data at that address.  */
433  ID (MSO_jmp); SC (pc + raddr + msp430->n_bytes);
434  msp430->cond = jmp;
435
436  /* Extended instructions.  */
437
438/** 0000 srcr 0000 dstr		MOVA @%1, %0 */
439  ID (MSO_mov); SM (srcr, 0); DR (dstr);
440  msp430->size = 20;
441  msp430->ofs_430x = 1;
442
443/** 0000 srcr 0001 dstr		MOVA @%1+, %0 */
444  ID (MSO_mov); SI (srcr); DR (dstr);
445  msp430->size = 20;
446  msp430->ofs_430x = 1;
447
448/** 0000 srcr 0010 dstr		MOVA &%1, %0 */
449  ID (MSO_mov); SA ((srcr << 16) + IMMU(2)); DR (dstr);
450  msp430->size = 20;
451  msp430->ofs_430x = 1;
452
453/** 0000 srcr 0011 dstr		MOVA %1, %0 */
454  ID (MSO_mov); SM (srcr, IMMS(2)); DR (dstr);
455  msp430->size = 20;
456  msp430->ofs_430x = 1;
457
458/** 0000 srcr 0110 dstr		MOVA %1, &%0 */
459  ID (MSO_mov); SR (srcr); DA ((dstr << 16) + IMMU(2));
460  msp430->size = 20;
461  msp430->ofs_430x = 1;
462
463/** 0000 srcr 0111 dstr		MOVA %1, &%0 */
464  ID (MSO_mov); SR (srcr); DM (dstr, IMMS(2));
465  msp430->size = 20;
466  msp430->ofs_430x = 1;
467
468/** 0000 srcr 1000 dstr		MOVA %1, %0 */
469  ID (MSO_mov); SC ((srcr << 16) + IMMU(2)); DR (dstr);
470  msp430->size = 20;
471  msp430->ofs_430x = 1;
472
473/** 0000 srcr 1001 dstr		CMPA %1, %0 */
474  ID (MSO_cmp); SC ((srcr << 16) + IMMU(2)); DR (dstr);
475  msp430->size = 20;
476  msp430->ofs_430x = 1;
477  F_VNZC;
478
479/** 0000 srcr 1010 dstr		ADDA %1, %0 */
480  ID (MSO_add); SC ((srcr << 16) + IMMU(2)); DR (dstr);
481  msp430->size = 20;
482  msp430->ofs_430x = 1;
483  F_VNZC;
484
485/** 0000 srcr 1011 dstr		SUBA %1, %0 */
486  ID (MSO_sub); SC ((srcr << 16) + IMMU(2)); DR (dstr);
487  msp430->size = 20;
488  msp430->ofs_430x = 1;
489  F_VNZC;
490
491/** 0000 srcr 1011 dstr		SUBA %1, %0 */
492  ID (MSO_sub); SC ((srcr << 16) + IMMU(2)); DR (dstr);
493  msp430->size = 20;
494  msp430->ofs_430x = 1;
495  F_VNZC;
496
497/** 0000 srcr 1100 dstr		MOVA %1, %0 */
498  ID (MSO_mov); SR (srcr); DR (dstr);
499  msp430->size = 20;
500  msp430->ofs_430x = 1;
501
502/** 0000 srcr 1101 dstr		CMPA %1, %0 */
503  ID (MSO_cmp); SR (srcr); DR (dstr);
504  msp430->size = 20;
505  msp430->ofs_430x = 1;
506  F_VNZC;
507
508/** 0000 srcr 1110 dstr		ADDA %1, %0 */
509  ID (MSO_add); SR (srcr); DR (dstr);
510  msp430->size = 20;
511  msp430->ofs_430x = 1;
512  F_VNZC;
513
514/** 0000 srcr 1111 dstr		SUBA %1, %0 */
515  ID (MSO_sub); SR (srcr); DR (dstr);
516  msp430->size = 20;
517  msp430->ofs_430x = 1;
518  F_VNZC;
519
520/** 0000 bt00 010w dstr		RRCM.A %c, %0 */
521  ID (MSO_rrc); DR (dstr); SR (dstr);
522  msp430->repeats = bt;
523  msp430->size = w ? 16 : 20;
524  msp430->ofs_430x = 1;
525  F_0NZC;
526
527/** 0000 bt01 010w dstr		RRAM.A %c, %0 */
528  ID (MSO_rra); DR (dstr); SR (dstr);
529  msp430->repeats = bt;
530  msp430->size = w ? 16 : 20;
531  msp430->ofs_430x = 1;
532  F_0NZC;
533
534/** 0000 bt10 010w dstr		RLAM.A %c, %0 */
535  ID (MSO_add); DR (dstr); SR (dstr);
536  msp430->repeats = bt;
537  msp430->size = w ? 16 : 20;
538  msp430->ofs_430x = 1;
539  F_0NZC;
540
541/** 0000 bt11 010w dstr		RRUM.A %c, %0 */
542  ID (MSO_rru); DR (dstr); SR (dstr);
543  msp430->repeats = bt;
544  msp430->size = w ? 16 : 20;
545  msp430->ofs_430x = 1;
546  F_0NZC;
547
548/** 0001 0011 0000 0000		RETI */
549  ID (MSO_reti);
550  msp430->size = 20;
551  msp430->ofs_430x = 1;
552
553/** 0001 0011 01as dstr		CALLA %0 */
554  ID (MSO_call); AS (dstr, as);
555  msp430->size = 20;
556  msp430->ofs_430x = 1;
557
558/** 0001 0011 1000 extb		CALLA %0 */
559  ID (MSO_call); SA (IMMU(2) | (extb << 16));
560  msp430->size = 20;
561  msp430->ofs_430x = 1;
562
563/** 0001 0011 1001 extb		CALLA %0 */
564  raddr = IMMU(2) | (extb << 16);
565  if (raddr & 0x80000)
566    raddr -= 0x100000;
567  ID (MSO_call); SA (pc + raddr + msp430->n_bytes);
568  msp430->size = 20;
569  msp430->ofs_430x = 1;
570
571/** 0001 0011 1011 extb		CALLA %0 */
572  ID (MSO_call); SC (IMMU(2) | (extb << 16));
573  msp430->size = 20;
574  msp430->ofs_430x = 1;
575
576/** 0001 010w bits srcr		PUSHM.A %0 */
577  ID (MSO_push); SR (srcr);
578  msp430->size = w ? 16 : 20;
579  msp430->repeats = bits;
580  msp430->ofs_430x = 1;
581
582/** 0001 011w bits dstr		POPM.A %0 */
583  ID (MSO_pop); DR (dstr);
584  msp430->size = w ? 16 : 20;
585  msp430->repeats = bits;
586  msp430->ofs_430x = 1;
587
588/** */
589
590  return msp430->n_bytes;
591}
592