1/* -*- c -*- */
2/* Copyright (C) 2013-2014 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	default:
241	  SM (reg, 0);
242	  break;
243	}
244      break;
245    case 3:
246      switch (reg)
247	{
248	case 0:
249	  {
250	    /* This fetch *is* the *PC++ that the opcode encodes :-)  */
251	    x = IMMU(2) | (ext << 16);
252	    SC (x);
253	  }
254	  break;
255	case 2:
256	  SC (8);
257	  break;
258	case 3:
259	  SC (-1);
260	  break;
261	default:
262	  SI (reg);
263	  break;
264	}
265      break;
266    }
267}
268
269static void
270encode_rep_zc (int srxt, int dsxt, LocalData *ld)
271{
272  MSP430_Opcode_Decoded *msp430 = ld->msp430;
273
274  msp430->repeat_reg = srxt & 1;
275  msp430->repeats = dsxt;
276  msp430->zc = (srxt & 2) ? 1 : 0;
277}
278
279#define REPZC(s,d) encode_rep_zc (s, d, ld)
280
281static int
282dopc_to_id (int dopc)
283{
284  switch (dopc)
285    {
286    case 4: return MSO_mov;
287    case 5: return MSO_add;
288    case 6: return MSO_addc;
289    case 7: return MSO_subc;
290    case 8: return MSO_sub;
291    case 9: return MSO_cmp;
292    case 10: return MSO_dadd;
293    case 11: return MSO_bit;
294    case 12: return MSO_bic;
295    case 13: return MSO_bis;
296    case 14: return MSO_xor;
297    case 15: return MSO_and;
298    default: return MSO_unknown;
299    }
300}
301
302static int
303sopc_to_id (int sop, int c)
304{
305  switch (sop * 2 + c)
306    {
307    case 0: return MSO_rrc;
308    case 1: return MSO_swpb;
309    case 2: return MSO_rra;
310    case 3: return MSO_sxt;
311    case 4: return MSO_push;
312    case 5: return MSO_call;
313    case 6: return MSO_reti;
314    default: return MSO_unknown;
315    }
316}
317
318int
319msp430_decode_opcode (unsigned long pc,
320		      MSP430_Opcode_Decoded *msp430,
321		      int (*getbyte)(void *),
322		      void *ptr)
323{
324  LocalData lds, *ld = &lds;
325  unsigned char op_buf[20] = {0};
326  unsigned char *op = op_buf;
327  int raddr;
328  int al_bit;
329  int srxt_bits, dsxt_bits;
330
331  lds.msp430 = msp430;
332  lds.getbyte = getbyte;
333  lds.ptr = ptr;
334  lds.op = op;
335  lds.op_ptr = 0;
336  lds.pc = pc;
337
338  memset (msp430, 0, sizeof (*msp430));
339
340  /* These are overridden by an extension word.  */
341  al_bit = 1;
342  srxt_bits = 0;
343  dsxt_bits = 0;
344
345 post_extension_word:
346  ;
347
348  /* 430X extention word.  */
349/** 0001 1srx t l 00 dsxt 	430x */
350
351  al_bit = l;
352  srxt_bits = srx * 2 + t;
353  dsxt_bits = dsxt;
354  op = op_buf + lds.op_ptr;
355  msp430->ofs_430x = 1;
356  goto post_extension_word;
357
358/* double-op insns:
359   opcode:4 sreg:4 Ad:1 BW:1 As:2 Dreg:4
360
361   single-op insn:
362   opcode:9 BW:1 Ad:2 DSreg:4
363
364   jumps:
365   opcode:3 Cond:3  pcrel:10. */
366
367/* Double-Operand "opcode" fields.  */
368/** VARY dopc 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111 */
369
370/** dopc sreg a b as dreg	%D%b	%1,%0				*/
371
372  ID (dopc_to_id (dopc)); ASX (sreg, as, srxt_bits); ADX (dreg, a, dsxt_bits); ABW (al_bit, b);
373  if (a == 0 && as == 0)
374    REPZC (srxt_bits, dsxt_bits);
375
376  switch (msp430->id)
377    {
378    case MSO_mov:	F_____; break;
379    case MSO_add:	F_VNZC; break;
380    case MSO_addc:	F_VNZC; break;
381    case MSO_subc:	F_VNZC; break;
382    case MSO_sub:	F_VNZC; break;
383    case MSO_cmp:	F_VNZC; break;
384    case MSO_dadd:	F_VNZC; break;
385    case MSO_bit:	F_0NZC; break;
386    case MSO_bic:	F_____; break;
387    case MSO_bis:	F_____; break;
388    case MSO_xor:	F_VNZC; break;
389    case MSO_and:	F_0NZC; break;
390    default: break;
391    }
392
393/** 0001 00so c b ad dreg	%S%b	%1				*/
394
395  ID (sopc_to_id (so,c)); ASX (dreg, ad, srxt_bits); ABW (al_bit, b);
396
397  if (ad == 0)
398    REPZC (srxt_bits, dsxt_bits);
399
400  /* The helper functions encode for source, but it's
401     both source and dest, with a few documented exceptions.  */
402  msp430->op[0] = msp430->op[1];
403
404  /* RETI ignores the operand.  */
405  if (msp430->id == MSO_reti)
406    msp430->syntax = "%S";
407
408  switch (msp430->id)
409    {
410    case MSO_rrc:	F_VNZC; break;
411    case MSO_swpb:	F_____; break;
412    case MSO_rra:	F_0NZC; break;
413    case MSO_sxt:	F_0NZC; break;
414    case MSO_push:	F_____; break;
415    case MSO_call:	F_____; break;
416    case MSO_reti:	F_VNZC; break;
417    default: break;
418    }
419
420  /* 20xx 0010 0000 ---- ----
421     3cxx 0011 1100 ---- ----
422          001j mp-- ---- ----.  */
423/** 001jmp aa addrlsbs		%J	%1				*/
424
425  raddr = (aa << 9) | (addrlsbs << 1);
426  if (raddr & 0x400)
427    raddr = raddr - 0x800;
428  /* This is a pc-relative jump, but we don't use SM because that
429     would load the target address from the memory at X(PC), not use
430     PC+X *as* the address.  So we use SC to use the address, not the
431     data at that address.  */
432  ID (MSO_jmp); SC (pc + raddr + msp430->n_bytes);
433  msp430->cond = jmp;
434
435  /* Extended instructions.  */
436
437/** 0000 srcr 0000 dstr		MOVA @%1, %0 */
438  ID (MSO_mov); SM (srcr, 0); DR (dstr);
439  msp430->size = 20;
440  msp430->ofs_430x = 1;
441
442/** 0000 srcr 0001 dstr		MOVA @%1+, %0 */
443  ID (MSO_mov); SI (srcr); DR (dstr);
444  msp430->size = 20;
445  msp430->ofs_430x = 1;
446
447/** 0000 srcr 0010 dstr		MOVA &%1, %0 */
448  ID (MSO_mov); SA ((srcr << 16) + IMMU(2)); DR (dstr);
449  msp430->size = 20;
450  msp430->ofs_430x = 1;
451
452/** 0000 srcr 0011 dstr		MOVA %1, %0 */
453  ID (MSO_mov); SM (srcr, IMMS(2)); DR (dstr);
454  msp430->size = 20;
455  msp430->ofs_430x = 1;
456
457/** 0000 srcr 0110 dstr		MOVA %1, &%0 */
458  ID (MSO_mov); SR (srcr); DA ((dstr << 16) + IMMU(2));
459  msp430->size = 20;
460  msp430->ofs_430x = 1;
461
462/** 0000 srcr 0111 dstr		MOVA %1, &%0 */
463  ID (MSO_mov); SR (srcr); DM (dstr, IMMS(2));
464  msp430->size = 20;
465  msp430->ofs_430x = 1;
466
467/** 0000 srcr 1000 dstr		MOVA %1, %0 */
468  ID (MSO_mov); SC ((srcr << 16) + IMMU(2)); DR (dstr);
469  msp430->size = 20;
470  msp430->ofs_430x = 1;
471
472/** 0000 srcr 1001 dstr		CMPA %1, %0 */
473  ID (MSO_cmp); SC ((srcr << 16) + IMMU(2)); DR (dstr);
474  msp430->size = 20;
475  msp430->ofs_430x = 1;
476  F_VNZC;
477
478/** 0000 srcr 1010 dstr		ADDA %1, %0 */
479  ID (MSO_add); SC ((srcr << 16) + IMMU(2)); DR (dstr);
480  msp430->size = 20;
481  msp430->ofs_430x = 1;
482  F_VNZC;
483
484/** 0000 srcr 1011 dstr		SUBA %1, %0 */
485  ID (MSO_sub); SC ((srcr << 16) + IMMU(2)); DR (dstr);
486  msp430->size = 20;
487  msp430->ofs_430x = 1;
488  F_VNZC;
489
490/** 0000 srcr 1011 dstr		SUBA %1, %0 */
491  ID (MSO_sub); SC ((srcr << 16) + IMMU(2)); DR (dstr);
492  msp430->size = 20;
493  msp430->ofs_430x = 1;
494  F_VNZC;
495
496/** 0000 srcr 1100 dstr		MOVA %1, %0 */
497  ID (MSO_mov); SR (srcr); DR (dstr);
498  msp430->size = 20;
499  msp430->ofs_430x = 1;
500
501/** 0000 srcr 1101 dstr		CMPA %1, %0 */
502  ID (MSO_cmp); SR (srcr); DR (dstr);
503  msp430->size = 20;
504  msp430->ofs_430x = 1;
505  F_VNZC;
506
507/** 0000 srcr 1110 dstr		ADDA %1, %0 */
508  ID (MSO_add); SR (srcr); DR (dstr);
509  msp430->size = 20;
510  msp430->ofs_430x = 1;
511  F_VNZC;
512
513/** 0000 srcr 1111 dstr		SUBA %1, %0 */
514  ID (MSO_sub); SR (srcr); DR (dstr);
515  msp430->size = 20;
516  msp430->ofs_430x = 1;
517  F_VNZC;
518
519/** 0000 bt00 010w dstr		RRCM.A %c, %0 */
520  ID (MSO_rrc); DR (dstr); SR (dstr);
521  msp430->repeats = bt;
522  msp430->size = w ? 16 : 20;
523  msp430->ofs_430x = 1;
524  F_0NZC;
525
526/** 0000 bt01 010w dstr		RRAM.A %c, %0 */
527  ID (MSO_rra); DR (dstr); SR (dstr);
528  msp430->repeats = bt;
529  msp430->size = w ? 16 : 20;
530  msp430->ofs_430x = 1;
531  F_0NZC;
532
533/** 0000 bt10 010w dstr		RLAM.A %c, %0 */
534  ID (MSO_add); DR (dstr); SR (dstr);
535  msp430->repeats = bt;
536  msp430->size = w ? 16 : 20;
537  msp430->ofs_430x = 1;
538  F_0NZC;
539
540/** 0000 bt11 010w dstr		RRUM.A %c, %0 */
541  ID (MSO_rru); DR (dstr); SR (dstr);
542  msp430->repeats = bt;
543  msp430->size = w ? 16 : 20;
544  msp430->ofs_430x = 1;
545  F_0NZC;
546
547/** 0001 0011 0000 0000		RETI */
548  ID (MSO_reti);
549  msp430->size = 20;
550  msp430->ofs_430x = 1;
551
552/** 0001 0011 01as dstr		CALLA %0 */
553  ID (MSO_call); AS (dstr, as);
554  msp430->size = 20;
555  msp430->ofs_430x = 1;
556
557/** 0001 0011 1000 extb		CALLA %0 */
558  ID (MSO_call); SA (IMMU(2) | (extb << 16));
559  msp430->size = 20;
560  msp430->ofs_430x = 1;
561
562/** 0001 0011 1001 extb		CALLA %0 */
563  raddr = IMMU(2) | (extb << 16);
564  if (raddr & 0x80000)
565    raddr -= 0x100000;
566  ID (MSO_call); SA (pc + raddr + msp430->n_bytes);
567  msp430->size = 20;
568  msp430->ofs_430x = 1;
569
570/** 0001 0011 1011 extb		CALLA %0 */
571  ID (MSO_call); SC (IMMU(2) | (extb << 16));
572  msp430->size = 20;
573  msp430->ofs_430x = 1;
574
575/** 0001 010w bits srcr		PUSHM.A %0 */
576  ID (MSO_push); SR (srcr);
577  msp430->size = w ? 16 : 20;
578  msp430->repeats = bits;
579  msp430->ofs_430x = 1;
580
581/** 0001 011w bits dstr		POPM.A %0 */
582  ID (MSO_pop); DR (dstr);
583  msp430->size = w ? 16 : 20;
584  msp430->repeats = bits;
585  msp430->ofs_430x = 1;
586
587/** */
588
589  return msp430->n_bytes;
590}
591