/* Simple assembler V1.06 24/2/08
   Copyright 2008 Jeffrey Lee
   This file is part of WOUM.
   WOUM is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
   WOUM is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   You should have received a copy of the GNU General Public License
   along with WOUM.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _SASM_H
#define _SASM_H

#define EQ 0
#define NE 1
#define CS 2
#define HS 2
#define CC 3
#define LO 3
#define MI 4
#define PL 5
#define VS 6
#define VC 7
#define HI 8
#define LS 9
#define GE 10
#define LT 11
#define GT 12
#define LE 13
#define AL 14
#define NV 15

#define AND 0 /* Codes for sasm_alu */
#define EOR 2
#define SUB 4
#define RSB 6
#define ADD 8
#define ADC 10
#define SBC 12
#define RSC 14
#define TST 16
#define TEQ 18
#define CMP 20
#define CMN 22
#define ORR 24
#define MOV 26
#define BIC 28
#define MVN 30

#define S 1 /* S bit, for alu/mul */

#define LSL 0 /* Shift types for '1' and '2' variants */
#define LSR 1
#define ASR 2
#define ROR 3

/* sasm_mem options */
#define L 1 /* Load */
#define W 2 /* Write back to rn */
#define B 4 /* Byte */
#define U 8 /* Up (add offset) */
#define PRE 16 /* Pre indexing */
#define H 32 /* Halfword */
#define SI 64 /* Signed */

/* sasm_mem4 stack options, can be used with W above */
#define LED L+PRE+U
#define LFD L+U
#define LEA L+PRE
#define LFA L
#define SFA PRE+U
#define SEA U
#define SFD PRE
#define SED 0

/* sasm_mem4 'other' options, can be used with W and L above */
#define IB PRE+U
#define IA U
#define DB PRE
#define DA 0

/* processor capabilities */
#define SASM_H 1 /* halfword load/store supported */
#define SASM_PLD 2 /* PLD supported */
#define SASM_M 4 /* 'M' processor (long mul) */
#define SASM_E 8 /* 'E' processor (DSP instructions) */

extern int sasm_capabilities; /* Current capability settings. This should be set by the user to control what instruction sasm outputs. */

extern int sasm_getcapabilities();
/* Examine CPU and return capability flags */

/* *a = address to place instruction
   c = condition code */

extern void sasm_b(int *a,int c,int l,int *d);
/* Branch (link if l == 1) to d */

extern void sasm_alu(int *a,int c,int o,int rd,int rn,int rm,int type,int amt);
/* rd = rn <o> rm <type> #amt
   If amt is 0, no shift is used
   <o> can be <o> or <o>+S
*/

extern void sasm_alu2(int *a,int c,int o,int rd,int rn,int rm,int type,int rs);
/* rd = rn <o> rm <type> rs
   <o> can be <o> or <o>+S
*/

extern void sasm_alu3(int *a,int c,int o,int rd,int rn,int val);
/* rd = rn <o> #val
   <o> can be <o> or <o>+S
*/

extern void sasm_mul(int *a,int c,int s,int rd,int rm,int rs);
/* rd = rm * rs
*/

extern void sasm_mla(int *a,int c,int s,int rd,int rm,int rs,int rn);
/* rd = rm * rs + rn
*/

extern void sasm_mem(int *a,int c,int o,int rd,int rn,int rm,int type,int amt);
/* <ldr/str>[b|h|sh|sb] rd,[rn <+/-> rm <type> #amt]
   If amt is 0 or h/sh/sb, no shift is used
*/

extern void sasm_mem2(int *a,int c,int o,int rd,int rn,int d);
/* <ldr/str>[b|h|sh|sb] rd,[rn <+/-> d]
   d is 8 bit for h|sh|sb; else 12 bit
*/

extern void sasm_mem3(int *a,int c,int o,int rd,int *d);
/* <ldr/str>[b] rd,d
   <o> must not have U set!
*/

extern void sasm_mem4(int *a,int c,int o,int rn,int regs);
/* <ldm/stm> rn,{regs}
   <o> must not have B set!
*/

extern void sasm_swi(int *a,int c,int n);
/* swi <n>
*/

extern void sasm_sync(int *a,int l);
/* Synchronise l bytes from a
*/

extern int sasm_name(int *a,char *n);
/* Embed the name of function 'n', returning how many bytes were written
*/

extern void sasm_adr(int *a,int c,int rd,int *d);
/* Assembler an ADR instruction, to make rd point to d
*/

extern char *sasm_dis(int *a);
/* Disassemble the given instruction.
   The string returned is provided by the OS, so might not be around for long.
*/

extern int sasm_getcpuid();
/* Return CPU ID of processor (ARMv2+) (sasm_s.s)
*/

#endif
