Initial commit, including vasm

This commit is contained in:
Elliot Nunn 2020-06-20 09:33:04 +08:00
commit 9d4022b833
200 changed files with 62211 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.app
edit.rom
.DS_Store

39
NetBoot.py Executable file
View File

@ -0,0 +1,39 @@
#!/usr/bin/env python3
# Multicast client
# Adapted from: http://chaos.weblogs.us/archives/164
import socket
ANY = "0.0.0.0"
MCAST_ADDR = "239.192.76.84"
MCAST_PORT = 1954
# Create a UDP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) # IPPROTO_UDP could just be 0
# Allow multiple sockets to use the same PORT number
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEPORT,1)
# Bind to the port that we know will receive multicast data
sock.bind((ANY,MCAST_PORT))
# Tell the kernel that we want to add ourselves to a multicast group
# The address for the multicast group is the third param
status = sock.setsockopt(socket.IPPROTO_IP,
socket.IP_ADD_MEMBERSHIP,
socket.inet_aton(MCAST_ADDR) + socket.inet_aton(ANY))
# setblocking(0) is equiv to settimeout(0.0) which means we poll the socket.
# But this will raise an error if recv() or send() can't immediately find or send data.
# sock.setblocking(0)
while 1:
try:
data, addr = sock.recvfrom(1024)
except socket.error as e:
pass
else:
print("From: ", addr)
print("Data: ", data)

28
README.md Normal file
View File

@ -0,0 +1,28 @@
netBOOT for Old World Macs
==========================
Read this thread: https://mac68k.info/forums/thread.jspa?threadID=76&tstart=0
Now I'm trying to get it working! The dream is to boot all my Classics over PhoneNet.
Progress so far
---------------
The best build options for Mini vMac are: `-br 37 -m Classic -lt -speed z -as 0 -chr 0`. Note that this requires the new (as of mid-2020) version of Mini vMac, with Rob Mitchelmore's clever LocalTalk-over-UDP tunneling.
The xo-rom-enable-netboot.py script can edit xo.rom (Macintosh Classic) to force-enable the netBOOT driver (essentially by editing PRAM). (It requires you to build vasm with a quick `make CPU=m68k SYNTAX=std`.) This enables quick iteration:
cp xo.rom edit.rom && ./xo-rom-enable-netboot.py edit.rom&& Mini\ vMac\ Classic.app/Co*/Ma*/* edit.rom
Running NetBoot.py simultaneously now shows the netBOOT driver sending DDP packets, and getting no response.
Trivia
------
The Classic is the only non-IIci non-SuperMario ROM with .netBOOT and .ATBOOT drivers. They are part of the overpatch imposed on the SE ROM, and were essentially backported (see the SuperMario forXO.a file). I use the Classic ROM here because it can be emulated in Mini vMac, but the newer netBOOT-equipped ROMs should work.
Credits
-------
To all the intrepid individuals on the mac68k forum thread. Join Freenode #mac68k to meet them.
Credit to bbraun http://synack.net/~bbraun/ for the contents of the "bbraun-pram" dir.

1
bbraun-pram/NBPRAM.c Normal file
View File

@ -0,0 +1 @@
/* * Initialize netboot pram * - Rob Braun <bbraun@synack.net> * 2012 */ #include <stdio.h> #include <stdlib.h> #include <time.h> #include <string.h> #include <Traps.h> void get_netboot_pram(struct netboot *nb); void set_netboot_pram(struct netboot *nb); #pragma parameter __D0 ReadXPRam(__D0, __D1, __A0) short ReadXPRam(short size, short offset, char *where) = {0x4840, 0x3001, _ReadXPRam}; #pragma parameter __D0 WriteXPRam(__D0, __D1, __A0) short WriteXPRam(short size, short offset, char *where) = {0x4840, 0x3001, _WriteXPRam}; struct netboot { char machineID; /* this is used as part of the boot protocol */ char protocol; char errors; char flags; /* Used to enable netbooting, and allow guest netbooting */ char intervalCount; /* high nibble is the retry count, low nibble is the interval between retries */ char timeout; unsigned long signature[4]; char userName[31]; char password[8]; short serverID; /* the value here will be translated to ascii encoded hex and used as the server name to boot from. */ char padding[7]; }; void get_netboot_pram(struct netboot *nb) { char *i = (char*)nb; ReadXPRam(4, 4, i); i += 4; ReadXPRam(3, 0xAB, i); i += 3; ReadXPRam(1, 0xBC, i); i++; ReadXPRam(0x20, 0x20, i); i += 0x20; ReadXPRam(0x20, 0x8B, i); return; } void set_netboot_pram(struct netboot *nb) { char *i = (char*)nb; WriteXPRam(4, 4, i); i += 4; WriteXPRam(3, 0xAB, i); i += 3; WriteXPRam(1, 0xBC, i); i++; WriteXPRam(0x20, 0x20, i); i += 0x20; WriteXPRam(0x20, 0x8B, i); return; } void main(void) { struct netboot nb; char *i; int n; memset(&nb, 0, sizeof(nb)); get_netboot_pram(&nb); for(i = (char*)&nb, n = 0; n < sizeof(nb); n++) { printf("0x%x ", i[n]); } printf("\n"); #if 1 memset(&nb, 0, sizeof(nb)); nb.machineID = 1; nb.protocol = 1; nb.errors = 0; nb.flags = 0xC0; nb.intervalCount = 0x24; /* low nibble is interval, high nibble is count for lookups */ nb.timeout = 127; nb.signature[0] = 'PWD '; //nb.userName[0] = '\0'; strcpy(nb.userName, "bbraun"); nb.password[0] = '\0'; nb.serverID = 0xEBAB; set_netboot_pram(&nb); #endif }

7
bbraun-pram/pram.c Normal file
View File

@ -0,0 +1,7 @@
scal void read_extended_PRAM(char * where, const short size) =
{ 0x4280, 0x301F, 0x4840, 0x205F, 0xA051 };
pascal void write_extended_PRAM
(const char * where, const short offset, const short size) =
{0x201F, 0x205F, 0xA052};

0
bbraun-pram/pramtest Normal file
View File

BIN
bbraun-pram/pramtest.SYM Normal file

Binary file not shown.

BIN
bbraun-pram/pramtest.proj Normal file

Binary file not shown.

18
vasm-1/Makefile Normal file
View File

@ -0,0 +1,18 @@
# Unix
# Define CC, when no compiler with the name "cc" exists.
TARGET =
TARGETEXTENSION =
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
CCOUT = -o
COPTS = -c -O2 -DUNIX $(OUTFMTS)
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS = -lm
RM = rm -f
include make.rules

18
vasm-1/Makefile.68k Normal file
View File

@ -0,0 +1,18 @@
# AmigaOS/68k
TARGET = _os3
TARGETEXTENSION =
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
CC = vc +aos68k
CCOUT = -o
COPTS = -c -c99 -cpu=68020 -DAMIGA $(OUTFMTS) -O1
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS = -lmieee
RM = delete force quiet
include make.rules

18
vasm-1/Makefile.Cygwin Normal file
View File

@ -0,0 +1,18 @@
# Windows compiled with gcc
TARGET = _win32
TARGETEXTENSION = .exe
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
CC = gcc
CCOUT = -o
COPTS = -c -O2 -DUNIX $(OUTFMTS)
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS = -lm
RM = rm -f
include make.rules

18
vasm-1/Makefile.Haiku Normal file
View File

@ -0,0 +1,18 @@
# Unix
TARGET =
TARGETEXTENSION =
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
CC = gcc
CCOUT = -o
COPTS = -c -O2 $(OUTFMTS)
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS =
RM = rm -f
include make.rules

18
vasm-1/Makefile.MOS Normal file
View File

@ -0,0 +1,18 @@
# MorphOS
TARGET = _mos
TARGETEXTENSION =
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
CC = vc +morphos
CCOUT = -o
COPTS = -c -DAMIGA -O1 $(OUTFMTS)
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS = -lm
RM = delete force quiet
include make.rules

18
vasm-1/Makefile.MiNT Normal file
View File

@ -0,0 +1,18 @@
# Atari TOS/MiNT
TARGET = _MiNT
TARGETEXTENSION =
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
CC = vc +mint
CCOUT = -o
COPTS = -c -c99 -cpu=68020 -O1 $(OUTFMTS)
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS = -lm
RM = rm -f
include make.rules

18
vasm-1/Makefile.OS4 Normal file
View File

@ -0,0 +1,18 @@
# AmigaOS 4.x/PPC
TARGET = _os4
TARGETEXTENSION =
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
CC = vc +aosppc
CCOUT = -o
COPTS = -c -DAMIGA -D__USE_INLINE__ -O1 $(OUTFMTS)
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS = -lm
RM = delete force quiet
include make.rules

18
vasm-1/Makefile.PUp Normal file
View File

@ -0,0 +1,18 @@
# PowerUp
TARGET = _pup
TARGETEXTENSION =
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
CC = vc +powerup
CCOUT = -o
COPTS = -c -c99 -DAMIGA -O1 $(OUTFMTS)
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS = -lm -lamiga
RM = delete force quiet
include make.rules

18
vasm-1/Makefile.TOS Normal file
View File

@ -0,0 +1,18 @@
# Atari TOS
TARGET = _TOS
TARGETEXTENSION = .ttp
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
CC = vc +tos
CCOUT = -o
COPTS = -c -c99 -O1 -DATARI $(OUTFMTS)
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS = -lm
RM = rm -f
include make.rules

18
vasm-1/Makefile.WOS Normal file
View File

@ -0,0 +1,18 @@
# WarpOS
TARGET = _wos
TARGETEXTENSION =
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
CC = vc +warpos
CCOUT = -o
COPTS = -c -c99 -DAMIGA -O1 $(OUTFMTS)
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS = -lm -lamiga
RM = delete force quiet
include make.rules

30
vasm-1/Makefile.Win32 Normal file
View File

@ -0,0 +1,30 @@
# Windows
# Tested with Visual Studio 2017: works fine under the Developer Command Prompt for VS2017
# Tested with Visual Studio 2005 Express Edition: works fine
# Tested with Visual C++ Toolkit 2003: works fine, but needs an external make tool (nmake is not included)
TARGET = _win32
TARGETEXTENSION = .exe
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
# If Visual Studio is unable to find <windows.h> when compiling vlink, try enabling the two
# lines below, and point them to where you have installed the Win32 Platform SDK.
#WIN32_PLATFORMSDK_INCLUDE = "/IC:\Code\Win32 Platform SDK\Include"
#WIN32_PLATFORMSDK_LIB = "/LIBPATH:C:\Code\Win32 Platform SDK\Lib"
CC = cl
CCOUT = /Fo
COPTS = $(OUTFMTS) /nologo /O2 /MT /c
COPTS = $(COPTS) /wd4996 # Disable warning regarding deprecated functions
# ("use strcpy_s instead of strcpy" etc)
COPTS = $(COPTS) $(WIN32_PLATFORMSDK_INCLUDE)
LD = link
LDOUT = /OUT:
LDFLAGS = /NOLOGO $(WIN32_PLATFORMSDK_LIB)
RM = rem
include make.rules

View File

@ -0,0 +1,22 @@
# Windows compiled on a Linux machine with mingw
TARGET = _win32
TARGETEXTENSION = .exe
OUTFMTS = -DOUTAOUT -DOUTBIN -DOUTELF -DOUTHUNK -DOUTSREC -DOUTTOS -DOUTVOBJ \
-DOUTXFIL
#CC = /usr/bin/i586-mingw32msvc-gcc
CC = /usr/bin/i686-w64-mingw32-gcc
CCOUT = -o
COPTS = -c -O2 $(OUTFMTS)
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS = -lm
RM = rm -f
include make.rules

672
vasm-1/atom.c Normal file
View File

@ -0,0 +1,672 @@
/* atom.c - atomic objects from source */
/* (c) in 2010-2020 by Volker Barthelmann and Frank Wille */
#include "vasm.h"
/* searches mnemonic list and tries to parse (via the cpu module)
the operands according to the mnemonic requirements; returns an
instruction or 0 */
instruction *new_inst(char *inst,int len,int op_cnt,char **op,int *op_len)
{
#if MAX_OPERANDS!=0
operand ops[MAX_OPERANDS];
int j,k,mnemo_opcnt,omitted,skipped;
#endif
int i,inst_found=0;
hashdata data;
instruction *new;
new = mymalloc(sizeof(*new));
#if HAVE_INSTRUCTION_EXTENSION
init_instruction_ext(&new->ext);
#endif
#if MAX_OPERANDS!=0 && NEED_CLEARED_OPERANDS!=0
/* reset operands to allow the cpu-backend to parse them only once */
memset(ops,0,sizeof(ops));
#endif
if (find_namelen_nc(mnemohash,inst,len,&data)) {
i = data.idx;
/* try all mnemonics with the same name until operands match */
do {
inst_found = 1;
if (!MNEMONIC_VALID(i)) {
i++;
continue; /* try next */
}
#if MAX_OPERANDS!=0
#if ALLOW_EMPTY_OPS
mnemo_opcnt = op_cnt<MAX_OPERANDS ? op_cnt : MAX_OPERANDS;
#else
for (j=0; j<MAX_OPERANDS; j++)
if (mnemonics[i].operand_type[j] == 0)
break;
mnemo_opcnt = j; /* number of expected operands for this mnemonic */
#endif
inst_found = 2;
save_symbols(); /* make sure we can restore symbols to this point */
for (j=k=omitted=skipped=0; j<mnemo_opcnt; j++) {
if (op_cnt+omitted < mnemo_opcnt &&
OPERAND_OPTIONAL(&ops[j],mnemonics[i].operand_type[j])) {
omitted++;
}
else {
int rc;
if (k >= op_cnt) /* missing mandatory operands */
break;
rc = parse_operand(op[k],op_len[k],&ops[j],
mnemonics[i].operand_type[j]);
if (rc == PO_CORRUPT) {
myfree(new);
restore_symbols();
return 0;
}
if (rc == PO_NOMATCH)
break;
/* MATCH, move to next parsed operand */
k++;
if (rc == PO_SKIP) { /* but skip next operand type from table */
j++;
skipped++;
}
}
}
#if IGNORE_FIRST_EXTRA_OP
if (mnemo_opcnt > 0)
#endif
if (j<mnemo_opcnt || k<op_cnt) {
/* No match. Try next mnemonic. */
i++;
restore_symbols();
continue;
}
/* Matched! Copy operands. */
mnemo_opcnt -= skipped;
for (j=0; j<mnemo_opcnt; j++) {
new->op[j] = mymalloc(sizeof(operand));
*new->op[j] = ops[j];
}
for(; j<MAX_OPERANDS; j++)
new->op[j] = 0;
#endif /* MAX_OPERANDS!=0 */
new->code = i;
return new;
}
while (i<mnemonic_cnt && !strnicmp(mnemonics[i].name,inst,len)
&& mnemonics[i].name[len]==0);
}
switch (inst_found) {
case 1:
general_error(8); /* instruction not supported by cpu */
break;
case 2:
general_error(0); /* illegal operand types */
break;
default:
general_error(1,cnvstr(inst,len)); /* completely unknown mnemonic */
break;
}
myfree(new);
return 0;
}
dblock *new_dblock(void)
{
dblock *new = mymalloc(sizeof(*new));
new->size = 0;
new->data = 0;
new->relocs = 0;
return new;
}
sblock *new_sblock(expr *space,size_t size,expr *fill)
{
sblock *sb = mymalloc(sizeof(sblock));
sb->space = 0;
sb->space_exp = space;
sb->size = size;
if (!(sb->fill_exp = fill))
memset(sb->fill,0,MAXPADBYTES);
sb->relocs = 0;
sb->maxalignbytes = 0;
sb->flags = 0;
return sb;
}
static size_t space_size(sblock *sb,section *sec,taddr pc)
{
utaddr space=0;
if (eval_expr(sb->space_exp,&space,sec,pc) || !final_pass)
sb->space = space;
else
general_error(30); /* expression must be constant */
if (final_pass && sb->fill_exp) {
if (sb->size <= sizeof(taddr)) {
/* space is filled with an expression which may also need relocations */
symbol *base=NULL;
taddr fill;
utaddr i;
if (!eval_expr(sb->fill_exp,&fill,sec,pc)) {
if (find_base(sb->fill_exp,&base,sec,pc)==BASE_ILLEGAL)
general_error(38); /* illegal relocation */
}
copy_cpu_taddr(sb->fill,fill,sb->size);
if (base && !sb->relocs) {
/* generate relocations */
for (i=0; i<space; i++)
add_extnreloc(&sb->relocs,base,fill,REL_ABS,
0,sb->size<<3,sb->size*i);
}
}
else
general_error(30); /* expression must be constant */
}
return sb->size * space;
}
static size_t roffs_size(reloffs *roffs,section *sec,taddr pc)
{
taddr offs;
eval_expr(roffs->offset,&offs,sec,pc);
offs = sec->org + offs - pc;
return offs>0 ? offs : 0;
}
/* adds an atom to the specified section; if sec==0, the current
section is used */
void add_atom(section *sec,atom *a)
{
if (!sec) {
sec = default_section();
if (!sec) {
general_error(3);
return;
}
}
a->changes = 0;
a->src = cur_src;
a->line = cur_src!=NULL ? cur_src->line : 0;
if (sec->last) {
atom *pa = sec->last;
pa->next = a;
/* make sure that a label on the same line gets the same alignment */
if (pa->type==LABEL && pa->line==a->line &&
(a->type==INSTRUCTION || a->type==DATADEF || a->type==SPACE))
pa->align = a->align;
}
else
sec->first = a;
a->next = 0;
sec->last = a;
sec->pc = pcalign(a,sec->pc);
a->lastsize = atom_size(a,sec,sec->pc);
sec->pc += a->lastsize;
if (a->align > sec->align)
sec->align = a->align;
if (listena) {
a->list = last_listing;
if (last_listing) {
if (!last_listing->atom)
last_listing->atom = a;
}
}
else
a->list = 0;
}
size_t atom_size(atom *p,section *sec,taddr pc)
{
switch(p->type) {
case VASMDEBUG:
case LABEL:
case LINE:
case OPTS:
case PRINTTEXT:
case PRINTEXPR:
case RORG:
case RORGEND:
case ASSERT:
case NLIST: /* it has a size, but not in the current section */
return 0;
case DATA:
return p->content.db->size;
case INSTRUCTION:
return p->content.inst->code>=0?
instruction_size(p->content.inst,sec,pc):0;
case SPACE:
return space_size(p->content.sb,sec,pc);
case DATADEF:
return (p->content.defb->bitsize+7)/8;
case ROFFS:
return roffs_size(p->content.roffs,sec,pc);
default:
ierror(0);
break;
}
return 0;
}
static void print_instruction(FILE *f,instruction *p)
{
int i;
printf("inst %d(%s) ",p->code,p->code>=0?mnemonics[p->code].name:"deleted");
#if MAX_OPERANDS!=0
for (i=0; i<MAX_OPERANDS; i++)
printf("%p ",(void *)p->op[i]);
#endif
}
void print_atom(FILE *f,atom *p)
{
size_t i;
rlist *rl;
switch (p->type) {
case VASMDEBUG:
fprintf(f,"vasm debug directive");
break;
case LABEL:
fprintf(f,"symbol: ");
print_symbol(f,p->content.label);
break;
case DATA:
fprintf(f,"data(%lu): ",(unsigned long)p->content.db->size);
for (i=0;i<p->content.db->size;i++)
fprintf(f,"%02x ",p->content.db->data[i]);
for (rl=p->content.db->relocs; rl; rl=rl->next)
print_reloc(f,rl->type,rl->reloc);
break;
case INSTRUCTION:
print_instruction(f,p->content.inst);
break;
case SPACE:
fprintf(f,"space(%lu,fill=",
(unsigned long)(p->content.sb->space*p->content.sb->size));
for (i=0; i<p->content.sb->size; i++)
fprintf(f,"%02x%c",(unsigned char)p->content.sb->fill[i],
(i==p->content.sb->size-1)?')':' ');
for (rl=p->content.sb->relocs; rl; rl=rl->next)
print_reloc(f,rl->type,rl->reloc);
break;
case DATADEF:
fprintf(f,"datadef(%lu bits)",(unsigned long)p->content.defb->bitsize);
break;
case LINE:
fprintf(f,"line: %d of %s",p->content.srcline,getdebugname());
break;
#if HAVE_CPU_OPTS
case OPTS:
print_cpu_opts(f,p->content.opts);
break;
#endif
case PRINTTEXT:
fprintf(f,"text: \"%s\"",p->content.ptext);
break;
case PRINTEXPR:
fprintf(f,"expr: ");
print_expr(f,p->content.pexpr->print_exp);
break;
case ROFFS:
fprintf(f,"roffs: offset ");
print_expr(f,p->content.roffs->offset);
fprintf(f,",fill=");
if (p->content.roffs->fillval)
print_expr(f,p->content.roffs->fillval);
else
fprintf(f,"none");
break;
case RORG:
fprintf(f,"rorg: relocate to 0x%llx",ULLTADDR(*p->content.rorg));
break;
case RORGEND:
fprintf(f,"rorg end");
break;
case ASSERT:
fprintf(f,"assert: %s (message: %s)\n",p->content.assert->expstr,
p->content.assert->msgstr?p->content.assert->msgstr:emptystr);
break;
case NLIST:
fprintf(f,"nlist: %s (type %d, other %d, desc %d) with value ",
p->content.nlist->name!=NULL ? p->content.nlist->name : "<NULL>",
p->content.nlist->type,p->content.nlist->other,
p->content.nlist->desc);
if (p->content.nlist->value != NULL)
print_expr(f,p->content.nlist->value);
else
fprintf(f,"NULL");
break;
default:
ierror(0);
}
}
/* prints and formats an expression from a PRINTEXPR atom */
void atom_printexpr(printexpr *pexp,section *sec,taddr pc)
{
taddr t;
long long v;
int i;
eval_expr(pexp->print_exp,&t,sec,pc);
if (pexp->type==PEXP_SDEC && (t&(1LL<<(pexp->size-1)))!=0) {
/* signed decimal */
v = -1;
v &= ~(long long)MAKEMASK(pexp->size);
}
else
v = 0;
v |= t & MAKEMASK(pexp->size);
switch (pexp->type) {
case PEXP_HEX:
printf("%llX",(unsigned long long)v);
break;
case PEXP_SDEC:
printf("%lld",v);
break;
case PEXP_UDEC:
printf("%llu",(unsigned long long)v);
break;
case PEXP_BIN:
for (i=pexp->size-1; i>=0; i--)
putchar((v & (1LL<<i)) ? '1' : '0');
break;
case PEXP_ASC:
for (i=((pexp->size+7)>>3)-1; i>=0; i--) {
unsigned char c = (v>>(i*8))&0xff;
putchar(isprint(c) ? c : '.');
}
break;
default:
ierror(0);
break;
}
}
atom *clone_atom(atom *a)
{
atom *new = mymalloc(sizeof(atom));
void *p;
memcpy(new,a,sizeof(atom));
switch (a->type) {
/* INSTRUCTION and DATADEF have to be cloned as well, because they will
be deallocated and transformed into DATA during assemble() */
case INSTRUCTION:
p = mymalloc(sizeof(instruction));
memcpy(p,a->content.inst,sizeof(instruction));
new->content.inst = p;
break;
case DATADEF:
p = mymalloc(sizeof(defblock));
memcpy(p,a->content.defb,sizeof(defblock));
new->content.defb = p;
break;
default:
break;
}
new->next = 0;
new->src = NULL;
new->line = 0;
new->list = NULL;
return new;
}
atom *add_data_atom(section *sec,size_t sz,taddr alignment,taddr c)
{
dblock *db = new_dblock();
atom *a;
db->size = sz;
db->data = mymalloc(sz);
if (sz > 1)
setval(BIGENDIAN,db->data,sz,c);
else
*(db->data) = c;
a = new_data_atom(db,alignment);
add_atom(sec,a);
return a;
}
void add_leb128_atom(section *sec,taddr c)
{
taddr b;
do {
b = c & 0x7f;
if ((c >>= 7) != 0)
b |= 0x80;
add_data_atom(sec,1,1,b);
} while (c != 0);
}
void add_sleb128_atom(section *sec,taddr c)
{
int done = 0;
taddr b;
do {
b = c & 0x7f;
c >>= 7; /* assumes arithmetic shifts! */
if ((c==0 && !(b&0x40)) || (c==-1 && (b&0x40)))
done = 1;
else
b |= 0x80;
add_data_atom(sec,1,1,b);
} while (!done);
}
atom *add_bytes_atom(section *sec,void *p,size_t sz)
{
dblock *db = new_dblock();
atom *a;
db->size = sz;
db->data = mymalloc(sz);
memcpy(db->data,p,sz);
a = new_data_atom(db,1);
add_atom(sec,a);
return a;
}
atom *new_atom(int type,taddr align)
{
atom *new = mymalloc(sizeof(*new));
new->next = NULL;
new->type = type;
new->align = align;
return new;
}
atom *new_inst_atom(instruction *p)
{
atom *new = new_atom(INSTRUCTION,inst_alignment);
new->content.inst = p;
return new;
}
atom *new_data_atom(dblock *p,taddr align)
{
atom *new = new_atom(DATA,align);
new->content.db = p;
return new;
}
atom *new_label_atom(symbol *p)
{
atom *new = new_atom(LABEL,1);
new->content.label = p;
return new;
}
atom *new_space_atom(expr *space,size_t size,expr *fill)
{
atom *new = new_atom(SPACE,1);
int i;
if (size<1)
ierror(0); /* usually an error in syntax-module */
new->content.sb = new_sblock(space,size,fill);
return new;
}
atom *new_datadef_atom(size_t bitsize,operand *op)
{
atom *new = new_atom(DATADEF,DATA_ALIGN(bitsize));
new->content.defb = mymalloc(sizeof(*new->content.defb));
new->content.defb->bitsize = bitsize;
new->content.defb->op = op;
return new;
}
atom *new_srcline_atom(int line)
{
atom *new = new_atom(LINE,1);
new->content.srcline = line;
return new;
}
atom *new_opts_atom(void *o)
{
atom *new = new_atom(OPTS,1);
new->content.opts = o;
return new;
}
atom *new_text_atom(char *txt)
{
atom *new = new_atom(PRINTTEXT,1);
new->content.ptext = txt ? txt : "\n";
return new;
}
atom *new_expr_atom(expr *exp,int type,int size)
{
atom *new = new_atom(PRINTEXPR,1);
new->content.pexpr = mymalloc(sizeof(*new->content.pexpr));
if (exp==NULL || type<PEXP_HEX || type>PEXP_ASC || size<1
|| size>sizeof(long long)*8)
ierror(0);
new->content.pexpr->print_exp = exp;
new->content.pexpr->type = type;
new->content.pexpr->size = size;
return new;
}
atom *new_roffs_atom(expr *offs,expr *fill)
{
atom *new = new_atom(ROFFS,1);
new->content.roffs = mymalloc(sizeof(*new->content.roffs));
new->content.roffs->offset = offs;
new->content.roffs->fillval = fill;
return new;
}
atom *new_rorg_atom(taddr raddr)
{
atom *new = new_atom(RORG,1);
taddr *newrorg = mymalloc(sizeof(taddr));
*newrorg = raddr;
new->content.rorg = newrorg;
return new;
}
atom *new_rorgend_atom(void)
{
return new_atom(RORGEND,1);
}
atom *new_assert_atom(expr *aexp,char *exp,char *msg)
{
atom *new = new_atom(ASSERT,1);
new->content.assert = mymalloc(sizeof(*new->content.assert));
new->content.assert->assert_exp = aexp;
new->content.assert->expstr = exp;
new->content.assert->msgstr = msg;
return new;
}
atom *new_nlist_atom(char *name,int type,int other,int desc,expr *value)
{
atom *new = new_atom(NLIST,1);
new->content.nlist = mymalloc(sizeof(*new->content.nlist));
new->content.nlist->name = name;
new->content.nlist->type = type;
new->content.nlist->other = other;
new->content.nlist->desc = desc;
new->content.nlist->value = value;
return new;
}

152
vasm-1/atom.h Normal file
View File

@ -0,0 +1,152 @@
/* atom.h - atomic objects from source */
/* (c) in 2010-2020 by Volker Barthelmann and Frank Wille */
#ifndef ATOM_H
#define ATOM_H
/* types of atoms */
#define VASMDEBUG 0
#define LABEL 1
#define DATA 2
#define INSTRUCTION 3
#define SPACE 4
#define DATADEF 5
#define LINE 6
#define OPTS 7
#define PRINTTEXT 8
#define PRINTEXPR 9
#define ROFFS 10
#define RORG 11
#define RORGEND 12
#define ASSERT 13
#define NLIST 14
/* a machine instruction */
typedef struct instruction {
int code;
#if MAX_QUALIFIERS!=0
char *qualifiers[MAX_QUALIFIERS];
#endif
#if MAX_OPERANDS!=0
operand *op[MAX_OPERANDS];
#endif
#if HAVE_INSTRUCTION_EXTENSION
instruction_ext ext;
#endif
} instruction;
typedef struct defblock {
size_t bitsize;
operand *op;
} defblock;
struct dblock {
size_t size;
unsigned char *data;
rlist *relocs;
};
struct sblock {
size_t space;
expr *space_exp; /* copied to space, when evaluated as constant */
size_t size;
uint8_t fill[MAXPADBYTES];
expr *fill_exp; /* copied to fill, when evaluated - may be NULL */
rlist *relocs;
taddr maxalignbytes;
uint32_t flags;
};
#define SPC_DATABSS 1 /* make sure no to allocate space in a data section */
typedef struct reloffs {
expr *offset;
expr *fillval;
} reloffs;
typedef struct printexpr {
expr *print_exp;
short type; /* hex, signed, unsigned */
short size; /* precision in bits */
} printexpr;
#define PEXP_HEX 0
#define PEXP_SDEC 1
#define PEXP_UDEC 2
#define PEXP_BIN 3
#define PEXP_ASC 4
typedef struct assertion {
expr *assert_exp;
char *expstr;
char *msgstr;
} assertion;
typedef struct aoutnlist {
char *name;
int type;
int other;
int desc;
expr *value;
} aoutnlist;
/* an atomic element of data */
typedef struct atom {
struct atom *next;
int type;
taddr align;
size_t lastsize;
unsigned changes;
source *src;
int line;
listing *list;
union {
instruction *inst;
dblock *db;
symbol *label;
sblock *sb;
defblock *defb;
void *opts;
int srcline;
char *ptext;
printexpr *pexpr;
reloffs *roffs;
taddr *rorg;
assertion *assert;
aoutnlist *nlist;
} content;
} atom;
#define MAXSIZECHANGES 5 /* warning, when atom changed size so many times */
instruction *new_inst(char *inst,int len,int op_cnt,char **op,int *op_len);
dblock *new_dblock();
sblock *new_sblock(expr *,size_t,expr *);
atom *new_atom(int,taddr);
void add_atom(section *,atom *);
size_t atom_size(atom *,section *,taddr);
void print_atom(FILE *,atom *);
void atom_printexpr(printexpr *,section *,taddr);
atom *clone_atom(atom *);
atom *add_data_atom(section *,size_t,taddr,taddr);
void add_leb128_atom(section *,taddr);
void add_sleb128_atom(section *,taddr);
atom *add_bytes_atom(section *,void *,size_t);
#define add_string_atom(s,p) add_bytes_atom(s,p,strlen(p)+1)
atom *new_inst_atom(instruction *);
atom *new_data_atom(dblock *,taddr);
atom *new_label_atom(symbol *);
atom *new_space_atom(expr *,size_t,expr *);
atom *new_datadef_atom(size_t,operand *);
atom *new_srcline_atom(int);
atom *new_opts_atom(void *);
atom *new_text_atom(char *);
atom *new_expr_atom(expr *,int,int);
atom *new_roffs_atom(expr *,expr *);
atom *new_rorg_atom(taddr);
atom *new_rorgend_atom(void);
atom *new_assert_atom(expr *,char *,char *);
atom *new_nlist_atom(char *,int,int,int,expr *);
#endif

85
vasm-1/cond.c Normal file
View File

@ -0,0 +1,85 @@
/* cond.c - conditional assembly support routines */
/* (c) in 2015 by Frank Wille */
#include "vasm.h"
int clev; /* conditional level */
static char cond[MAXCONDLEV+1];
static char *condsrc[MAXCONDLEV+1];
static int condline[MAXCONDLEV+1];
static int ifnesting;
/* initialize conditional assembly */
void cond_init(void)
{
cond[0] = 1;
clev = ifnesting = 0;
}
/* return true, when current level allows assembling */
int cond_state(void)
{
return cond[clev];
}
/* ensures that all conditional block are closed at the end of the source */
void cond_check(void)
{
if (clev > 0)
general_error(66,condsrc[clev],condline[clev]); /* "endc/endif missing */
}
/* establish a new level of conditional assembly */
void cond_if(char flag)
{
if (++clev >= MAXCONDLEV)
general_error(65,clev); /* nesting depth exceeded */
cond[clev] = flag;
condsrc[clev] = cur_src->name;
condline[clev] = cur_src->line;
}
/* handle skipped if statement */
void cond_skipif(void)
{
ifnesting++;
}
/* handle else statement after skipped if-branch */
void cond_else(void)
{
if (ifnesting == 0)
cond[clev] = 1;
}
/* handle else statement after assembled if-branch */
void cond_skipelse(void)
{
if (clev > 0)
cond[clev] = 0;
else
general_error(63); /* else without if */
}
/* handle end-if statement */
void cond_endif(void)
{
if (ifnesting == 0) {
if (clev > 0)
clev--;
else
general_error(64); /* unexpected endif without if */
}
else /* the whole conditional block was ignored */
ifnesting--;
}

25
vasm-1/cond.h Normal file
View File

@ -0,0 +1,25 @@
/* cond.h - conditional assembly support routines */
/* (c) in 2015 by Frank Wille */
#ifndef COND_H
#define COND_H
/* defines */
#ifndef MAXCONDLEV
#define MAXCONDLEV 63
#endif
/* global variables */
extern int clev;
/* functions */
void cond_init(void);
int cond_state(void);
void cond_check(void);
void cond_if(char);
void cond_skipif(void);
void cond_else(void);
void cond_skipelse(void);
void cond_endif(void);
#endif /* COND_H */

588
vasm-1/cpus/6502/cpu.c Normal file
View File

@ -0,0 +1,588 @@
/*
** cpu.c 650x/65C02/6510/6280 cpu-description file
** (c) in 2002,2006,2008-2012,2014-2020 by Frank Wille
*/
#include "vasm.h"
mnemonic mnemonics[] = {
#include "opcodes.h"
};
int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]);
char *cpu_copyright="vasm 6502 cpu backend 0.8c (c) 2002,2006,2008-2012,2014-2020 Frank Wille";
char *cpuname = "6502";
int bitsperbyte = 8;
int bytespertaddr = 2;
static uint16_t cpu_type = M6502;
static int branchopt = 0;
static int modifier; /* set by find_base() */
static utaddr dpage = 0; /* default zero/direct page - set with SETDP */
static int bbcade; /* GMGM - set for BBC ADE compatibility */
int ext_unary_type(char *s)
{
if (bbcade) /* GMGM - BBC ADE assembler swaps meaning of < and > */
return *s=='<' ? HIBYTE : LOBYTE;
return *s=='<' ? LOBYTE : HIBYTE;
}
int ext_unary_eval(int type,taddr val,taddr *result,int cnst)
{
switch (type) {
case LOBYTE:
*result = cnst ? (val & 0xff) : val;
return 1;
case HIBYTE:
*result = cnst ? ((val >> 8) & 0xff) : val;
return 1;
default:
break;
}
return 0; /* unknown type */
}
int ext_find_base(symbol **base,expr *p,section *sec,taddr pc)
{
/* addr/256 equals >addr, addr%256 and addr&255 equal <addr */
if (p->type==DIV || p->type==MOD) {
if (p->right->type==NUM && p->right->c.val==256)
p->type = p->type == DIV ? HIBYTE : LOBYTE;
}
else if (p->type==BAND && p->right->type==NUM && p->right->c.val==255)
p->type = LOBYTE;
if (p->type==LOBYTE || p->type==HIBYTE) {
modifier = p->type;
return find_base(p->left,base,sec,pc);
}
return BASE_ILLEGAL;
}
int parse_operand(char *p,int len,operand *op,int required)
{
char *start = p;
int indir = 0;
p = skip(p);
if (len>0 && required!=DATAOP && check_indir(p,start+len)) {
indir = 1;
p = skip(p+1);
}
switch (required) {
case IMMED:
if (*p++ != '#')
return PO_NOMATCH;
p = skip(p);
break;
case INDIR:
case INDIRX:
case INDX:
case INDY:
case DPINDIR:
if (!indir)
return PO_NOMATCH;
break;
case WBIT:
if (*p == '#') /* # is optional */
p = skip(p+1);
default:
if (indir)
return PO_NOMATCH;
break;
}
op->dp = dpage;
if (required < ACCU)
op->value = parse_expr(&p);
else
op->value = NULL;
switch (required) {
case INDX:
case INDIRX:
if (*p++ == ',') {
p = skip(p);
if (toupper((unsigned char)*p++) != 'X')
return PO_NOMATCH;
}
else
return PO_NOMATCH;
break;
case ACCU:
if (len != 0) {
if (len!=1 || toupper((unsigned char)*p++) != 'A')
return PO_NOMATCH;
}
break;
case DUMX:
if (toupper((unsigned char)*p++) != 'X')
return PO_NOMATCH;
break;
case DUMY:
if (toupper((unsigned char)*p++) != 'Y')
return PO_NOMATCH;
break;
}
if (required==INDIR || required==INDX || required==INDY
|| required==DPINDIR || required==INDIRX) {
p = skip(p);
if (*p++ != ')') {
cpu_error(2); /* missing closing parenthesis */
return PO_CORRUPT;
}
}
p = skip(p);
if (p-start < len)
cpu_error(1); /* trailing garbage in operand */
op->type = required;
return PO_MATCH;
}
char *parse_cpu_special(char *start)
{
char *name=start,*s=start;
if (ISIDSTART(*s)) {
s++;
while (ISIDCHAR(*s))
s++;
if (s-name==5 && !strnicmp(name,"setdp",5)) {
s = skip(s);
dpage = (utaddr)parse_constexpr(&s);
eol(s);
return skip_line(s);
}
else if (s-name==5 && !strnicmp(name,"zpage",5)) {
char *name;
s = skip(s);
if (name = parse_identifier(&s)) {
symbol *sym = new_import(name);
myfree(name);
sym->flags |= ZPAGESYM;
eol(s);
}
else
cpu_error(8); /* identifier expected */
return skip_line(s);
}
}
return start;
}
static instruction *copy_instruction(instruction *ip)
/* copy an instruction and its operands */
{
static instruction newip;
static operand newop[MAX_OPERANDS];
int i;
newip.code = ip->code;
for (i=0; i<MAX_OPERANDS; i++) {
if (ip->op[i] != NULL) {
newip.op[i] = &newop[i];
*newip.op[i] = *ip->op[i];
}
else
newip.op[i] = NULL;
}
return &newip;
}
static void optimize_instruction(instruction *ip,section *sec,
taddr pc,int final)
{
mnemonic *mnemo = &mnemonics[ip->code];
symbol *base;
operand *op;
taddr val;
int i;
for (i=0; i<MAX_OPERANDS; i++) {
if ((op = ip->op[i]) != NULL) {
if (op->value != NULL) {
if (eval_expr(op->value,&val,sec,pc))
base = NULL; /* val is constant/absolute */
else
find_base(op->value,&base,sec,pc); /* get base-symbol */
if ((op->type==ABS || op->type==ABSX || op->type==ABSY) &&
((base==NULL
&& ((val>=0 && val<=0xff) ||
((utaddr)val>=op->dp && (utaddr)val<=op->dp+0xff))) ||
(base!=NULL && (base->flags&ZPAGESYM)))
&& mnemo->ext.zp_opcode!=0) {
/* we can use a zero page addressing mode for absolute 16-bit */
op->type += ZPAGE-ABS;
}
else if (op->type==REL && (base==NULL || !is_pc_reloc(base,sec))) {
taddr bd = val - (pc + 2);
if ((bd<-0x80 || bd>0x7f) && branchopt) {
/* branch dest. out of range: use a B!cc/JMP combination */
op->type = RELJMP;
}
}
}
}
}
}
static size_t get_inst_size(instruction *ip)
{
size_t sz = 1;
int i;
for (i=0; i<MAX_OPERANDS; i++) {
if (ip->op[i] != NULL) {
switch (ip->op[i]->type) {
case REL:
case INDX:
case INDY:
case DPINDIR:
case IMMED:
case ZPAGE:
case ZPAGEX:
case ZPAGEY:
sz += 1;
break;
case ABS:
case ABSX:
case ABSY:
case INDIR:
case INDIRX:
sz += 2;
break;
case RELJMP:
sz += 4;
break;
}
}
}
return sz;
}
size_t instruction_size(instruction *ip,section *sec,taddr pc)
{
instruction *ipcopy;
int i;
for (i=0; i<MAX_OPERANDS-1; i++) {
/* convert DUMX/DUMY operands into real addressing modes first */
if (ip->op[i]!=NULL && ip->op[i+1]!=NULL) {
if (ip->op[i]->type == ABS) {
if (ip->op[i+1]->type == DUMX) {
ip->op[i]->type = ABSX;
break;
}
else if (ip->op[i+1]->type == DUMY) {
ip->op[i]->type = ABSY;
break;
}
}
else if (ip->op[i]->type == INDIR) {
if (ip->op[i+1]->type == DUMY) {
ip->op[0]->type = INDY;
break;
}
}
}
}
if (++i < MAX_OPERANDS) {
/* we removed a DUMX/DUMY operand at the end */
myfree(ip->op[i]);
ip->op[i] = NULL;
}
ipcopy = copy_instruction(ip);
optimize_instruction(ipcopy,sec,pc,0);
return get_inst_size(ipcopy);
}
static void rangecheck(taddr val,operand *op)
{
switch (op->type) {
case ZPAGE:
case ZPAGEX:
case ZPAGEY:
case INDX:
case INDY:
case DPINDIR:
if ((utaddr)val>=op->dp && (utaddr)val<=op->dp+0xff)
break;
case IMMED:
if (val<-0x80 || val>0xff)
cpu_error(5,8); /* operand doesn't fit into 8-bits */
break;
case REL:
if (val<-0x80 || val>0x7f)
cpu_error(6); /* branch destination out of range */
break;
case WBIT:
if (val<0 || val>7)
cpu_error(7); /* illegal bit number */
break;
}
}
dblock *eval_instruction(instruction *ip,section *sec,taddr pc)
{
dblock *db = new_dblock();
unsigned char *d,oc;
int optype,i;
taddr val;
optimize_instruction(ip,sec,pc,1); /* really execute optimizations now */
db->size = get_inst_size(ip);
d = db->data = mymalloc(db->size);
/* write opcode */
oc = mnemonics[ip->code].ext.opcode;
for (i=0; i<MAX_OPERANDS; i++) {
optype = ip->op[i]!=NULL ? ip->op[i]->type : IMPLIED;
switch (optype) {
case ZPAGE:
case ZPAGEX:
case ZPAGEY:
oc = mnemonics[ip->code].ext.zp_opcode;
break;
case RELJMP:
oc ^= 0x20; /* B!cc branch */
break;
}
}
*d++ = oc;
for (i=0; i<MAX_OPERANDS; i++) {
if (ip->op[i] != NULL){
operand *op = ip->op[i];
int offs = d - db->data;
symbol *base;
optype = (int)op->type;
if (op->value != NULL) {
if (!eval_expr(op->value,&val,sec,pc)) {
modifier = 0;
if (optype!=WBIT && find_base(op->value,&base,sec,pc) == BASE_OK) {
if (optype==REL && !is_pc_reloc(base,sec)) {
/* relative branch requires no relocation */
val = val - (pc + offs + 1);
}
else {
int type = REL_ABS;
int size;
rlist *rl;
switch (optype) {
case ABS:
case ABSX:
case ABSY:
case INDIR:
case INDIRX:
size = 16;
break;
case INDX:
case INDY:
case DPINDIR:
case ZPAGE:
case ZPAGEX:
case ZPAGEY:
case IMMED:
size = 8;
break;
case RELJMP:
size = 16;
offs = 3;
break;
case REL:
type = REL_PC;
size = 8;
break;
default:
ierror(0);
break;
}
rl = add_extnreloc(&db->relocs,base,val,type,0,size,offs);
switch (modifier) {
case LOBYTE:
if (rl)
((nreloc *)rl->reloc)->mask = 0xff;
val = val & 0xff;
break;
case HIBYTE:
if (rl)
((nreloc *)rl->reloc)->mask = 0xff00;
val = (val >> 8) & 0xff;
break;
}
}
}
else
general_error(38); /* illegal relocation */
}
else {
/* constant/absolute value */
if (optype == REL)
val = val - (pc + offs + 1);
}
rangecheck(val,op);
/* write operand data */
switch (optype) {
case ABSX:
case ABSY:
if (!*(db->data)) /* STX/STY allow only ZeroPage addressing mode */
cpu_error(5,8); /* operand doesn't fit into 8 bits */
case ABS:
case INDIR:
case INDIRX:
*d++ = val & 0xff;
*d++ = (val>>8) & 0xff;
break;
case DPINDIR:
case INDX:
case INDY:
case ZPAGE:
case ZPAGEX:
case ZPAGEY:
if ((utaddr)val>=op->dp && (utaddr)val<=op->dp+0xff)
val -= op->dp;
case IMMED:
case REL:
*d++ = val & 0xff;
break;
case RELJMP:
if (d - db->data > 1)
ierror(0);
*d++ = 3; /* B!cc *+3 */
*d++ = 0x4c; /* JMP */
*d++ = val & 0xff;
*d++ = (val>>8) & 0xff;
break;
case WBIT:
*(db->data) |= (val&7) << 4; /* set bit number in opcode */
break;
}
}
}
}
return db;
}
dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
{
dblock *db = new_dblock();
taddr val;
if (bitsize!=8 && bitsize!=16 && bitsize!=32)
cpu_error(3,bitsize); /* data size not supported */
db->size = bitsize >> 3;
db->data = mymalloc(db->size);
if (!eval_expr(op->value,&val,sec,pc)) {
symbol *base;
int btype;
rlist *rl;
modifier = 0;
btype = find_base(op->value,&base,sec,pc);
if (btype==BASE_OK || (btype==BASE_PCREL && modifier==0)) {
rl = add_extnreloc(&db->relocs,base,val,
btype==BASE_PCREL?REL_PC:REL_ABS,0,bitsize,0);
switch (modifier) {
case LOBYTE:
if (rl)
((nreloc *)rl->reloc)->mask = 0xff;
val = val & 0xff;
break;
case HIBYTE:
if (rl)
((nreloc *)rl->reloc)->mask = 0xff00;
val = (val >> 8) & 0xff;
break;
}
}
else if (btype != BASE_NONE)
general_error(38); /* illegal relocation */
}
if (bitsize < 16) {
if (val<-0x80 || val>0xff)
cpu_error(5,8); /* operand doesn't fit into 8-bits */
} else if (bitsize < 32) {
if (val<-0x8000 || val>0xffff)
cpu_error(5,16); /* operand doesn't fit into 16-bits */
}
setval(0,db->data,db->size,val);
return db;
}
operand *new_operand()
{
operand *new = mymalloc(sizeof(*new));
new->type = -1;
return new;
}
int cpu_available(int idx)
{
return (mnemonics[idx].ext.available & cpu_type) != 0;
}
int init_cpu()
{
return 1;
}
int cpu_args(char *p)
{
if (!strcmp(p,"-opt-branch"))
branchopt = 1;
else if (!strcmp(p,"-bbcade")) /* GMGM */
bbcade = 1;
else if (!strcmp(p,"-illegal"))
cpu_type |= ILL;
else if (!strcmp(p,"-dtv"))
cpu_type |= DTV;
else if (!strcmp(p,"-c02"))
cpu_type = M6502 | M65C02;
else if (!strcmp(p,"-wdc02"))
cpu_type = M6502 | M65C02 | WDC02;
else if (!strcmp(p,"-ce02"))
cpu_type = M6502 | M65C02 | WDC02 | CSGCE02;
else if (!strcmp(p,"-6280"))
cpu_type = M6502 | M65C02 | WDC02 | HU6280;
else
return 0;
return 1;
}

96
vasm-1/cpus/6502/cpu.h Normal file
View File

@ -0,0 +1,96 @@
/*
** cpu.h 650x/65C02/6510/6280 cpu-description header-file
** (c) in 2002,2008,2009,2014,2018,2020 by Frank Wille
*/
#define BIGENDIAN 0
#define LITTLEENDIAN 1
#define VASM_CPU_650X 1
/* maximum number of operands for one mnemonic */
#define MAX_OPERANDS 3
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 0
/* data type to represent a target-address */
typedef int32_t taddr;
typedef uint32_t utaddr;
/* minimum instruction alignment */
#define INST_ALIGN 1
/* default alignment for n-bit data */
#define DATA_ALIGN(n) 1
/* operand class for n-bit data definitions */
#define DATA_OPERAND(n) DATAOP
/* returns true when instruction is valid for selected cpu */
#define MNEMONIC_VALID(i) cpu_available(i)
/* we define two additional unary operations, '<' and '>' */
int ext_unary_type(char *);
int ext_unary_eval(int,taddr,taddr *,int);
int ext_find_base(symbol **,expr *,section *,taddr);
#define LOBYTE (LAST_EXP_TYPE+1)
#define HIBYTE (LAST_EXP_TYPE+2)
#define EXT_UNARY_NAME(s) (*s=='<'||*s=='>')
#define EXT_UNARY_TYPE(s) ext_unary_type(s)
#define EXT_UNARY_EVAL(t,v,r,c) ext_unary_eval(t,v,r,c)
#define EXT_FIND_BASE(b,e,s,p) ext_find_base(b,e,s,p)
/* type to store each operand */
typedef struct {
int type;
expr *value;
utaddr dp;
} operand;
/* additional mnemonic data */
typedef struct {
unsigned char opcode;
unsigned char zp_opcode; /* !=0 means optimization to zero page allowed */
uint16_t available;
} mnemonic_extension;
/* available */
#define M6502 1 /* standard 6502 instruction set */
#define ILL 2 /* illegal 6502 instructions */
#define DTV 4 /* C64 DTV instruction set extension */
#define M65C02 8 /* basic 65C02 extensions on 6502 instruction set */
#define WDC02 16 /* WDC65C02 extensions on 65C02 instruction set */
#define CSGCE02 32 /* CSG65CE02 extensions on WDC65C02 instruction set */
#define HU6280 64 /* HuC6280 extensions on WDC65C02 instruction set */
/* adressing modes */
#define IMPLIED 0
#define ABS 1 /* $1234 */
#define ABSX 2 /* $1234,X */
#define ABSY 3 /* $1234,Y */
#define INDIR 4 /* ($1234) - JMP only */
#define INDX 5 /* ($12,X) */
#define INDY 6 /* ($12),Y */
#define DPINDIR 7 /* ($12) */
#define INDIRX 8 /* ($1234,X) - JMP only */
#define ZPAGE 9 /* add ZPAGE-ABS to optimize ABS/ABSX/ABSY */
#define ZPAGEX 10
#define ZPAGEY 11
#define RELJMP 12 /* B!cc/JMP construction */
#define REL 13 /* $1234 - 8-bit signed relative branch */
#define IMMED 14 /* #$12 */
#define WBIT 15 /* bit-number (WDC65C02) */
#define DATAOP 16 /* data operand */
#define ACCU 17 /* A */
#define DUMX 18 /* dummy X as 'second' operand */
#define DUMY 19 /* dummy Y as 'second' operand */
/* cpu-specific symbol-flags */
#define ZPAGESYM (RSRVD_C<<0) /* symbol will reside in the zero/direct-page */
/* exported by cpu.c */
int cpu_available(int);

View File

@ -0,0 +1,9 @@
"instruction not supported on selected architecture",ERROR,
"trailing garbage in operand",WARNING,
"missing closing parenthesis in addressing mode",ERROR,
"data size %d not supported",ERROR,
"relocation does not allow hi/lo modifier",ERROR,
"operand doesn't fit into %d bits",ERROR, /* 05 */
"branch destination out of range",ERROR,
"illegal bit number",ERROR,
"identifier expected",ERROR,

287
vasm-1/cpus/6502/opcodes.h Normal file
View File

@ -0,0 +1,287 @@
"adc", {IMMED , }, {0x69,0x00,M6502},
"adc", {ABS , }, {0x6d,0x65,M6502},
"adc", {INDX , }, {0x61,0x00,M6502},
"adc", {DPINDIR, }, {0x72,0x00,M65C02},
"adc", {INDIR ,DUMY }, {0x71,0x00,M6502},
"adc", {ABS ,DUMX }, {0x7d,0x75,M6502},
"adc", {ABS ,DUMY }, {0x79,0x00,M6502},
"ahx", {INDIR ,DUMY }, {0x93,0x00,ILL},
"ahx", {ABS ,DUMY }, {0x9f,0x00,ILL},
"alr", {IMMED , }, {0x4b,0x00,ILL},
"anc", {IMMED , }, {0x0b,0x00,ILL},
"anc2", {IMMED , }, {0x2b,0x00,ILL},
"and", {IMMED , }, {0x29,0x00,M6502},
"and", {ABS , }, {0x2d,0x25,M6502},
"and", {INDX , }, {0x21,0x00,M6502},
"and", {DPINDIR, }, {0x32,0x00,M65C02},
"and", {INDIR ,DUMY }, {0x31,0x00,M6502},
"and", {ABS ,DUMX }, {0x3d,0x35,M6502},
"and", {ABS ,DUMY }, {0x39,0x00,M6502},
"arr", {IMMED , }, {0x6b,0x00,ILL},
"asl", {ACCU , }, {0x0a,0x00,M6502},
"asl", {ABS , }, {0x0e,0x06,M6502},
"asl", {IMPLIED, }, {0x0a,0x00,M6502},
"asl", {ABS ,DUMX }, {0x1e,0x16,M6502},
"aso", {ABS , }, {0x0f,0x07,ILL},
"aso", {INDX , }, {0x03,0x00,ILL},
"aso", {INDIR ,DUMY }, {0x13,0x00,ILL},
"aso", {ABS ,DUMX }, {0x1f,0x17,ILL},
"aso", {ABS ,DUMY }, {0x1b,0x00,ILL},
"axa", {INDIR ,DUMY }, {0x93,0x00,ILL},
"axa", {ABS ,DUMY }, {0x9f,0x00,ILL},
"axs", {IMMED , }, {0xcb,0x00,ILL},
"axs", {ABS , }, {0x8f,0x87,ILL},
"axs", {INDX , }, {0x83,0x00,ILL},
"axs", {ABS ,DUMY }, {0x00,0x97,ILL},
"bbr", {WBIT ,ZPAGE ,REL }, {0x00,0x0f,WDC02},
"bbr0", {ZPAGE ,REL }, {0x00,0x0f,WDC02},
"bbr1", {ZPAGE ,REL }, {0x00,0x1f,WDC02},
"bbr2", {ZPAGE ,REL }, {0x00,0x2f,WDC02},
"bbr3", {ZPAGE ,REL }, {0x00,0x3f,WDC02},
"bbr4", {ZPAGE ,REL }, {0x00,0x4f,WDC02},
"bbr5", {ZPAGE ,REL }, {0x00,0x5f,WDC02},
"bbr6", {ZPAGE ,REL }, {0x00,0x6f,WDC02},
"bbr7", {ZPAGE ,REL }, {0x00,0x7f,WDC02},
"bbs", {WBIT ,ZPAGE ,REL }, {0x00,0x8f,WDC02},
"bbs0", {ZPAGE ,REL }, {0x00,0x8f,WDC02},
"bbs1", {ZPAGE ,REL }, {0x00,0x9f,WDC02},
"bbs2", {ZPAGE ,REL }, {0x00,0xaf,WDC02},
"bbs3", {ZPAGE ,REL }, {0x00,0xbf,WDC02},
"bbs4", {ZPAGE ,REL }, {0x00,0xcf,WDC02},
"bbs5", {ZPAGE ,REL }, {0x00,0xdf,WDC02},
"bbs6", {ZPAGE ,REL }, {0x00,0xef,WDC02},
"bbs7", {ZPAGE ,REL }, {0x00,0xff,WDC02},
"bcc", {REL , }, {0x90,0x00,M6502},
"bcs", {REL , }, {0xb0,0x00,M6502},
"beq", {REL , }, {0xf0,0x00,M6502},
"bit", {IMMED , }, {0x89,0x00,M65C02},
"bit", {ABS , }, {0x2c,0x24,M6502},
"bit", {ABS ,DUMX }, {0x3c,0x34,M65C02},
"bmi", {REL , }, {0x30,0x00,M6502},
"bne", {REL , }, {0xd0,0x00,M6502},
"bpl", {REL , }, {0x10,0x00,M6502},
"bra", {REL , }, {0x12,0x00,DTV},
"bra", {REL , }, {0x80,0x00,M65C02},
"brk", {IMPLIED, }, {0x00,0x00,M6502},
"bsr", {REL , }, {0x44,0x00,HU6280},
"bvc", {REL , }, {0x50,0x00,M6502},
"bvs", {REL , }, {0x70,0x00,M6502},
"cla", {IMPLIED, }, {0x62,0x00,HU6280},
"clc", {IMPLIED, }, {0x18,0x00,M6502},
"cld", {IMPLIED, }, {0xd8,0x00,M6502},
"cli", {IMPLIED, }, {0x58,0x00,M6502},
"clv", {IMPLIED, }, {0xb8,0x00,M6502},
"clx", {IMPLIED, }, {0x82,0x00,HU6280},
"cly", {IMPLIED, }, {0xc2,0x00,HU6280},
"cmp", {IMMED , }, {0xc9,0x00,M6502},
"cmp", {ABS , }, {0xcd,0xc5,M6502},
"cmp", {INDX , }, {0xc1,0x00,M6502},
"cmp", {DPINDIR, }, {0xd2,0x00,M65C02},
"cmp", {INDIR ,DUMY }, {0xd1,0x00,M6502},
"cmp", {ABS ,DUMX }, {0xdd,0xd5,M6502},
"cmp", {ABS ,DUMY }, {0xd9,0x00,M6502},
"cpx", {IMMED , }, {0xe0,0x00,M6502},
"cpx", {ABS , }, {0xec,0xe4,M6502},
"cpy", {IMMED , }, {0xc0,0x00,M6502},
"cpy", {ABS , }, {0xcc,0xc4,M6502},
"csh", {IMPLIED, }, {0xd4,0x00,HU6280},
"csl", {IMPLIED, }, {0x54,0x00,HU6280},
"dcm", {ABS , }, {0xcf,0xc7,ILL},
"dcm", {INDX , }, {0xc3,0x00,ILL},
"dcm", {INDIR ,DUMY }, {0xd3,0x00,ILL},
"dcm", {ABS ,DUMX }, {0xdf,0xd7,ILL},
"dcm", {ABS ,DUMY }, {0xdb,0x00,ILL},
"dcp", {ABS , }, {0xcf,0xc7,ILL},
"dcp", {INDX , }, {0xc3,0x00,ILL},
"dcp", {INDIR ,DUMY }, {0xd3,0x00,ILL},
"dcp", {ABS ,DUMX }, {0xdf,0xd7,ILL},
"dcp", {ABS ,DUMY }, {0xdb,0x00,ILL},
"dea", {IMPLIED, }, {0x3a,0x00,M65C02},
"dec", {ACCU , }, {0x3a,0x00,M65C02},
"dec", {IMPLIED, }, {0x3a,0x00,M65C02},
"dec", {ABS , }, {0xce,0xc6,M6502},
"dec", {ABS ,DUMX }, {0xde,0xd6,M6502},
"dex", {IMPLIED, }, {0xca,0x00,M6502},
"dey", {IMPLIED, }, {0x88,0x00,M6502},
"eor", {IMMED , }, {0x49,0x00,M6502},
"eor", {ABS , }, {0x4d,0x45,M6502},
"eor", {INDX , }, {0x41,0x00,M6502},
"eor", {DPINDIR, }, {0x52,0x00,M65C02},
"eor", {INDIR ,DUMY }, {0x51,0x00,M6502},
"eor", {ABS ,DUMX }, {0x5d,0x55,M6502},
"eor", {ABS ,DUMY }, {0x59,0x00,M6502},
"ina", {IMPLIED, }, {0x1a,0x00,M65C02},
"inc", {ACCU , }, {0x1a,0x00,M65C02},
"inc", {IMPLIED, }, {0x1a,0x00,M65C02},
"inc", {ABS , }, {0xee,0xe6,M6502},
"inc", {ABS ,DUMX }, {0xfe,0xf6,M6502},
"ins", {ABS , }, {0xef,0xe7,ILL},
"ins", {INDX , }, {0xe3,0x00,ILL},
"ins", {INDIR ,DUMY }, {0xf3,0x00,ILL},
"ins", {ABS ,DUMX }, {0xff,0xf7,ILL},
"ins", {ABS ,DUMY }, {0xfb,0x00,ILL},
"inx", {IMPLIED, }, {0xe8,0x00,M6502},
"iny", {IMPLIED, }, {0xc8,0x00,M6502},
"isc", {ABS , }, {0xef,0xe7,ILL},
"isc", {INDX , }, {0xe3,0x00,ILL},
"isc", {INDIR ,DUMY }, {0xf3,0x00,ILL},
"isc", {ABS ,DUMX }, {0xff,0xf7,ILL},
"isc", {ABS ,DUMY }, {0xfb,0x00,ILL},
"jmp", {ABS , }, {0x4c,0x00,M6502},
"jmp", {INDIRX , }, {0x7c,0x00,M65C02},
"jmp", {INDIR , }, {0x6c,0x00,M6502},
"jsr", {ABS , }, {0x20,0x00,M6502},
"las", {ABS ,DUMY }, {0xbb,0x00,ILL},
"lax", {IMMED , }, {0xab,0x00,ILL},
"lax", {ABS , }, {0xaf,0xa7,ILL},
"lax", {ABS ,DUMY }, {0xbf,0xb7,ILL},
"lax", {INDX , }, {0xa3,0x00,ILL},
"lax", {INDIR ,DUMY }, {0xb3,0x00,ILL},
"lda", {IMMED , }, {0xa9,0x00,M6502},
"lda", {ABS , }, {0xad,0xa5,M6502},
"lda", {INDX , }, {0xa1,0x00,M6502},
"lda", {DPINDIR, }, {0xb2,0x00,M65C02},
"lda", {INDIR ,DUMY }, {0xb1,0x00,M6502},
"lda", {ABS ,DUMX }, {0xbd,0xb5,M6502},
"lda", {ABS ,DUMY }, {0xb9,0x00,M6502},
"ldx", {IMMED , }, {0xa2,0x00,M6502},
"ldx", {ABS , }, {0xae,0xa6,M6502},
"ldx", {ABS ,DUMY }, {0xbe,0xb6,M6502},
"ldy", {IMMED , }, {0xa0,0x00,M6502},
"ldy", {ABS , }, {0xac,0xa4,M6502},
"ldy", {ABS ,DUMX }, {0xbc,0xb4,M6502},
"lse", {ABS , }, {0x4f,0x47,ILL},
"lse", {INDX , }, {0x43,0x00,ILL},
"lse", {INDIR ,DUMY }, {0x53,0x00,ILL},
"lse", {ABS ,DUMX }, {0x5f,0x57,ILL},
"lse", {ABS ,DUMY }, {0x5b,0x00,ILL},
"lsr", {ACCU , }, {0x4a,0x00,M6502},
"lsr", {ABS , }, {0x4e,0x46,M6502},
"lsr", {IMPLIED, }, {0x4a,0x00,M6502},
"lsr", {ABS ,DUMX }, {0x5e,0x56,M6502},
"nop", {IMPLIED, }, {0xea,0x00,M6502},
"oal", {IMMED , }, {0xab,0x00,ILL},
"ora", {IMMED , }, {0x09,0x00,M6502},
"ora", {ABS , }, {0x0d,0x05,M6502},
"ora", {INDX , }, {0x01,0x00,M6502},
"ora", {DPINDIR, }, {0x12,0x00,M65C02},
"ora", {INDIR ,DUMY }, {0x11,0x00,M6502},
"ora", {ABS ,DUMX }, {0x1d,0x15,M6502},
"ora", {ABS ,DUMY }, {0x19,0x00,M6502},
"pha", {IMPLIED, }, {0x48,0x00,M6502},
"php", {IMPLIED, }, {0x08,0x00,M6502},
"phx", {IMPLIED, }, {0xda,0x00,M65C02},
"phy", {IMPLIED, }, {0x5a,0x00,M65C02},
"pla", {IMPLIED, }, {0x68,0x00,M6502},
"plp", {IMPLIED, }, {0x28,0x00,M6502},
"plx", {IMPLIED, }, {0xfa,0x00,M65C02},
"ply", {IMPLIED, }, {0x7a,0x00,M65C02},
"rla", {ABS , }, {0x2f,0x27,ILL},
"rla", {INDX , }, {0x23,0x00,ILL},
"rla", {INDIR ,DUMY }, {0x33,0x00,ILL},
"rla", {ABS ,DUMX }, {0x3f,0x37,ILL},
"rla", {ABS ,DUMY }, {0x3b,0x00,ILL},
"rmb", {WBIT ,ZPAGE }, {0x00,0x07,WDC02},
"rmb0", {ZPAGE }, {0x00,0x07,WDC02},
"rmb1", {ZPAGE }, {0x00,0x17,WDC02},
"rmb2", {ZPAGE }, {0x00,0x27,WDC02},
"rmb3", {ZPAGE }, {0x00,0x37,WDC02},
"rmb4", {ZPAGE }, {0x00,0x47,WDC02},
"rmb5", {ZPAGE }, {0x00,0x57,WDC02},
"rmb6", {ZPAGE }, {0x00,0x67,WDC02},
"rmb7", {ZPAGE }, {0x00,0x77,WDC02},
"rol", {ACCU , }, {0x2a,0x00,M6502},
"rol", {ABS , }, {0x2e,0x26,M6502},
"rol", {IMPLIED, }, {0x2a,0x00,M6502},
"rol", {ABS ,DUMX }, {0x3e,0x36,M6502},
"ror", {ACCU , }, {0x6a,0x00,M6502},
"ror", {ABS , }, {0x6e,0x66,M6502},
"ror", {IMPLIED, }, {0x6a,0x00,M6502},
"ror", {ABS ,DUMX }, {0x7e,0x76,M6502},
"rra", {ABS , }, {0x6f,0x67,ILL},
"rra", {INDX , }, {0x63,0x00,ILL},
"rra", {INDIR ,DUMY }, {0x73,0x00,ILL},
"rra", {ABS ,DUMX }, {0x7f,0x77,ILL},
"rra", {ABS ,DUMY }, {0x7b,0x00,ILL},
"rti", {IMPLIED, }, {0x40,0x00,M6502},
"rts", {IMPLIED, }, {0x60,0x00,M6502},
"sac", {IMMED , }, {0x32,0x00,DTV},
"sax", {IMMED , }, {0xcb,0x00,ILL},
"sax", {ABS , }, {0x8f,0x87,ILL},
"sax", {INDX , }, {0x83,0x00,ILL},
"sax", {ABS ,DUMY }, {0x00,0x97,ILL},
"sax", {IMPLIED, }, {0x22,0x00,HU6280},
"say", {ABS ,DUMX }, {0x9c,0x00,ILL},
"say", {IMPLIED, }, {0x42,0x00,HU6280},
"sbc", {IMMED , }, {0xe9,0x00,M6502},
"sbc", {ABS , }, {0xed,0xe5,M6502},
"sbc", {INDX , }, {0xe1,0x00,M6502},
"sbc", {DPINDIR, }, {0xf2,0x00,M65C02},
"sbc", {INDIR ,DUMY }, {0xf1,0x00,M6502},
"sbc", {ABS ,DUMX }, {0xfd,0xf5,M6502},
"sbc", {ABS ,DUMY }, {0xf9,0x00,M6502},
"sbc2", {IMMED , }, {0xeb,0x00,ILL},
"sec", {IMPLIED, }, {0x38,0x00,M6502},
"sed", {IMPLIED, }, {0xf8,0x00,M6502},
"sei", {IMPLIED, }, {0x78,0x00,M6502},
"set", {IMPLIED, }, {0xf4,0x00,HU6280},
"shx", {ABS ,DUMY }, {0x9e,0x00,ILL},
"shy", {ABS ,DUMX }, {0x9c,0x00,ILL},
"sir", {IMMED , }, {0x42,0x00,DTV},
"slo", {ABS , }, {0x0f,0x07,ILL},
"slo", {INDX , }, {0x03,0x00,ILL},
"slo", {INDIR ,DUMY }, {0x13,0x00,ILL},
"slo", {ABS ,DUMX }, {0x1f,0x17,ILL},
"slo", {ABS ,DUMY }, {0x1b,0x00,ILL},
"smb", {WBIT ,ZPAGE }, {0x00,0x87,WDC02},
"smb0", {ZPAGE }, {0x00,0x87,WDC02},
"smb1", {ZPAGE }, {0x00,0x97,WDC02},
"smb2", {ZPAGE }, {0x00,0xa7,WDC02},
"smb3", {ZPAGE }, {0x00,0xb7,WDC02},
"smb4", {ZPAGE }, {0x00,0xc7,WDC02},
"smb5", {ZPAGE }, {0x00,0xd7,WDC02},
"smb6", {ZPAGE }, {0x00,0xe7,WDC02},
"smb7", {ZPAGE }, {0x00,0xf7,WDC02},
"sre", {ABS , }, {0x4f,0x47,ILL},
"sre", {INDX , }, {0x43,0x00,ILL},
"sre", {INDIR ,DUMY }, {0x53,0x00,ILL},
"sre", {ABS ,DUMX }, {0x5f,0x57,ILL},
"sre", {ABS ,DUMY }, {0x5b,0x00,ILL},
"st0", {IMMED , }, {0x03,0x00,HU6280},
"st1", {IMMED , }, {0x13,0x00,HU6280},
"st2", {IMMED , }, {0x23,0x00,HU6280},
"sta", {ABS , }, {0x8d,0x85,M6502},
"sta", {INDX , }, {0x81,0x00,M6502},
"sta", {DPINDIR, }, {0x92,0x00,M65C02},
"sta", {INDIR ,DUMY }, {0x91,0x00,M6502},
"sta", {ABS ,DUMX }, {0x9d,0x95,M6502},
"sta", {ABS ,DUMY }, {0x99,0x00,M6502},
"stp", {IMPLIED, }, {0xdb,0x00,WDC02},
"stx", {ABS , }, {0x8e,0x86,M6502},
"stx", {ABS ,DUMY }, {0x00,0x96,M6502},
"sty", {ABS , }, {0x8c,0x84,M6502},
"sty", {ABS ,DUMX }, {0x00,0x94,M6502},
"stz", {ABS , }, {0x9c,0x64,M65C02},
"stz", {ABS ,DUMX }, {0x9e,0x74,M65C02},
"sxy", {IMPLIED, }, {0x02,0x00,HU6280},
"tai", {ABS ,ABS ,ABS }, {0xf3,0x00,HU6280},
"tam", {IMMED , }, {0x53,0x00,HU6280},
"tas", {ABS ,DUMY }, {0x9b,0x00,ILL},
"tax", {IMPLIED, }, {0xaa,0x00,M6502},
"tay", {IMPLIED, }, {0xa8,0x00,M6502},
"tdd", {ABS ,ABS ,ABS }, {0xc3,0x00,HU6280},
"tia", {ABS ,ABS ,ABS }, {0xe3,0x00,HU6280},
"tii", {ABS ,ABS ,ABS }, {0x73,0x00,HU6280},
"tin", {ABS ,ABS ,ABS }, {0xd3,0x00,HU6280},
"tma", {IMMED , }, {0x43,0x00,HU6280},
"trb", {ABS , }, {0x1c,0x14,M65C02},
"tsb", {ABS , }, {0x0c,0x04,M65C02},
"tst", {IMMED ,ABS }, {0x93,0x83,HU6280},
"tst", {IMMED ,ABS ,DUMX }, {0xb3,0xa3,HU6280},
"tsx", {IMPLIED, }, {0xba,0x00,M6502},
"txa", {IMPLIED, }, {0x8a,0x00,M6502},
"txs", {IMPLIED, }, {0x9a,0x00,M6502},
"tya", {IMPLIED, }, {0x98,0x00,M6502},
"wai", {IMPLIED, }, {0xcb,0x00,WDC02},
"xaa", {IMMED , }, {0x8b,0x00,ILL},
"xas", {ABS ,DUMY }, {0x9e,0x00,ILL},

398
vasm-1/cpus/6800/cpu.c Normal file
View File

@ -0,0 +1,398 @@
/*
* cpu.c 6800 cpu description file
* (c) in 2013-2016,2019 by Esben Norby and Frank Wille
*/
#include "vasm.h"
mnemonic mnemonics[] = {
#include "opcodes.h"
};
int mnemonic_cnt = sizeof(mnemonics) / sizeof(mnemonics[0]);
int bitsperbyte = 8;
int bytespertaddr = 2;
char * cpu_copyright = "vasm 6800/6801/68hc11 cpu backend 0.4 (c) 2013-2016,2019 Esben Norby";
char * cpuname = "6800";
static uint8_t cpu_type = M6800;
static int modifier; /* set by find_base() */
int
init_cpu()
{
return 1;
}
int
cpu_args(char *p)
{
if (!strncmp(p, "-m68", 4)) {
p += 4;
if (p[0] == '0' && p[3] == '\0') {
switch(p[1]) {
case '0':
case '2':
case '8':
/* 6802 and 6808 are a 6800 with embedded ROM/RAM */
cpu_type = M6800;
break;
case '1':
case '3':
/* 6803 is a 6801 with embedded ROM/RAM */
cpu_type = M6801;
break;
default:
/* 6804 and 6805 are not opcode compatible
* 6809 is somewhat compatible, but not completely
* 6806 and 6807 do not exist, to my knowledge
*/
return 0;
}
} else if (!stricmp(p, "hc11"))
cpu_type = M68HC11;
else
return 0;
return 1;
}
return 0;
}
char *
parse_cpu_special(char *start)
{
return start;
}
operand *
new_operand()
{
operand *new = mymalloc(sizeof(*new));
new->type = -1;
return new;
}
int
parse_operand(char *p, int len, operand *op, int required)
{
char *start = p;
op->value = NULL;
switch (required) {
case IMM:
case IMM16:
if (*p++ != '#')
return PO_NOMATCH;
p = skip(p);
/* fall through */
case REL:
case DATAOP:
op->value = parse_expr(&p);
break;
case ADDR:
if (*p == '<') {
required = DIR;
p++;
}
else if (*p == '>') {
required = EXT;
p++;
}
op->value = parse_expr(&p);
break;
case DIR:
if (*p == '>')
return PO_NOMATCH;
else if (*p == '<')
p++;
op->value = parse_expr(&p);
break;
case EXT:
if (*p == '<')
return PO_NOMATCH;
else if (*p == '>')
p++;
op->value = parse_expr(&p);
break;
case REGX:
if (toupper((unsigned char)*p++) != 'X')
return PO_NOMATCH;
break;
case REGY:
if (toupper((unsigned char)*p++) != 'Y')
return PO_NOMATCH;
break;
default:
return PO_NOMATCH;
}
op->type = required;
return PO_MATCH;
}
static size_t
eval_oper(operand *op, section *sec, taddr pc, taddr offs, dblock *db)
{
size_t size = 0;
symbol *base = NULL;
int btype;
taddr val;
if (op->value != NULL && !eval_expr(op->value, &val, sec, pc)) {
modifier = 0;
btype = find_base(op->value, &base, sec, pc);
}
switch (op->type) {
case ADDR:
if (base != NULL || val < 0 || val > 0xff) {
op->type = EXT;
size = 2;
}
else {
op->type = DIR;
size = 1;
}
break;
case DIR:
size = 1;
if (db != NULL && (val < 0 || val > 0xff))
cpu_error(1); /* operand doesn't fit into 8-bits */
break;
case IMM:
size = 1;
if (db != NULL && !modifier && (val < -0x80 || val > 0xff))
cpu_error(1); /* operand doesn't fit into 8-bits */
break;
case EXT:
case IMM16:
size = 2;
break;
case REL:
size = 1;
break;
}
if (size > 0 && db != NULL) {
/* create relocation entry and code for this operand */
if (op->type == REL && base == NULL) {
/* relative branch to absolute label */
val = val - (pc + offs + 1);
if (val < -0x80 || val > 0x7f)
cpu_error(2); /* branch out of range */
}
else if (op->type == REL && base != NULL && btype == BASE_OK) {
/* relative branches */
if (!is_pc_reloc(base, sec)) {
val = val - (pc + offs + 1);
if (val < -0x80 || val > 0x7f)
cpu_error(2); /* branch out of range */
}
else
add_extnreloc(&db->relocs, base, val, REL_PC,
0, 8, offs);
}
else if (base != NULL && btype != BASE_ILLEGAL) {
rlist *rl;
rl = add_extnreloc(&db->relocs, base, val,
btype==BASE_PCREL? REL_PC : REL_ABS,
0, size << 3, offs);
switch (modifier) {
case LOBYTE:
if (rl) ((nreloc *)rl->reloc)->mask = 0xff;
val &= 0xff;
break;
case HIBYTE:
if (rl) ((nreloc *)rl->reloc)->mask = 0xff00;
val = (val >> 8) & 0xff;
break;
}
}
else if (base != NULL)
general_error(38); /* illegal relocation */
if (size == 1) {
op->code[0] = val & 0xff;
}
else if (size == 2) {
op->code[0] = (val >> 8) & 0xff;
op->code[1] = val & 0xff;
}
else
ierror(0);
}
return (size);
}
size_t
instruction_size(instruction *ip, section *sec, taddr pc)
{
operand op;
int i;
size_t size;
size = (mnemonics[ip->code].ext.prebyte != 0) ? 2 : 1;
for (i = 0; i < MAX_OPERANDS && ip->op[i] != NULL; i++) {
op = *(ip->op[i]);
size += eval_oper(&op, sec, pc, size, NULL);
}
return (size);
}
dblock *
eval_instruction(instruction *ip, section *sec, taddr pc)
{
dblock *db = new_dblock();
uint8_t opcode;
uint8_t *d;
int i;
size_t size;
/* evaluate operands and determine instruction size */
opcode = mnemonics[ip->code].ext.opcode;
size = (mnemonics[ip->code].ext.prebyte != 0) ? 2 : 1;
for (i = 0; i < MAX_OPERANDS && ip->op[i] != NULL; i++) {
size += eval_oper(ip->op[i], sec, pc, size, db);
if (ip->op[i]->type == DIR)
opcode = mnemonics[ip->code].ext.dir_opcode;
}
/* allocate and fill data block */
db->size = size;
d = db->data = mymalloc(size);
if (mnemonics[ip->code].ext.prebyte != 0)
*d++ = mnemonics[ip->code].ext.prebyte;
*d++ = opcode;
/* write operands */
for (i = 0; i < MAX_OPERANDS && ip->op[i] != NULL; i++) {
switch (ip->op[i]->type) {
case IMM:
case DIR:
case REL:
*d++ = ip->op[i]->code[0];
break;
case IMM16:
case EXT:
*d++ = ip->op[i]->code[0];
*d++ = ip->op[i]->code[1];
break;
}
}
return (db);
}
dblock *
eval_data(operand *op, size_t bitsize, section *sec, taddr pc)
{
dblock *db = new_dblock();
uint8_t *d;
taddr val;
if (bitsize != 8 && bitsize != 16)
cpu_error(0,bitsize); /* data size not supported */
db->size = bitsize >> 3;
d = db->data = mymalloc(db->size);
if (!eval_expr(op->value, &val, sec, pc)) {
symbol *base;
int btype;
rlist *rl;
modifier = 0;
btype = find_base(op->value, &base, sec, pc);
if (btype==BASE_OK || (btype==BASE_PCREL && modifier==0)) {
rl = add_extnreloc(&db->relocs, base, val,
btype==BASE_PCREL ? REL_PC : REL_ABS,
0, bitsize, 0);
switch (modifier) {
case LOBYTE:
if (rl) ((nreloc *)rl->reloc)->mask = 0xff;
val &= 0xff;
break;
case HIBYTE:
if (rl) ((nreloc *)rl->reloc)->mask = 0xff00;
val = (val >> 8) & 0xff;
break;
}
}
else if (btype != BASE_NONE)
general_error(38); /* illegal relocation */
}
if (bitsize == 8) {
if (val < -0x80 || val > 0xff)
cpu_error(1); /* operand doesn't fit into 8-bits */
}
else /* 16 bits */
*d++ = (val >> 8) & 0xff;
*d = val & 0xff;
return (db);
}
int
ext_unary_eval(int type, taddr val, taddr *result, int cnst)
{
switch (type) {
case LOBYTE:
*result = cnst ? (val & 0xff) : val;
return 1;
case HIBYTE:
*result = cnst ? ((val >> 8) & 0xff) : val;
return 1;
default:
break;
}
return 0; /* unknown type */
}
int
ext_find_base(symbol **base, expr *p, section *sec, taddr pc)
{
/* addr/256 equals >addr, addr%256 and addr&255 equal <addr */
if (p->type==DIV || p->type==MOD) {
if (p->right->type==NUM && p->right->c.val==256)
p->type = p->type == DIV ? HIBYTE : LOBYTE;
}
else if (p->type==BAND && p->right->type==NUM && p->right->c.val==255)
p->type = LOBYTE;
if (p->type==LOBYTE || p->type==HIBYTE) {
modifier = p->type;
return find_base(p->left,base,sec,pc);
}
return BASE_ILLEGAL;
}
int
cpu_available(int idx)
{
return (mnemonics[idx].ext.available & cpu_type) != 0;
}

80
vasm-1/cpus/6800/cpu.h Normal file
View File

@ -0,0 +1,80 @@
/*
* cpu.h 6800 cpu description file
* (c) in 2013-2014 by Esben Norby and Frank Wille
*/
#define BIGENDIAN 1
#define LITTLEENDIAN 0
#define VASM_CPU_6800 1
/* maximum number of operands for one mnemonic */
#define MAX_OPERANDS 4
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 0
/* data type to represent a target-address */
typedef int16_t taddr;
typedef uint16_t utaddr;
/* minimum instruction alignment */
#define INST_ALIGN 1
/* default alignment for n-bit data */
#define DATA_ALIGN(n) 1
/* operand class for n-bit data definitions */
#define DATA_OPERAND(n) DATAOP
/* returns true when instruction is valid for selected cpu */
#define MNEMONIC_VALID(i) cpu_available(i)
/* allow commas and blanks at the same time to separate instruction operands */
#define OPERSEP_COMMA 1
#define OPERSEP_BLANK 1
/* we define two additional unary operations, '<' and '>' */
int ext_unary_eval(int,taddr,taddr *,int);
int ext_find_base(symbol **,expr *,section *,taddr);
#define LOBYTE (LAST_EXP_TYPE+1)
#define HIBYTE (LAST_EXP_TYPE+2)
#define EXT_UNARY_NAME(s) (*s=='<'||*s=='>')
#define EXT_UNARY_TYPE(s) (*s=='<'?LOBYTE:HIBYTE)
#define EXT_UNARY_EVAL(t,v,r,c) ext_unary_eval(t,v,r,c)
#define EXT_FIND_BASE(b,e,s,p) ext_find_base(b,e,s,p)
/* type to store each operand */
typedef struct {
uint16_t type;
uint8_t code[2];
expr *value;
} operand;
/* additional mnemonic data */
typedef struct {
unsigned char prebyte;
unsigned char opcode;
unsigned char dir_opcode; /* !=0 means optimization to DIR allowed */
uint8_t available;
} mnemonic_extension;
/* available */
#define M6800 1
#define M6801 2 /* 6801/6803: Adds D register and some extras */
#define M68HC11 4 /* standard 68HC11 instruction set */
/* adressing modes */
#define INH 0
#define IMM 1 /* #$12 */ /* IMM ii */
#define IMM16 2 /* #$1234 */ /* IMM jj kk */
#define ADDR 3
#define EXT 4 /* EXT hh */
#define DIR 5 /* DIR dd */
#define REL 6 /* REL rr */
#define REGX 7
#define REGY 8
#define DATAOP 9 /* data operand */
/* exported by cpu.c */
int cpu_available(int);

View File

@ -0,0 +1,3 @@
"data size %d not supported",ERROR,
"operand doesn't fit into 8-bits",ERROR,
"branch destination out of range",ERROR,

339
vasm-1/cpus/6800/opcodes.h Normal file
View File

@ -0,0 +1,339 @@
"aba", {INH }, {0x00, 0x1B, 0x00, M6800|M6801|M68HC11},
"abx", {INH }, {0x00, 0x3A, 0x00, M6801|M68HC11},
"aby", {INH }, {0x18, 0x3A, 0x00, M68HC11},
"adca", {IMM }, {0x00, 0x89, 0x00, M6800|M6801|M68HC11},
"adca", {ADDR }, {0x00, 0xB9, 0x99, M6800|M6801|M68HC11},
"adca", {DIR, REGX }, {0x00, 0x00, 0xA9, M6800|M6801|M68HC11},
"adca", {DIR, REGY }, {0x18, 0x00, 0xA9, M68HC11},
"adcb", {IMM }, {0x00, 0xC9, 0x00, M6800|M6801|M68HC11},
"adcb", {ADDR }, {0x00, 0xF9, 0xD9, M6800|M6801|M68HC11},
"adcb", {DIR, REGX }, {0x00, 0x00, 0xE9, M6800|M6801|M68HC11},
"adcb", {DIR, REGY }, {0x18, 0x00, 0xE9, M68HC11},
"adda", {IMM }, {0x00, 0x8B, 0x00, M6800|M6801|M68HC11},
"adda", {ADDR }, {0x00, 0xBB, 0x9B, M6800|M6801|M68HC11},
"adda", {DIR, REGX }, {0x00, 0x00, 0xAB, M6800|M6801|M68HC11},
"adda", {DIR, REGY }, {0x18, 0x00, 0xAB, M68HC11},
"addb", {IMM }, {0x00, 0xCB, 0x00, M6800|M6801|M68HC11},
"addb", {ADDR }, {0x00, 0xFB, 0xDB, M6800|M6801|M68HC11},
"addb", {DIR, REGX }, {0x00, 0x00, 0xEB, M6800|M6801|M68HC11},
"addb", {DIR, REGY }, {0x18, 0x00, 0xEB, M68HC11},
"addd", {IMM16 }, {0x00, 0xC3, 0x00, M6801|M68HC11},
"addd", {ADDR }, {0x00, 0xF3, 0xD3, M6801|M68HC11},
"addd", {DIR, REGX }, {0x00, 0x00, 0xE3, M6801|M68HC11},
"addd", {DIR, REGY }, {0x18, 0x00, 0xE3, M68HC11},
"anda", {IMM }, {0x00, 0x84, 0x00, M6800|M6801|M68HC11},
"anda", {ADDR }, {0x00, 0xB4, 0x94, M6800|M6801|M68HC11},
"anda", {DIR, REGX }, {0x00, 0x00, 0xA4, M6800|M6801|M68HC11},
"anda", {DIR, REGY }, {0x18, 0x00, 0xA4, M68HC11},
"andb", {IMM }, {0x00, 0xC4, 0x00, M6800|M6801|M68HC11},
"andb", {ADDR }, {0x00, 0xF4, 0xD4, M6800|M6801|M68HC11},
"andb", {DIR, REGX }, {0x00, 0x00, 0xE4, M6800|M6801|M68HC11},
"andb", {DIR, REGY }, {0x18, 0x00, 0xE4, M68HC11},
"asl", {EXT }, {0x00, 0x78, 0x00, M6800|M6801|M68HC11},
"asl", {DIR, REGX }, {0x00, 0x00, 0x68, M6800|M6801|M68HC11},
"asl", {DIR, REGY }, {0x18, 0x00, 0x68, M68HC11},
"asla", {INH }, {0x00, 0x48, 0x00, M6800|M6801|M68HC11},
"aslb", {INH }, {0x00, 0x58, 0x00, M6800|M6801|M68HC11},
"asld", {INH }, {0x00, 0x05, 0x00, M6800|M6801|M68HC11},
"asr", {EXT }, {0x00, 0x77, 0x00, M6800|M6801|M68HC11},
"asr", {DIR, REGX }, {0x00, 0x00, 0x67, M6800|M6801|M68HC11},
"asr", {DIR, REGY }, {0x18, 0x00, 0x67, M68HC11},
"asra", {INH, }, {0x00, 0x47, 0x00, M6800|M6801|M68HC11},
"asrb", {INH, }, {0x00, 0x57, 0x00, M6800|M6801|M68HC11},
"bclr", {DIR, IMM }, {0x00, 0x00, 0x15, M68HC11},
"bclr", {DIR, REGX, IMM }, {0x00, 0x00, 0x1D, M68HC11},
"bclr", {DIR, REGY, IMM }, {0x18, 0x00, 0x1D, M68HC11},
"bcc", {REL, }, {0x00, 0x24, 0x00, M6800|M6801|M68HC11},
"bcs", {REL, }, {0x00, 0x25, 0x00, M6800|M6801|M68HC11},
"beq", {REL, }, {0x00, 0x27, 0x00, M6800|M6801|M68HC11},
"bge", {REL, }, {0x00, 0x2C, 0x00, M6800|M6801|M68HC11},
"bgt", {REL, }, {0x00, 0x2E, 0x00, M6800|M6801|M68HC11},
"bhi", {REL, }, {0x00, 0x22, 0x00, M6800|M6801|M68HC11},
"bhs", {REL, }, {0x00, 0x24, 0x00, M6800|M6801|M68HC11},
"bita", {IMM }, {0x00, 0x85, 0x00, M6800|M6801|M68HC11},
"bita", {ADDR, }, {0x00, 0xB5, 0x95, M6800|M6801|M68HC11},
"bita", {DIR, REGX }, {0x00, 0x00, 0xA5, M6800|M6801|M68HC11},
"bita", {DIR, REGY }, {0x18, 0x00, 0xA5, M68HC11},
"bitb", {IMM }, {0x00, 0xC5, 0x00, M6800|M6801|M68HC11},
"bitb", {ADDR, }, {0x00, 0xF5, 0xD5, M6800|M6801|M68HC11},
"bitb", {DIR, REGX }, {0x00, 0x00, 0xE5, M6800|M6801|M68HC11},
"bitb", {DIR, REGY }, {0x18, 0x00, 0xE5, M68HC11},
"ble", {REL, }, {0x00, 0x2F, 0x00, M6800|M6801|M68HC11},
"blo", {REL, }, {0x00, 0x25, 0x00, M6800|M6801|M68HC11},
"bls", {REL, }, {0x00, 0x23, 0x00, M6800|M6801|M68HC11},
"blt", {REL, }, {0x00, 0x2D, 0x00, M6800|M6801|M68HC11},
"bmi", {REL, }, {0x00, 0x2B, 0x00, M6800|M6801|M68HC11},
"bne", {REL, }, {0x00, 0x26, 0x00, M6800|M6801|M68HC11},
"bpl", {REL, }, {0x00, 0x2A, 0x00, M6800|M6801|M68HC11},
"bra", {REL, }, {0x00, 0x20, 0x00, M6800|M6801|M68HC11},
"jr", {REL, }, {0x00, 0x20, 0x00, M6800|M6801|M68HC11}, /* bra */
"brclr",{DIR, IMM, REL }, {0x00, 0x00, 0x13, M68HC11},
"brclr",{DIR, REGX, IMM, REL}, {0x00, 0x00, 0x1F, M68HC11},
"brclr",{DIR, REGY, IMM, REL}, {0x18, 0x00, 0x1F, M68HC11},
"brn", {REL, }, {0x00, 0x21, 0x00, M6801|M68HC11},
"brset",{DIR, IMM, REL }, {0x00, 0x00, 0x12, M68HC11},
"brset",{DIR, REGX, IMM, REL}, {0x00, 0x00, 0x1E, M68HC11},
"brset",{DIR, REGY, IMM, REL}, {0x18, 0x00, 0x1E, M68HC11},
"bset", {DIR, IMM }, {0x00, 0x00, 0x14, M68HC11},
"bset", {DIR, REGX, IMM }, {0x00, 0x00 ,0x1C, M68HC11},
"bset", {DIR, REGY, IMM }, {0x18, 0x00 ,0x1C, M68HC11},
"bsr", {REL, }, {0x00, 0x8D, 0x00, M6800|M6801|M68HC11},
"callr",{REL, }, {0x00, 0x8D, 0x00, M6800|M6801|M68HC11}, /* bsr */
"bvc", {REL, }, {0x00, 0x28, 0x00, M6800|M6801|M68HC11},
"bvs", {REL, }, {0x00, 0x29, 0x00, M6800|M6801|M68HC11},
"cba", {INH, }, {0x00, 0x11, 0x00, M6800|M6801|M68HC11},
"clc", {INH, }, {0x00, 0x0C, 0x00, M6800|M6801|M68HC11},
"cli", {INH, }, {0x00, 0x0E, 0x00, M6800|M6801|M68HC11},
"ei", {INH, }, {0x00, 0x0E, 0x00, M6800|M6801|M68HC11}, /* cli */
"clr", {EXT, }, {0x00, 0x7F, 0x00, M6800|M6801|M68HC11},
"clr", {DIR, REGX }, {0x00, 0x00, 0x6F, M6800|M6801|M68HC11},
"clr", {DIR, REGY }, {0x18, 0x00, 0x6F, M68HC11},
"clra", {INH, }, {0x00, 0x4F, 0x00, M6800|M6801|M68HC11},
"clrb", {INH, }, {0x00, 0x5F, 0x00, M6800|M6801|M68HC11},
"clv", {INH, }, {0x00, 0x0A, 0x00, M6800|M6801|M68HC11},
"cmpa", {IMM }, {0x00, 0x81, 0x00, M6800|M6801|M68HC11},
"cmpa", {ADDR, }, {0x00, 0xB1, 0x91, M6800|M6801|M68HC11},
"cmpa", {DIR, REGX }, {0x00, 0x00, 0xA1, M6800|M6801|M68HC11},
"cmpa", {DIR, REGY }, {0x18, 0x00, 0xA1, M68HC11},
"cmpb", {IMM }, {0x00, 0xC1, 0x00, M6800|M6801|M68HC11},
"cmpb", {ADDR, }, {0x00, 0xF1, 0xD1, M6800|M6801|M68HC11},
"cmpb", {DIR, REGX }, {0x00, 0x00, 0xE1, M6800|M6801|M68HC11},
"cmpb", {DIR, REGY }, {0x18, 0x00, 0xE1, M68HC11},
"com", {EXT, }, {0x00, 0x73, 0x00, M6800|M6801|M68HC11},
"com", {DIR, REGX }, {0x00, 0x00, 0x63, M6800|M6801|M68HC11},
"com", {DIR, REGY }, {0x18, 0x00, 0x63, M68HC11},
"coma", {INH, }, {0x00, 0x43, 0x00, M6800|M6801|M68HC11},
"comb", {INH, }, {0x00, 0x53, 0x00, M6800|M6801|M68HC11},
"cpd", {IMM16 }, {0x1A, 0x83, 0x00, M68HC11},
"cpd", {ADDR, }, {0x1A, 0xB3, 0x93, M68HC11},
"cpd", {DIR, REGX }, {0x1A, 0x00, 0xA3, M68HC11},
"cpd", {DIR, REGY }, {0xCD, 0x00, 0xA3, M68HC11},
"cmpd", {IMM16 }, {0x1A, 0x83, 0x00, M68HC11}, /* cpd */
"cmpd", {ADDR, }, {0x1A, 0xB3, 0x93, M68HC11}, /* cpd */
"cmpd", {DIR, REGX }, {0x1A, 0x00, 0xA3, M68HC11}, /* cpd */
"cmpd", {DIR, REGY }, {0xCD, 0x00, 0xA3, M68HC11}, /* cpd */
"cpx", {IMM16 }, {0x00, 0x8C, 0x00, M6800|M6801|M68HC11},
"cpx", {ADDR, }, {0x00, 0xBC, 0x9C, M6800|M6801|M68HC11},
"cpx", {DIR, REGX }, {0x00, 0x00, 0xAC, M6800|M6801|M68HC11},
"cpx", {DIR, REGY }, {0xCD, 0x00, 0xAC, M68HC11},
"cmpx", {IMM16 }, {0x00, 0x8C, 0x00, M6800|M6801|M68HC11}, /* cpx */
"cmpx", {ADDR, }, {0x00, 0xBC, 0x9C, M6800|M6801|M68HC11}, /* cpx */
"cmpx", {DIR, REGX }, {0x00, 0x00, 0xAC, M6800|M6801|M68HC11}, /* cpx */
"cmpx", {DIR, REGY }, {0xCD, 0x00, 0xAC, M68HC11}, /* cpx */
"cpy", {IMM16 }, {0x18, 0x8C, 0x00, M68HC11},
"cpy", {ADDR, }, {0x18, 0xBC, 0x9C, M68HC11},
"cpy", {DIR, REGX }, {0x1A, 0x00, 0xAC, M68HC11},
"cpy", {DIR, REGY }, {0x18, 0x00, 0xAC, M68HC11},
"cmpy", {IMM16 }, {0x18, 0x8C, 0x00, M68HC11}, /* cpy */
"cmpy", {ADDR, }, {0x18, 0xBC, 0x9C, M68HC11}, /* cpy */
"cmpy", {DIR, REGX }, {0x1A, 0x00, 0xAC, M68HC11}, /* cpy */
"cmpy", {DIR, REGY }, {0x18, 0x00, 0xAC, M68HC11}, /* cpy */
"daa", {INH, }, {0x00, 0x19, 0x00, M6800|M6801|M68HC11},
"dec", {EXT, }, {0x00, 0x7A, 0x00, M6800|M6801|M68HC11},
"dec", {DIR, REGX }, {0x00, 0x00, 0x6A, M6800|M6801|M68HC11},
"dec", {DIR, REGY }, {0x18, 0x00, 0x6A, M68HC11},
"deca", {INH, }, {0x00, 0x4A, 0x00, M6800|M6801|M68HC11},
"decb", {INH, }, {0x00, 0x5A, 0x00, M6800|M6801|M68HC11},
"des", {INH, }, {0x00, 0x34, 0x00, M6800|M6801|M68HC11},
"decs", {INH, }, {0x00, 0x34, 0x00, M6800|M6801|M68HC11}, /* des */
"dex", {INH, }, {0x00, 0x09, 0x00, M6800|M6801|M68HC11},
"decx", {INH, }, {0x00, 0x09, 0x00, M6800|M6801|M68HC11}, /* dex */
"dey", {INH, }, {0x18, 0x09, 0x00, M68HC11},
"decy", {INH, }, {0x18, 0x09, 0x00, M68HC11}, /* dey */
"eora", {IMM, }, {0x00, 0x88, 0x00, M6800|M6801|M68HC11},
"eora", {ADDR, }, {0x00, 0xB8, 0x98, M6800|M6801|M68HC11},
"eora", {DIR, REGX }, {0x00, 0x00, 0xA8, M6800|M6801|M68HC11},
"eora", {DIR, REGY }, {0x18, 0x00, 0xA8, M68HC11},
"xora", {IMM, }, {0x00, 0x88, 0x00, M6800|M6801|M68HC11}, /* eora */
"xora", {ADDR, }, {0x00, 0xB8, 0x98, M6800|M6801|M68HC11}, /* eora */
"xora", {DIR, REGX }, {0x00, 0x00, 0xA8, M6800|M6801|M68HC11}, /* eora */
"xora", {DIR, REGY }, {0x18, 0x00, 0xA8, M68HC11}, /* eora */
"eorb", {IMM, }, {0x00, 0xC8, 0x00, M6800|M6801|M68HC11},
"eorb", {ADDR, }, {0x00, 0xF8, 0xD8, M6800|M6801|M68HC11},
"eorb", {DIR, REGX }, {0x00, 0x00, 0xE8, M6800|M6801|M68HC11},
"eorb", {DIR, REGY }, {0x18, 0x00, 0xE8, M68HC11},
"xorb", {IMM, }, {0x00, 0xC8, 0x00, M6800|M6801|M68HC11}, /* eorb */
"xorb", {ADDR, }, {0x00, 0xF8, 0xD8, M6800|M6801|M68HC11}, /* eorb */
"xorb", {DIR, REGX }, {0x00, 0x00, 0xE8, M6800|M6801|M68HC11}, /* eorb */
"xorb", {DIR, REGY }, {0x18, 0x00, 0xE8, M68HC11}, /* eorb */
"fdiv", {INH, }, {0x00, 0x03, 0x00, M68HC11},
"idiv", {INH, }, {0x00, 0x02, 0x00, M68HC11},
"inc", {EXT, }, {0x00, 0x7C, 0x00, M6800|M6801|M68HC11},
"inc", {DIR, REGX }, {0x00, 0x00, 0x6C, M6800|M6801|M68HC11},
"inc", {DIR, REGY }, {0x18, 0x00, 0x6C, M68HC11},
"inca", {INH, }, {0x00, 0x4C, 0x00, M6800|M6801|M68HC11},
"incb", {INH, }, {0x00, 0x5C, 0x00, M6800|M6801|M68HC11},
"ins", {INH, }, {0x00, 0x31, 0x00, M6800|M6801|M68HC11},
"incs", {INH, }, {0x00, 0x31, 0x00, M6800|M6801|M68HC11}, /* ins */
"inx", {INH, }, {0x00, 0x08, 0x00, M6800|M6801|M68HC11},
"incx", {INH, }, {0x00, 0x08, 0x00, M6800|M6801|M68HC11}, /* inx */
"iny", {INH, }, {0x18, 0x08, 0x00, M68HC11},
"incy", {INH, }, {0x18, 0x08, 0x00, M68HC11}, /* iny */
"jmp", {EXT, }, {0x00, 0x7E, 0x00, M6800|M6801|M68HC11},
"jmp", {DIR, REGX }, {0x00, 0x00, 0x6E, M6800|M6801|M68HC11},
"jmp", {DIR, REGY }, {0x18, 0x00, 0x6E, M68HC11},
"jsr", {ADDR, }, {0x00, 0xBD, 0x9D, M6800|M6801|M68HC11},
"jsr", {DIR, REGX }, {0x00, 0x00, 0xAD, M6800|M6801|M68HC11},
"jsr", {DIR, REGY }, {0x18, 0x00, 0xAD, M68HC11},
"call", {ADDR, }, {0x00, 0xBD, 0x9D, M6800|M6801|M68HC11}, /* jsr */
"call", {DIR, REGX }, {0x00, 0x00, 0xAD, M6800|M6801|M68HC11}, /* jsr */
"call", {DIR, REGY }, {0x18, 0x00, 0xAD, M68HC11}, /* jsr */
"lda", {IMM, }, {0x00, 0x86, 0x00, M6800|M6801|M68HC11},
"lda", {ADDR, }, {0x00, 0xB6, 0x96, M6800|M6801|M68HC11},
"lda", {DIR, REGX }, {0x00, 0x00, 0xA6, M6800|M6801|M68HC11},
"lda", {DIR, REGY }, {0x18, 0x00, 0xA6, M68HC11},
"ldaa", {IMM, }, {0x00, 0x86, 0x00, M6800|M6801|M68HC11},
"ldaa", {ADDR, }, {0x00, 0xB6, 0x96, M6800|M6801|M68HC11},
"ldaa", {DIR, REGX }, {0x00, 0x00, 0xA6, M6800|M6801|M68HC11},
"ldaa", {DIR, REGY }, {0x18, 0x00, 0xA6, M68HC11},
"ldb", {IMM, }, {0x00, 0xC6, 0x00, M6800|M6801|M68HC11},
"ldb", {ADDR, }, {0x00, 0xF6, 0xD6, M6800|M6801|M68HC11},
"ldb", {DIR, REGX }, {0x00, 0x00, 0xE6, M6800|M6801|M68HC11},
"ldb", {DIR, REGY }, {0x18, 0x00, 0xE6, M68HC11},
"ldab", {IMM, }, {0x00, 0xC6, 0x00, M6800|M6801|M68HC11},
"ldab", {ADDR, }, {0x00, 0xF6, 0xD6, M6800|M6801|M68HC11},
"ldab", {DIR, REGX }, {0x00, 0x00, 0xE6, M6800|M6801|M68HC11},
"ldab", {DIR, REGY }, {0x18, 0x00, 0xE6, M68HC11},
"ldd", {IMM16, }, {0x00, 0xCC, 0x00, M6801|M68HC11},
"ldd", {ADDR, }, {0x00, 0xFC, 0xDC, M6801|M68HC11},
"ldd", {DIR, REGX }, {0x00, 0x00, 0xEC, M6801|M68HC11},
"ldd", {DIR, REGY }, {0x18, 0x00, 0xEC, M68HC11},
"lds", {IMM16, }, {0x00, 0x8E, 0x00, M6800|M6801|M68HC11},
"lds", {ADDR, }, {0x00, 0xBE, 0x9E, M6800|M6801|M68HC11},
"lds", {DIR, REGX }, {0x00, 0x00, 0xAE, M6800|M6801|M68HC11},
"lds", {DIR, REGY }, {0x18, 0x00, 0xAE, M68HC11},
"ldx", {IMM16, }, {0x00, 0xCE, 0x00, M6800|M6801|M68HC11},
"ldx", {ADDR, }, {0x00, 0xFE, 0xDE, M6800|M6801|M68HC11},
"ldx", {DIR, REGX }, {0x00, 0x00, 0xEE, M6800|M6801|M68HC11},
"ldx", {DIR, REGY }, {0xCD, 0x00, 0xEE, M68HC11},
"ldy", {IMM16, }, {0x18, 0xCE, 0x00, M68HC11},
"ldy", {ADDR, }, {0x18, 0xFE, 0xDE, M68HC11},
"ldy", {DIR, REGX }, {0x1A, 0x00, 0xEE, M68HC11},
"ldy", {DIR, REGY }, {0x18, 0x00, 0xEE, M68HC11},
"lsl", {EXT, }, {0x00, 0x78, 0x00, M6800|M6801|M68HC11},
"lsl", {DIR, REGX }, {0x00, 0x00, 0x68, M6800|M6801|M68HC11},
"lsl", {DIR, REGY }, {0x18, 0x00, 0x68, M68HC11},
"lsla", {INH, }, {0x00, 0x48, 0x00, M6800|M6801|M68HC11},
"lslb", {INH, }, {0x00, 0x58, 0x00, M6800|M6801|M68HC11},
"lsld", {INH, }, {0x00, 0x05, 0x00, M6801|M68HC11},
"lsr", {EXT, }, {0x00, 0x74, 0x00, M6800|M6801|M68HC11},
"lsr", {DIR, REGX }, {0x00, 0x00, 0x64, M6800|M6801|M68HC11},
"lsr", {DIR, REGY }, {0x18, 0x00, 0x64, M68HC11},
"lsra", {INH, }, {0x00, 0x44, 0x00, M6800|M6801|M68HC11},
"lsrb", {INH, }, {0x00, 0x54, 0x00, M6800|M6801|M68HC11},
"lsrd", {INH, }, {0x00, 0x04, 0x00, M6801|M68HC11},
"mul", {INH, }, {0x00, 0x3D, 0x00, M6801|M68HC11},
"neg", {EXT, }, {0x00, 0x70, 0x00, M6800|M6801|M68HC11},
"neg", {DIR, REGX }, {0x00, 0x00, 0x60, M6800|M6801|M68HC11},
"neg", {DIR, REGY }, {0x18, 0x00, 0x60, M68HC11},
"nega", {INH, }, {0x00, 0x40, 0x00, M6800|M6801|M68HC11},
"negb", {INH, }, {0x00, 0x50, 0x00, M6800|M6801|M68HC11},
"nop", {INH, }, {0x00, 0x01, 0x00, M6800|M6801|M68HC11},
"oraa", {IMM, }, {0x00, 0x8A, 0x00, M6800|M6801|M68HC11},
"oraa", {ADDR, }, {0x00, 0xBA, 0x9A, M6800|M6801|M68HC11},
"oraa", {DIR, REGX }, {0x00, 0x00, 0xAA, M6800|M6801|M68HC11},
"oraa", {DIR, REGY }, {0x18, 0x00, 0xAA, M68HC11},
"orab", {IMM, }, {0x00, 0xCA, 0x00, M6800|M6801|M68HC11},
"orab", {ADDR, }, {0x00, 0xFA, 0xDA, M6800|M6801|M68HC11},
"orab", {DIR, REGX }, {0x00, 0x00, 0xEA, M6800|M6801|M68HC11},
"orab", {DIR, REGY }, {0x18, 0x00, 0xEA, M68HC11},
"psha", {INH, }, {0x00, 0x36, 0x00, M6800|M6801|M68HC11},
"pusha",{INH, }, {0x00, 0x36, 0x00, M6800|M6801|M68HC11}, /* psha */
"pshb", {INH, }, {0x00, 0x37, 0x00, M6800|M6801|M68HC11},
"pushb",{INH, }, {0x00, 0x37, 0x00, M6800|M6801|M68HC11}, /* pshb */
"pshx", {INH, }, {0x00, 0x3C, 0x00, M6801|M68HC11},
"pushx",{INH, }, {0x00, 0x3C, 0x00, M6801|M68HC11}, /* pshx */
"pshy", {INH, }, {0x18, 0x3C, 0x00, M68HC11},
"pushy", {INH, }, {0x18, 0x3C, 0x00, M68HC11}, /* pshy */
"pula", {INH, }, {0x00, 0x32, 0x00, M6800|M6801|M68HC11},
"popa", {INH, }, {0x00, 0x32, 0x00, M6800|M6801|M68HC11}, /* pula */
"pulb", {INH, }, {0x00, 0x33, 0x00, M6800|M6801|M68HC11},
"popb", {INH, }, {0x00, 0x33, 0x00, M6800|M6801|M68HC11}, /* pulb */
"pulx", {INH, }, {0x00, 0x38, 0x00, M6801|M68HC11},
"popx", {INH, }, {0x00, 0x38, 0x00, M6801|M68HC11}, /* pulx */
"puly", {INH, }, {0x18, 0x38, 0x00, M68HC11},
"popy", {INH, }, {0x18, 0x38, 0x00, M68HC11}, /* puly */
"rol", {EXT, }, {0x00, 0x79, 0x00, M6800|M6801|M68HC11},
"rol", {DIR, REGX }, {0x00, 0x00, 0x69, M6800|M6801|M68HC11},
"rol", {DIR, REGY }, {0x18, 0x00, 0x69, M68HC11},
"rola", {INH, }, {0x00, 0x49, 0x00, M6800|M6801|M68HC11},
"rolb", {INH, }, {0x00, 0x59, 0x00, M6800|M6801|M68HC11},
"ror", {EXT, }, {0x00, 0x76, 0x00, M6800|M6801|M68HC11},
"ror", {DIR, REGX }, {0x00, 0x00, 0x66, M6800|M6801|M68HC11},
"ror", {DIR, REGY }, {0x18, 0x00, 0x66, M68HC11},
"rora", {INH, }, {0x00, 0x46, 0x00, M6800|M6801|M68HC11},
"rorb", {INH, }, {0x00, 0x56, 0x00, M6800|M6801|M68HC11},
"rti", {INH, }, {0x00, 0x3B, 0x00, M6800|M6801|M68HC11},
"reti", {INH, }, {0x00, 0x3B, 0x00, M6800|M6801|M68HC11}, /* rti */
"rts", {INH, }, {0x00, 0x39, 0x00, M6800|M6801|M68HC11},
"ret", {INH, }, {0x00, 0x39, 0x00, M6800|M6801|M68HC11}, /* rts */
"sba", {INH, }, {0x00, 0x10, 0x00, M6800|M6801|M68HC11},
"sbca", {IMM, }, {0x00, 0x82, 0x00, M6800|M6801|M68HC11},
"sbca", {ADDR, }, {0x00, 0xB2, 0x92, M6800|M6801|M68HC11},
"sbca", {DIR, REGX }, {0x00, 0x00, 0xA2, M6800|M6801|M68HC11},
"sbca", {DIR, REGY }, {0x18, 0x00, 0xA2, M68HC11},
"sbcb", {IMM, }, {0x00, 0xC2, 0x00, M6800|M6801|M68HC11},
"sbcb", {ADDR, }, {0x00, 0xF2, 0xD2, M6800|M6801|M68HC11},
"sbcb", {DIR, REGX }, {0x00, 0x00, 0xE2, M6800|M6801|M68HC11},
"sbcb", {DIR, REGY }, {0x18, 0x00, 0xE2, M68HC11},
"sec", {INH, }, {0x00, 0x0D, 0x00, M6800|M6801|M68HC11},
"sei", {INH, }, {0x00, 0x0F, 0x00, M6800|M6801|M68HC11},
"di", {INH, }, {0x00, 0x0F, 0x00, M6800|M6801|M68HC11}, /* sei */
"sev", {INH, }, {0x00, 0x0B, 0x00, M6800|M6801|M68HC11},
"staa", {ADDR, }, {0x00, 0xB7, 0x97, M6800|M6801|M68HC11},
"staa", {DIR, REGX }, {0x00, 0x00, 0xA7, M6800|M6801|M68HC11},
"staa", {DIR, REGY }, {0x18, 0x00, 0xA7, M68HC11},
"stab", {ADDR, }, {0x00, 0xF7, 0xD7, M6800|M6801|M68HC11},
"stab", {DIR, REGX }, {0x00, 0x00, 0xE7, M6800|M6801|M68HC11},
"stab", {DIR, REGY }, {0x18, 0x00, 0xE7, M68HC11},
"std", {ADDR, }, {0x00, 0xFD, 0xDD, M6801|M68HC11},
"std", {DIR, REGX }, {0x00, 0x00, 0xED, M6801|M68HC11},
"std", {DIR, REGY }, {0x18, 0x00, 0xED, M68HC11},
"stop", {INH, }, {0x00, 0xCF, 0x00, M68HC11},
"sts", {ADDR, }, {0x00, 0xBF, 0x9F, M6800|M6801|M68HC11},
"sts", {DIR, REGX }, {0x00, 0x00, 0xAF, M6800|M6801|M68HC11},
"sts", {DIR, REGY }, {0x18, 0x00, 0xAF, M68HC11},
"stx", {ADDR, }, {0x00, 0xFF, 0xDF, M6800|M6801|M68HC11},
"stx", {DIR, REGX }, {0x00, 0x00, 0xEF, M6800|M6801|M68HC11},
"stx", {DIR, REGY }, {0xCD, 0x00, 0xEF, M68HC11},
"sty", {ADDR, }, {0x18, 0xFF, 0xDF, M68HC11},
"sty", {DIR, REGX }, {0x1A, 0x00, 0xEF, M68HC11},
"sty", {DIR, REGY }, {0x18, 0x00, 0xEF, M68HC11},
"suba", {IMM, }, {0x00, 0x80, 0x00, M6800|M6801|M68HC11},
"suba", {ADDR, }, {0x00, 0xB0, 0x90, M6800|M6801|M68HC11},
"suba", {DIR, REGX }, {0x00, 0x00, 0xA0, M6800|M6801|M68HC11},
"suba", {DIR, REGY }, {0x18, 0x00, 0xA0, M68HC11},
"subb", {IMM, }, {0x00, 0xC0, 0x00, M6800|M6801|M68HC11},
"subb", {ADDR, }, {0x00, 0xF0, 0xD0, M6800|M6801|M68HC11},
"subb", {DIR, REGX }, {0x00, 0x00, 0xE0, M6800|M6801|M68HC11},
"subb", {DIR, REGY }, {0x18, 0x00, 0xE0, M68HC11},
"subd", {IMM16, }, {0x00, 0x83, 0x00, M6801|M68HC11},
"subd", {ADDR, }, {0x00, 0xB3, 0x93, M6801|M68HC11},
"subd", {DIR, REGX }, {0x00, 0x00, 0xA3, M6801|M68HC11},
"subd", {DIR, REGY }, {0x18, 0x00, 0xA3, M68HC11},
"swi", {INH, }, {0x00, 0x3F, 0x00, M6800|M6801|M68HC11},
"tab", {INH, }, {0x00, 0x16, 0x00, M6800|M6801|M68HC11},
"tap", {INH, }, {0x00, 0x06, 0x00, M6800|M6801|M68HC11},
"tba", {INH, }, {0x00, 0x17, 0x00, M6800|M6801|M68HC11},
"test", {INH, }, {0x00, 0x00, 0x00, M68HC11},
"tpa", {INH, }, {0x00, 0x07, 0x00, M6800|M6801|M68HC11},
"tst", {EXT, }, {0x00, 0x7D, 0x00, M6800|M6801|M68HC11},
"tst", {DIR, REGX }, {0x00, 0x00, 0x6D, M6800|M6801|M68HC11},
"tst", {DIR, REGY }, {0x18, 0x00, 0x6D, M68HC11},
"tsta", {INH, }, {0x00, 0x4D, 0x00, M6800|M6801|M68HC11},
"tstb", {INH, }, {0x00, 0x5D, 0x00, M6800|M6801|M68HC11},
"tsx", {INH, }, {0x00, 0x30, 0x00, M6800|M6801|M68HC11},
"tsy", {INH, }, {0x18, 0x30, 0x00, M68HC11},
"txs", {INH, }, {0x00, 0x35, 0x00, M6800|M6801|M68HC11},
"tys", {INH, }, {0x18, 0x35, 0x00, M68HC11},
"wai", {INH, }, {0x00, 0x3E, 0x00, M6800|M6801|M68HC11},
"xgdx", {INH, }, {0x00, 0x8F, 0x00, M68HC11},
"xgdy", {INH, }, {0x18, 0x8F, 0x00, M68HC11},

1751
vasm-1/cpus/arm/cpu.c Normal file

File diff suppressed because it is too large Load Diff

214
vasm-1/cpus/arm/cpu.h Normal file
View File

@ -0,0 +1,214 @@
/* cpu.h ARM cpu-description header-file */
/* (c) in 2004,2014,2016 by Frank Wille */
#define LITTLEENDIAN (!arm_be_mode)
#define BIGENDIAN (arm_be_mode)
#define VASM_CPU_ARM 1
/* maximum number of operands in one mnemonic */
#define MAX_OPERANDS 6
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 2
/* but no qualifiers for macros */
#define NO_MACRO_QUALIFIERS
/* valid parentheses for cpu's operands */
#define START_PARENTH(x) ((x)=='(' || (x)=='{')
#define END_PARENTH(x) ((x)==')' || (x)=='}')
/* data type to represent a target-address */
typedef int32_t taddr;
typedef uint32_t utaddr;
/* minimum instruction alignment */
#define INST_ALIGN 0 /* Handled internally! */
/* default alignment for n-bit data */
#define DATA_ALIGN(n) ((n)<=8 ? 1 : ((n)<=16 ? 2 : 4))
/* operand class for n-bit data definitions */
#define DATA_OPERAND(n) (n==64 ? DATA64_OP : DATA_OP)
/* returns true when instruction is valid for selected cpu */
#define MNEMONIC_VALID(i) cpu_available(i)
/* type to store each operand */
typedef struct {
uint16_t type; /* type of operand from mnemonic.operand_type */
uint16_t flags; /* see below */
expr *value; /* single register, immed. val. or branch loc.*/
} operand;
/* flags: */
#define OFL_SHIFTOP (0x0003) /* mask for shift-operation */
#define OFL_IMMEDSHIFT (0x0004) /* uses immediate shift value */
#define OFL_WBACK (0x0008) /* set write-back flag in opcode */
#define OFL_UP (0x0010) /* set up-flag, add offset to base */
#define OFL_SPSR (0x0020) /* 1:SPSR, 0:CPSR */
#define OFL_FORCE (0x0040) /* LDM/STM PSR & force user bit */
/* operand types - WARNING: the order is important! See defines below. */
enum {
/* ARM operands */
NOOP=0,
DATA_OP, /* data operand */
DATA64_OP, /* 64-bit data operand (greater than taddr) */
BRA24, /* 24-bit branch offset to label */
PCL12, /* 12-bit PC-relative offset with up/down-flag to label */
PCLCP, /* 8-bit * 4 PC-relative offset with up/down-flag to label */
PCLRT, /* 8-bit rotated PC-relative offset to label */
CPOP4, /* 4-bit coprocessor operation code at 23..20 */
CPOP3, /* 3-bit coprocessor operation code at 23..21 */
CPTYP, /* 3-bit coprocessor operation type at 7..5 */
SWI24, /* 24-bit immediate at 23..0 (SWI instruction) */
IROTV, /* explicit 4-bit rotate value at 11..8 */
REG03, /* Rn at 3..0 */
REG11, /* Rn at 11..8 */
REG15, /* Rn at 15..12 */
REG19, /* Rn at 19..16 */
R19WB, /* Rn at 19..16 with optional write-back '!' */
R19PR, /* [Rn, pre-indexed at 19..16 */
R19PO, /* [Rn], post-indexed or indir. without index, at 19..16 */
R3UD1, /* +/-Rn], pre-indexed at 3..0 with optional write-back '!' */
R3UD2, /* +/-Rn, at 3..0, pre- or post-indexed */
IMUD1, /* #+/-Imm12] pre-indexed with ']' and optional w-back '!' */
IMUD2, /* #+/-Imm12 post-indexed */
IMCP1, /* #+/-Imm10>>2 pre-indexed with ']' and optional w-back '!' */
IMCP2, /* #+/-Imm10>>2 post-indexed */
IMMD8, /* #Immediate, 8-bit */
IMROT, /* #Imm32, 8-bit auto-rotated */
SHIFT, /* <shift-op> Rs | <shift-op> #Imm5 | RRX = ROR #0 */
SHIM1, /* <shift-op> #Imm5 | RRX, pre-indexed with terminating ] or ]! */
SHIM2, /* <shift-op> #Imm5 | RRX, post-indexed */
CSPSR, /* CPSR or SPSR */
PSR_F, /* PSR-field: SPSR_<field>, CPSR_<field> */
RLIST, /* register list */
/* THUMB operands */
TRG02, /* Rn at 2..0 */
TRG05, /* Rn at 5..3 */
TRG08, /* Rn at 8..6 */
TRG10, /* Rn at 10..8 */
THR02, /* Hi-Rn at 2..0 */
THR05, /* Hi-Rn at 5..3 */
TR5IN, /* [Rn at 5..3 */
TR8IN, /* Rn] at 8..6 */
TR10W, /* Rn! at 10..8 with write-back '!' */
TPCRG, /* "PC" */
TSPRG, /* "SP" */
TPCPR, /* "[PC" */
TSPPR, /* "[SP" */
TRLST, /* register list for r0-r7 */
TRLLR, /* extended register list, includes LR */
TRLPC, /* extended register list, includes PC */
TUIM3, /* 3-bit unsigned immediate at 8..6 */
TUIM5, /* 5-bit unsigned immediate at 10..6 */
TUIM8, /* 8-bit unsigned immediate at 7..0 */
TUIM9, /* 9-bit unsigned immediate >> 2 at 6..0 */
TUIMA, /* 10-bit unsigned immediate >> 2 at 7..0 */
TUI5I, /* 5-bit unsigned immediate at 10..6 with terminating ] */
TUI6I, /* 6-bit unsigned immediate >> 1 at 10..6 with terminating ] */
TUI7I, /* 7-bit unsigned immediate >> 2 at 10..6 with terminating ] */
TUIAI, /* 10-bit unsigned immediate >> 2 at 7..0 with terminating ] */
TSWI8, /* 8-bit immediate at 7..0 (SWI instruction) */
TPCLW, /* PC-relative label, has to fit into 10-bit uns.imm. >> 2 */
TBR08, /* 9-bit branch offset >> 1 to label at 7..0 */
TBR11, /* 12-bit branch offset >> 1 to label at 10..0 */
TBRHL /* 23-bit branch offset >> 1 splitted into two 11-bit instr. */
};
#define ARMOPER(x) ((x)>=BRA24 && (x)<=RLIST)
#define STDOPER(x) ((x)>=DATA_OP && (x)<=IMROT)
#define CPOPCODE(x) ((x)>=CPOP4 && (x)<=CPTYP)
#define REGOPER(x) ((x)>=REG03 && (x)<=R3UD2)
#define REG19OPER(x) ((x)>=REG19 && (x)<=R19PO)
#define REG15OPER(x) ((x)==REG15)
#define REG11OPER(x) ((x)==REG11)
#define REG03OPER(x) ((x)==REG03 || (x)==R3UD1 || (x)==R3UD2)
#define UPDOWNOPER(x) ((x)>=R3UD1 && (x)<=IMCP2)
#define IMMEDOPER(x) ((x)>=IMUD1 && (x)<=IMROT)
#define SHIFTOPER(x) ((x)>=SHIFT && (x)<=SHIM2)
#define THUMBOPER(x) ((x)==0 || (x)>=TRG02)
#define THREGOPER(x) ((x)>=TRG02 && (x)<=TSPPR)
#define THPCORSP(x) ((x)>=TPCRG && (x)<=TSPPR)
#define THREGLIST(x) ((x)>=TRLST && (x)<=TRLPC)
#define THIMMOPER(x) ((x)>=TUIM3 && (x)<=TUIAI)
#define THIMMINDIR(x) ((x)>=TUI5I && (x)<=TUIAI)
#define THBRANCH(x) ((x)>=TBR08 && (x)<=TBRHL)
/* additional mnemonic data */
typedef struct {
uint32_t opcode;
uint32_t available;
uint32_t flags;
} mnemonic_extension;
/* flags: */
#define DIFR19 (0x00000001) /* DIFFRxx registers must be different */
#define DIFR15 (0x00000002)
#define DIFR11 (0x00000004)
#define DIFR03 (0x00000008)
#define NOPC (0x00000010) /* R15 is not allowed as source or dest. */
#define NOPCR03 (0x00000020) /* R15 is not allowed for Rm (3..0) */
#define NOPCWB (0x00000040) /* R15 is not allowed in Write-Back mode */
#define SETCC (0x00000100) /* instruction supports S-bit */
#define SETPSR (0x00000200) /* instruction supports P-bit */
#define THUMB (0x10000000) /* THUMB instruction */
/* register symbols */
#define HAVE_REGSYMS
#define REGSYMHTSIZE 256
/* cpu types for availability check */
#define ARM2 (1L<<0)
#define ARM250 (1L<<1)
#define ARM3 (1L<<2)
#define ARM6 (1L<<3)
#define ARM60 (1L<<4)
#define ARM600 (1L<<5)
#define ARM610 (1L<<6)
#define ARM7 (1L<<7)
#define ARM710 (1L<<8)
#define ARM7500 (1L<<9)
#define ARM7d (1L<<10)
#define ARM7di (1L<<11)
#define ARM7dm (1L<<12)
#define ARM7dmi (1L<<13)
#define ARM7tdmi (1L<<14)
#define ARM8 (1L<<15)
#define ARM810 (1L<<16)
#define ARM9 (1L<<17)
#define ARM920 (1L<<18)
#define ARM920t (1L<<19)
#define ARM9tdmi (1L<<20)
#define SA1 (1L<<21)
#define STRONGARM (1L<<22)
#define STRONGARM110 (1L<<23)
#define STRONGARM1100 (1L<<24)
/* ARM architectures */
#define AA2 (ARM2|ARM250|ARM3)
#define AA3 (ARM6|ARM60|ARM600|ARM610|ARM7|ARM710|ARM7500|ARM7d|ARM7di)
#define AA3M (ARM7dm|ARM7dmi)
#define AA4 (ARM8|ARM810|ARM9|ARM920|SA1|STRONGARM|STRONGARM110|STRONGARM1100)
#define AA4T (ARM7tdmi|ARM920t|ARM9tdmi)
#define AA4TUP (AA4T)
#define AA4UP (AA4|AA4T)
#define AA3MUP (AA3M|AA4|AA4T)
#define AA3UP (AA3|AA3M|AA4|AA4T)
#define AA2UP (AA2|AA3|AA3M|AA4|AA4T)
#define AAANY (~0)
/* exported by cpu.c */
extern int arm_be_mode;
int cpu_available(int);

View File

@ -0,0 +1,31 @@
"instruction not supported on selected architecture",ERROR,
"trailing garbage in operand",WARNING,
"label from current section required",ERROR,
"branch offset (%ld) is out of range",ERROR,
"PC-relative load/store (offset %ld) out of range",ERROR,
"cannot make rotated immediate from PC-relative offset (0x%lx)",ERROR,/*05*/
"constant integer expression required",ERROR,
"constant (0x%lx) not suitable for 8-bit rotated immediate",ERROR,
"branch to an unaligned address (offset %ld)",ERROR,
"not a valid ARM register",ERROR,
"PC (r15) not allowed in this mode",ERROR, /*10*/
"PC (r15) not allowed for offset register Rm",ERROR,
"PC (r15) not allowed with write-back",ERROR,
"register r%ld was used multiple times",ERROR,
"illegal immediate shift count (%ld)",ERROR,
"not a valid shift register",ERROR, /*15*/
"24-bit unsigned immediate expected",ERROR,
"data size %d not supported",ERROR,
"illegal addressing mode: %s",ERROR,
"signed/halfword ldr/str doesn't support shifts",ERROR,
"%d-bit immediate offset out of range (%ld)",ERROR, /*20*/
"post-indexed addressing mode exptected",ERROR,
"operation not allowed on external symbols",ERROR,
"ldc/stc offset has to be a multiple of 4",ERROR,
"illegal coprocessor operation mode or type: %ld\n",ERROR,
"%d-bit unsigned immediate offset out of range (%ld)",ERROR, /*25*/
"offset has to be a multiple of %d",ERROR,
"instruction at unaligned address",ERROR,
"TSTP/TEQP/CMNP/CMPP deprecated on 32-bit architectures",WARNING,
"rotate constant must be an even number between 0 and 30: %ld",ERROR,
"%d-bit unsigned constant required: %ld",ERROR, /*30*/

201
vasm-1/cpus/arm/opcodes.h Normal file
View File

@ -0,0 +1,201 @@
"add", {REG15,REG19,IMROT}, {0x02800000,AAANY,SETCC},
"add", {REG15,REG19,IMMD8,IROTV}, {0x02800000,AAANY,SETCC},
"add", {REG15,REG19,REG03}, {0x00800000,AAANY,SETCC},
"add", {REG15,REG19,REG03,SHIFT}, {0x00800000,AAANY,SETCC},
"add", {TRG02,TRG05,TRG08}, {0x1800,AA4TUP,THUMB},
"add", {TRG02,TRG05,TUIM3}, {0x1c00,AA4TUP,THUMB},
"add", {TRG10,TUIM8}, {0x3000,AA4TUP,THUMB},
"add", {TRG02,THR05}, {0x4440,AA4TUP,THUMB},
"add", {THR02,TRG05}, {0x4480,AA4TUP,THUMB},
"add", {THR02,THR05}, {0x44c0,AA4TUP,THUMB},
"add", {TRG10,TPCRG,TUIMA}, {0xa000,AA4TUP,THUMB},
"add", {TRG10,TSPRG,TUIMA}, {0xa800,AA4TUP,THUMB},
"add", {TSPRG,TUIM9}, {0xb000,AA4TUP,THUMB},
"adc", {REG15,REG19,IMROT}, {0x02a00000,AAANY,SETCC},
"adc", {REG15,REG19,IMMD8,IROTV}, {0x02a00000,AAANY,SETCC},
"adc", {REG15,REG19,REG03}, {0x00a00000,AAANY,SETCC},
"adc", {REG15,REG19,REG03,SHIFT}, {0x00a00000,AAANY,SETCC},
"adc", {TRG02,TRG05}, {0x4140,AA4TUP,THUMB},
"adr", {REG15,PCLRT}, {0x028f0000,AAANY,0},
"adr", {TRG10,TPCLW}, {0xa000,AA4TUP,THUMB},
"and", {REG15,REG19,IMROT}, {0x02000000,AAANY,SETCC},
"and", {REG15,REG19,IMMD8,IROTV}, {0x02000000,AAANY,SETCC},
"and", {REG15,REG19,REG03}, {0x00000000,AAANY,SETCC},
"and", {REG15,REG19,REG03,SHIFT}, {0x00000000,AAANY,SETCC},
"and", {TRG02,TRG05}, {0x4000,AA4TUP,THUMB},
"asr", {TRG02,TRG05,TUIM5}, {0x1000,AA4TUP,THUMB},
"asr", {TRG02,TRG05}, {0x4100,AA4TUP,THUMB},
"b", {BRA24}, {0x0a000000,AAANY,0},
"b", {TBR11}, {0xe000,AA4TUP,THUMB},
"beq", {TBR08}, {0xd000,AA4TUP,THUMB},
"bne", {TBR08}, {0xd100,AA4TUP,THUMB},
"bcs", {TBR08}, {0xd200,AA4TUP,THUMB},
"bcc", {TBR08}, {0xd300,AA4TUP,THUMB},
"bmi", {TBR08}, {0xd400,AA4TUP,THUMB},
"bpl", {TBR08}, {0xd500,AA4TUP,THUMB},
"bvs", {TBR08}, {0xd600,AA4TUP,THUMB},
"bvc", {TBR08}, {0xd700,AA4TUP,THUMB},
"bhi", {TBR08}, {0xd800,AA4TUP,THUMB},
"bls", {TBR08}, {0xd900,AA4TUP,THUMB},
"bge", {TBR08}, {0xda00,AA4TUP,THUMB},
"blt", {TBR08}, {0xdb00,AA4TUP,THUMB},
"bgt", {TBR08}, {0xdc00,AA4TUP,THUMB},
"ble", {TBR08}, {0xdd00,AA4TUP,THUMB},
"bhs", {TBR08}, {0xd200,AA4TUP,THUMB},
"blo", {TBR08}, {0xd300,AA4TUP,THUMB},
"bul", {TBR08}, {0xd300,AA4TUP,THUMB},
"bic", {REG15,REG19,IMROT}, {0x03c00000,AAANY,SETCC},
"bic", {REG15,REG19,IMMD8,IROTV}, {0x03c00000,AAANY,SETCC},
"bic", {REG15,REG19,REG03}, {0x01c00000,AAANY,SETCC},
"bic", {REG15,REG19,REG03,SHIFT}, {0x01c00000,AAANY,SETCC},
"bic", {TRG02,TRG05}, {0x4380,AA4TUP,THUMB},
"bl", {BRA24}, {0x0b000000,AAANY,0},
"bl", {TBRHL}, {0xf000,AA4TUP,THUMB},
"bx", {REG03}, {0x012fff10,AA4TUP,NOPC},
"bx", {TRG05}, {0x4700,AA4TUP,THUMB},
"bx", {THR05}, {0x4740,AA4TUP,THUMB},
"cdp", {REG11,CPOP4,REG15,REG19,REG03}, {0x0e000000,AA2UP,0},
"cdp", {REG11,CPOP4,REG15,REG19,REG03,CPTYP},{0x0e000000,AA2UP,0},
"cmn", {REG19,IMROT}, {0x03700000,AAANY,SETPSR},
"cmn", {REG19,IMMD8,IROTV}, {0x03700000,AAANY,SETPSR},
"cmn", {REG19,REG03}, {0x01700000,AAANY,SETPSR},
"cmn", {REG19,REG03,SHIFT}, {0x01700000,AAANY,SETPSR},
"cmn", {TRG02,TRG05}, {0x42c0,AA4TUP,THUMB},
"cmp", {REG19,IMROT}, {0x03500000,AAANY,SETPSR},
"cmp", {REG19,IMMD8,IROTV}, {0x03500000,AAANY,SETPSR},
"cmp", {REG19,REG03}, {0x01500000,AAANY,SETPSR},
"cmp", {REG19,REG03,SHIFT}, {0x01500000,AAANY,SETPSR},
"cmp", {TRG10,TUIM8}, {0x2800,AA4TUP,THUMB},
"cmp", {TRG02,TRG05}, {0x4280,AA4TUP,THUMB},
"cmp", {TRG02,THR05}, {0x4540,AA4TUP,THUMB},
"cmp", {THR02,TRG05}, {0x4580,AA4TUP,THUMB},
"cmp", {THR02,THR05}, {0x45c0,AA4TUP,THUMB},
"eor", {REG15,REG19,IMROT}, {0x02200000,AAANY,SETCC},
"eor", {REG15,REG19,IMMD8,IROTV}, {0x02200000,AAANY,SETCC},
"eor", {REG15,REG19,REG03}, {0x00200000,AAANY,SETCC},
"eor", {REG15,REG19,REG03,SHIFT}, {0x00200000,AAANY,SETCC},
"eor", {TRG02,TRG05}, {0x4040,AA4TUP,THUMB},
"ldc", {REG11,REG15,PCLCP}, {0x0d1f0000,AA2UP,0},
"ldc", {REG11,REG15,R19PR,IMCP1}, {0x0d100000,AA2UP,0},
"ldc", {REG11,REG15,R19PO}, {0x0d100000,AA2UP,0},
"ldc", {REG11,REG15,R19PO,IMCP2}, {0x0c100000,AA2UP,0},
"ldm", {R19WB,RLIST}, {0x08100000,AAANY,NOPC},
"ldmia",{TR10W,TRLST}, {0xc800,AA4TUP,THUMB},
"ldr", {REG15,PCL12}, {0x051f0000,AAANY,NOPCWB},
"ldr", {REG15,R19PR,IMUD1}, {0x05100000,AAANY,NOPCWB},
"ldr", {REG15,R19PR,R3UD1}, {0x07100000,AAANY,NOPCWB|NOPCR03},
"ldr", {REG15,R19PR,R3UD2,SHIM1}, {0x07100000,AAANY,NOPCWB|NOPCR03},
"ldr", {REG15,R19PO}, {0x05900000,AAANY,NOPCWB},
"ldr", {REG15,R19PO,IMUD2}, {0x04100000,AAANY,NOPCWB},
"ldr", {REG15,R19PO,R3UD2}, {0x06100000,AAANY,NOPCWB|NOPCR03},
"ldr", {REG15,R19PO,R3UD2,SHIM2}, {0x06100000,AAANY,NOPCWB|NOPCR03},
"ldr", {TRG10,TPCLW}, {0x4800,AA4TUP,THUMB},
"ldr", {TRG10,TPCPR,TUIAI}, {0x4800,AA4TUP,THUMB},
"ldr", {TRG02,TR5IN,TR8IN}, {0x5800,AA4TUP,THUMB},
"ldr", {TRG02,TR5IN,TUI7I}, {0x6800,AA4TUP,THUMB},
"ldr", {TRG10,TSPPR,TUIAI}, {0x9800,AA4TUP,THUMB},
"ldrb", {TRG02,TR5IN,TR8IN}, {0x5c00,AA4TUP,THUMB},
"ldrb", {TRG02,TR5IN,TUI5I}, {0x7800,AA4TUP,THUMB},
"ldrh", {TRG02,TR5IN,TR8IN}, {0x5a00,AA4TUP,THUMB},
"ldrh", {TRG02,TR5IN,TUI6I}, {0x8800,AA4TUP,THUMB},
"ldsb", {TRG02,TR5IN,TR8IN}, {0x5600,AA4TUP,THUMB},
"ldsh", {TRG02,TR5IN,TR8IN}, {0x5e00,AA4TUP,THUMB},
"lsl", {TRG02,TRG05,TUIM5}, {0x0000,AA4TUP,THUMB},
"lsl", {TRG02,TRG05}, {0x4080,AA4TUP,THUMB},
"lsr", {TRG02,TRG05,TUIM5}, {0x0800,AA4TUP,THUMB},
"lsr", {TRG02,TRG05}, {0x40c0,AA4TUP,THUMB},
"mcr", {REG11,CPOP3,REG15,REG19,REG03}, {0x0e000010,AA2UP,0},
"mcr", {REG11,CPOP3,REG15,REG19,REG03,CPTYP},{0x0e000010,AA2UP,0},
"mov", {REG15,IMROT}, {0x03a00000,AAANY,SETCC},
"mov", {REG15,IMMD8,IROTV}, {0x03a00000,AAANY,SETCC},
"mov", {REG15,REG03}, {0x01a00000,AAANY,SETCC},
"mov", {REG15,REG03,SHIFT}, {0x01a00000,AAANY,SETCC},
"mov", {TRG10,TUIM8}, {0x2000,AA4TUP,THUMB},
"mov", {TRG02,TRG05}, {0x1c00,AA4TUP,THUMB},
"mov", {TRG02,THR05}, {0x4640,AA4TUP,THUMB},
"mov", {THR02,TRG05}, {0x4680,AA4TUP,THUMB},
"mov", {THR02,THR05}, {0x46c0,AA4TUP,THUMB},
"mrc", {REG11,CPOP3,REG15,REG19,REG03}, {0x0e100010,AA2UP,0},
"mrc", {REG11,CPOP3,REG15,REG19,REG03,CPTYP},{0x0e100010,AA2UP,0},
"mrs", {REG15,CSPSR}, {0x01000000,AA3UP,NOPC},
"mla", {REG19,REG03,REG11,REG15}, {0x00200090,AA2UP,SETCC|NOPC|DIFR19|DIFR03},
"msr", {PSR_F,IMROT}, {0x0320f000,AA3UP,0},
"msr", {PSR_F,IMMD8,IROTV}, {0x0320f000,AA3UP,0},
"msr", {PSR_F,REG03}, {0x0120f000,AA3UP,NOPC},
"mul", {REG19,REG03,REG11}, {0x00000090,AA2UP,SETCC|NOPC|DIFR19|DIFR03},
"mul", {TRG02,TRG05}, {0x4340,AA4TUP,THUMB},
"mvn", {REG15,IMROT}, {0x03e00000,AAANY,SETCC},
"mvn", {REG15,IMMD8,IROTV}, {0x03e00000,AAANY,SETCC},
"mvn", {REG15,REG03}, {0x01e00000,AAANY,SETCC},
"mvn", {REG15,REG03,SHIFT}, {0x01e00000,AAANY,SETCC},
"mvn", {TRG02,TRG05}, {0x43c0,AA4TUP,THUMB},
"neg", {TRG02,TRG05}, {0x4240,AA4TUP,THUMB},
"nop", {0}, {0x01a00000,AAANY,0},
"orr", {REG15,REG19,IMROT}, {0x03800000,AAANY,SETCC},
"orr", {REG15,REG19,IMMD8,IROTV}, {0x03800000,AAANY,SETCC},
"orr", {REG15,REG19,REG03}, {0x01800000,AAANY,SETCC},
"orr", {REG15,REG19,REG03,SHIFT}, {0x01800000,AAANY,SETCC},
"orr", {TRG02,TRG05}, {0x4300,AA4TUP,THUMB},
"pop", {TRLPC}, {0xbc00,AA4TUP,THUMB},
"push", {TRLLR}, {0xb400,AA4TUP,THUMB},
"ror", {TRG02,TRG05}, {0x41c0,AA4TUP,THUMB},
"rsb", {REG15,REG19,IMROT}, {0x02600000,AAANY,SETCC},
"rsb", {REG15,REG19,IMMD8,IROTV}, {0x02600000,AAANY,SETCC},
"rsb", {REG15,REG19,REG03}, {0x00600000,AAANY,SETCC},
"rsb", {REG15,REG19,REG03,SHIFT}, {0x00600000,AAANY,SETCC},
"rsc", {REG15,REG19,IMROT}, {0x02e00000,AAANY,SETCC},
"rsc", {REG15,REG19,IMMD8,IROTV}, {0x02e00000,AAANY,SETCC},
"rsc", {REG15,REG19,REG03}, {0x00e00000,AAANY,SETCC},
"rsc", {REG15,REG19,REG03,SHIFT}, {0x00e00000,AAANY,SETCC},
"smlal", {REG15,REG19,REG03,REG11}, {0x00e00090,AA3MUP,SETCC|NOPC|DIFR19|DIFR15|DIFR03},
"smull", {REG15,REG19,REG03,REG11}, {0x00c00090,AA3MUP,SETCC|NOPC|DIFR19|DIFR15|DIFR03},
"stc", {REG11,REG15,PCLCP}, {0x0d0f0000,AA2UP,0},
"stc", {REG11,REG15,R19PR,IMCP1}, {0x0d000000,AA2UP,0},
"stc", {REG11,REG15,R19PO}, {0x0d000000,AA2UP,0},
"stc", {REG11,REG15,R19PO,IMCP2}, {0x0c000000,AA2UP,0},
"stm", {R19WB,RLIST}, {0x08000000,AAANY,NOPC},
"stmia",{TR10W,TRLST}, {0xc000,AA4TUP,THUMB},
"str", {REG15,PCL12}, {0x050f0000,AAANY,NOPCWB},
"str", {REG15,R19PR,IMUD1}, {0x05000000,AAANY,NOPCWB},
"str", {REG15,R19PR,R3UD1}, {0x07000000,AAANY,NOPCWB|NOPCR03},
"str", {REG15,R19PR,R3UD2,SHIM1}, {0x07000000,AAANY,NOPCWB|NOPCR03},
"str", {REG15,R19PO}, {0x05800000,AAANY,NOPCWB},
"str", {REG15,R19PO,IMUD2}, {0x04000000,AAANY,NOPCWB},
"str", {REG15,R19PO,R3UD2}, {0x06000000,AAANY,NOPCWB|NOPCR03},
"str", {REG15,R19PO,R3UD2,SHIM2}, {0x06000000,AAANY,NOPCWB|NOPCR03},
"str", {TRG02,TR5IN,TR8IN}, {0x5000,AA4TUP,THUMB},
"str", {TRG02,TR5IN,TUI7I}, {0x6000,AA4TUP,THUMB},
"str", {TRG10,TSPPR,TUIAI}, {0x9000,AA4TUP,THUMB},
"strb", {TRG02,TR5IN,TR8IN}, {0x5400,AA4TUP,THUMB},
"strb", {TRG02,TR5IN,TUI5I}, {0x7000,AA4TUP,THUMB},
"strh", {TRG02,TR5IN,TR8IN}, {0x5200,AA4TUP,THUMB},
"strh", {TRG02,TR5IN,TUI6I}, {0x8000,AA4TUP,THUMB},
"sbc", {REG15,REG19,IMROT}, {0x02c00000,AAANY,SETCC},
"sbc", {REG15,REG19,IMMD8,IROTV}, {0x02c00000,AAANY,SETCC},
"sbc", {REG15,REG19,REG03}, {0x00c00000,AAANY,SETCC},
"sbc", {REG15,REG19,REG03,SHIFT}, {0x00c00000,AAANY,SETCC},
"sbc", {TRG02,TRG05}, {0x4180,AA4TUP,THUMB},
"sub", {REG15,REG19,IMROT}, {0x02400000,AAANY,SETCC},
"sub", {REG15,REG19,IMMD8,IROTV}, {0x02400000,AAANY,SETCC},
"sub", {REG15,REG19,REG03}, {0x00400000,AAANY,SETCC},
"sub", {REG15,REG19,REG03,SHIFT}, {0x00400000,AAANY,SETCC},
"sub", {TRG02,TRG05,TRG08}, {0x1a00,AA4TUP,THUMB},
"sub", {TRG02,TRG05,TUIM3}, {0x1e00,AA4TUP,THUMB},
"sub", {TRG10,TUIM8}, {0x3800,AA4TUP,THUMB},
"sub", {TSPRG,TUIM9}, {0xb080,AA4TUP,THUMB},
"svc", {SWI24}, {0x0f000000,AAANY,0},
"svc", {TSWI8}, {0xdf00,AA4TUP,THUMB},
"swi", {SWI24}, {0x0f000000,AAANY,0},
"swi", {TSWI8}, {0xdf00,AA4TUP,THUMB},
"swp", {REG15,REG03,R19PO}, {0x01000090,AA3UP,NOPC},
"teq", {REG19,IMROT}, {0x03300000,AAANY,SETPSR},
"teq", {REG19,IMMD8,IROTV}, {0x03300000,AAANY,SETPSR},
"teq", {REG19,REG03}, {0x01300000,AAANY,SETPSR},
"teq", {REG19,REG03,SHIFT}, {0x01300000,AAANY,SETPSR},
"tst", {REG19,IMROT}, {0x03100000,AAANY,SETPSR},
"tst", {REG19,IMMD8,IROTV}, {0x03100000,AAANY,SETPSR},
"tst", {REG19,REG03}, {0x01100000,AAANY,SETPSR},
"tst", {REG19,REG03,SHIFT}, {0x01100000,AAANY,SETPSR},
"tst", {TRG02,TRG05}, {0x4200,AA4TUP,THUMB},
"umlal", {REG15,REG19,REG03,REG11}, {0x00a00090,AA3MUP,SETCC|NOPC|DIFR19|DIFR15|DIFR03},
"umull", {REG15,REG19,REG03,REG11}, {0x00800090,AA3MUP,SETCC|NOPC|DIFR19|DIFR15|DIFR03},

786
vasm-1/cpus/c16x/cpu.c Normal file
View File

@ -0,0 +1,786 @@
/* cpu.c example cpu-description file */
/* (c) in 2002 by Volker Barthelmann */
#include "vasm.h"
char *cpu_copyright="vasm c16x/st10 cpu backend 0.2c (c) in 2002-2005 Volker Barthelmann";
char *cpuname="c16x";
mnemonic mnemonics[]={
#include "opcodes.h"
};
int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]);
int bitsperbyte=8;
int bytespertaddr=4;
static int JMPA,JMPR,JMPS,JNB,JB,JBC,JNBS,JMP;
static int notrans,tojmpa;
#define JMPCONV 256
#define INVCC(c) (((c)&1)?(c)-1:(c)+1)
#define ISBIT 1
typedef struct sfr {
struct sfr *next;
int flags;
unsigned int laddr,saddr,boffset;
} sfr;
sfr *first_sfr;
#define SFRHTSIZE 1024
hashtable *sfrhash;
static char *skip_reg(char *s,int *reg)
{
int r=-1;
if(*s!='r'&&*s!='R'){
cpu_error(1);
return s;
}
s++;
if(*s<'0'||*s>'9'){
cpu_error(1);
return s;
}
r=*s++-'0';
if(*s>='0'&&*s<='5')
r=10*r+*s++-'0';
*reg=r;
return s;
}
int parse_operand(char *p,int len,operand *op,int requires)
{
op->type=-1;
op->mod=-1;
p=skip(p);
if(requires==OP_REL){
char *s=p;
op->type=OP_REL;
op->offset=parse_expr(&s);
simplify_expr(op->offset);
if(s==p)
return 0;
else
return 1;
}
if(requires==OP_CC){
op->type=OP_CC;
if(len<4||len>6||p[0]!='c'||p[1]!='c'||p[2]!='_')
return 0;
if(len==4){
if(p[3]=='z')
op->cc=2;
else if(p[3]=='v')
op->cc=4;
else if(p[3]=='n')
op->cc=6;
else if(p[3]=='c')
op->cc=8;
else
return 0;
}else if(len==5){
if(p[3]=='u'&&p[4]=='c')
op->cc=0;
else if(p[3]=='n'&&p[4]=='z')
op->cc=3;
else if(p[3]=='n'&&p[4]=='v')
op->cc=5;
else if(p[3]=='n'&&p[4]=='n')
op->cc=7;
else if(p[3]=='n'&&p[4]=='c')
op->cc=0;
else if(p[3]=='e'&&p[4]=='q')
op->cc=2;
else if(p[3]=='n'&&p[4]=='e')
op->cc=3;
else
return 0;
}else if(len==6){
if(!strncmp(p+3,"ult",3))
op->cc=8;
else if(!strncmp(p+3,"ule",3))
op->cc=0xf;
else if(!strncmp(p+3,"uge",3))
op->cc=0x9;
else if(!strncmp(p+3,"ugt",3))
op->cc=0xe;
else if(!strncmp(p+3,"slt",3))
op->cc=0xc;
else if(!strncmp(p+3,"sle",3))
op->cc=0xb;
else if(!strncmp(p+3,"sge",3))
op->cc=0xd;
else if(!strncmp(p+3,"sgt",3))
op->cc=0xa;
else if(!strncmp(p+3,"net",3))
op->cc=0x1;
else
return 0;
}
return 1;
}
if((p[0]=='r'||p[0]=='R')&&p[1]>='0'&&p[1]<='9'&&(len==2||p[2]=='.')){
op->type=OP_GPR;
op->reg=p[1]-'0';
op->regsfr=op->reg+0xf0;
if(len>2){
op->type=OP_BADDR;
if(requires==OP_BADDR){
p=skip(p+3);
op->boffset=parse_expr(&p);
op->offset=number_expr(op->regsfr);
}
}
}else if((p[0]=='r'||p[0]=='R')&&p[1]=='1'&&p[2]>='0'&&p[2]<='5'&&(len==3||p[3]=='.')){
op->type=OP_GPR;
op->reg=(p[1]-'0')*10+p[2]-'0';
op->regsfr=op->reg+0xf0;
if(len>3){
op->type=OP_BADDR;
if(requires==OP_BADDR){
p=skip(p+4);
op->boffset=parse_expr(&p);
op->offset=number_expr(op->regsfr);
}
}
}else if(len==3&&(p[0]=='r'||p[0]=='R')&&(p[1]=='l'||p[1]=='L')&&p[2]>='0'&&p[2]<='7'){
op->type=OP_BGPR;
op->reg=(p[2]-'0')*2;
op->regsfr=op->reg+0xf0;
}else if(len==3&&(p[0]=='r'||p[0]=='R')&&(p[1]=='h'||p[1]=='H')&&p[2]>='0'&&p[2]<='7'){
op->type=OP_BGPR;
op->reg=(p[2]-'0')*2+1;
op->regsfr=op->reg+0xf0;
}else if(p[0]=='#'){
op->type=OP_IMM16;
p=skip(p+1);
if((!strncmp("SOF",p,3)||!strncmp("sof",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SOF;p=skip(p+3);}
if((!strncmp("SEG",p,3)||!strncmp("seg",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SEG;p=skip(p+3);}
if((!strncmp("DPP0:",p,5)||!strncmp("dpp0:",p,5))){op->mod=MOD_DPP0;p=skip(p+5);}
if((!strncmp("DPP1:",p,5)||!strncmp("dpp1:",p,5))){op->mod=MOD_DPP1;p=skip(p+5);}
if((!strncmp("DPP2:",p,5)||!strncmp("dpp2:",p,5))){op->mod=MOD_DPP2;p=skip(p+5);}
if((!strncmp("DPP3:",p,5)||!strncmp("dpp3:",p,5))){op->mod=MOD_DPP3;p=skip(p+5);}
if((!strncmp("DPPX:",p,5)||!strncmp("dppx:",p,5))){op->mod=MOD_DPPX;p=skip(p+5);}
op->offset=parse_expr(&p);
simplify_expr(op->offset);
#if 0
if(op->offset->type==NUM){
taddr val=op->offset->c.val;
if(val>=0&&val<=7)
op->type=OP_IMM3;
else if(val>=0&&val<=15)
op->type=OP_IMM4;
else if(val>=0&&val<=127)
op->type=OP_IMM7;
else if(val>=0&&val<=255)
op->type=OP_IMM8;
}
#endif
}else if(*p=='['){
p=skip(p+1);
if(*p=='-'){
p=skip(p+1);
p=skip_reg(p,&op->reg);
p=skip(p);
if(*p!=']')
cpu_error(0);
if(op->reg<=3)
op->type=OP_PREDEC03;
else
op->type=OP_PREDEC;
}else{
p=skip_reg(p,&op->reg);
p=skip(p);
if(*p=='+'){
p=skip(p+1);
if(*p==']'){
if(op->reg<=3)
op->type=OP_POSTINC03;
else
op->type=OP_POSTINC;
}else{
if(*p!='#')
cpu_error(0);
p=skip(p+1);
op->offset=parse_expr(&p);
p=skip(p);
op->type=OP_REGDISP;
}
}else{
if(op->reg<=3)
op->type=OP_REG03IND;
else
op->type=OP_REGIND;
}
if(*p!=']')
cpu_error(0);
}
}else{
if(ISIDSTART(*p)){
char *name=p;
hashdata data;
while((p==name||ISIDCHAR(*p))&&*p!='.')
p++;
if(find_namelen(sfrhash,name,p-name,&data)){
sfr *sfr;
sfr=data.ptr;
if(sfr->flags&ISBIT){
op->offset=number_expr(sfr->saddr);
op->type=OP_BADDR;
op->boffset=number_expr(sfr->boffset);
}else{
if(requires==OP_SFR||requires==OP_BSFR||requires==OP_BWORD){
op->offset=number_expr(sfr->saddr);
op->type=requires;
}else if(requires==OP_BADDR&&*p=='.'){
op->offset=number_expr(sfr->saddr);
p=skip(p+1);
op->boffset=parse_expr(&p);
op->type=OP_BADDR;
}else if(requires==OP_ABS||requires==OP_BABS){
op->type=requires;
op->offset=number_expr((2*sfr->saddr)+(sfr->laddr<<8));
}
}
}
if(op->type==-1)
p=name;
}
if(op->type==-1){
if((!strncmp("SOF",p,3)||!strncmp("sof",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SOF;p=skip(p+3);}
if((!strncmp("SEG",p,3)||!strncmp("seg",p,3))&&isspace((unsigned char)p[3])){op->mod=MOD_SEG;p=skip(p+3);}
if((!strncmp("DPP0:",p,5)||!strncmp("dpp0:",p,5))){op->mod=MOD_DPP0;p=skip(p+5);}
if((!strncmp("DPP1:",p,5)||!strncmp("dpp1:",p,5))){op->mod=MOD_DPP1;p=skip(p+5);}
if((!strncmp("DPP2:",p,5)||!strncmp("dpp2:",p,5))){op->mod=MOD_DPP2;p=skip(p+5);}
if((!strncmp("DPP3:",p,5)||!strncmp("dpp3:",p,5))){op->mod=MOD_DPP3;p=skip(p+5);}
if((!strncmp("DPPX:",p,5)||!strncmp("dppx:",p,5))){op->mod=MOD_DPPX;p=skip(p+5);}
op->offset=parse_expr(&p);
op->type=OP_ABS;
}
}
if(requires==op->type)
return 1;
if(requires==OP_BWORD&&op->type==OP_SFR)
return 1;
if(op->type==OP_IMM16&&(requires>=OP_IMM2&&requires<=OP_IMM16))
return 1;
if(op->type==OP_PREDEC03&&requires==OP_PREDEC)
return 1;
if(op->type==OP_POSTINC03&&requires==OP_POSTINC)
return 1;
if(op->type==OP_REG03IND&&requires==OP_REGIND)
return 1;
if((requires==OP_SFR&&op->type==OP_GPR)||
(requires==OP_BWORD&&op->type==OP_GPR)||
(requires==OP_BWORD&&op->type==OP_BGPR)||
(requires==OP_BSFR&&op->type==OP_BGPR)){
op->offset=number_expr(op->regsfr);
return 1;
}
if(requires==OP_BSFR&&op->type==OP_BGPR)
return 1;
if(requires==OP_JADDR&&op->type==OP_ABS)
return 1;
if(requires==OP_BABS&&op->type==OP_ABS)
return 1;
/*FIXME*/
return 0;
}
static taddr reloffset(expr *tree,section *sec,taddr pc)
{
symbol *sym;
int btype;
taddr val;
simplify_expr(tree);
if(tree->type==NUM){
/* should we do it like this?? */
val=tree->c.val;
}else{
btype=find_base(tree,&sym,sec,pc);
if(btype!=BASE_OK||!LOCREF(sym)||sym->sec!=sec)
val=0xffff;
else{
eval_expr(tree,&val,sec,pc);
val=val-pc;
}
}
return val;
}
static taddr absoffset2(expr *tree,int mod,section *sec,taddr pc,rlist **relocs,int roffset,int size,taddr mask)
{
taddr val;
if(mod==MOD_SOF){
if(mask!=0xffffffff&&mask!=0xffff) cpu_error(5);
mask=0xffff;
}
if(mod==MOD_SEG){
if(mask!=0xff&&mask!=0xffff&&mask!=0xffffffff) cpu_error(6);
mask<<=16;
}
if(mod==MOD_DPP0||mod==MOD_DPP1||mod==MOD_DPP2||mod==MOD_DPP3||mod==MOD_DPPX){
if(mask!=0xffffffff&&mask!=0xffff) cpu_error(7);
mask=0x3fff;
}
if(!eval_expr(tree,&val,sec,pc)){
taddr addend=val;
symbol *base;
if(find_base(tree,&base,sec,pc)!=BASE_OK){
general_error(38);
return val;
}
if(mod==MOD_DPP1) val|=0x4000;
if(mod==MOD_DPP2) val|=0x8000;
if(mod==MOD_DPP3) val|=0xc000;
if(mod==MOD_DPPX){
static int dpplen;
static char *dppname;
char *id=base->name;
symbol *dppsym;
size-=2;
if(strlen(id)+9>dpplen){
myfree(dppname);
dppname=mymalloc(dpplen=strlen(id)+9);
}
strcpy(dppname,"___DPP_");
strcat(dppname,id);
dppsym=new_import(dppname);
if(dppsym->type==EXPRESSION){
if(!eval_expr(dppsym->expr,&val,0,0))
ierror(0);
val<<=14;
}else{
add_nreloc_masked(relocs,dppsym,0,REL_ABS,2,roffset+14,0x3);
}
}
add_nreloc_masked(relocs,base,addend,REL_ABS,size,roffset,mask);
return val;
}
val&=mask;
if(mod==MOD_DPPX) cpu_error(7);
if(mod==MOD_DPP1) val|=0x4000;
if(mod==MOD_DPP2) val|=0x8000;
if(mod==MOD_DPP3) val|=0xc000;
if(mod==MOD_SEG) val>>=16;
/*FIXME: range check */
#if 1
if(size==16)
return val&0xffff;
else
return val&((1<<size)-1);
#else
return val;
#endif
}
static taddr absoffset(expr *tree,int mod,section *sec,taddr pc,rlist **relocs,int roffset,int size)
{
/* taddr mask=size==32?0xffffffff:((((taddr)1)<<size)-1);*/
return absoffset2(tree,mod,sec,pc,relocs,roffset,size,0xffffffff);
}
static taddr absval(expr *tree,section *sec,taddr pc,int bits)
{
taddr val;
if(!eval_expr(tree,&val,sec,pc))
cpu_error(0);
if(bits==2){
/* ext instructions */
if(val<1||val>4)
cpu_error(3,2);
return val;
}else if(val<0||val>=(1<<bits))
cpu_error(3,bits);
return val&((1<<bits)-1);
}
static int translate(instruction *p,section *sec,taddr pc)
{
int c=p->code;
taddr val;
/* choose one of jmpr/jmpa */
if(c==JMP||(!notrans&&(c==JMPA||c==JMPR||c==JB||c==JNB))){
val=reloffset(p->op[1]->offset,sec,pc);
if(val<-256||val>254||val%2){
if(c==JB) return JNB|JMPCONV;
if(c==JNB) return JB|JMPCONV;
if(c==JMPA) return JMPA;
if(tojmpa) return JMPA;
if(p->op[0]->cc==0)
return JMPS;
else
return JMPR|JMPCONV;
}else{
if(c==JB||c==JNB)
return c;
return JMPR;
}
}
/* choose between gpr,#imm3 and reg,#imm16 */
if(mnemonics[c].operand_type[1]==OP_IMM3){
if(!eval_expr(p->op[1]->offset,&val,sec,pc)||val<0||val>7){
if(!strcmp(mnemonics[c].name,mnemonics[c+1].name))
return c+1;
}
}
/* choose between gpr,#imm4 and reg,#imm16 */
if(mnemonics[c].operand_type[1]==OP_IMM4){
if(!eval_expr(p->op[1]->offset,&val,sec,pc)||val<0||val>7){
if(!strcmp(mnemonics[c].name,mnemonics[c+1].name))
return c+1;
}
}
return c;
}
/* Convert an instruction into a DATA atom including relocations,
if necessary. */
dblock *eval_instruction(instruction *p,section *sec,taddr pc)
{
dblock *db=new_dblock();
int opcode,c,jmpconv=0,osize;
unsigned long code;
char *d;
taddr val;
rlist *relocs=0;
operand *jmpaddr;
c=translate(p,sec,pc);
if(c&JMPCONV){ jmpconv=1;c&=~JMPCONV;}
if((mnemonics[p->code].operand_type[0]==OP_GPR&&mnemonics[c].operand_type[0]==OP_SFR)||
(mnemonics[p->code].operand_type[0]==OP_BGPR&&mnemonics[c].operand_type[0]==OP_BSFR))
p->op[0]->offset=number_expr(p->op[0]->regsfr);
db->size=osize=mnemonics[c].ext.len*2;
if(jmpconv) db->size+=4;
db->data=mymalloc(db->size);
opcode=mnemonics[c].ext.opcode;
switch(mnemonics[c].ext.encoding){
case 0:
code=opcode<<16|(opcode>>8)<<8|opcode>>8;
break;
case 1:
code=opcode;
break;
case 2:
code=opcode|p->op[0]->reg<<4|p->op[1]->reg;
break;
case 3:
code=opcode|p->op[0]->reg|p->op[1]->reg<<4;
break;
case 4:
code=opcode|p->op[0]->reg<<4|p->op[1]->reg|8;
break;
case 5:
code=opcode|p->op[0]->reg<<4|p->op[1]->reg|12;
break;
case 6:
code=opcode|p->op[0]->reg<<4|absval(p->op[1]->offset,sec,pc,3);
break;
case 7:
/* fall through */
case 8:
code=opcode<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,20,8)<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
break;
case 9:
code=opcode|p->op[0]->reg|absval(p->op[1]->offset,sec,pc,4)<<4;
break;
case 10:
/* rfi: reorder bmov operands */
code=opcode<<16|
absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,8,8)<<16|
absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,8)<<0|
absoffset(p->op[1]->boffset,0,sec,pc,&relocs,24,4)<<12|
absoffset(p->op[0]->boffset,0,sec,pc,&relocs,28,4)<<8;
break;
case 11:
code=opcode|absoffset(p->op[0]->boffset,0,sec,pc,&relocs,0,4)<<12|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8);
break;
case 12:
code=opcode<<16|
absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
absoffset(p->op[2]->offset,p->op[2]->mod,sec,pc,&relocs,16,8)<<8|
absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,24,8);
break;
case 13:
code=opcode<<16|
absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,8)<<8|
absoffset(p->op[2]->offset,p->op[2]->mod,sec,pc,&relocs,24,8);
break;
case 14:
code=opcode<<16|p->op[0]->cc<<20|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
break;
case 15:
code=opcode|p->op[0]->cc<<4|p->op[1]->reg;
break;
case 16:
val=((reloffset(p->op[0]->offset,sec,pc)-2)>>1)&255;
code=opcode|val;
break;
case 17:
if(p->op[0]->type==OP_CC){
/* jmp cc_uc was converted to jmps */
code=opcode<<16|absoffset2(p->op[1]->offset,0,sec,pc,&relocs,8,8,0xffff0000)<<16|absoffset2(p->op[1]->offset,0,sec,pc,&relocs,16,16,0xffff);
}else{
code=opcode<<16|absoffset2(p->op[0]->offset,0,sec,pc,&relocs,8,8,0xffff0000)<<16|absoffset2(p->op[0]->offset,0,sec,pc,&relocs,16,16,0xffff);
}
break;
case 18:
/* fall through */
case 19:
code=opcode<<16|0xf<<20|p->op[0]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
break;
case 20:
code=opcode|p->op[0]->reg<<4;
break;
case 21:
code=opcode|p->op[0]->reg<<4|p->op[0]->reg;
break;
case 22:
if(!jmpconv){
val=((reloffset(p->op[1]->offset,sec,pc)-4)>>1)&255;
code=opcode<<16|
absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
absoffset(p->op[0]->boffset,0,sec,pc,&relocs,24,4)<<12|
val;
}else{
code=opcode<<16|
absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8)<<16|
absoffset(p->op[0]->boffset,0,sec,pc,&relocs,24,4)<<12|
2;
jmpaddr=p->op[1];
}
break;
case 23:
if(!jmpconv){
val=((reloffset(p->op[1]->offset,sec,pc)-2)>>1)&255;
code=opcode|p->op[0]->cc<<12|val;
}else{
code=opcode|INVCC(p->op[0]->cc)<<12|2;
jmpaddr=p->op[1];
}
break;
case 24:
code=opcode<<16|p->op[0]->reg<<20|p->op[1]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
break;
case 25:
code=opcode<<16|p->op[0]->reg<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,16,16);
break;
case 26:
code=opcode|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,8,8);
break;
case 27:
code=opcode|absval(p->op[0]->offset,sec,pc,7)<<1;
break;
case 28:
code=opcode<<16|p->op[0]->reg<<16|p->op[1]->reg<<20|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16);
break;
case 29:
code=opcode<<16|absoffset(p->op[1]->offset,p->op[1]->mod,sec,pc,&relocs,8,8)<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16);
break;
case 30:
code=opcode<<16|p->op[1]->reg<<16|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,16);
break;
case 31:
code=opcode|((absval(p->op[0]->offset,sec,pc,2)-1)<<4);
break;
case 32:
code=opcode|p->op[0]->reg|((absval(p->op[1]->offset,sec,pc,2)-1)<<4);
break;
case 34:
code=opcode<<16|((absval(p->op[1]->offset,sec,pc,2)-1)<<20)|absoffset(p->op[0]->offset,p->op[0]->mod,sec,pc,&relocs,16,8);
break;
case 33:
default:
ierror(mnemonics[c].ext.encoding);
}
d=db->data;
if(osize==4){
*d++=code>>24;
*d++=code>>16;
*d++=code;
*d++=code>>8;
}else{
*d++=code>>8;
*d++=code;
}
if(jmpconv){
*d++=0xfa;
*d++=absoffset2(jmpaddr->offset,0,sec,pc,&relocs,8+8*osize,8,0xffff0000);
val=absoffset2(jmpaddr->offset,0,sec,pc,&relocs,16+8*osize,16,0xffff);
*d++=val>>8;
*d++=val;
}
db->relocs=relocs;
return db;
}
/* Create a dblock (with relocs, if necessary) for size bits of data. */
dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
{
dblock *new=new_dblock();
taddr val;
new->size=(bitsize+7)/8;
new->data=mymalloc(new->size);
if(op->type!=OP_ABS)
ierror(0);
if(bitsize!=8&&bitsize!=16&&bitsize!=32)
cpu_error(4);
val=absoffset(op->offset,op->mod,sec,pc,&new->relocs,0,bitsize);
if(bitsize==32){
new->data[3]=val>>24;
new->data[2]=val>>16;
new->data[1]=val>>8;
new->data[0]=val;
}else if(bitsize==16){
new->data[1]=val>>8;
new->data[0]=val;
}else
new->data[0]=val;
return new;
}
/* Calculate the size of the current instruction; must be identical
to the data created by eval_instruction. */
size_t instruction_size(instruction *p,section *sec,taddr pc)
{
int c=translate(p,sec,pc),add=0;
if(c&JMPCONV){ add=4;c&=~JMPCONV;}
return mnemonics[c].ext.len*2+add;
}
operand *new_operand()
{
operand *new=mymalloc(sizeof(*new));
new->type=-1;
return new;
}
/* return true, if initialization was successfull */
int init_cpu()
{
int i;
for(i=0;i<mnemonic_cnt;i++){
if(!strcmp(mnemonics[i].name,"jmp"))
JMP=i;
if(!strcmp(mnemonics[i].name,"jmpr"))
JMPR=i;
if(!strcmp(mnemonics[i].name,"jmpa"))
JMPA=i;
if(!strcmp(mnemonics[i].name,"jmps"))
JMPS=i;
if(!strcmp(mnemonics[i].name,"jb"))
JB=i;
if(!strcmp(mnemonics[i].name,"jbc"))
JBC=i;
if(!strcmp(mnemonics[i].name,"jnb"))
JNB=i;
if(!strcmp(mnemonics[i].name,"jnbs"))
JNBS=i;
}
sfrhash=new_hashtable(SFRHTSIZE);
return 1;
}
/* return true, if the passed argument is understood */
int cpu_args(char *p)
{
if(!strcmp(p,"-no-translations")){
notrans=1;
return 1;
}
if(!strcmp(p,"-jmpa")){
tojmpa=1;
return 1;
}
return 0;
}
/* parse cpu-specific directives; return pointer to end of
cpu-specific text */
char *parse_cpu_special(char *s)
{
char *name=s,*merk=s;
if(ISIDSTART(*s)){
s++;
while(ISIDCHAR(*s))
s++;
if(s-name==4&&!strncmp(name,".sfr",4)){
sfr *new;
hashdata data;
expr *tree;
s=skip(s);
if(!ISIDSTART(*s))
cpu_error(0);
name=s++;
while(ISIDCHAR(*s))
s++;
if(find_namelen(sfrhash,name,s-name,&data))
new=data.ptr;
else{
data.ptr=new=mymalloc(sizeof(*new));
add_hashentry(sfrhash,cnvstr(name,s-name),data);
new->next=first_sfr;
first_sfr=new;
}
new->flags=new->laddr=new->saddr=0;
new->boffset=0;
s=skip(s);
if(*s!=',')
cpu_error(0);
else
s=skip(s+1);
tree=parse_expr(&s);
simplify_expr(tree);
if(!tree||tree->type!=NUM)
cpu_error(0);
else
new->laddr=tree->c.val;
s=skip(s);
if(tree->c.val==0xfe||tree->c.val==0xf0){
if(*s!=',')
cpu_error(0);
else
s=skip(s+1);
free_expr(tree);
tree=parse_expr(&s);
simplify_expr(tree);
if(!tree||tree->type!=NUM)
cpu_error(0);
else
new->saddr=tree->c.val;
free_expr(tree);
s=skip(s);
}else{
if(tree->c.val>=0xfe00)
new->laddr=0xfe;
else
new->laddr=0xf0;
new->saddr=(tree->c.val-(new->laddr<<8))/2;
if((new->laddr<<8)+2*new->saddr!=tree->c.val) ierror(0);
free_expr(tree);
}
if(*s==','){
s=skip(s+1);
tree=parse_expr(&s);
simplify_expr(tree);
new->boffset=tree->c.val;
new->flags|=ISBIT;
free_expr(tree);
}
return skip(s);
}
}
return merk;
}

88
vasm-1/cpus/c16x/cpu.h Normal file
View File

@ -0,0 +1,88 @@
/* cpu.h c16x/st10 cpu-description header-file */
/* (c) in 2002 by Volker Barthelmann */
/* maximum number of operands in one mnemonic */
#define MAX_OPERANDS 3
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 0
/* maximum number of additional command-line-flags for this cpu */
/* data type to represent a target-address */
typedef int32_t taddr;
typedef uint32_t utaddr;
#define LITTLEENDIAN 1
#define BIGENDIAN 0
#define VASM_CPU_C16X 1
/* minimum instruction alignment */
#define INST_ALIGN 2
/* default alignment for n-bit data */
#define DATA_ALIGN(n) ((n)<=8?1:2)
/* operand class for n-bit data definitions */
#define DATA_OPERAND(n) OP_ABS
#define cc reg
/* type to store each operand */
typedef struct {
int type;
int mod;
int reg,regsfr; /* also cc and boff */
expr *offset,*boffset;
} operand;
/* operand-types */
#define OP_GPR 1
#define OP_BGPR 2
#define OP_SFR 3
#define OP_BSFR 4
#define OP_ABS 5
#define OP_SEG OP_ABS
#define OP_BABS 6
#define OP_REGDISP 7
#define OP_REGIND 8
#define OP_REG03IND 9
#define OP_BWORD 10
#define OP_BADDR 11
#define OP_IMM2 12
#define OP_IMM3 13
#define OP_IMM4 14
#define OP_IMM7 15
#define OP_IMM8 16
#define OP_IMM16 17
#define OP_CC 18
#define OP_REL 19
#define OP_JADDR 20
#define OP_POSTINC03 21
#define OP_PREDEC03 22
#define OP_POSTINC 23
#define OP_PREDEC 24
#define OP_PROTECTED 0
/* mod types */
#define MOD_SOF 1
#define MOD_SEG 2
#define MOD_DPP0 3
#define MOD_DPP1 4
#define MOD_DPP2 5
#define MOD_DPP3 6
#define MOD_DPPX 7
#define CPU_C166 1
#define CPU_C167 2
#define CPU_ALL (-1)
typedef struct {
unsigned int len;
unsigned int opcode;
unsigned int match;
unsigned int lose;
unsigned int encoding;
unsigned int available;
} mnemonic_extension;

View File

@ -0,0 +1,8 @@
"illegal operand",ERROR,
"word register expected",ERROR,
"",ERROR,
"value does not find in %d bits",WARNING,
"data size not supported",ERROR,
"illegal use of SOF",WARNING,
"illegal use of SEG",WARNING,
"illegal use of DPP prefix",WARNING,

233
vasm-1/cpus/c16x/opcodes.h Normal file
View File

@ -0,0 +1,233 @@
"add",OP_GPR,OP_GPR,0,1,0x0000,0x0000,0xff00,2,CPU_ALL,
"add",OP_GPR,OP_REG03IND,0,1,0x0800,0x0808,0xf704,4,CPU_ALL,
"add",OP_GPR,OP_POSTINC03,0,1,0x0800,0x080c,0xf700,5,CPU_ALL,
"add",OP_GPR,OP_IMM3,0,1,0x0800,0x0800,0xf708,6,CPU_ALL,
"add",OP_SFR,OP_IMM16,0,2,0x0600,0x0600,0xf900,7,CPU_ALL,
"add",OP_SFR,OP_ABS,0,2,0x0200,0x0200,0xfd00,8,CPU_ALL,
"add",OP_ABS,OP_SFR,0,2,0x0400,0x0400,0xfb00,29,CPU_ALL,
"addb",OP_BGPR,OP_BGPR,0,1,0x0100,0x0100,0xfe00,2,CPU_ALL,
"addb",OP_BGPR,OP_REG03IND,0,1,0x0900,0x0908,0xf604,4,CPU_ALL,
"addb",OP_BGPR,OP_POSTINC03,0,1,0x0900,0x090c,0xf600,5,CPU_ALL,
"addb",OP_BGPR,OP_IMM3,0,1,0x0900,0x0900,0xf608,6,CPU_ALL,
"addb",OP_BSFR,OP_IMM16,0,2,0x0700,0x0700,0xf800,7,CPU_ALL,
"addb",OP_BSFR,OP_BABS,0,2,0x0300,0x0300,0xfc00,8,CPU_ALL,
"addb",OP_BABS,OP_BSFR,0,2,0x0500,0x0500,0xfa00,29,CPU_ALL,
"addc",OP_GPR,OP_GPR,0,1,0x1000,0x1000,0xef00,2,CPU_ALL,
"addc",OP_GPR,OP_REG03IND,0,1,0x1800,0x1808,0xe704,4,CPU_ALL,
"addc",OP_GPR,OP_POSTINC03,0,1,0x1800,0x180c,0xe700,5,CPU_ALL,
"addc",OP_GPR,OP_IMM3,0,1,0x1800,0x1800,0xe708,6,CPU_ALL,
"addc",OP_SFR,OP_IMM16,0,2,0x1600,0x1600,0xe900,7,CPU_ALL,
"addc",OP_SFR,OP_ABS,0,2,0x1200,0x1200,0xed00,8,CPU_ALL,
"addc",OP_ABS,OP_SFR,0,2,0x1400,0x1400,0xeb00,29,CPU_ALL,
"addcb",OP_BGPR,OP_BGPR,0,1,0x1100,0x1100,0xee00,2,CPU_ALL,
"addcb",OP_BGPR,OP_REG03IND,0,1,0x1900,0x1908,0xe604,4,CPU_ALL,
"addcb",OP_BGPR,OP_POSTINC03,0,1,0x1900,0x190c,0xe600,5,CPU_ALL,
"addcb",OP_BGPR,OP_IMM3,0,1,0x1900,0x1900,0xe608,6,CPU_ALL,
"addcb",OP_BSFR,OP_IMM16,0,2,0x1700,0x1700,0xe800,7,CPU_ALL,
"addcb",OP_BSFR,OP_BABS,0,2,0x1300,0x1300,0xec00,8,CPU_ALL,
"addcb",OP_BABS,OP_BSFR,0,2,0x1500,0x1500,0xea00,29,CPU_ALL,
"and",OP_GPR,OP_GPR,0,1,0x6000,0x6000,0x9f00,2,CPU_ALL,
"and",OP_GPR,OP_REG03IND,0,1,0x6800,0x6808,0x9704,4,CPU_ALL,
"and",OP_GPR,OP_POSTINC03,0,1,0x6800,0x680c,0x9700,5,CPU_ALL,
"and",OP_GPR,OP_IMM3,0,1,0x6800,0x6800,0x9708,6,CPU_ALL,
"and",OP_SFR,OP_IMM16,0,2,0x6600,0x6600,0x9900,7,CPU_ALL,
"and",OP_SFR,OP_ABS,0,2,0x6200,0x6200,0x9d00,8,CPU_ALL,
"and",OP_ABS,OP_SFR,0,2,0x6400,0x6400,0x9b00,29,CPU_ALL,
"andb",OP_BGPR,OP_BGPR,0,1,0x6100,0x6100,0x9e00,2,CPU_ALL,
"andb",OP_BGPR,OP_REG03IND,0,1,0x6900,0x6908,0x9604,4,CPU_ALL,
"andb",OP_BGPR,OP_POSTINC03,0,1,0x6900,0x690c,0x9600,5,CPU_ALL,
"andb",OP_BGPR,OP_IMM3,0,1,0x6900,0x6900,0x9608,6,CPU_ALL,
"andb",OP_BSFR,OP_IMM16,0,2,0x6700,0x6700,0x9800,7,CPU_ALL,
"andb",OP_BSFR,OP_BABS,0,2,0x6300,0x6300,0x9c00,8,CPU_ALL,
"andb",OP_BABS,OP_BSFR,0,2,0x6500,0x6500,0x9a00,29,CPU_ALL,
"ashr",OP_GPR,OP_GPR,0,1,0xac00,0xac00,0x5300,2,CPU_ALL,
"ashr",OP_GPR,OP_IMM4,0,1,0xbc00,0xbc00,0x4300,9,CPU_ALL,
"atomic",OP_IMM3,0,0,1,0xd100,0xd100,0x2ecf,31,CPU_C167,
"band",OP_BADDR,OP_BADDR,0,2,0x6a00,0x6a00,0x9500,10,CPU_ALL,
"bclr",OP_BADDR,0,0,1,0x0e00,0x0e00,0x0100,11,CPU_ALL,
"bcmp",OP_BADDR,OP_BADDR,0,2,0x2a00,0x2a00,0xd500,10,CPU_ALL,
"bfldh",OP_BWORD,OP_IMM8,OP_IMM8,2,0x1a00,0x1a00,0xe500,12,CPU_ALL,
"bfldl",OP_BWORD,OP_IMM8,OP_IMM8,2,0x0a00,0x0a00,0xf500,13,CPU_ALL,
"bmov",OP_BADDR,OP_BADDR,0,2,0x4a00,0x4a00,0xb500,10,CPU_ALL,
"bmovn",OP_BADDR,OP_BADDR,0,2,0x3a00,0x3a00,0xc500,10,CPU_ALL,
"bor",OP_BADDR,OP_BADDR,0,2,0x5a00,0x5a00,0xa500,10,CPU_ALL,
"bset",OP_BADDR,0,0,1,0x0f00,0x0f00,0x0000,11,CPU_ALL,
"bxor",OP_BADDR,OP_BADDR,0,2,0x7a00,0x7a00,0x8500,10,CPU_ALL,
"call",OP_REL,0,0,1,0xbb00,0xbb00,0x4400,16,CPU_ALL,
"calla",OP_CC,OP_JADDR,0,2,0xca00,0xca00,0x350f,14,CPU_ALL,
"calli",OP_CC,OP_REGIND,0,1,0xab00,0xab00,0x5400,15,CPU_ALL,
"callr",OP_REL,0,0,1,0xbb00,0xbb00,0x4400,16,CPU_ALL,
"calls",OP_JADDR,0,0,2,0xda00,0xda00,0x2500,17,CPU_ALL,
"cmp",OP_GPR,OP_GPR,0,1,0x4000,0x4000,0xbf00,2,CPU_ALL,
"cmp",OP_GPR,OP_REG03IND,0,1,0x4800,0x4808,0xb704,4,CPU_ALL,
"cmp",OP_GPR,OP_POSTINC03,0,1,0x4800,0x480c,0xb700,5,CPU_ALL,
"cmp",OP_GPR,OP_IMM3,0,1,0x4800,0x4800,0xb708,6,CPU_ALL,
"cmp",OP_SFR,OP_IMM16,0,2,0x4600,0x4600,0xb900,7,CPU_ALL,
"cmp",OP_SFR,OP_ABS,0,2,0x4200,0x4200,0xbd00,8,CPU_ALL,
"cmpb",OP_BGPR,OP_BGPR,0,1,0x4100,0x4100,0xbe00,2,CPU_ALL,
"cmpb",OP_BGPR,OP_REG03IND,0,1,0x4900,0x4908,0xb604,4,CPU_ALL,
"cmpb",OP_BGPR,OP_POSTINC03,0,1,0x4900,0x490c,0xb600,5,CPU_ALL,
"cmpb",OP_BGPR,OP_IMM3,0,1,0x4900,0x4900,0xb608,6,CPU_ALL,
"cmpb",OP_BSFR,OP_IMM16,0,2,0x4700,0x4700,0xb800,7,CPU_ALL,
"cmpb",OP_BSFR,OP_BABS,0,2,0x4300,0x4300,0xbc00,8,CPU_ALL,
"cmpd1",OP_GPR,OP_IMM4,0,1,0xa000,0xa000,0x5f00,9,CPU_ALL,
"cmpd1",OP_GPR,OP_IMM16,0,2,0xa600,0xa6f0,0x5900,18,CPU_ALL,
"cmpd1",OP_GPR,OP_ABS,0,2,0xa200,0xa2f0,0x5d00,19,CPU_ALL,
"cmpd2",OP_GPR,OP_IMM4,0,1,0xb000,0xb000,0x4f00,9,CPU_ALL,
"cmpd2",OP_GPR,OP_IMM16,0,2,0xb600,0xb6f0,0x4900,18,CPU_ALL,
"cmpd2",OP_GPR,OP_ABS,0,2,0xb200,0xb2f0,0x4d00,19,CPU_ALL,
"cmpi1",OP_GPR,OP_IMM4,0,1,0x8000,0x8000,0x7f00,9,CPU_ALL,
"cmpi1",OP_GPR,OP_IMM16,0,2,0x8600,0x86f0,0x7900,18,CPU_ALL,
"cmpi1",OP_GPR,OP_ABS,0,2,0x8200,0x82f0,0x7d00,19,CPU_ALL,
"cmpi2",OP_GPR,OP_IMM4,0,1,0x9000,0x9000,0x6f00,9,CPU_ALL,
"cmpi2",OP_GPR,OP_IMM16,0,2,0x9600,0x96f0,0x6900,18,CPU_ALL,
"cmpi2",OP_GPR,OP_ABS,0,2,0x9200,0x92f0,0x6d00,19,CPU_ALL,
"cpl",OP_GPR,0,0,1,0x9100,0x9100,0x6e0f,20,CPU_ALL,
"cplb",OP_BGPR,0,0,1,0xb100,0xb100,0x4e0f,20,CPU_ALL,
"diswdt",OP_PROTECTED,0,0,2,0xa55a,0xa55a,0x5aa5,0,CPU_ALL,
"div",OP_GPR,0,0,1,0x4b00,0x4b00,0xb400,21,CPU_ALL,
"divl",OP_GPR,0,0,1,0x6b00,0x6b00,0x9400,21,CPU_ALL,
"divlu",OP_GPR,0,0,1,0x7b00,0x7b00,0x8400,21,CPU_ALL,
"divu",OP_GPR,0,0,1,0x5b00,0x5b00,0xa400,21,CPU_ALL,
"einit",OP_PROTECTED,0,0,2,0xb54a,0xb54a,0x4ab5,0,CPU_ALL,
"extp",OP_GPR,OP_IMM3,0,1,0xdc40,0xdc40,0x2380,32,CPU_C167,
"extp",OP_IMM16,OP_IMM3,0,2,0xd740,0xd740,0x288f,33,CPU_C167,
"extr",OP_IMM3,0,0,1,0xd180,0xd180,0x2e4f,31,CPU_C167,
"extpr",OP_GPR,OP_IMM3,0,1,0xdcc0,0xdcc0,0x2300,32,CPU_C167,
"extpr",OP_IMM16,OP_IMM3,0,2,0xd7c0,0xd7c0,0x280f,33,CPU_C167,
"exts",OP_GPR,OP_IMM3,0,1,0xdc00,0xdc00,0x23c0,32,CPU_C167,
"exts",OP_IMM8,OP_IMM3,0,2,0xd700,0xd700,0x28cf,34,CPU_C167,
"extsr",OP_GPR,OP_IMM3,0,1,0xdc80,0xdc80,0x2340,32,CPU_C167,
"extsr",OP_IMM8,OP_IMM3,0,2,0xd780,0xd780,0x284f,34,CPU_C167,
"idle",OP_PROTECTED,0,0,2,0x8778,0x8778,0x7887,0,CPU_ALL,
"jb",OP_BADDR,OP_REL,0,2,0x8a00,0x8a00,0x7500,22,CPU_ALL,
"jbc",OP_BADDR,OP_REL,0,2,0xaa00,0xaa00,0x5500,22,CPU_ALL,
"jmp",OP_CC,OP_REL,0,1,0x0d00,0x0d00,0x0200,23,CPU_ALL,
"jmpa",OP_CC,OP_JADDR,0,2,0xea00,0xea00,0x150f,14,CPU_ALL,
"jmpi",OP_CC,OP_REGIND,0,1,0x9c00,0x9c00,0x6300,15,CPU_ALL,
"jmpr",OP_CC,OP_REL,0,1,0x0d00,0x0d00,0x0200,23,CPU_ALL,
"jmps",OP_JADDR,0,0,2,0xfa00,0xfa00,0x0500,17,CPU_ALL,
"jnb",OP_BADDR,OP_REL,0,2,0x9a00,0x9a00,0x6500,22,CPU_ALL,
"jnbs",OP_BADDR,OP_REL,0,2,0xba00,0xba00,0x4500,22,CPU_ALL,
"mov",OP_GPR,OP_GPR,0,1,0xf000,0xf000,0x0f00,2,CPU_ALL,
"mov",OP_GPR,OP_IMM4,0,1,0xe000,0xe000,0x1f00,9,CPU_ALL,
"mov",OP_SFR,OP_IMM16,0,2,0xe600,0xe600,0x1900,7,CPU_ALL,
"mov",OP_GPR,OP_REGIND,0,1,0xa800,0xa800,0x5700,2,CPU_ALL,
"mov",OP_GPR,OP_POSTINC,0,1,0x9800,0x9800,0x6700,2,CPU_ALL,
"mov",OP_REGIND,OP_GPR,0,1,0xb800,0xb800,0x4700,3,CPU_ALL,
"mov",OP_PREDEC,OP_GPR,0,1,0x8800,0x8800,0x7700,3,CPU_ALL,
"mov",OP_REGIND,OP_REGIND,0,1,0xc800,0xc800,0x3700,2,CPU_ALL,
"mov",OP_POSTINC,OP_REGIND,0,1,0xd800,0xd800,0x2700,2,CPU_ALL,
"mov",OP_REGIND,OP_POSTINC,0,1,0xe800,0xe800,0x1700,2,CPU_ALL,
"mov",OP_GPR,OP_REGDISP,0,2,0xd400,0xd400,0x2b00,24,CPU_ALL,
"mov",OP_REGDISP,OP_GPR,0,2,0xc400,0xc400,0x3b00,28,CPU_ALL,
"mov",OP_REGIND,OP_ABS,0,2,0x8400,0x8400,0x7bf0,25,CPU_ALL,
"mov",OP_ABS,OP_REGIND,0,2,0x9400,0x9400,0x6bf0,30,CPU_ALL,
"mov",OP_SFR,OP_ABS,0,2,0xf200,0xf200,0x0d00,8,CPU_ALL,
"mov",OP_ABS,OP_SFR,0,2,0xf600,0xf600,0x0900,29,CPU_ALL,
"movb",OP_BGPR,OP_BGPR,0,1,0xf100,0xf100,0x0e00,2,CPU_ALL,
"movb",OP_BGPR,OP_IMM4,0,1,0xe100,0xe100,0x1e00,9,CPU_ALL,
"movb",OP_BSFR,OP_IMM16,0,2,0xe700,0xe700,0x1800,7,CPU_ALL,
"movb",OP_BGPR,OP_REGIND,0,1,0xa900,0xa900,0x5600,2,CPU_ALL,
"movb",OP_BGPR,OP_POSTINC,0,1,0x9900,0x9900,0x6600,2,CPU_ALL,
"movb",OP_REGIND,OP_BGPR,0,1,0xb900,0xb900,0x4600,3,CPU_ALL,
"movb",OP_PREDEC,OP_BGPR,0,1,0x8900,0x8900,0x7600,3,CPU_ALL,
"movb",OP_REGIND,OP_REGIND,0,1,0xc900,0xc900,0x3600,2,CPU_ALL,
"movb",OP_POSTINC,OP_REGIND,0,1,0xd900,0xd900,0x2600,2,CPU_ALL,
"movb",OP_REGIND,OP_POSTINC,0,1,0xe900,0xe900,0x1600,2,CPU_ALL,
"movb",OP_BGPR,OP_REGDISP,0,2,0xf400,0xf400,0x0b00,24,CPU_ALL,
"movb",OP_REGDISP,OP_BGPR,0,2,0xe400,0xe400,0x1b00,28,CPU_ALL,
"movb",OP_REGIND,OP_BABS,0,2,0xa400,0xa400,0x5bf0,25,CPU_ALL,
"movb",OP_BABS,OP_REGIND,0,2,0xb400,0xb400,0x4bf0,30,CPU_ALL,
"movb",OP_BSFR,OP_BABS,0,2,0xf300,0xf300,0x0c00,8,CPU_ALL,
"movb",OP_BABS,OP_BSFR,0,2,0xf700,0xf700,0x0800,29,CPU_ALL,
"movbs",OP_GPR,OP_BGPR,0,1,0xd000,0xd000,0x2f00,3,CPU_ALL,
"movbs",OP_SFR,OP_BABS,0,2,0xd200,0xd200,0x2d00,8,CPU_ALL,
"movbs",OP_ABS,OP_BSFR,0,2,0xd500,0xd500,0x2a00,29,CPU_ALL,
"movbz",OP_GPR,OP_BGPR,0,1,0xc000,0xc000,0x3f00,3,CPU_ALL,
"movbz",OP_SFR,OP_BABS,0,2,0xc200,0xc200,0x3d00,8,CPU_ALL,
"movbz",OP_ABS,OP_BSFR,0,2,0xc500,0xc500,0x3a00,29,CPU_ALL,
"mul",OP_GPR,OP_GPR,0,1,0x0b00,0x0b00,0xf400,2,CPU_ALL,
"mulu",OP_GPR,OP_GPR,0,1,0x1b00,0x1b00,0xe400,2,CPU_ALL,
"neg",OP_GPR,0,0,1,0x8100,0x8100,0x7e0f,20,CPU_ALL,
"negb",OP_BGPR,0,0,1,0xa100,0xa100,0x5e0f,20,CPU_ALL,
"nop",0,0,0,1,0xcc00,0xcc00,0x33ff,1,CPU_ALL,
"or",OP_GPR,OP_GPR,0,1,0x7000,0x7000,0x8f00,2,CPU_ALL,
"or",OP_GPR,OP_REG03IND,0,1,0x7800,0x7808,0x8704,4,CPU_ALL,
"or",OP_GPR,OP_POSTINC03,0,1,0x7800,0x780c,0x8700,5,CPU_ALL,
"or",OP_GPR,OP_IMM3,0,1,0x7800,0x7800,0x8708,6,CPU_ALL,
"or",OP_SFR,OP_IMM16,0,2,0x7600,0x7600,0x8900,7,CPU_ALL,
"or",OP_SFR,OP_ABS,0,2,0x7200,0x7200,0x8d00,8,CPU_ALL,
"or",OP_ABS,OP_SFR,0,2,0x7400,0x7400,0x8b00,29,CPU_ALL,
"orb",OP_BGPR,OP_BGPR,0,1,0x7100,0x7100,0x8e00,2,CPU_ALL,
"orb",OP_BGPR,OP_REG03IND,0,1,0x7900,0x7908,0x8604,4,CPU_ALL,
"orb",OP_BGPR,OP_POSTINC03,0,1,0x7900,0x790c,0x8600,5,CPU_ALL,
"orb",OP_BGPR,OP_IMM3,0,1,0x7900,0x7900,0x8608,6,CPU_ALL,
"orb",OP_BSFR,OP_IMM16,0,2,0x7700,0x7700,0x8800,7,CPU_ALL,
"orb",OP_BSFR,OP_BABS,0,2,0x7300,0x7300,0x8c00,8,CPU_ALL,
"orb",OP_BABS,OP_BSFR,0,2,0x7500,0x7500,0x8a00,29,CPU_ALL,
"pcall",OP_SFR,OP_JADDR,0,2,0xe200,0xe200,0x1d00,8,CPU_ALL,
"pop",OP_SFR,0,0,1,0xfc00,0xfc00,0x0300,26,CPU_ALL,
"prior",OP_GPR,OP_GPR,0,1,0x2b00,0x2b00,0xd400,2,CPU_ALL,
"push",OP_SFR,0,0,1,0xec00,0xec00,0x1300,26,CPU_ALL,
"pwrdn",OP_PROTECTED,0,0,2,0x9768,0x9768,0x6897,0,CPU_ALL,
"ret",0,0,0,1,0xcb00,0xcb00,0x34ff,1,CPU_ALL,
"reti",0,0,0,1,0xfb88,0xfb88,0x0477,1,CPU_ALL,
"retp",OP_SFR,0,0,1,0xeb00,0xeb00,0x1400,26,CPU_ALL,
"rets",0,0,0,1,0xdb00,0xdb00,0x24ff,1,CPU_ALL,
"rol",OP_GPR,OP_GPR,0,1,0x0c00,0x0c00,0xf300,2,CPU_ALL,
"rol",OP_GPR,OP_IMM4,0,1,0x1c00,0x1c00,0xe300,9,CPU_ALL,
"ror",OP_GPR,OP_GPR,0,1,0x2c00,0x2c00,0xd300,2,CPU_ALL,
"ror",OP_GPR,OP_IMM4,0,1,0x3c00,0x3c00,0xc300,9,CPU_ALL,
"scxt",OP_SFR,OP_IMM16,0,2,0xc600,0xc600,0x3900,7,CPU_ALL,
"scxt",OP_SFR,OP_ABS,0,2,0xd600,0xd600,0x2900,8,CPU_ALL,
"shl",OP_GPR,OP_GPR,0,1,0x4c00,0x4c00,0xb300,2,CPU_ALL,
"shl",OP_GPR,OP_IMM4,0,1,0x5c00,0x5c00,0xa300,9,CPU_ALL,
"shr",OP_GPR,OP_GPR,0,1,0x6c00,0x6c00,0x9300,2,CPU_ALL,
"shr",OP_GPR,OP_IMM4,0,1,0x7c00,0x7c00,0x8300,9,CPU_ALL,
"srst",OP_PROTECTED,0,0,2,0xb748,0xb748,0x48b7,0,CPU_ALL,
"srvwdt",OP_PROTECTED,0,0,2,0xa758,0xa758,0x58a7,0,CPU_ALL,
"sub",OP_GPR,OP_GPR,0,1,0x2000,0x2000,0xdf00,2,CPU_ALL,
"sub",OP_GPR,OP_REG03IND,0,1,0x2800,0x2808,0xd704,4,CPU_ALL,
"sub",OP_GPR,OP_POSTINC03,0,1,0x2800,0x280c,0xd700,5,CPU_ALL,
"sub",OP_GPR,OP_IMM3,0,1,0x2800,0x2800,0xd708,6,CPU_ALL,
"sub",OP_SFR,OP_IMM16,0,2,0x2600,0x2600,0xd900,7,CPU_ALL,
"sub",OP_SFR,OP_ABS,0,2,0x2200,0x2200,0xdd00,8,CPU_ALL,
"sub",OP_ABS,OP_SFR,0,2,0x2400,0x2400,0xdb00,29,CPU_ALL,
"subb",OP_BGPR,OP_BGPR,0,1,0x2100,0x2100,0xde00,2,CPU_ALL,
"subb",OP_BGPR,OP_REG03IND,0,1,0x2900,0x2908,0xd604,4,CPU_ALL,
"subb",OP_BGPR,OP_POSTINC03,0,1,0x2900,0x290c,0xd600,5,CPU_ALL,
"subb",OP_BGPR,OP_IMM3,0,1,0x2900,0x2900,0xd608,6,CPU_ALL,
"subb",OP_BSFR,OP_IMM16,0,2,0x2700,0x2700,0xd800,7,CPU_ALL,
"subb",OP_BSFR,OP_BABS,0,2,0x2300,0x2300,0xdc00,8,CPU_ALL,
"subb",OP_BABS,OP_BSFR,0,2,0x2500,0x2500,0xda00,29,CPU_ALL,
"subc",OP_GPR,OP_GPR,0,1,0x3000,0x3000,0xcf00,2,CPU_ALL,
"subc",OP_GPR,OP_REG03IND,0,1,0x3800,0x3808,0xc704,4,CPU_ALL,
"subc",OP_GPR,OP_POSTINC03,0,1,0x3800,0x380c,0xc700,5,CPU_ALL,
"subc",OP_GPR,OP_IMM3,0,1,0x3800,0x3800,0xc708,6,CPU_ALL,
"subc",OP_SFR,OP_IMM16,0,2,0x3600,0x3600,0xc900,7,CPU_ALL,
"subc",OP_SFR,OP_ABS,0,2,0x3200,0x3200,0xcd00,8,CPU_ALL,
"subc",OP_ABS,OP_SFR,0,2,0x3400,0x3400,0xcb00,29,CPU_ALL,
"subcb",OP_BGPR,OP_BGPR,0,1,0x3100,0x3100,0xce00,2,CPU_ALL,
"subcb",OP_BGPR,OP_REG03IND,0,1,0x3900,0x3908,0xc604,4,CPU_ALL,
"subcb",OP_BGPR,OP_POSTINC03,0,1,0x3900,0x390c,0xc600,5,CPU_ALL,
"subcb",OP_BGPR,OP_IMM3,0,1,0x3900,0x3900,0xc608,6,CPU_ALL,
"subcb",OP_BSFR,OP_IMM16,0,2,0x3700,0x3700,0xc800,7,CPU_ALL,
"subcb",OP_BSFR,OP_BABS,0,2,0x3300,0x3300,0xcc00,8,CPU_ALL,
"subcb",OP_BABS,OP_BSFR,0,2,0x3500,0x3500,0xca00,29,CPU_ALL,
"trap",OP_IMM7,0,0,1,0x9b00,0x9b00,0x6401,27,CPU_ALL,
"xor",OP_GPR,OP_GPR,0,1,0x5000,0x5000,0xaf00,2,CPU_ALL,
"xor",OP_GPR,OP_REG03IND,0,1,0x5800,0x5808,0xa704,4,CPU_ALL,
"xor",OP_GPR,OP_POSTINC03,0,1,0x5800,0x580c,0xa700,5,CPU_ALL,
"xor",OP_GPR,OP_IMM3,0,1,0x5800,0x5800,0xa708,6,CPU_ALL,
"xor",OP_SFR,OP_IMM16,0,2,0x5600,0x5600,0xa900,7,CPU_ALL,
"xor",OP_SFR,OP_ABS,0,2,0x5200,0x5200,0xad00,8,CPU_ALL,
"xor",OP_ABS,OP_SFR,0,2,0x5400,0x5400,0xab00,29,CPU_ALL,
"xorb",OP_BGPR,OP_BGPR,0,1,0x5100,0x5100,0xae00,2,CPU_ALL,
"xorb",OP_BGPR,OP_REG03IND,0,1,0x5900,0x5908,0xa604,4,CPU_ALL,
"xorb",OP_BGPR,OP_POSTINC03,0,1,0x5900,0x590c,0xa600,5,CPU_ALL,
"xorb",OP_BGPR,OP_IMM3,0,1,0x5900,0x5900,0xa608,6,CPU_ALL,
"xorb",OP_BSFR,OP_IMM16,0,2,0x5700,0x5700,0xa800,7,CPU_ALL,
"xorb",OP_BSFR,OP_BABS,0,2,0x5300,0x5300,0xac00,8,CPU_ALL,
"xorb",OP_BABS,OP_BSFR,0,2,0x5500,0x5500,0xaa00,29,CPU_ALL,

616
vasm-1/cpus/jagrisc/cpu.c Normal file
View File

@ -0,0 +1,616 @@
/*
* cpu.c Jaguar RISC cpu description file
* (c) in 2014-2017 by Frank Wille
*/
#include "vasm.h"
mnemonic mnemonics[] = {
#include "opcodes.h"
};
int mnemonic_cnt = sizeof(mnemonics) / sizeof(mnemonics[0]);
char *cpu_copyright = "vasm Jaguar RISC cpu backend 0.4c (c) 2014-2017 Frank Wille";
char *cpuname = "jagrisc";
int bitsperbyte = 8;
int bytespertaddr = 4;
int jag_big_endian = 1; /* defaults to big-endian (Atari Jaguar 68000) */
static uint8_t cpu_type = GPU|DSP;
static int OC_MOVEI,OC_UNPACK;
/* condition codes */
static regsym cc_regsyms[] = {
{"T", RTYPE_CC, 0, 0x00},
{"NE", RTYPE_CC, 0, 0x01},
{"EQ", RTYPE_CC, 0, 0x02},
{"CC", RTYPE_CC, 0, 0x04},
{"HI", RTYPE_CC, 0, 0x05},
{"CS", RTYPE_CC, 0, 0x08},
{"PL", RTYPE_CC, 0, 0x14},
{"MI", RTYPE_CC, 0, 0x18},
{"t", RTYPE_CC, 0, 0x00},
{"ne", RTYPE_CC, 0, 0x01},
{"eq", RTYPE_CC, 0, 0x02},
{"cc", RTYPE_CC, 0, 0x04},
{"hi", RTYPE_CC, 0, 0x05},
{"cs", RTYPE_CC, 0, 0x08},
{"pl", RTYPE_CC, 0, 0x14},
{"mi", RTYPE_CC, 0, 0x18},
{NULL, 0, 0, 0}
};
int init_cpu(void)
{
int i;
regsym *r;
for (i=0; i<mnemonic_cnt; i++) {
if (!strcmp(mnemonics[i].name,"movei"))
OC_MOVEI = i;
else if (!strcmp(mnemonics[i].name,"unpack"))
OC_UNPACK = i;
}
/* define all condition code register symbols */
for (r=cc_regsyms; r->reg_name!=NULL; r++)
add_regsym(r);
return 1;
}
int cpu_args(char *p)
{
if (!strncmp(p,"-m",2)) {
p += 2;
if (!stricmp(p,"gpu") || !stricmp(p,"tom"))
cpu_type = GPU;
else if (!stricmp(p,"dsp") || !stricmp(p,"jerry"))
cpu_type = DSP;
else if (!strcmp(p,"any"))
cpu_type = GPU|DSP;
else
return 0;
}
else if (!strcmp(p,"-big"))
jag_big_endian = 1;
else if (!strcmp(p,"-little"))
jag_big_endian = 0;
else
return 0;
return 1;
}
static int parse_reg(char **p)
{
int reg = -1;
char *rp = skip(*p);
char *s;
if (s = skip_identifier(rp)) {
regsym *sym = find_regsym(rp,s-rp);
if (sym!=NULL && sym->reg_type==RTYPE_R) {
reg = sym->reg_num;
}
else if (toupper((unsigned char)*rp++) == 'R') {
if (sscanf(rp,"%d",&reg)!=1 || reg<0 || reg>31)
reg = -1;
}
if (reg >= 0)
*p = s;
}
return reg;
}
static expr *parse_cc(char **p)
{
char *end;
*p = skip(*p);
if (end = skip_identifier(*p)) {
regsym *sym = find_regsym(*p,end-*p);
if (sym!=NULL && sym->reg_type==RTYPE_CC) {
*p = end;
return number_expr((taddr)sym->reg_num);
}
}
/* otherwise the condition code is any expression */
return parse_expr(p);
}
static void jagswap32(char *d,int32_t w)
/* write a 32-bit word with swapped halfs (Jaguar MOVEI) */
{
if (jag_big_endian) {
*d++ = (w >> 8) & 0xff;
*d++ = w & 0xff;
*d++ = (w >> 24) & 0xff;
*d = (w >> 16) & 0xff;
}
else {
/* @@@ Need to verify this! */
*d++ = w & 0xff;
*d++ = (w >> 8) & 0xff;
*d++ = (w >> 16) & 0xff;
*d = (w >> 24) & 0xff;
}
}
char *parse_cpu_special(char *start)
/* parse cpu-specific directives; return pointer to end of cpu-specific text */
{
char *name=start;
char *s;
if (s = skip_identifier(name)) {
/* Atari MadMac compatibility directives */
if (*name == '.') /* ignore leading dot */
name++;
if (s-name==3 && !strnicmp(name,"dsp",3)) {
cpu_type = DSP;
eol(s);
return skip_line(s);
}
else if (s-name==3 && !strnicmp(name,"gpu",3)) {
cpu_type = GPU;
eol(s);
return skip_line(s);
}
else if (s-name==8 && !strnicmp(name,"regundef",8) ||
s-name==9 && !strnicmp(name,"equrundef",9)) {
/* undefine a register symbol */
s = skip(s);
if (name = parse_identifier(&s)) {
undef_regsym(name,0,RTYPE_R);
myfree(name);
eol(s);
return skip_line(s);
}
}
else if (s-name==7 && !strnicmp(name,"ccundef",7)) {
/* undefine a condition code symbol */
s = skip(s);
if (name = parse_identifier(&s)) {
undef_regsym(name,0,RTYPE_CC);
myfree(name);
eol(s);
return skip_line(s);
}
}
}
return start;
}
int parse_cpu_label(char *labname,char **start)
/* parse cpu-specific directives following a label field,
return zero when no valid directive was recognized */
{
char *dir=*start;
char *s,*name;
hashdata data;
if (*dir == '.') /* ignore leading dot */
dir++;
if (s = skip_identifier(dir)) {
if (s-dir==6 && !strnicmp(dir,"regequ",6) ||
s-dir==4 && !strnicmp(dir,"equr",4)) {
/* label REGEQU Rn || label EQUR Rn */
int r;
if ((r = parse_reg(&s)) >= 0)
new_regsym(0,0,labname,RTYPE_R,0,r);
else
cpu_error(3); /* register expected */
eol(s);
*start = skip_line(s);
return 1;
}
else if (s-dir==5 && !strnicmp(dir,"ccdef",5)) {
/* label CCDEF expr */
expr *ccexp;
taddr val;
if ((ccexp = parse_cc(&s)) != NULL) {
if (eval_expr(ccexp,&val,NULL,0))
new_regsym(0,0,labname,RTYPE_CC,0,(int)val);
else
general_error(30); /* expression must be a constant */
}
else
general_error(9); /* @@@ */
eol(s);
*start = skip_line(s);
return 1;
}
}
return 0;
}
operand *new_operand(void)
{
operand *new = mymalloc(sizeof(*new));
new->type = NO_OP;
return new;
}
int jag_data_operand(int bits)
/* return data operand type for these number of bits */
{
if (bits & OPSZ_SWAP)
return DATAI_OP;
return bits==64 ? DATA64_OP : DATA_OP;
}
int parse_operand(char *p, int len, operand *op, int required)
{
int reg;
switch (required) {
case IMM0:
case IMM1:
case IMM1S:
case SIMM:
case IMMLW:
if (*p == '#')
p = skip(p+1); /* skip optional '#' */
case REL:
case DATA_OP:
case DATAI_OP:
if (required == IMM1S) {
op->val = make_expr(SUB,number_expr(32),parse_expr(&p));
required = IMM1; /* turn into IMM1 32-val for SHLQ */
}
else
op->val = parse_expr(&p);
break;
case DATA64_OP:
op->val = parse_expr_huge(&p);
break;
case REG: /* Rn */
op->reg = parse_reg(&p);
if (op->reg < 0)
return PO_NOMATCH;
break;
case IREG: /* (Rn) */
if (*p++ != '(')
return PO_NOMATCH;
op->reg = parse_reg(&p);
if (op->reg < 0)
return PO_NOMATCH;
if (*p != ')')
return PO_NOMATCH;
break;
case IR14D: /* (R14+d) */
case IR15D: /* (R15+d) */
if (*p++ != '(')
return PO_NOMATCH;
reg = parse_reg(&p);
if ((required==IR14D && reg!=14) || (required==IR15D && reg!=15))
return PO_NOMATCH;
if (*p++ != '+')
return PO_NOMATCH;
p = skip(p);
op->val = parse_expr(&p);
p = skip(p);
if (*p != ')')
return PO_NOMATCH;
break;
case IR14R: /* (R14+Rn) */
case IR15R: /* (R15+Rn) */
if (*p++ != '(')
return PO_NOMATCH;
reg = parse_reg(&p);
if ((required==IR14R && reg!=14) || (required==IR15R && reg!=15))
return PO_NOMATCH;
if (*p++ != '+')
return PO_NOMATCH;
op->reg = parse_reg(&p);
if (op->reg < 0)
return PO_NOMATCH;
if (*p != ')')
return PO_NOMATCH;
break;
case CC: /* condition code: t, eq, ne, mi, pl, cc, cs, ... */
op->val = parse_cc(&p);
break;
case PC: /* PC register */
if (toupper((unsigned char)*p) != 'P' ||
toupper((unsigned char)*(p+1)) != 'C' ||
ISIDCHAR(*(p+2)))
return PO_NOMATCH;
break;
default:
return PO_NOMATCH;
}
op->type = required;
return PO_MATCH;
}
static int32_t eval_oper(instruction *ip,operand *op,section *sec,
taddr pc,dblock *db)
{
symbol *base = NULL;
int optype = op->type;
int btype;
taddr val,loval,hival,mask;
switch (optype) {
case PC:
return 0;
case REG:
case IREG:
case IR14R:
case IR15R:
return op->reg;
case IMM0:
case IMM1:
case SIMM:
case IMMLW:
case IR14D:
case IR15D:
case REL:
case CC:
mask = 0x1f;
if (!eval_expr(op->val,&val,sec,pc))
btype = find_base(op->val,&base,sec,pc);
if (optype==IMM0 || optype==CC || optype==IMM1 || optype==SIMM) {
if (base != NULL) {
loval = -32;
hival = 32;
if (btype != BASE_ILLEGAL) {
if (db) {
add_extnreloc_masked(&db->relocs,base,val,
btype==BASE_PCREL?REL_PC:REL_ABS,
jag_big_endian?6:5,5,0,0x1f);
base = NULL;
}
}
}
else if (optype==IMM1) {
loval = 1;
hival = 32;
}
else if (optype==SIMM) {
loval = -16;
hival = 15;
}
else {
loval = 0;
hival = 31;
}
}
else if (optype==IR14D || optype==IR15D) {
if (base==NULL && val==0) {
/* Optimize (Rn+0) to (Rn). Assume that the "load/store (Rn+d)"
instructions follow directly after "load/store (Rn)". */
ip->code -= optype==IR14D ? 1 : 2;
op->type = IREG;
op->reg = optype==IR14D ? 14 : 15;
return op->reg;
}
loval = 1;
hival = 32;
}
else if (optype==IMMLW) {
mask = ~0;
if (base != NULL) {
if (btype != BASE_ILLEGAL) {
if (db) {
/* two relocations for LSW first, then MSW */
add_extnreloc_masked(&db->relocs,base,val,
btype==BASE_PCREL?REL_PC:REL_ABS,
0,16,2,0xffff);
add_extnreloc_masked(&db->relocs,base,val,
btype==BASE_PCREL?REL_PC:REL_ABS,
16,16,2,0xffff0000);
base = NULL;
}
}
}
}
else if (optype==REL) {
loval = -16;
hival = 15;
if ((base!=NULL && btype==BASE_OK && !is_pc_reloc(base,sec)) ||
base==NULL) {
/* known label from same section or absolute label */
val = (val - (pc + 2)) / 2;
}
else if (btype == BASE_OK) {
/* external label or from a different section (distance / 2) */
add_extnreloc_masked(&db->relocs,base,val-2,REL_PC,
jag_big_endian?6:5,5,0,0x3e);
}
base = NULL;
}
else ierror(0);
if (base != NULL)
general_error(38); /* bad or unhandled reloc: illegal relocation */
/* range check for this addressing mode */
if (mask!=~0 && (val<loval || val>hival))
cpu_error(1,(long)loval,(long)hival);
return val & mask;
default:
ierror(0);
break;
}
return 0; /* default */
}
size_t instruction_size(instruction *ip, section *sec, taddr pc)
{
return ip->code==OC_MOVEI ? 6 : 2;
}
dblock *eval_instruction(instruction *ip, section *sec, taddr pc)
{
dblock *db = new_dblock();
int32_t src=0,dst=0,extra;
int size = 2;
uint16_t inst;
/* get source and destination argument, when present */
if (ip->op[0])
dst = eval_oper(ip,ip->op[0],sec,pc,db);
if (ip->op[1]) {
if (ip->code == OC_MOVEI) {
extra = dst;
size = 6;
}
else
src = dst;
dst = eval_oper(ip,ip->op[1],sec,pc,db);
}
else if (ip->code == OC_UNPACK)
src = 1; /* pack(src=0)/unpack(src=1) use the same opcode */
/* store and jump instructions need the second operand in the source field */
if (mnemonics[ip->code].ext.flags & OPSWAP) {
extra = src;
src = dst;
dst = extra;
}
/* allocate dblock data for instruction */
db->size = size;
db->data = mymalloc(size);
/* construct the instruction word out of opcode and source/dest. value */
inst = (mnemonics[ip->code].ext.opcode & 63) << 10;
inst |= ((src&31) << 5) | (dst & 31);
/* write instruction */
if (jag_big_endian) {
db->data[0] = (inst >> 8) & 0xff;
db->data[1] = inst & 0xff;
}
else {
db->data[0] = inst & 0xff;
db->data[1] = (inst >> 8) & 0xff;
}
/* extra words for MOVEI are always written in the order lo-word, hi-word */
if (size == 6)
jagswap32(&db->data[2],extra);
return db;
}
dblock *eval_data(operand *op, size_t bitsize, section *sec, taddr pc)
{
dblock *db = new_dblock();
taddr val;
if (bitsize!=8 && bitsize!=16 && bitsize!=32 && bitsize!=64)
cpu_error(0,bitsize); /* data size not supported */
if (op->type!=DATA_OP && op->type!=DATA64_OP && op->type!=DATAI_OP)
ierror(0);
db->size = bitsize >> 3;
db->data = mymalloc(db->size);
if (op->type == DATA64_OP) {
thuge hval;
if (!eval_expr_huge(op->val,&hval))
general_error(59); /* cannot evaluate huge integer */
huge_to_mem(jag_big_endian,db->data,db->size,hval);
}
else {
if (!eval_expr(op->val,&val,sec,pc)) {
symbol *base;
int btype;
btype = find_base(op->val,&base,sec,pc);
if (base!=NULL && btype!=BASE_ILLEGAL) {
if (op->type == DATAI_OP) {
/* swapped: two relocations for LSW first, then MSW */
add_extnreloc_masked(&db->relocs,base,val,
btype==BASE_PCREL?REL_PC:REL_ABS,
0,16,0,0xffff);
add_extnreloc_masked(&db->relocs,base,val,
btype==BASE_PCREL?REL_PC:REL_ABS,
16,16,0,0xffff0000);
}
else /* normal 8, 16, 32 bit relocation */
add_extnreloc(&db->relocs,base,val,
btype==BASE_PCREL?REL_PC:REL_ABS,0,bitsize,0);
}
else if (btype != BASE_NONE)
general_error(38); /* illegal relocation */
}
switch (db->size) {
case 1:
db->data[0] = val & 0xff;
break;
case 2:
case 4:
if (op->type == DATAI_OP)
jagswap32(db->data,(int32_t)val);
else
setval(jag_big_endian,db->data,db->size,val);
break;
default:
ierror(0);
break;
}
}
return db;
}
int cpu_available(int idx)
{
return (mnemonics[idx].ext.flags & cpu_type) != 0;
}

86
vasm-1/cpus/jagrisc/cpu.h Normal file
View File

@ -0,0 +1,86 @@
/*
** cpu.h Jaguar RISC cpu-description header-file
** (c) in 2014-2017 by Frank Wille
*/
extern int jag_big_endian;
#define BIGENDIAN (jag_big_endian)
#define LITTLEENDIAN (!jag_big_endian)
#define VASM_CPU_JAGRISC 1
/* maximum number of operands for one mnemonic */
#define MAX_OPERANDS 2
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 0
/* data type to represent a target-address */
typedef int32_t taddr;
typedef uint32_t utaddr;
/* minimum instruction alignment */
#define INST_ALIGN 2
/* default alignment for n-bit data */
#define DATA_ALIGN(n) ((n<=8)?1:2)
/* operand class for n-bit data definitions */
int jag_data_operand(int);
#define DATA_OPERAND(n) jag_data_operand(n)
/* returns true when instruction is valid for selected cpu */
#define MNEMONIC_VALID(i) cpu_available(i)
/* type to store each operand */
typedef struct {
uint8_t type;
int8_t reg;
expr *val;
} operand;
/* operand types */
enum {
NO_OP=0,
DATA_OP,
DATA64_OP,
DATAI_OP, /* 32-bit with swapped halfwords */
REG, /* register Rn */
IMM0, /* 5-bit immediate expression (0-31) */
IMM1, /* 5-bit immediate expression (1-32) */
IMM1S, /* 5-bit immediate expression 32-(1-32) for SHLQ */
SIMM, /* 5-bit signed immediate expression (-16 - 15) */
IMMLW, /* 32-bit immediate expression in extra longword */
IREG, /* register indirect (Rn) */
IR14D, /* register R14 plus displacement indirect (R14+n) */
IR15D, /* register R15 plus displacement indirect (R15+n) */
IR14R, /* register R14 plus register Rn indirect (R14+Rn) */
IR15R, /* register R15 plus register Rn indirect (R15+Rn) */
CC, /* condition code, t, cc, cs, eq, ne, mi, pl, hi */
REL, /* relative branch, PC + 2 + (-16..15) words */
PC /* PC register */
};
/* additional mnemonic data */
typedef struct {
uint8_t opcode;
uint8_t flags;
} mnemonic_extension;
/* Values defined for the 'flags' field of mnemonic_extension. */
#define GPU 1
#define DSP 2
#define ANY GPU|DSP
#define OPSWAP 128 /* swapped operands in instruction word encoding */
/* Register symbols */
#define HAVE_REGSYMS
#define REGSYMHTSIZE 64
#define RTYPE_R 0 /* R0-R31 */
#define RTYPE_CC 1 /* condition codes (0-31) */
/* Prototypes */
int cpu_available(int);
int parse_cpu_label(char *,char **);
#define PARSE_CPU_LABEL(l,s) parse_cpu_label(l,s)

View File

@ -0,0 +1,3 @@
"data size %d not supported",ERROR,
"value from %ld to %ld required",ERROR,
"register expected",ERROR,

View File

@ -0,0 +1,72 @@
"abs", { REG }, { 22, ANY },
"add", { REG, REG }, { 0, ANY },
"addc", { REG, REG }, { 1, ANY },
"addq", { IMM1, REG }, { 2, ANY },
"addqmod", { IMM1, REG }, { 63, DSP },
"addqt", { IMM1, REG }, { 3, ANY },
"and", { REG, REG }, { 9, ANY },
"bclr", { IMM0, REG }, { 15, ANY },
"bset", { IMM0, REG }, { 14, ANY },
"btst", { IMM0, REG }, { 13, ANY },
"cmp", { REG, REG }, { 30, ANY },
"cmpq", { SIMM, REG }, { 31, ANY },
"div", { REG, REG }, { 21, ANY },
"imacn", { REG, REG }, { 20, ANY },
"imult", { REG, REG }, { 17, ANY },
"imultn", { REG, REG }, { 18, ANY },
"jr", { REL }, { 53, ANY|OPSWAP },
"jr", { CC, REL }, { 53, ANY|OPSWAP },
"jump", { IREG }, { 52, ANY|OPSWAP },
"jump", { CC, IREG }, { 52, ANY|OPSWAP },
"load", { IREG, REG }, { 41, ANY },
"load", { IR14R, REG }, { 58, ANY },
"load", { IR15R, REG }, { 59, ANY },
"load", { IR14D, REG }, { 43, ANY },
"load", { IR15D, REG }, { 44, ANY },
"loadb", { IREG, REG }, { 39, ANY },
"loadp", { IREG, REG }, { 42, GPU },
"loadw", { IREG, REG }, { 40, ANY },
"mirror", { REG, IREG }, { 48, DSP|OPSWAP },
"mmult", { REG, REG }, { 54, ANY },
"move", { REG, REG }, { 34, ANY },
"move", { PC, REG }, { 51, ANY },
"movefa", { REG, REG }, { 37, ANY },
"movei", { IMMLW, REG }, { 38, ANY },
"moveq", { IMM0, REG }, { 35, ANY },
"moveta", { REG, REG }, { 36, ANY },
"mtoi", { REG, REG }, { 55, ANY },
"mult", { REG, REG }, { 16, ANY },
"neg", { REG }, { 8, ANY },
"nop", { NO_OP }, { 57, ANY },
"normi", { REG, REG }, { 56, ANY },
"not", { REG }, { 12, ANY },
"or", { REG, REG }, { 10, ANY },
"pack", { REG }, { 63, GPU },
"resmac", { REG }, { 19, ANY },
"ror", { REG, REG }, { 28, ANY },
"rorq", { IMM1, REG }, { 29, ANY },
"sat8", { REG }, { 32, GPU },
"sat16", { REG }, { 33, GPU },
"sat16s", { REG }, { 33, DSP },
"sat24", { REG }, { 62, GPU },
"sat32s", { REG }, { 42, DSP },
"sh", { REG, REG }, { 23, ANY },
"sha", { REG, REG }, { 26, ANY },
"sharq", { IMM1, REG }, { 27, ANY },
"shlq", { IMM1S, REG }, { 24, ANY },
"shrq", { IMM1, REG }, { 25, ANY },
"store", { REG, IREG }, { 47, ANY|OPSWAP },
"store", { REG, IR14R }, { 60, ANY|OPSWAP },
"store", { REG, IR15R }, { 61, ANY|OPSWAP },
"store", { REG, IR14D }, { 49, ANY|OPSWAP },
"store", { REG, IR15D }, { 50, ANY|OPSWAP },
"storeb", { REG, IREG }, { 45, ANY|OPSWAP },
"storep", { REG, IREG }, { 48, GPU|OPSWAP },
"storew", { REG, IREG }, { 46, ANY|OPSWAP },
"sub", { REG, REG }, { 4, ANY },
"subc", { REG, REG }, { 5, ANY },
"subq", { IMM1, REG }, { 6, ANY },
"subqmod", { IMM1, REG }, { 32, DSP },
"subqt", { IMM1, REG }, { 7, ANY },
"unpack", { REG }, { 63, GPU },
"xor", { REG, REG }, { 11, ANY },

6003
vasm-1/cpus/m68k/cpu.c Normal file

File diff suppressed because it is too large Load Diff

441
vasm-1/cpus/m68k/cpu.h Normal file
View File

@ -0,0 +1,441 @@
/*
** cpu.h Motorola M68k, CPU32 and ColdFire cpu-description header-file
** (c) in 2002,2006-2020 by Frank Wille
*/
#define BIGENDIAN 1
#define LITTLEENDIAN 0
#define VASM_CPU_M68K 1
#define MNEMOHTABSIZE 0x4000
/* maximum number of operands for one mnemonic */
#define MAX_OPERANDS 6
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 1
/* maximum number of additional command-line-flags for this cpu */
/* data type to represent a target-address */
typedef int32_t taddr;
typedef uint32_t utaddr;
/* instruction extension */
#define HAVE_INSTRUCTION_EXTENSION 1
typedef struct {
union {
struct {
unsigned char flags;
signed char last_size;
signed char orig_ext;
char unused;
} real;
struct {
struct instruction *next;
} copy;
} un;
} instruction_ext;
#define IFL_RETAINLASTSIZE 1 /* retain current last_size value */
#define IFL_UNSIZED 2 /* instruction had no size extension */
/* we use OPTS atoms for cpu-specific options */
#define HAVE_CPU_OPTS 1
typedef struct {
int cmd;
int arg;
} optcmd;
/* optcmd commands - warning: print_cpu_opts() depends on the order! */
enum {
OCMD_NOP,
OCMD_CPU,
OCMD_FPU,
OCMD_SDREG,
OCMD_NOOPT,
OCMD_OPTGEN,
OCMD_OPTMOVEM,
OCMD_OPTPEA,
OCMD_OPTCLR,
OCMD_OPTST,
OCMD_OPTLSL,
OCMD_OPTMUL,
OCMD_OPTDIV,
OCMD_OPTFCONST,
OCMD_OPTBRAJMP,
OCMD_OPTJBRA,
OCMD_OPTPC,
OCMD_OPTBRA,
OCMD_OPTDISP,
OCMD_OPTABS,
OCMD_OPTMOVEQ,
OCMD_OPTNMOVQ,
OCMD_OPTQUICK,
OCMD_OPTBRANOP,
OCMD_OPTBDISP,
OCMD_OPTODISP,
OCMD_OPTLEA,
OCMD_OPTLQUICK,
OCMD_OPTIMMADDR,
OCMD_OPTSPEED,
OCMD_OPTSIZE,
OCMD_SMALLCODE,
OCMD_SMALLDATA,
OCMD_OPTWARN,
OCMD_CHKPIC,
OCMD_CHKTYPE,
OCMD_NOWARN
};
/* minimum instruction alignment */
#define INST_ALIGN 2
/* default alignment for n-bit data */
#define DATA_ALIGN(n) ((n<=8)?1:2)
/* operand class for n-bit data definitions */
#define DATA_OPERAND(n) m68k_data_operand(n)
/* returns true when instruction is valid for selected cpu */
#define MNEMONIC_VALID(n) m68k_available(n)
/* parse cpu-specific directives with label */
#define PARSE_CPU_LABEL(l,s) parse_cpu_label(l,s)
/* we define one additional, but internal, unary operation, to count 1-bits */
int ext_unary_eval(int,taddr,taddr *,int);
int ext_find_base(symbol **,expr *,section *,taddr);
#define CNTONES (LAST_EXP_TYPE+1)
#define EXT_UNARY_EVAL(t,v,r,c) ext_unary_eval(t,v,r,c)
#define EXT_FIND_BASE(b,e,s,p) BASE_ILLEGAL
/* type to store each operand */
typedef struct {
signed char mode;
signed char reg;
uint16_t format; /* used for (d8,An/PC,Rn) and ext.addr.modes */
unsigned char bf_offset; /* bitfield offset, k-factor or MAC Upper Word */
unsigned char bf_width; /* bitfield width or MAC-MASK '&' */
int8_t basetype[2]; /* BASE_OK=normal, BASE=PCREL=pc-relative base */
uint32_t flags;
expr *value[2]; /* immediate, abs. or displacem. expression */
/* filled during instruction_size(): */
taddr extval[2]; /* evaluated expression from value[0/1] */
symbol *base[2]; /* symbol base for value[0/1], NULL otherwise */
} operand;
/* flags */
/* Note: FL_CheckMask bits are used together with optype.flags OTF-bits */
#define FL_ExtVal0 1 /* extval[0] is set */
#define FL_ExtVal1 2 /* extval[1] is set */
#define FL_UsesFormat 4 /* operand uses format word */
#define FL_020up 8 /* 020+ addressing mode */
#define FL_noCPU32 0x10 /* addressing mode not available for CPU32 */
#define FL_BFoffsetDyn 0x20 /* dynamic bitfield offset specified */
#define FL_BFwidthDyn 0x40 /* dynamic bitfield width specified */
#define FL_DoNotEval 0x80 /* do not evaluate, extval and base are ok */
/*#define FL_PossRegList 0x80 parser is not sure if operand is RegList */
#define FL_NoOptBase 0x100 /* never optimize base displacement */
#define FL_NoOptOuter 0x200 /* never optimize outer displacement */
#define FL_NoOpt 0x300 /* never optimize this whole operand */
#define FL_ZBase 0x400 /* ZAn base register specified */
#define FL_ZIndex 0x800 /* ZRn index register specified */
#define FL_BaseReg 0x1000 /* BASEREG expression in exp.value[0] */
#define FL_BnReg 0x4000 /* Apollo: Bn register instead of An */
#define FL_MAC 0x8000 /* ColdFire MAC specific extensions */
#define FL_Bitfield 0x10000 /* operand uses bf_offset/bf_width */
#define FL_DoubleReg 0x20000 /* Dm:Dn or (Rm):(Rn), where both registers
are put into "reg": 0nnn0mmm */
#define FL_KFactor 0x40000 /* k-factor <ea>{#n} or <ea>{Dn}, which
can be found in bf_offset */
#define FL_FPSpec 0x80000 /* special FPU reg. FPIAR/FPCR/FPSR only */
#define FL_CheckMask 0xfc000 /* bits to check, when comparing with
flags from struct optype */
/* addressing modes */
#define MODE_Dn 0
#define MODE_An 1
#define MODE_AnIndir 2
#define MODE_AnPostInc 3
#define MODE_AnPreDec 4
#define MODE_An16Disp 5
#define MODE_An8Format 6 /* uses format word */
#define MODE_Extended 7 /* reg determines addressing mode */
#define MODE_FPn 8 /* FPU register */
#define MODE_SpecReg 9 /* reg determines index into SpecRegs */
/* reg encodings for MODE_Extended: */
#define REG_AbsShort 0
#define REG_AbsLong 1
#define REG_PC16Disp 2
#define REG_PC8Format 3 /* uses format word */
#define REG_Immediate 4
#define REG_RnList 5 /* An/Dn register list in value[0] */
#define REG_FPnList 6 /* FPn register list in value[0] */
/* format word */
#define FW_IndexAn 0x8000
#define FW_IndexReg_Shift 12
#define FW_IndexReg(n) ((n)<<FW_IndexReg_Shift)
#define FW_LongIndex 0x0800
#define FW_Scale_Shift 9
#define FW_Scale(n) ((n)<<FW_Scale_Shift)
#define FW_FullFormat 0x0100
#define FW_BaseSuppress 0x0080
#define FW_IndexSuppress 0x0040
#define FW_BDSize_Shift 4
#define FW_BDSize(n) ((n)<<FW_BDSize_Shift)
#define FW_getBDSize(n) (((n)>>FW_BDSize_Shift)&3)
#define FW_Postindexed 0x0004
#define FW_IndSize(n) (n)
#define FW_getIndSize(n) (n&3)
#define FW_None 0
#define FW_Null 1
#define FW_Word 2
#define FW_Long 3
#define FW_SizeMask 3
/* register macros */
#define REGAn 8
#define REGPC 0x10
#define REGBn 0x20 /* Apollo only */
#define REGZero 0x80
#define REGisAn(n) ((n)&REGAn)
#define REGisDn(n) (!((n)&REGAn))
#define REGisPC(n) ((n)&REGPC)
#define REGisZero(n) ((n)&REGZero)
#define REGisBn(n) ((n)&REGBn) /* Apollo only */
#define REGget(n) ((n)&(REGAn-1))
#define REGgetA(n) ((n)&(REGPC-1))
#define REGext_Shift 8
#define REGext(n) (((n)&0x700)>>REGext_Shift)
#define REGscale_Shift 12
#define REGscale(n) (((n)&0x3000)>>REGscale_Shift)
/* MAC scale-factor, stored as value[0] */
#define MACSF_None 0
#define MACSF_ShiftLeft 1
#define MACSF_ShiftRight 3
/* special CPU registers */
struct specreg {
char *name;
int code; /* -1 means no code, syntax-check only */
uint32_t available;
};
/* extension codes */
#define EXT_BYTE 1
#define EXT_WORD 2
#define EXT_LONG 3
#define EXT_SINGLE 4
#define EXT_DOUBLE 5
#define EXT_EXTENDED 6
#define EXT_PACKED 7
#define EXT_UPPER 2 /* ColdFire MAC upper register word */
#define EXT_LOWER 3 /* ColdFire MAC lower register word */
#define EXT_MASK 7
struct addrmode {
signed char mode;
signed char reg;
};
#define AM_Dn 0
#define AM_An 1
#define AM_AnIndir 2
#define AM_AnPostInc 3
#define AM_AnPreDec 4
#define AM_An16Disp 5
#define AM_An8Format 6
#define AM_AbsShort 7
#define AM_AbsLong 8
#define AM_PC16Disp 9
#define AM_PC8Format 10
#define AM_Immediate 11
#define AM_RnList 12
#define AM_FPnList 13
#define AM_FPn 14
#define AM_SpecReg 15
/* operand types */
struct optype {
uint16_t modes; /* addressing modes allowed (0-15, see above) */
uint32_t flags;
unsigned char first;
unsigned char last;
};
/* flags */
/* Note: Do not allocate bits from FL_CheckMask! */
#define OTF_NOSIZE 1 /* this addr. mode requires no additional bytes */
#define OTF_BRANCH 2 /* branch instruction */
#define OTF_DATA 4 /* data definition */
#define OTF_FLTIMM 8 /* base10 immediate values are floating point */
#define OTF_QUADIMM 0x10 /* immediate values are 64 bits */
#define OTF_SPECREG 0x20 /* check for special registers during parse */
#define OTF_SRRANGE 0x40 /* check range between first/last only */
#define OTF_REGLIST 0x80 /* register list required, even when single reg. */
#define OTF_CHKVAL 0x100 /* compare op. value against first/last */
#define OTF_CHKREG 0x200 /* compare op. register against first/last */
#define OTF_VXRNG2 0x400 /* Apollo AMMX Rn:Rn+1 vector register range */
#define OTF_VXRNG4 0x800 /* Apollo AMMX Rn-Rn+3 vector register range */
/* additional mnemonic data */
typedef struct {
uint16_t place[MAX_OPERANDS];
uint16_t opcode[2];
uint16_t size;
uint32_t available;
} mnemonic_extension;
/* size qualifiers, lowest two bits specify opcode size in words! */
#define SIZE_UNSIZED 0
#define SIZE_BYTE 0x100
#define SIZE_WORD 0x200
#define SIZE_LONG 0x400
#define SIZE_SINGLE 0x800
#define SIZE_DOUBLE 0x1000
#define SIZE_EXTENDED 0x2000
#define SIZE_PACKED 0x4000
#define SIZE_MASK 0x7f00
#define SIZE_UNAMBIG 0x8000 /* only a single size allowed for this mnemonic */
#define S_CFCHECK 0x80 /* SIZE_LONG only, when mcf (Coldfire) set */
#define S_NONE 4
#define S_STD S_NONE+4 /* 1st word, bits 6-7 */
#define S_STD1 S_STD+4 /* 1st word, bits 6-7, b=1,w=2,l=3 */
#define S_HI S_STD1+4 /* 1st word, bits 9-10 */
#define S_CAS S_HI+4 /* 1st word, bits 9-10, b=1,w=2,l=3 */
#define S_MOVE S_CAS+4 /* move instruction, 1st word bits 12-13 */
#define S_WL8 S_MOVE+4 /* w/l flag in 1st word bit 8 */
#define S_LW7 S_WL8+4 /* l/w flag in 1st word bit 7 */
#define S_WL6 S_LW7+4 /* w/l flag in 1st word bit 6 */
#define S_TRAP S_WL6+4 /* 1st word, bits 1-0, w=2, l=3 */
#define S_EXT S_TRAP+4 /* 2nd word, bits 6-7 */
#define S_FP S_EXT+4 /* 2nd word, bits 12-10 (l=0,s,x,p,w,d,b) */
#define S_MAC S_FP+4 /* w/l flag in 2nd word bit 11 */
#define S_OPCODE_SIZE(n) (n&3)
#define S_SIZEMODE(n) (n&0x7c)
/* short cuts */
#define UNS SIZE_UNSIZED
#define B SIZE_BYTE
#define W SIZE_WORD
#define L SIZE_LONG
#define Q SIZE_DOUBLE
#define SBW (SIZE_BYTE|SIZE_WORD|SIZE_SINGLE) /* .s = .b for branches */
#define SBWL (SIZE_BYTE|SIZE_WORD|SIZE_LONG|SIZE_SINGLE)
#define BW (SIZE_BYTE|SIZE_WORD)
#define WL (SIZE_WORD|SIZE_LONG)
#define BWL (SIZE_BYTE|SIZE_WORD|SIZE_LONG)
#define CFWL (SIZE_WORD|SIZE_LONG|S_CFCHECK)
#define CFBWL (SIZE_BYTE|SIZE_WORD|SIZE_LONG|S_CFCHECK)
#define ANY (SIZE_BYTE|SIZE_WORD|SIZE_LONG|SIZE_SINGLE|SIZE_DOUBLE| \
SIZE_EXTENDED|SIZE_PACKED)
#define CFANY (SIZE_BYTE|SIZE_WORD|SIZE_LONG|SIZE_SINGLE|SIZE_DOUBLE)
#define FX SIZE_EXTENDED
#define FD SIZE_DOUBLE
/* operand insertion info */
struct oper_insert {
unsigned char mode; /* insert mode (see below) */
unsigned char size; /* number of bits to insert */
unsigned char pos; /* bit position for inserted value in stream */
unsigned char flags;
void (*insert)(unsigned char *,struct oper_insert *,operand *);
};
/* insert modes */
#define M_nop 0 /* do nothing for this operand */
#define M_noea 1 /* don't store ea, only extension words */
#define M_ea 2 /* insert mode/reg in lowest 6 bits */
#define M_high_ea 3 /* insert reg/mode in bits 11-6 (MOVE) */
#define M_bfea 4 /* insert std. ea and bitfield offset/width */
#define M_kfea 5 /* insert std. ea and k-factor/dest.format */
#define M_func 6 /* use insert() function */
#define M_branch 7 /* extval0 contains branch label */
#define M_val0 8 /* extval0 at specified position */
#define M_reg 9 /* insert reg at specified position */
/* flags */
#define IIF_MASK 1 /* value 2^size is represented by a 0 (M_val0)
recognize MASK-flag for MAC instr. (M_ea) */
#define IIF_BCC 2 /* Bcc branch, opcode is modified */
#define IIF_REVERSE 4 /* store bits in reverse order (M_val0) */
#define IIF_NOMODE 8 /* don't store ea mode specifier in opcode */
#define IIF_SIGNED 16 /* value is signed (M_val0) */
#define IIF_3Q 64 /* MOV3Q: -1 is written as 0 (M_val0) */
#define IIF_ABSVAL 128 /* make sure first expr. is absolute (M_func) */
/* redefinition for AMMX special registers (M_func) */
#define IIF_A 8 /* RegBit 4 to A-bit (bit-position 8) */
#define IIF_B 7 /* RegBit 4 to B-bit (bit-position 7) */
#define IIF_D 6 /* RegBit 4 to D-bit (bit-position 6) */
/* CPU models and their type-flags */
struct cpu_models {
char name[8];
uint32_t type;
};
/* cpu types for availability check - warning: order is important */
#define CPUMASK 0x00ffffff
#define m68000 0x00000001
#define m68010 0x00000002
#define m68020 0x00000004
#define m68030 0x00000008
#define m68040 0x00000010
#define m68060 0x00000020
#define m68881 0x00000040
#define m68882 m68881
#define m68851 0x00000080
#define cpu32 0x00000100
#define mcfa 0x00000200
#define mcfaplus 0x00000400
#define mcfb 0x00000800
#define mcfc 0x00001000
#define mcfhwdiv 0x00002000
#define mcfmac 0x00004000
#define mcfemac 0x00008000
#define mcfusp 0x00010000
#define mcffpu 0x00020000
#define mcfmmu 0x00040000
#define ac68080 0x00100000
#define mgas 0x20000000 /* a GNU-as specific mnemonic */
#define malias 0x40000000 /* a bad alias which we should warn about */
#define mfpu 0x80000000 /* just to check if CP-ID needs to be inserted */
/* handy aliases */
#define m68k (m68000|m68010|m68020|m68030|m68040|m68060)
#define apollo (ac68080)
#define mcf (mcfa|mcfaplus|mcfb|mcfc)
#define mcf_all (mcfa|mcfaplus|mcfb|mcfc|mcfhwdiv|mcfmac|mcfemac|mcfusp|mcffpu|mcfmmu)
#define mfloat (mfpu|m68881|m68882|m68040|m68060)
#define mmmu (m68851|m68030|m68040|m68060)
#define m68040up (m68040|m68060|apollo)
#define m68030up (m68030|m68040up)
#define m68020up (m68020|m68030up)
#define m68010up (m68010|cpu32|m68020up)
#define m68000up (m68000|m68010up)
/* register symbols */
#define HAVE_REGSYMS
#define REGSYMHTSIZE 256
#define RSTYPE_Dn 0
#define RSTYPE_An 1
#define RSTYPE_FPn 2
#define RSTYPE_Bn 3 /* Apollo only */
/* MID for a.out format */
extern int m68k_mid;
#define MID m68k_mid
/* exported functions */
int m68k_available(int);
int m68k_data_operand(int);
int parse_cpu_label(char *,char **);

View File

@ -0,0 +1,72 @@
"instruction not supported on selected architecture",FATAL|ERROR,
"illegal addressing mode",ERROR,
"invalid register list",ERROR,
"missing ) in register indirect addressing mode",ERROR,
"address register required",ERROR,
"bad size extension",ERROR, /* 05 */
"displacement at bad position",WARNING,
"base or index register expected",ERROR,
"missing ] in memory indirect addressing mode",ERROR,
"no extension allowed here",WARNING,
"illegal scale factor",ERROR, /* 10 */
"can't scale PC register",WARNING,
"index register expected",ERROR,
"too many ] in memory indirect addressing mode",ERROR,
"missing outer displacement",ERROR,
"%c expected",ERROR, /* 15 */
"can't use PC register as index",ERROR,
"double registers in list",WARNING,
"data register required",ERROR,
"illegal bitfield width/offset",ERROR,
"constant integer expression required",ERROR, /* 20 */
"value from -64 to 63 required for k-factor",ERROR,
"need 32 bits to reference a program label",WARNING,
"option expected",ERROR,
"absolute value expected",ERROR,
"operand value out of range: %ld (valid: %ld..%ld)",ERROR, /* 25 */
"label in operand required",ERROR,
"using signed operand as unsigned: %ld (valid: %ld..%ld), "
"%ld to fix",WARNING,
"branch destination out of range",ERROR,
"displacement out of range",ERROR,
"absolute displacement expected",ERROR, /* 30 */
"unknown option %c%c ignored",WARNING,
"absolute short address out of range",ERROR,
"deprecated instruction alias",WARNING,
"illegal opcode extension",FATAL|ERROR,
"extension for unsized instruction ignored",WARNING, /* 35 */
"immediate operand out of range",ERROR,
"immediate operand has illegal type or size",ERROR,
"data objects with %d bits size are not supported",ERROR,
"data out of range",ERROR,
"data has illegal type",ERROR, /* 40 */
"illegal combination of ColdFire addressing modes",ERROR,
"FP register required",ERROR,
"unknown cpu type",ERROR,
"register expected",ERROR,
"link.w changed to link.l",WARNING, /* 45 */
"branch out of range changed to jmp",WARNING,
"lea-displacement out of range, changed into move/add",WARNING,
"translated (A%d) into (0,A%d) for movep",WARNING,
"operand optimized: %s",MESSAGE,
"operand translated: %s",MESSAGE, /* 50 */
"instruction optimized: %s",MESSAGE,
"instruction translated: %s",MESSAGE,
"branch optimized into: b<cc>.%c",MESSAGE,
"branch translated into: b<cc>.%c",MESSAGE,
"basereg A%d already in use",ERROR, /* 55 */
"basereg A%d is already free",WARNING,
"short-branch to following instruction turned into a nop",WARNING,
"not a valid small data register",ERROR,
"small data mode is not enabled",ERROR,
"division by zero",WARNING, /* 60 */
"can't use B%d register as index",ERROR,
"register list on both sides",ERROR,
"\"%s\" directive was replaced by an instruction with the same name",NOLINE|WARNING,
"Addr.reg. operand at level #0 causes F-line exception",WARNING,
"Dr and Dq are identical, transforming DIVxL.L effectively into "
"DIVx.L",WARNING, /* 65 */
"not a valid register list symbol",ERROR,
"trailing garbage in operand",WARNING,
"encoding absolute displacement directly",WARNING,
"internal symbol %s has been modified",WARNING,

View File

@ -0,0 +1,129 @@
{ "68000", m68000 },
{ "68008", m68000 },
{ "68010", m68010 },
{ "68020", m68020 },
{ "68030", m68030 },
{ "68040", m68040 },
{ "68060", m68060 },
{ "68020up", m68020up & ~apollo },
{ "68881", m68881 },
{ "68882", m68881 },
{ "68851", m68851 },
{ "68302", m68000 },
{ "68306", m68000 },
{ "68307", m68000 },
{ "6830x", m68000 },
{ "68322", m68000 },
{ "68356", m68000 },
{ "cpu32", cpu32 },
{ "68328", cpu32 },
{ "68330", cpu32 },
{ "68331", cpu32 },
{ "68332", cpu32 },
{ "68333", cpu32 },
{ "68334", cpu32 },
{ "68336", cpu32 },
{ "6833x", cpu32 },
{ "68340", cpu32 },
{ "68349", cpu32 },
{ "68360", cpu32 },
{ "683xx", cpu32 },
{ "68080", ac68080 },
{ "5202", mcfa },
{ "5204", mcfa },
{ "5206", mcfa },
{ "520x", mcfa },
{ "5206e", mcfa|mcfhwdiv|mcfmac },
{ "5207", mcfaplus|mcfhwdiv|mcfemac },
{ "5208", mcfaplus|mcfhwdiv|mcfemac },
{ "5210a", mcfaplus|mcfhwdiv|mcfmac },
{ "5211a", mcfaplus|mcfhwdiv|mcfmac },
{ "5211", mcfaplus|mcfhwdiv|mcfmac },
{ "5212", mcfaplus|mcfhwdiv|mcfmac },
{ "5213", mcfaplus|mcfhwdiv|mcfmac },
{ "5214", mcfaplus|mcfhwdiv|mcfemac },
{ "5216", mcfaplus|mcfhwdiv|mcfemac },
{ "5224", mcfaplus|mcfhwdiv|mcfmac },
{ "5225", mcfaplus|mcfhwdiv|mcfmac },
{ "5232", mcfaplus|mcfhwdiv|mcfemac },
{ "5233", mcfaplus|mcfhwdiv|mcfemac },
{ "5234", mcfaplus|mcfhwdiv|mcfemac },
{ "5235", mcfaplus|mcfhwdiv|mcfemac },
{ "523x", mcfaplus|mcfhwdiv|mcfemac },
{ "5249", mcfa|mcfhwdiv|mcfemac },
{ "5250", mcfa|mcfhwdiv|mcfemac },
{ "5253", mcfa|mcfhwdiv|mcfemac },
{ "5270", mcfaplus|mcfhwdiv|mcfemac },
{ "5271", mcfaplus|mcfhwdiv },
{ "5272", mcfa|mcfhwdiv|mcfmac },
{ "5274", mcfaplus|mcfhwdiv|mcfemac },
{ "5275", mcfaplus|mcfhwdiv|mcfemac },
{ "5280", mcfaplus|mcfhwdiv|mcfemac },
{ "5281", mcfaplus|mcfhwdiv|mcfemac },
{ "5282", mcfaplus|mcfhwdiv|mcfemac },
{ "528x", mcfaplus|mcfhwdiv|mcfemac },
{ "52221", mcfaplus|mcfhwdiv|mcfmac },
{ "52223", mcfaplus|mcfhwdiv|mcfmac },
{ "52230", mcfaplus|mcfhwdiv|mcfemac },
{ "52231", mcfaplus|mcfhwdiv|mcfemac },
{ "52232", mcfaplus|mcfhwdiv|mcfemac },
{ "52233", mcfaplus|mcfhwdiv|mcfemac },
{ "52234", mcfaplus|mcfhwdiv|mcfemac },
{ "52235", mcfaplus|mcfhwdiv|mcfemac },
{ "52252", mcfaplus|mcfhwdiv|mcfemac },
{ "52254", mcfaplus|mcfhwdiv|mcfemac },
{ "52255", mcfaplus|mcfhwdiv|mcfemac },
{ "52256", mcfaplus|mcfhwdiv|mcfemac },
{ "52258", mcfaplus|mcfhwdiv|mcfemac },
{ "52259", mcfaplus|mcfhwdiv|mcfemac },
{ "52274", mcfaplus|mcfhwdiv|mcfemac },
{ "52277", mcfaplus|mcfhwdiv|mcfemac },
{ "v2", mcfa },
{ "5307", mcfa|mcfhwdiv|mcfmac },
{ "5327", mcfaplus|mcfhwdiv|mcfemac },
{ "5328", mcfaplus|mcfhwdiv|mcfemac },
{ "5329", mcfaplus|mcfhwdiv|mcfemac },
{ "532x", mcfaplus|mcfhwdiv|mcfemac },
{ "5372", mcfaplus|mcfhwdiv|mcfemac },
{ "5373", mcfaplus|mcfhwdiv|mcfemac },
{ "537x", mcfaplus|mcfhwdiv|mcfemac },
{ "53011", mcfaplus|mcfhwdiv|mcfemac },
{ "53012", mcfaplus|mcfhwdiv|mcfemac },
{ "53013", mcfaplus|mcfhwdiv|mcfemac },
{ "53014", mcfaplus|mcfhwdiv|mcfemac },
{ "53015", mcfaplus|mcfhwdiv|mcfemac },
{ "53016", mcfaplus|mcfhwdiv|mcfemac },
{ "53017", mcfaplus|mcfhwdiv|mcfemac },
{ "5301x", mcfaplus|mcfhwdiv|mcfemac },
{ "v3", mcfaplus|mcfhwdiv|mcfemac },
{ "5407", mcfb|mcfhwdiv|mcfmac },
{ "v4", mcfb|mcfhwdiv|mcfmac },
{ "5470", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "5471", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "5472", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "5473", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "5474", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "5475", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "547x", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "5480", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "5481", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "5482", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "5483", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "5484", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "5485", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "548x", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "v4e", mcfb|mcfhwdiv|mcfemac|mcfusp|mcffpu|mcfmmu },
{ "54450", mcfc|mcfhwdiv|mcfemac|mcfusp|mcfmmu },
{ "54451", mcfc|mcfhwdiv|mcfemac|mcfusp|mcfmmu },
{ "54452", mcfc|mcfhwdiv|mcfemac|mcfusp|mcfmmu },
{ "54453", mcfc|mcfhwdiv|mcfemac|mcfusp|mcfmmu },
{ "54454", mcfc|mcfhwdiv|mcfemac|mcfusp|mcfmmu },
{ "5445x", mcfc|mcfhwdiv|mcfemac|mcfusp|mcfmmu },

2273
vasm-1/cpus/m68k/opcodes.h Normal file

File diff suppressed because it is too large Load Diff

631
vasm-1/cpus/m68k/operands.h Normal file
View File

@ -0,0 +1,631 @@
struct addrmode addrmodes[] = {
MODE_Dn,-1, /* 0 */
MODE_An,-1,
MODE_AnIndir,-1,
MODE_AnPostInc,-1,
MODE_AnPreDec,-1,
MODE_An16Disp,-1,
MODE_An8Format,-1, /* 6 */
MODE_Extended,REG_AbsShort, /* 7 */
MODE_Extended,REG_AbsLong,
MODE_Extended,REG_PC16Disp,
MODE_Extended,REG_PC8Format,
MODE_Extended,REG_Immediate,
MODE_Extended,REG_RnList,
MODE_Extended,REG_FPnList, /* 13 */
MODE_FPn,-1,
MODE_SpecReg,-1 /* 15 */
};
/* specregs.h */
enum {
REG_CCR=0,REG_SR,REG_NC,REG_DC,REG_IC,REG_BC,
REG_ACC,REG_ACC0,REG_ACC1,REG_ACC2,REG_ACC3,REG_ACCX01,REG_ACCX23,
REG_MACSR,REG_MASK,REG_SFLEFT,REG_SFRIGHT,
REG_VX00,REG_VX01,REG_VX02,REG_VX03,REG_VX04,REG_VX05,REG_VX06,REG_VX07,
REG_VX08,REG_VX09,REG_VX10,REG_VX11,REG_VX12,REG_VX13,REG_VX14,REG_VX15,
REG_VX16,REG_VX17,REG_VX18,REG_VX19,REG_VX20,REG_VX21,REG_VX22,REG_VX23,
REG_TC,REG_SRP,REG_CRP,REG_DRP,REG_CAL,REG_VAL,REG_SCC,REG_AC,
REG_BAC0,REG_BAC1,REG_BAC2,REG_BAC3,REG_BAC4,REG_BAC5,REG_BAC6,REG_BAC7,
REG_BAD0,REG_BAD1,REG_BAD2,REG_BAD3,REG_BAD4,REG_BAD5,REG_BAD6,REG_BAD7,
REG_MMUSR,REG_PSR,REG_PCSR,REG_TT0,REG_TT1,
#if 0
REG_ACUSR,REG_AC0,REG_AC1,
#endif
/* MOVEC control registers _CTRL */
REG_SFC,REG_DFC,REG_CACR,REG_ASID,REG_TC_,
REG_ITT0,REG_ITT1,REG_DTT0,REG_DTT1,
REG_IACR0,REG_IACR1,REG_DACR0,REG_DACR1,
REG_ACR0,REG_ACR1,REG_ACR2,REG_ACR3,
REG_BUSCR,REG_MMUBAR,
REG_STR,REG_STC,REG_STH,REG_STB,REG_MWR,
REG_USP,REG_VBR,REG_CAAR,REG_MSP,
REG_ISP,REG_MMUSR_,REG_URP,REG_SRP_,REG_PCR,
REG_CCC,REG_IEP1,REG_IEP2,REG_BPC,REG_BPW,REG_DCH,REG_DCM,
REG_ROMBAR,REG_ROMBAR0,REG_ROMBAR1,
REG_RAMBAR,REG_RAMBAR0,REG_RAMBAR1,
REG_MPCR,REG_EDRAMBAR,REG_SECMBAR,REG_MBAR,
REG_PCR1U0,REG_PCR1L0,REG_PCR2U0,REG_PCR2L0,REG_PCR3U0,REG_PCR3L0,
REG_PCR1U1,REG_PCR1L1,REG_PCR2U1,REG_PCR2L1,REG_PCR3U1,REG_PCR3L1,
};
#define _(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p) \
((a)|((b)<<1)|((c)<<2)|((d)<<3)|((e)<<4)|((f)<<5)|((g)<<6)|((h)<<7)| \
((i)<<8)|((j)<<9)|((k)<<10)|((l)<<11)|((m)<<12)|((n)<<13)| \
((o)<<14)|((p)<<15))
enum {
OP_D8=1,OP_D16,OP_D32,OP_D64,OP_F32,OP_F64,OP_F96,
D_,A_,B_,AI,IB,R_,RM,DD,CS,VDR2,VDR4,PA,AP,DP,
F_,FF,FR,FPIAR,IM,QI,IR,BR,AB,VA,M6,RL,FL,FS,
AY,AM,MA,MI,FA,CF,MAQ,CFAM,CM,AL,DA,DN,CFDA,CT,AC,AD,CFAD,
BD,BS,AK,MS,MR,CFMM,CFMN,ND,NI,NJ,NK,BY,BI,BJ,
_CCR,_SR,_USP,_CACHES,_ACC,_MACSR,_MASK,_CTRL,_ACCX,_AEXT,
_VAL,_FC,_RP_030,_RP_851,_TC,_AC,_M1_B,_BAC,_BAD,_PSR,_PCSR,
_TT,SH,VX,VXR2,VXR4
};
struct optype optypes[] = {
0,0,0,0,
/* OP_D8 8-bit data */
_(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0),OTF_DATA,0,0,
/* OP_D16 16-bit data */
_(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0),OTF_DATA,0,0,
/* OP_D32 32-bit data */
_(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0),OTF_DATA,0,0,
/* OP_D64 64-bit data */
_(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0),OTF_DATA|OTF_QUADIMM,0,0,
/* OP_F32 32-bit data */
_(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0),OTF_DATA|OTF_FLTIMM,0,0,
/* OP_F64 64-bit data */
_(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0),OTF_DATA|OTF_FLTIMM,0,0,
/* OP_F96 96-bit data */
_(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0),OTF_DATA|OTF_FLTIMM,0,0,
/* D_ data register */
_(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),0,0,0,
/* A_ address register */
_(0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0),0,0,0,
/* B_ (Apollo) base register */
_(0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0),FL_BnReg,0,0,
/* AI address register indirect */
_(0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0),0,0,0,
/* IB (Apollo) base register indirect */
_(0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0),FL_BnReg,0,0,
/* R_ any data or address register */
_(1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0),0,0,0,
/* RM any data or address register with optional U/L extension (MAC) */
_(1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0),FL_MAC,0,0,
/* DD double data register */
_(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),FL_DoubleReg,0,0,
/* CS any double data or address register indirect (cas2) */
_(0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0),FL_DoubleReg,0,0,
/* VDR2 (Apollo) Dn:Dn+1 */
_(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),OTF_VXRNG2,0,0,
/* VDR4 (Apollo) Dn-Dn+3 */
_(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),OTF_VXRNG4,0,0,
/* PA address register indirect with predecrement */
_(0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0),0,0,0,
/* AP address register indirect with postincrement */
_(0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0),0,0,0,
/* DP address register indirect with displacement (movep) */
_(0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0),0,0,0,
/* F_ FPU register FPn */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0),0,0,0,
/* FF double FPU register */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0),FL_DoubleReg,0,0,
/* FR FPU special register FPCR/FPSR/FPIAR */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0),FL_FPSpec,0,0,
/* FPIAR FPU special register FPIAR */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0),OTF_CHKREG|FL_FPSpec,1,1,
/* IM immediate data */
_(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0),0,0,0,
/* QI quick immediate data (moveq, addq, subq) */
_(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0),OTF_NOSIZE,0,0,
/* IR immediate register list value (movem) */
_(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0),OTF_NOSIZE,0,0,
/* BR branch destination */
_(0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0),OTF_BRANCH,0,0,
/* AB absolute long destination */
_(0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0),0,0,0,
/* VA absolute value */
_(0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0),OTF_NOSIZE,0,0,
/* M6 mode 6 - addr. reg. indirect with index and displacement */
_(0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0),0,0,0,
/* RL An/Dn register list */
_(0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0),OTF_REGLIST,0,0,
/* FL FPn register list */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0),OTF_REGLIST,0,0,
/* FS FPIAR/FPSR/FPCR register list */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0),OTF_REGLIST|FL_FPSpec,0,0,
/* ea addressing modes */
/* AY all addressing modes 0-6,7.0-4 */
_(1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0),0,0,0,
/* AM alterable memory 2-6,7.0-1 */
_(0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0),0,0,0,
/* MA memory addressing modes 2-6,7.0-4 */
_(0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0),0,0,0,
/* MI memory addressing modes 2-6,7.0-3 without immediate */
_(0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0),0,0,0,
/* FA memory addressing modes 2-6,7.0-4 with float immediate */
_(0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0),OTF_FLTIMM,0,0,
/* CF (ColdFire) float addressing modes 2-5 and 7.2 */
_(0,0,1,1,1,1,0,0,0,1,0,0,0,0,0,0),0,0,0,
/* MAQ memory addressing modes 2-6,7.0-4 with 64-bit immediate */
_(0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0),OTF_QUADIMM,0,0,
/* CFAM (ColdFire) alterable memory 2-5 */
_(0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0),0,0,0,
/* CM (ColdFire) alterable memory 2-5 with MASK-flag (MAC) */
_(0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0),FL_MAC,0,0,
/* AL alterable 0-6,7.0-1 */
_(1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0),0,0,0,
/* DA data 0,2-6,7.0-4 */
_(1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0),0,0,0,
/* DN data, but not immediate 0,2-6,7.0-3 */
_(1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0),0,0,0,
/* CFDA (ColdFire) float data 0,2-6,7.0-4 (=CF + mode 0) */
_(1,0,1,1,1,1,0,0,0,1,0,0,0,0,0,0),0,0,0,
/* CT control, 2,5-6,7.0-3 */
_(0,0,1,0,0,1,1,1,1,1,1,0,0,0,0,0),0,0,0,
/* AC alterable control, 2,5-6,7.0-1 */
_(0,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0),0,0,0,
/* AD alterable data, 0,2-6,7.0-1 */
_(1,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0),0,0,0,
/* CFAD (ColdFire) alterable data, 0,2-5 */
_(1,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0),0,0,0,
/* BD alterable control or data (bitfield), 0,2,5-6,7.0-1 */
_(1,0,1,0,0,1,1,1,1,0,0,0,0,0,0,0),FL_Bitfield,0,0,
/* BS control or data register (bitfield), 0,2,5-6,7.0-3 */
_(1,0,1,0,0,1,1,1,1,1,1,0,0,0,0,0),FL_Bitfield,0,0,
/* AK alterable memory (incl. k-factor) 2-6,7.0-1 */
_(0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0),FL_KFactor,0,0,
/* MS save operands, 2,4-6,7.0-1 */
_(0,0,1,0,1,1,1,1,1,0,0,0,0,0,0,0),0,0,0,
/* MR restore operands, 2-3,5-6,7.0-3 */
_(0,0,1,1,0,1,1,1,1,1,1,0,0,0,0,0),0,0,0,
/* CFMM (ColdFire) MOVEM, 2,5 */
_(0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0),0,0,0,
/* CFMN (ColdFire) FMOVEM src-ea, 2,5,7.2 */
_(0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0),0,0,0,
/* ND (Apollo) all except Dn, 1-6,7.0-4 */
_(0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0),0,0,0,
/* NI (Apollo) all except immediate, 0-6,7.0-3 */
_(1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0),0,0,0,
/* NJ (Apollo) all except Dn and immediate, 1-6,7.0-3 */
_(0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0),0,0,0,
/* NK (Apollo) all except An and immediate, 0,2-6,7.0-3 */
_(1,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0),0,0,0,
/* BY (Apollo) all addressing modes 0-6,7.0-4 with An replaced by Bn */
_(1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0),FL_BnReg,0,0,
/* BI (Apollo) all except immediate, 0-6,7.0-3 with An repl. by Bn */
_(1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0),FL_BnReg,0,0,
/* BJ (Apollo) all except Dn/An & immediate, 0-6,7.0-3, An -> Bn */
_(0,0,1,1,1,1,1,1,1,1,1,0,0,0,0,0),FL_BnReg,0,0,
/* special registers */
/* _CCR */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_CCR,REG_CCR,
/* _SR */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_SR,REG_SR,
/* _USP */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_USP,REG_USP,
/* _CACHES */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_NC,REG_BC,
/* _ACC */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_ACC,REG_ACC,
/* _MACSR */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_MACSR,REG_MACSR,
/* _MASK */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_MASK,REG_MASK,
/* _CTRL */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_SRRANGE|OTF_CHKREG,
REG_SFC,REG_PCR3L1,
/* _ACCX */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_SRRANGE|OTF_CHKREG,
REG_ACC0,REG_ACC3,
/* _AEXT */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_SRRANGE|OTF_CHKREG,
REG_ACCX01,REG_ACCX23,
/* _VAL */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_VAL,REG_VAL,
/* _FC */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_SFC,REG_DFC,
/* _RP_030 */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_SRP,REG_CRP,
/* _RP_851 */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_SRP,REG_DRP,
/* _TC */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_TC,REG_TC,
/* _AC */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_AC,REG_AC,
/* _M1_B */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_CAL,REG_SCC,
/* _BAC */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_BAC0,REG_BAC7,
/* _BAD */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_BAD0,REG_BAD7,
/* _PSR */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_MMUSR,REG_PSR,
/* _PCSR */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_MMUSR,REG_PCSR,
/* _TT */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_TT0,REG_TT1,
/* SH */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_CHKREG,REG_SFLEFT,REG_SFRIGHT,
/* VX (Apollo) */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_SRRANGE|OTF_CHKREG,REG_VX00,REG_VX23,
/* VXR2 (Apollo) En:En+1 */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_VXRNG2|OTF_SRRANGE|OTF_CHKREG,REG_VX00,REG_VX23,
/* VXR4 (Apollo) En-En+3 */
_(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1),OTF_SPECREG|OTF_VXRNG4|OTF_SRRANGE|OTF_CHKREG,REG_VX00,REG_VX23,
};
#undef _
/* special operand insertion functions */
static void write_val(unsigned char *,int,int,taddr,int);
static void insert_cas2(unsigned char *d,struct oper_insert *i,operand *o)
{
uint16_t w1 = (*(d+2)<<8) | *(d+3);
uint16_t w2 = (*(d+4)<<8) | *(d+5);
w1 |= (i->size==4 ? o->reg&15 : o->reg&7) << (16-((i->pos-16)+i->size));
w2 |= (o->reg>>4) << (16-((i->pos-16)+i->size));
*(d+2) = w1>>8;
*(d+3) = w1&0xff;
*(d+4) = w2>>8;
*(d+5) = w2&0xff;
}
static void insert_macreg(unsigned char *d,struct oper_insert *i,operand *o)
{
if (i->pos == 4) {
/* special case: MSB is at bit-position 9 */
write_val(d,4,3,o->reg,0);
*(d+1) |= o->mode << 6;
}
else
write_val(d,i->pos,4,(o->mode<<3)+o->reg,0);
if (o->bf_offset) /* .u extension selects upper word, else lower */
*(d+3) |= i->size; /* size holds the U/L mask for this register */
}
static void insert_muldivl(unsigned char *d,struct oper_insert *i,operand *o)
{
unsigned char r = o->reg & 7;
if (o->mode == MODE_An)
r |= REGAn;
*(d+2) |= r << 4;
*(d+3) |= r;
}
static void insert_divl(unsigned char *d,struct oper_insert *i,operand *o)
{
*(d+2) |= o->reg & 0xf0;
*(d+3) |= o->reg & 0xf;
}
static void insert_tbl(unsigned char *d,struct oper_insert *i,operand *o)
{
*(d+1) |= o->reg & 7;
*(d+3) |= (o->reg & 0x70) >> 4;
}
static void insert_fp(unsigned char *d,struct oper_insert *i,operand *o)
{
*(d+2) |= ((o->reg&7) << 2) | ((o->reg&7) >> 1);
*(d+3) |= (o->reg&1) << 7;
}
static void insert_fpcs(unsigned char *d,struct oper_insert *i,operand *o)
{
*(d+2) |= (o->reg&0x60) >> 5;
*(d+3) |= ((o->reg&0x10) << 3) | (o->reg & 7);
}
static void insert_accx(unsigned char *d,struct oper_insert *i,operand *o)
{
unsigned char v = o->extval[0];
*(d+1) |= (v&1) << 7;
*(d+3) |= (v&2) << 3;
}
static void insert_accx_rev(unsigned char *d,struct oper_insert *i,operand *o)
{
unsigned char v = o->extval[0];
*(d+1) |= ((v&1) ^ 1) << 7;
*(d+3) |= (v&2) << 3;
}
static void insert_ammx(unsigned char *d,struct oper_insert *i,operand *o)
{
unsigned char v = o->extval[0];
write_val(d,i->pos,i->size,v&15,0);
write_val(d,15-(i->flags&15),1,(v&16)!=0,0);
}
/* place to put an operand */
enum {
NOP=0,NEA,SEA,MEA,BEA,KEA,REA,EAM,BRA,DBR,RHI,RLO,RL4,R2H,R2M,R2L,R2P,
FPN,FPM,FMD,C2H,A2M,A2L,AXA,AXB,AXD,AX0,CS1,CS2,CS3,MDL,DVL,TBL,FPS,FPC,
RMM,RMW,RMY,RMX,ACX,ACR,DL8,DL4,D3Q,DL3,CAC,D16,S16,D2R,ELC,EL8,E8R,
EL3,EL4,EM3,EM4,EH3,BAX,FCR,F13,M3Q,MSF,ACW,AHI,ALO,LIN
};
struct oper_insert insert_info[] = {
/* NOP do nothing for this operand (usually a special reg.) */
M_nop,0,0,0,0,
/* NEA don't store effective address, but extension words */
M_noea,0,0,0,0,
/* SEA standard effective address */
M_ea,0,0,0,0,
/* MEA high effective address for MOVE */
M_high_ea,0,0,0,0,
/* BEA std. EA including bitfield offset/width */
M_bfea,0,0,0,0,
/* KEA std. EA including K-factor */
M_kfea,0,0,0,0,
/* REA store only register-part of effective address */
M_ea,0,0,IIF_NOMODE,0,
/* EAM standard effective address with MAC MASK-flag in bit 5 of 2nd word */
M_ea,0,5,IIF_MASK,0,
/* BRA pc-relative branch to label */
M_branch,0,0,IIF_BCC,0,
/* DBR DBcc, FBcc or PBcc branch to label */
M_branch,0,0,0,0,
/* RHI register 3 bits in bits 11-9 */
M_reg,3,4,0,0,
/* RLO register 3 bits in bits 2-0 */
M_reg,3,13,0,0,
/* RL4 register 4 bits in bits 3-0 */
M_reg,4,12,0,0,
/* R2H register 3 bits in 2nd word bits 14-12 */
M_reg,3,17,0,0,
/* R2M register 3 bits in 2nd word bits 8-6 */
M_reg,3,23,0,0,
/* R2L register 3 bits in 2nd word bits 2-0 */
M_reg,3,29,0,0,
/* R2P register 3 bits in 2nd word bits 7-5 */
M_reg,3,24,0,0,
/* FPN register 3 bits in 2nd word bits 9-7 (FPn) */
M_reg,3,22,0,0,
/* FPM register 3 bits in 2nd word bits 12-10 (FPm) */
M_reg,3,19,0,0,
/* FMD register 3 bits in 2nd word bits 6-4 (FMOVE dynamic) */
M_reg,3,25,0,0,
/* C2H register 4 bits in 2nd word bits 15-12 (cmp2,chk2,moves) */
M_reg,4,16,0,0,
/* A2M register 4 bits in 2nd word bits 11-8 (Apollo AMMX) */
M_reg,4,20,0,0,
/* A2L register 4 bits in 2nd word bits 3-0 (Apollo AMMX) */
M_reg,4,28,0,0,
/* AXA vector register field A (Apollo AMMX) */
M_func,4,28,IIF_A|IIF_ABSVAL,insert_ammx,
/* AXB vector register field B (Apollo AMMX) */
M_func,4,16,IIF_B|IIF_ABSVAL,insert_ammx,
/* AXD vector register field D (Apollo AMMX) */
M_func,4,20,IIF_D|IIF_ABSVAL,insert_ammx,
/* AX0 vector register field A in first word (Apollo AMMX) */
M_func,4,12,IIF_A|IIF_ABSVAL,insert_ammx,
/* CS1 register 3 bits for CAS2 bits 2-0 */
M_func,3,29,0,insert_cas2,
/* CS2 register 3 bits for CAS2 bits 8-6 */
M_func,3,23,0,insert_cas2,
/* CS3 register 4 bits for CAS2 (CAS2) bits 15-12 */
M_func,4,16,0,insert_cas2,
/* MDL insert 4 bit reg. Dq/Dl into 2nd word bits 15-12/3-0 */
M_func,0,0,0,insert_muldivl,
/* DVL 4 bit Dq to 2nd word bits 15-12, Dr to bits 3-0 */
M_func,0,0,0,insert_divl,
/* TBL 3 bit Dym to 1st w. bits 2-0, Dyn to 2nd w. 2-0 */
M_func,0,0,0,insert_tbl,
/* FPS 3 bit FPn to 2nd word bits 12-10 (FPm) and 9-7 (FPn) */
M_func,0,0,0,insert_fp,
/* FPC 3 bit FPc to 2nd word bits 2-0, FPs to bits 9-7 */
M_func,0,0,0,insert_fpcs,
/* RMM register 4 bits in bits 3-0, MAC U/L flag in bit 6 of 2nd word */
M_func,0x40,12,0,insert_macreg,
/* RMW register 4 bits in bits 6,11-9, MAC U/L flag in bit 7 of 2nd word */
M_func,0x80,4,0,insert_macreg,
/* RMY register 4 bits in 2nd word bits 3-0, MAC U/L flag in bit 6 */
M_func,0x40,28,0,insert_macreg,
/* RMX register 4 bits in 2nd word bits 15-12, MAC U/L flag in bit 7 */
M_func,0x80,16,0,insert_macreg,
/* ACX 2 bits ACC: MSB in bit 4 of 2nd word, LSB in bit 7 of first word */
M_func,0,0,IIF_ABSVAL,insert_accx,
/* ACR 2 bits ACC: MSB in bit 4 of 2nd word, reversed LSB in bit 7 of first */
M_func,0,0,IIF_ABSVAL,insert_accx_rev,
/* DL8 8-bit data in lo-byte */
M_val0,8,8,IIF_SIGNED,0,
/* DL4 4-bit value in bits 3-0 */
M_val0,4,12,0,0,
/* D3Q addq/subq 3-bit quick data in bits 11-9 */
M_val0,3,4,IIF_MASK,0,
/* DL3 3-bit value in bits 2-0 */
M_val0,3,13,0,0,
/* CAC 2-bit cache field in bits 7-6 */
M_val0,2,8,0,0,
/* D16 16-bit data in 2nd word */
M_val0,16,16,0,0,
/* S16 signed 16-bit data in 2nd word */
M_val0,16,16,IIF_SIGNED,0,
/* D2R 16-bit reversed data in 2nd word (movem predec.) */
M_val0,16,16,IIF_REVERSE,0,
/* ELC 12-bit value in bits 11-0 of 2nd word */
M_val0,12,20,0,0,
/* EL8 8-bit data in lo-byte of extension word (2nd word) */
M_val0,8,24,0,0,
/* E8R 8-bit reversed data in lo-byte of 2nd word (fmovem) */
M_val0,8,24,IIF_REVERSE,0,
/* EL3 3-bit value in bits 2-0 of 2nd word */
M_val0,3,29,0,0,
/* EL4 4-bit value in bits 3-0 of 2nd word */
M_val0,4,28,0,0,
/* EM3 3-bit value in bits 7-5 of 2nd word */
M_val0,3,24,0,0,
/* EM4 4-bit value in bits 8-5 of 2nd word */
M_val0,4,23,0,0,
/* EH3 3-bit value in bits 12-10 of 2nd word */
M_val0,3,19,0,0,
/* BAX 3-bit number of BAC/BAD reg. in bits 4-2 of 2nd word */
M_val0,3,27,0,0,
/* FCR 7-bit ROM offset in bits 6-0 of 2nd word (FMOVECR) */
M_val0,7,25,0,0,
/* F13 13-bit special register mask in bits 12-0 of 2nd word (FMOVEM) */
M_val0,13,19,0,0,
/* M3Q mov3q 3-bit quick data in bits 11-9, -1 is written as 0 */
M_val0,3,4,IIF_3Q,0,
/* MSF 2-bit MAC scale factor in bits 10-9 of 2nd word */
M_val0,2,21,0,0,
/* ACW 2-bit ACC in bits 3-2 of 2nd word */
M_val0,2,28,0,0,
/* AHI 2-bit ACC in bits 10-9 */
M_val0,2,5,0,0,
/* ALO 2-bit ACC in bits 1-0 */
M_val0,2,14,0,0,
/* LIN 12-bit value in bits 0-11 (LINE-A, LINE-F) */
M_val0,12,4,0,0,
};

151
vasm-1/cpus/m68k/specregs.h Normal file
View File

@ -0,0 +1,151 @@
"CCR", -1, m68000up|mcf,
"SR", -1, m68000up|mcf,
"NC", 0, m68040up,
"DC", 1, m68040up,
"IC", 2, m68040up,
"BC", 3, m68040up,
/* ColdFire */
"ACC", 0, mcfmac|mcfemac,
"ACC0", 0, mcfemac,
"ACC1", 1, mcfemac,
"ACC2", 2, mcfemac,
"ACC3", 3, mcfemac,
"ACCext01",1, mcfemac,
"ACCext23",3, mcfemac,
"MACSR", -1, mcfmac|mcfemac,
"MASK", -1, mcfmac|mcfemac,
"<<", MACSF_ShiftLeft, mcfmac|mcfemac,
">>", MACSF_ShiftRight,mcfmac|mcfemac,
/* Apollo AMMX */
"E0", 8, apollo,
"E1", 9, apollo,
"E2", 10, apollo,
"E3", 11, apollo,
"E4", 12, apollo,
"E5", 13, apollo,
"E6", 14, apollo,
"E7", 15, apollo,
"E8", 16, apollo,
"E9", 17, apollo,
"E10", 18, apollo,
"E11", 19, apollo,
"E12", 20, apollo,
"E13", 21, apollo,
"E14", 22, apollo,
"E15", 23, apollo,
"E16", 24, apollo,
"E17", 25, apollo,
"E18", 26, apollo,
"E19", 27, apollo,
"E20", 28, apollo,
"E21", 29, apollo,
"E22", 30, apollo,
"E23", 31, apollo,
/* pmove format 1 68030+68851 */
"TC", 0, m68030|m68851,
"SRP", 2, m68030|m68851,
"CRP", 3, m68030|m68851,
/* pmove format 1 68851 only */
"DRP", 1, m68851,
"CAL", 4, m68851,
"VAL", 5, m68851,
"SCC", 6, m68851,
"AC", 7, m68851,
/* pmove format 2 BADx, BACx */
"BAC0", 0, m68851,
"BAC1", 1, m68851,
"BAC2", 2, m68851,
"BAC3", 3, m68851,
"BAC4", 4, m68851,
"BAC5", 5, m68851,
"BAC6", 6, m68851,
"BAC7", 7, m68851,
"BAD0", 0, m68851,
"BAD1", 1, m68851,
"BAD2", 2, m68851,
"BAD3", 3, m68851,
"BAD4", 4, m68851,
"BAD5", 5, m68851,
"BAD6", 6, m68851,
"BAD7", 7, m68851,
/* pmove format 3 */
"MMUSR", 0, m68030|m68851,
"PSR", 0, m68030|m68851,
"PCSR", 1, m68851,
/* pmove 030 only */
"TT0", 2, m68030,
"TT1", 3, m68030,
#if 0
/* pmove 68ec030 */
"ACUSR", -1, m68030,
"AC0", 1, m68030,
"AC1", 3, m68030,
#endif
/* movec control registers */
"SFC", 0x000, m68010up|cpu32,
"DFC", 0x001, m68010up|cpu32,
"CACR", 0x002, m68020up|mcf,
"ASID", 0x003, mcf,
"TC", 0x003, m68040up,
"ITT0", 0x004, m68040up,
"ITT1", 0x005, m68040up,
"DTT0", 0x006, m68040up,
"DTT1", 0x007, m68040up,
"IACR0", 0x004, m68040up,
"IACR1", 0x005, m68040up,
"DACR0", 0x006, m68040up,
"DACR1", 0x007, m68040up,
"ACR0", 0x004, mcf,
"ACR1", 0x005, mcf,
"ACR2", 0x006, mcf,
"ACR3", 0x007, mcf,
"BUSCR", 0x008, m68060,
"MMUBAR", 0x008, mcf,
"STR", 0x00a, ac68080,
"STC", 0x00b, ac68080,
"STH", 0x00c, ac68080,
"STB", 0x00d, ac68080,
"MWR", 0x00e, ac68080,
"USP", 0x800, m68000up|mcfb|mcfc,
"VBR", 0x801, m68010up|cpu32|mcf,
"CAAR", 0x802, m68020|m68030,
"MSP", 0x803, m68020|m68030|m68040,
"ISP", 0x804, m68020|m68030|m68040,
"MMUSR", 0x805, m68040,
"URP", 0x806, m68040up,
"SRP", 0x807, m68040up,
"PCR", 0x808, m68060|ac68080,
/*"PC",0x80f, @@@ hmmm?*/
"CCC", 0x809, ac68080,
"IEP1", 0x80a, ac68080,
"IEP2", 0x80b, ac68080,
"BPC", 0x80c, ac68080,
"BPW", 0x80d, ac68080,
"DCH", 0x80e, ac68080,
"DCM", 0x80f, ac68080,
"ROMBAR", 0xc00, mcf,
"ROMBAR0", 0xc00, mcf,
"ROMBAR1", 0xc01, mcf,
"RAMBAR", 0xc04, mcf,
"RAMBAR0", 0xc04, mcf,
"RAMBAR1", 0xc05, mcf,
"MPCR", 0xc0c, mcf,
"EDRAMBAR",0xc0d, mcf,
"SECMBAR", 0xc0e, mcf,
"MBAR", 0xc0f, mcf,
"PCR1U0", 0xd02, mcf,
"PCR1L0", 0xd03, mcf,
"PCR2U0", 0xd04, mcf,
"PCR2L0", 0xd05, mcf,
"PCR3U0", 0xd06, mcf,
"PCR3L0", 0xd07, mcf,
"PCR1U1", 0xd0a, mcf,
"PCR1L1", 0xd0b, mcf,
"PCR2U1", 0xd0c, mcf,
"PCR2L1", 0xd0d, mcf,
"PCR3U1", 0xd0e, mcf,
"PCR3L1", 0xd0f, mcf,

913
vasm-1/cpus/ppc/cpu.c Normal file
View File

@ -0,0 +1,913 @@
/*
** cpu.c PowerPC cpu-description file
** (c) in 2002-2019 by Frank Wille
*/
#include "vasm.h"
#include "operands.h"
mnemonic mnemonics[] = {
#include "opcodes.h"
};
int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]);
char *cpu_copyright="vasm PowerPC cpu backend 3.1 (c) 2002-2019 Frank Wille";
char *cpuname = "PowerPC";
int bitsperbyte = 8;
int bytespertaddr = 4;
int ppc_endianess = 1;
static uint64_t cpu_type = CPU_TYPE_PPC | CPU_TYPE_ALTIVEC | CPU_TYPE_32 | CPU_TYPE_ANY;
static int regnames = 1;
static taddr sdreg = 13; /* this is default for V.4, PowerOpen = 2 */
static taddr sd2reg = 2;
static unsigned char opt_branch = 0;
int ppc_data_align(int n)
{
if (n<=8) return 1;
if (n<=16) return 2;
if (n<=32) return 4;
return 8;
}
int ppc_data_operand(int n)
{
if (n&OPSZ_FLOAT) return OPSZ_BITS(n)>32?OP_F64:OP_F32;
if (OPSZ_BITS(n)<=8) return OP_D8;
if (OPSZ_BITS(n)<=16) return OP_D16;
if (OPSZ_BITS(n)<=32) return OP_D32;
return OP_D64;
}
int ppc_operand_optional(operand *op,int type)
{
if (powerpc_operands[type].flags & OPER_OPTIONAL) {
op->attr = REL_NONE;
op->mode = OPM_NONE;
op->basereg = NULL;
op->value = number_expr(0); /* default value 0 */
if (powerpc_operands[type].flags & OPER_NEXT)
op->type = NEXT;
else
op->type = type;
return 1;
}
else if (powerpc_operands[type].flags & OPER_FAKE) {
op->type = type;
op->value = NULL;
return 1;
}
return 0;
}
int ppc_available(int idx)
/* Check if mnemonic is available for selected cpu_type. */
{
uint64_t avail = mnemonics[idx].ext.available;
uint64_t datawidth = CPU_TYPE_32 | CPU_TYPE_64;
if ((avail & cpu_type) != 0) {
if ((avail & cpu_type & ~datawidth)!=0 || (cpu_type & CPU_TYPE_ANY)!=0) {
if (avail & datawidth)
return (avail & datawidth) == (cpu_type & datawidth)
|| (cpu_type & CPU_TYPE_64_BRIDGE) != 0;
else
return 1;
}
}
return 0;
}
static char *parse_reloc_attr(char *p,operand *op)
{
p = skip(p);
while (*p == '@') {
unsigned char chk;
p++;
chk = op->attr;
if (!strncmp(p,"got",3)) {
op->attr = REL_GOT;
p += 3;
}
else if (!strncmp(p,"plt",3)) {
op->attr = REL_PLT;
p += 3;
}
else if (!strncmp(p,"sdax",4)) {
op->attr = REL_SD;
p += 4;
}
else if (!strncmp(p,"sdarx",5)) {
op->attr = REL_SD;
p += 5;
}
else if (!strncmp(p,"sdarel",6)) {
op->attr = REL_SD;
p += 6;
}
else if (!strncmp(p,"sectoff",7)) {
op->attr = REL_SECOFF;
p += 7;
}
else if (!strncmp(p,"local",5)) {
op->attr = REL_LOCALPC;
p += 5;
}
else if (!strncmp(p,"globdat",7)) {
op->attr = REL_GLOBDAT;
p += 7;
}
else if (!strncmp(p,"sda2rel",7)) {
op->attr = REL_PPCEABI_SDA2;
p += 7;
}
else if (!strncmp(p,"sda21",5)) {
op->attr = REL_PPCEABI_SDA21;
p += 5;
}
else if (!strncmp(p,"sdai16",6)) {
op->attr = REL_PPCEABI_SDAI16;
p += 6;
}
else if (!strncmp(p,"sda2i16",7)) {
op->attr = REL_PPCEABI_SDA2I16;
p += 7;
}
else if (!strncmp(p,"drel",4)) {
op->attr = REL_MORPHOS_DREL;
p += 4;
}
else if (!strncmp(p,"brel",4)) {
op->attr = REL_AMIGAOS_BREL;
p += 4;
}
if (chk!=REL_NONE && chk!=op->attr)
cpu_error(7); /* multiple relocation attributes */
chk = op->mode;
if (!strncmp(p,"ha",2)) {
op->mode = OPM_HA;
p += 2;
}
if (*p == 'h') {
op->mode = OPM_HI;
p++;
}
if (*p == 'l') {
op->mode = OPM_LO;
p++;
}
if (chk!=OPM_NONE && chk!=op->mode)
cpu_error(8); /* multiple hi/lo modifiers */
}
return p;
}
int parse_operand(char *p,int len,operand *op,int optype)
/* Parses operands, reads expressions and assigns relocation types. */
{
char *start = p;
int rc = PO_MATCH;
op->attr = REL_NONE;
op->mode = OPM_NONE;
op->basereg = NULL;
p = skip(p);
op->value = OP_FLOAT(optype) ? parse_expr_float(&p) : parse_expr(&p);
if (!OP_DATA(optype)) {
p = parse_reloc_attr(p,op);
p = skip(p);
if (p-start < len && *p=='(') {
/* parse d(Rn) load/store addressing mode */
if (powerpc_operands[optype].flags & OPER_PARENS) {
p++;
op->basereg = parse_expr(&p);
p = skip(p);
if (*p == ')') {
p = skip(p+1);
rc = PO_SKIP;
}
else {
cpu_error(5); /* missing closing parenthesis */
rc = PO_CORRUPT;
goto leave;
}
}
else {
cpu_error(4); /* illegal operand type */
rc = PO_CORRUPT;
goto leave;
}
}
}
if (p-start < len)
cpu_error(3); /* trailing garbage in operand */
leave:
op->type = optype;
return rc;
}
static taddr read_sdreg(char **s,taddr def)
{
expr *tree;
taddr val = def;
*s = skip(*s);
tree = parse_expr(s);
simplify_expr(tree);
if (tree->type==NUM && tree->c.val>=0 && tree->c.val<=31)
val = tree->c.val;
else
cpu_error(13); /* not a valid register */
free_expr(tree);
return val;
}
char *parse_cpu_special(char *start)
/* parse cpu-specific directives; return pointer to end of
cpu-specific text */
{
char *name=start,*s=start;
if (ISIDSTART(*s)) {
s++;
while (ISIDCHAR(*s))
s++;
if (s-name==6 && !strncmp(name,".sdreg",6)) {
sdreg = read_sdreg(&s,sdreg);
return s;
}
else if (s-name==7 && !strncmp(name,".sd2reg",7)) {
sd2reg = read_sdreg(&s,sd2reg);
return s;
}
}
return start;
}
static int get_reloc_type(operand *op)
{
int rtype = REL_NONE;
if (OP_DATA(op->type)) { /* data relocs */
return REL_ABS;
}
else { /* handle instruction relocs */
const struct powerpc_operand *ppcop = &powerpc_operands[op->type];
if (ppcop->shift == 0) {
if (ppcop->bits == 16 || ppcop->bits == 26) {
if (ppcop->flags & OPER_RELATIVE) { /* a relative branch */
switch (op->attr) {
case REL_NONE:
rtype = REL_PC;
break;
case REL_PLT:
rtype = REL_PLTPC;
break;
case REL_LOCALPC:
rtype = REL_LOCALPC;
break;
default:
cpu_error(11); /* reloc attribute not supported by operand */
break;
}
}
else if (ppcop->flags & OPER_ABSOLUTE) { /* absolute branch */
switch (op->attr) {
case REL_NONE:
rtype = REL_ABS;
break;
case REL_PLT:
case REL_GLOBDAT:
case REL_SECOFF:
rtype = op->attr;
break;
default:
cpu_error(11); /* reloc attribute not supported by operand */
break;
}
}
else { /* immediate 16 bit or load/store d16(Rn) instruction */
switch (op->attr) {
case REL_NONE:
rtype = REL_ABS;
break;
case REL_GOT:
case REL_PLT:
case REL_SD:
case REL_PPCEABI_SDA2:
case REL_PPCEABI_SDA21:
case REL_PPCEABI_SDAI16:
case REL_PPCEABI_SDA2I16:
case REL_MORPHOS_DREL:
case REL_AMIGAOS_BREL:
rtype = op->attr;
break;
default:
cpu_error(11); /* reloc attribute not supported by operand */
break;
}
}
}
}
}
return rtype;
}
static int valid_hiloreloc(int type)
/* checks if this relocation type allows a @l/@h/@ha modifier */
{
switch (type) {
case REL_ABS:
case REL_GOT:
case REL_PLT:
case REL_MORPHOS_DREL:
case REL_AMIGAOS_BREL:
return 1;
}
cpu_error(6); /* relocation does not allow hi/lo modifier */
return 0;
}
static taddr make_reloc(int reloctype,operand *op,section *sec,
taddr pc,rlist **reloclist)
/* create a reloc-entry when operand contains a non-constant expression */
{
taddr val;
if (!eval_expr(op->value,&val,sec,pc)) {
/* non-constant expression requires a relocation entry */
symbol *base;
int btype,pos,size,offset;
taddr addend,mask;
btype = find_base(op->value,&base,sec,pc);
pos = offset = 0;
if (btype > BASE_ILLEGAL) {
if (btype == BASE_PCREL) {
if (reloctype == REL_ABS)
reloctype = REL_PC;
else
goto illreloc;
}
if (op->mode != OPM_NONE) {
/* check if reloc allows @ha/@h/@l */
if (!valid_hiloreloc(reloctype))
op->mode = OPM_NONE;
}
if (reloctype == REL_PC && !is_pc_reloc(base,sec)) {
/* a relative branch - reloc is only needed for external reference */
return val-pc;
}
/* determine reloc size, offset and mask */
if (OP_DATA(op->type)) { /* data operand */
switch (op->type) {
case OP_D8:
size = 8;
break;
case OP_D16:
size = 16;
break;
case OP_D32:
case OP_F32:
size = 32;
break;
case OP_D64:
case OP_F64:
size = 64;
break;
default:
ierror(0);
break;
}
addend = val;
mask = -1;
}
else { /* instruction operand */
const struct powerpc_operand *ppcop = &powerpc_operands[op->type];
if (ppcop->flags & (OPER_RELATIVE|OPER_ABSOLUTE)) {
/* branch instruction */
if (ppcop->bits == 26) {
size = 24;
pos = 6;
mask = 0x3fffffc;
}
else {
size = 14;
offset = 2;
mask = 0xfffc;
}
addend = (btype == BASE_PCREL) ? val + offset : val;
}
else {
/* load/store or immediate */
size = 16;
offset = 2;
addend = (btype == BASE_PCREL) ? val + offset : val;
switch (op->mode) {
case OPM_LO:
mask = 0xffff;
break;
case OPM_HI:
mask = 0xffff0000;
break;
case OPM_HA:
add_extnreloc_masked(reloclist,base,addend,reloctype,
pos,size,offset,0x8000);
mask = 0xffff0000;
break;
default:
mask = -1;
break;
}
}
}
add_extnreloc_masked(reloclist,base,addend,reloctype,
pos,size,offset,mask);
}
else if (btype != BASE_NONE) {
illreloc:
general_error(38); /* illegal relocation */
}
}
else {
if (reloctype == REL_PC) {
/* a relative reference to an absolute label */
return val-pc;
}
}
return val;
}
static void fix_reloctype(dblock *db,int rtype)
{
rlist *rl;
for (rl=db->relocs; rl!=NULL; rl=rl->next)
rl->type = rtype;
}
static int cnt_insn_ops(instruction *p)
{
int cnt = 0;
while (cnt<MAX_OPERANDS && p->op[cnt]!=NULL)
cnt++;
return cnt;
}
static int cnt_mnemo_ops(mnemonic *p)
{
int cnt = 0;
while (cnt<MAX_OPERANDS && p->operand_type[cnt]!=UNUSED)
cnt++;
return cnt;
}
static void range_check(taddr val,const struct powerpc_operand *o,dblock *db)
/* checks if a value fits the allowed range for this operand field */
{
int32_t v = (int32_t)val;
int32_t minv = 0;
int32_t maxv = (1L << o->bits) - 1;
int force_signopt = 0;
if (db) {
if (db->relocs) {
switch (db->relocs->type) {
case REL_SD:
case REL_PPCEABI_SDA2:
case REL_PPCEABI_SDA21:
force_signopt = 1; /* relocation allows full positive range */
break;
}
}
}
if (o->flags & OPER_SIGNED) {
minv = ~(maxv >> 1);
/* @@@ Only recognize this flag in 32-bit mode! Don't care for now */
if (!(o->flags & OPER_SIGNOPT) && !force_signopt)
maxv >>= 1;
}
if (o->flags & OPER_NEGATIVE)
v = -v;
if (v<minv || v>maxv)
cpu_error(12,v,minv,maxv); /* operand out of range */
}
static void negate_bo_cond(uint32_t *p)
/* negates all conditions in a branch instruction's BO field */
{
if (!(*p & 0x02000000))
*p ^= 0x01000000;
if (!(*p & 0x00800000))
*p ^= 0x00400000;
}
static uint32_t insertcode(uint32_t i,taddr val,
const struct powerpc_operand *o)
{
if (o->insert) {
const char *errmsg = NULL;
i = (o->insert)(i,(int32_t)val,&errmsg);
if (errmsg)
cpu_error(0,errmsg);
}
else
i |= ((int32_t)val & ((1<<o->bits)-1)) << o->shift;
return i;
}
size_t eval_operands(instruction *ip,section *sec,taddr pc,
uint32_t *insn,dblock *db)
/* evaluate expressions and try to optimize instruction,
return size of instruction */
{
mnemonic *mnemo = &mnemonics[ip->code];
size_t isize = 4;
int i,j,omitted;
operand op;
if (insn != NULL)
*insn = mnemo->ext.opcode;
for (i=0; i<MAX_OPERANDS && ip->op[i]!=NULL; i++) {
const struct powerpc_operand *ppcop;
int reloctype;
taddr val;
op = *(ip->op[i]);
if (op.type == NEXT) {
/* special case: operand omitted and use this operand's type + 1
for the next operand */
op = *(ip->op[++i]);
op.type = mnemo->operand_type[i-1] + 1;
}
ppcop = &powerpc_operands[op.type];
if (ppcop->flags & OPER_FAKE) {
if (insn != NULL) {
if (op.value != NULL)
cpu_error(16); /* ignoring fake operand */
*insn = insertcode(*insn,0,ppcop);
}
continue;
}
if ((reloctype = get_reloc_type(&op)) != REL_NONE) {
if (db != NULL) {
val = make_reloc(reloctype,&op,sec,pc,&db->relocs);
}
else {
if (!eval_expr(op.value,&val,sec,pc)) {
if (reloctype == REL_PC)
val -= pc;
}
}
}
else {
if (!eval_expr(op.value,&val,sec,pc))
if (insn != NULL)
cpu_error(2); /* constant integer expression required */
}
/* execute modifier on val */
if (op.mode) {
switch (op.mode) {
case OPM_LO:
val &= 0xffff;
break;
case OPM_HI:
val = (val>>16) & 0xffff;
break;
case OPM_HA:
val = ((val>>16) + ((val & 0x8000) ? 1 : 0) & 0xffff);
break;
}
if ((ppcop->flags & OPER_SIGNED) && (val & 0x8000))
val -= 0x10000;
}
/* do optimizations here: */
if (opt_branch) {
if (reloctype==REL_PC &&
(op.type==BD || op.type==BDM || op.type==BDP)) {
if (val<-0x8000 || val>0x7fff) {
/* "B<cc>" branch destination out of range, convert into
a "B<!cc> ; B" combination */
if (insn != NULL) {
negate_bo_cond(insn);
*insn = insertcode(*insn,8,ppcop); /* B<!cc> $+8 */
insn++;
*insn = B(18,0,0); /* set B instruction opcode */
val -= 4;
}
ppcop = &powerpc_operands[LI]; /* set oper. for B instruction */
isize = 8;
}
}
}
if (ppcop->flags & OPER_PARENS) {
if (op.basereg) {
/* a load/store instruction d(Rn) carries basereg in current op */
taddr reg;
if (db!=NULL && op.mode==OPM_NONE && op.attr==REL_NONE) {
if (eval_expr(op.basereg,&reg,sec,pc)) {
if (reg == sdreg) /* is it a small data reference? */
fix_reloctype(db,REL_SD);
else if (reg == sd2reg) /* EABI small data 2 */
fix_reloctype(db,REL_PPCEABI_SDA2);
}
}
/* write displacement */
if (insn != NULL) {
range_check(val,ppcop,db);
*insn = insertcode(*insn,val,ppcop);
}
/* move to next operand type to handle base register */
op.type = mnemo->operand_type[++i];
ppcop = &powerpc_operands[op.type];
op.attr = REL_NONE;
op.mode = OPM_NONE;
op.value = op.basereg;
if (!eval_expr(op.value,&val,sec,pc))
if (insn != NULL)
cpu_error(2); /* constant integer expression required */
}
else if (insn != NULL)
cpu_error(14); /* missing base register */
}
/* write val (register, immediate, etc.) */
if (insn != NULL) {
range_check(val,ppcop,db);
*insn = insertcode(*insn,val,ppcop);
}
}
return isize;
}
size_t instruction_size(instruction *ip,section *sec,taddr pc)
/* Calculate the size of the current instruction; must be identical
to the data created by eval_instruction. */
{
/* determine optimized size, when needed */
if (opt_branch)
return eval_operands(ip,sec,pc,NULL,NULL);
/* otherwise an instruction is always 4 bytes */
return 4;
}
dblock *eval_instruction(instruction *ip,section *sec,taddr pc)
/* Convert an instruction into a DATA atom including relocations,
when necessary. */
{
dblock *db = new_dblock();
uint32_t insn[2];
if (db->size = eval_operands(ip,sec,pc,insn,db)) {
unsigned char *d = db->data = mymalloc(db->size);
int i;
for (i=0; i<db->size/4; i++)
d = setval(1,d,4,insn[i]);
}
return db;
}
dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
/* Create a dblock (with relocs, if necessary) for size bits of data. */
{
dblock *db = new_dblock();
taddr val;
tfloat flt;
if ((bitsize & 7) || bitsize > 64)
cpu_error(9,bitsize); /* data size not supported */
if (!OP_DATA(op->type))
ierror(0);
db->size = bitsize >> 3;
db->data = mymalloc(db->size);
if (type_of_expr(op->value) == FLT) {
if (!eval_expr_float(op->value,&flt))
general_error(60); /* cannot evaluate floating point */
switch (bitsize) {
case 32:
conv2ieee32(1,db->data,flt);
break;
case 64:
conv2ieee64(1,db->data,flt);
break;
default:
cpu_error(10); /* data has illegal type */
break;
}
}
else {
val = make_reloc(get_reloc_type(op),op,sec,pc,&db->relocs);
switch (db->size) {
case 1:
db->data[0] = val & 0xff;
break;
case 2:
case 4:
case 8:
setval(ppc_endianess,db->data,db->size,val);
break;
default:
ierror(0);
break;
}
}
return db;
}
operand *new_operand()
{
operand *new = mymalloc(sizeof(*new));
new->type = -1;
new->mode = OPM_NONE;
return new;
}
static void define_regnames(void)
{
char r[4];
int i;
for (i=0; i<32; i++) {
sprintf(r,"r%d",i);
set_internal_abs(r,(taddr)i);
r[0] = 'f';
set_internal_abs(r,(taddr)i);
r[0] = 'v';
set_internal_abs(r,(taddr)i);
}
for (i=0; i<8; i++) {
sprintf(r,"cr%d",i);
set_internal_abs(r,(taddr)i);
}
set_internal_abs("vrsave",256);
set_internal_abs("lt",0);
set_internal_abs("gt",1);
set_internal_abs("eq",2);
set_internal_abs("so",3);
set_internal_abs("un",3);
set_internal_abs("sp",1);
set_internal_abs("rtoc",2);
set_internal_abs("fp",31);
set_internal_abs("fpscr",0);
set_internal_abs("xer",1);
set_internal_abs("lr",8);
set_internal_abs("ctr",9);
}
int init_cpu()
{
if (regnames)
define_regnames();
return 1;
}
int cpu_args(char *p)
{
int i;
if (!strncmp(p,"-m",2)) {
p += 2;
if (!strcmp(p,"pwrx") || !strcmp(p,"pwr2"))
cpu_type = CPU_TYPE_POWER | CPU_TYPE_POWER2 | CPU_TYPE_32;
else if (!strcmp(p,"pwr"))
cpu_type = CPU_TYPE_POWER | CPU_TYPE_32;
else if (!strcmp(p,"601"))
cpu_type = CPU_TYPE_601 | CPU_TYPE_PPC | CPU_TYPE_32;
else if (!strcmp(p,"ppc") || !strcmp(p,"ppc32") || !strncmp(p,"60",2) ||
!strncmp(p,"75",2) || !strncmp(p,"85",2))
cpu_type = CPU_TYPE_PPC | CPU_TYPE_32;
else if (!strcmp(p,"ppc64") || !strcmp(p,"620"))
cpu_type = CPU_TYPE_PPC | CPU_TYPE_64;
else if (!strcmp(p,"7450"))
cpu_type = CPU_TYPE_PPC | CPU_TYPE_7450 | CPU_TYPE_32 | CPU_TYPE_ALTIVEC;
else if (!strncmp(p,"74",2) || !strcmp(p,"avec") || !strcmp(p,"altivec"))
cpu_type = CPU_TYPE_PPC | CPU_TYPE_32 | CPU_TYPE_ALTIVEC;
else if (!strcmp(p,"403"))
cpu_type = CPU_TYPE_PPC | CPU_TYPE_403 | CPU_TYPE_32;
else if (!strcmp(p,"405"))
cpu_type = CPU_TYPE_PPC | CPU_TYPE_403 | CPU_TYPE_405 | CPU_TYPE_32;
else if (!strncmp(p,"44",2) || !strncmp(p,"46",2))
cpu_type = CPU_TYPE_PPC | CPU_TYPE_440 | CPU_TYPE_BOOKE | CPU_TYPE_ISEL
| CPU_TYPE_RFMCI | CPU_TYPE_32;
else if (!strcmp(p,"821") || !strcmp(p,"850") || !strcmp(p,"860"))
cpu_type = CPU_TYPE_PPC | CPU_TYPE_860 | CPU_TYPE_32;
else if (!strcmp(p,"e300"))
cpu_type = CPU_TYPE_PPC | CPU_TYPE_E300 | CPU_TYPE_32;
else if (!strcmp(p,"e500"))
cpu_type = CPU_TYPE_PPC | CPU_TYPE_E500 | CPU_TYPE_BOOKE | CPU_TYPE_ISEL
| CPU_TYPE_SPE | CPU_TYPE_EFS | CPU_TYPE_PMR | CPU_TYPE_RFMCI
| CPU_TYPE_32;
else if (!strcmp(p,"booke"))
cpu_type = CPU_TYPE_PPC | CPU_TYPE_BOOKE;
else if (!strcmp(p,"com"))
cpu_type = CPU_TYPE_COMMON | CPU_TYPE_32;
else if (!strcmp(p,"any"))
cpu_type |= CPU_TYPE_ANY;
else
return 0;
}
else if (!strcmp(p,"-no-regnames"))
regnames = 0;
else if (!strcmp(p,"-little"))
ppc_endianess = 0;
else if (!strcmp(p,"-big"))
ppc_endianess = 1;
else if (!strncmp(p,"-sdreg=",7)) {
i = atoi(p+7);
if (i>=0 && i<=31)
sdreg = i;
else
cpu_error(13); /* not a valid register */
}
else if (!strncmp(p,"-sd2reg=",8)) {
i = atoi(p+8);
if (i>=0 && i<=31)
sd2reg = i;
else
cpu_error(13); /* not a valid register */
}
else if (!strcmp(p,"-opt-branch"))
opt_branch = 1;
else
return 0;
return 1;
}

264
vasm-1/cpus/ppc/cpu.h Normal file
View File

@ -0,0 +1,264 @@
/*
** cpu.h PowerPC cpu-description header-file
** (c) in 2002,2006,2011-2016 by Frank Wille
*/
extern int ppc_endianess;
#define BIGENDIAN (ppc_endianess)
#define LITTLEENDIAN (!ppc_endianess)
#define VASM_CPU_PPC 1
#define MNEMOHTABSIZE 0x18000
/* maximum number of operands for one mnemonic */
#define MAX_OPERANDS 5
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 0
/* data type to represent a target-address */
typedef int64_t taddr;
typedef uint64_t utaddr;
/* minimum instruction alignment */
#define INST_ALIGN 4
/* default alignment for n-bit data */
#define DATA_ALIGN(n) ppc_data_align(n)
/* operand class for n-bit data definitions */
#define DATA_OPERAND(n) ppc_data_operand(n)
/* returns true when instruction is valid for selected cpu */
#define MNEMONIC_VALID(i) ppc_available(i)
/* returns true when operand type is optional; may init default operand */
#define OPERAND_OPTIONAL(p,t) ppc_operand_optional(p,t)
/* special data operand types: */
#define OP_D8 0x1001
#define OP_D16 0x1002
#define OP_D32 0x1003
#define OP_D64 0x1004
#define OP_F32 0x1005
#define OP_F64 0x1006
#define OP_DATA(t) (t >= OP_D8)
#define OP_FLOAT(t) (t >= OP_F32)
/* PPC specific relocations */
#define REL_PPCEABI_SDA2 (LAST_STANDARD_RELOC+1)
#define REL_PPCEABI_SDA21 (LAST_STANDARD_RELOC+2)
#define REL_PPCEABI_SDAI16 (LAST_STANDARD_RELOC+3)
#define REL_PPCEABI_SDA2I16 (LAST_STANDARD_RELOC+4)
#define REL_MORPHOS_DREL (LAST_STANDARD_RELOC+5)
#define REL_AMIGAOS_BREL (LAST_STANDARD_RELOC+6)
#define LAST_PPC_RELOC (LAST_STANDARD_RELOC+6)
/* type to store each operand */
typedef struct {
int16_t type;
unsigned char attr; /* reloc attribute != REL_NONE when present */
unsigned char mode; /* @l/h/ha */
expr *value;
expr *basereg; /* only for d(Rn) load/store addressing mode */
} operand;
/* operand modifier */
#define OPM_NONE 0
#define OPM_LO 1 /* low 16 bits */
#define OPM_HI 2 /* high 16 bits */
#define OPM_HA 3 /* high 16 bits with addi compensation */
/* additional mnemonic data */
typedef struct {
uint64_t available;
uint32_t opcode;
} mnemonic_extension;
/* Values defined for the 'available' field of mnemonic_extension. */
#define CPU_TYPE_PPC (1ULL)
#define CPU_TYPE_POWER (2ULL)
#define CPU_TYPE_POWER2 (4ULL)
#define CPU_TYPE_601 (8ULL)
#define CPU_TYPE_COMMON (0x10ULL)
#define CPU_TYPE_ALTIVEC (0x20ULL)
#define CPU_TYPE_403 (0x40ULL)
#define CPU_TYPE_405 (0x80ULL)
#define CPU_TYPE_440 (0x100ULL)
#define CPU_TYPE_476 (0x200ULL)
#define CPU_TYPE_BOOKE (0x400ULL)
#define CPU_TYPE_E300 (0x800ULL)
#define CPU_TYPE_E500 (0x1000ULL)
#define CPU_TYPE_VLE (0x2000ULL)
#define CPU_TYPE_E500MC (0x4000ULL)
#define CPU_TYPE_750 (0x8000ULL)
#define CPU_TYPE_7450 (0x10000ULL)
#define CPU_TYPE_ISEL (0x20000ULL)
#define CPU_TYPE_RFMCI (0x40000ULL)
#define CPU_TYPE_PMR (0x80000ULL)
#define CPU_TYPE_TMR (0x100000ULL)
#define CPU_TYPE_SPE (0x200000ULL)
#define CPU_TYPE_EFS (0x400000ULL)
#define CPU_TYPE_860 (0x800000ULL)
#define CPU_TYPE_ANY (0x1000000000000000ULL)
#define CPU_TYPE_64_BRIDGE (0x2000000000000000ULL)
#define CPU_TYPE_32 (0x4000000000000000ULL)
#define CPU_TYPE_64 (0x8000000000000000ULL)
/* Shortcuts for PPC instruction sets */
#undef PPC
#define PPC CPU_TYPE_PPC
#define PPCCOM (CPU_TYPE_PPC | CPU_TYPE_COMMON)
#define PPC32 (CPU_TYPE_PPC | CPU_TYPE_32)
#define PPC64 (CPU_TYPE_PPC | CPU_TYPE_64)
#define PPCONLY CPU_TYPE_PPC
#define PPC403 CPU_TYPE_403
#define PPC405 CPU_TYPE_405
#define PPC440 CPU_TYPE_440
#define PPC750 PPC
#define PPC860 CPU_TYPE_860
#define AVEC CPU_TYPE_ALTIVEC
#define BOOKE CPU_TYPE_BOOKE
#define E300 CPU_TYPE_E300
#define E500 CPU_TYPE_E500
#define E500MC CPU_TYPE_E500MC
#define RFMCI CPU_TYPE_RFMCI
#define ISEL (CPU_TYPE_ISEL | CPU_TYPE_VLE)
#define SPE (CPU_TYPE_SPE | CPU_TYPE_VLE)
#define EFS (CPU_TYPE_EFS | CPU_TYPE_VLE)
#define PPCPMR CPU_TYPE_PMR
#define PPC43 (CPU_TYPE_403 | CPU_TYPE_440)
#define PPC45 (CPU_TYPE_405 | CPU_TYPE_440)
#define BE3403 (CPU_TYPE_403 | CPU_TYPE_476 | CPU_TYPE_E300 | CPU_TYPE_BOOKE)
#define BE403 (CPU_TYPE_403 | CPU_TYPE_476 | CPU_TYPE_BOOKE)
#define BE476 (CPU_TYPE_476 | CPU_TYPE_BOOKE)
#define VLCOM (CPU_TYPE_PPC | CPU_TYPE_COMMON | CPU_TYPE_VLE)
#define RFMC476 (CPU_TYPE_RFMCI | CPU_TYPE_476)
#define VLRFMCI (CPU_TYPE_RFMCI | CPU_TYPE_VLE)
#define VLBE403 (CPU_TYPE_403 | CPU_TYPE_476 | CPU_TYPE_BOOKE | CPU_TYPE_VLE)
#define VLBE405 (CPU_TYPE_405 | CPU_TYPE_BOOKE | CPU_TYPE_VLE)
#define VL43 (CPU_TYPE_403 | CPU_TYPE_440 | CPU_TYPE_VLE)
#define VL45 (CPU_TYPE_405 | CPU_TYPE_440 | CPU_TYPE_VLE)
#define VL4376 (CPU_TYPE_403 | CPU_TYPE_440 | CPU_TYPE_476 | CPU_TYPE_VLE)
#define VLBE (CPU_TYPE_BOOKE | CPU_TYPE_VLE)
#define VLBE476 (CPU_TYPE_476 | CPU_TYPE_BOOKE | CPU_TYPE_VLE)
#define VLBE3 (CPU_TYPE_476 | CPU_TYPE_E300 | CPU_TYPE_BOOKE | CPU_TYPE_VLE)
#define VL7450 (CPU_TYPE_405 | CPU_TYPE_476 | CPU_TYPE_BOOKE | CPU_TYPE_7450 | CPU_TYPE_VLE)
#define VLBEPMR (CPU_TYPE_PMR | CPU_TYPE_BOOKE | CPU_TYPE_VLE)
#define POWER CPU_TYPE_POWER
#define POWER2 (CPU_TYPE_POWER | CPU_TYPE_POWER2)
#define PPCPWR2 (CPU_TYPE_PPC | CPU_TYPE_POWER | CPU_TYPE_POWER2)
#define POWER32 (CPU_TYPE_POWER | CPU_TYPE_32)
#define COM (CPU_TYPE_POWER | CPU_TYPE_PPC | CPU_TYPE_COMMON)
#define COM32 (CPU_TYPE_POWER | CPU_TYPE_PPC | CPU_TYPE_COMMON | CPU_TYPE_32)
#define M601 (CPU_TYPE_POWER | CPU_TYPE_601)
#define PWRCOM (CPU_TYPE_POWER | CPU_TYPE_601 | CPU_TYPE_COMMON)
#define MFDEC1 CPU_TYPE_POWER
#define MFDEC2 (CPU_TYPE_PPC | CPU_TYPE_601)
/* Macros used to form opcodes */
#define OP(x) ((((uint32_t)(x)) & 0x3f) << 26)
#define OPTO(x,to) (OP (x) | ((((uint32_t)(to)) & 0x1f) << 21))
#define OPL(x,l) (OP (x) | ((((uint32_t)(l)) & 1) << 21))
#define A(op, xop, rc) \
(OP (op) | ((((uint32_t)(xop)) & 0x1f) << 1) | (((uint32_t)(rc)) & 1))
#define B(op, aa, lk) (OP (op) | ((((uint32_t)(aa)) & 1) << 1) | ((lk) & 1))
#define BBO(op, bo, aa, lk) (B ((op), (aa), (lk)) | ((((uint32_t)(bo)) & 0x1f) << 21))
#define BBOCB(op, bo, cb, aa, lk) \
(BBO ((op), (bo), (aa), (lk)) | ((((uint32_t)(cb)) & 0x3) << 16))
#define DSO(op, xop) (OP (op) | ((xop) & 0x3))
#define M(op, rc) (OP (op) | ((rc) & 1))
#define MME(op, me, rc) (M ((op), (rc)) | ((((uint32_t)(me)) & 0x1f) << 1))
#define MD(op, xop, rc) \
(OP (op) | ((((uint32_t)(xop)) & 0x7) << 2) | ((rc) & 1))
#define MDS(op, xop, rc) \
(OP (op) | ((((uint32_t)(xop)) & 0xf) << 1) | ((rc) & 1))
#define SC(op, sa, lk) (OP (op) | ((((uint32_t)(sa)) & 1) << 1) | ((lk) & 1))
#define VX(op, xop) (OP (op) | (((uint32_t)(xop)) & 0x7ff))
#define VXA(op, xop) (OP (op) | (((uint32_t)(xop)) & 0x07f))
#define VXR(op, xop, rc) \
(OP (op) | (((rc) & 1) << 10) | (((uint32_t)(xop)) & 0x3ff))
#define X(op, xop) (OP (op) | ((((uint32_t)(xop)) & 0x3ff) << 1))
#define XRC(op, xop, rc) (X ((op), (xop)) | ((rc) & 1))
#define XCMPL(op, xop, l) (X ((op), (xop)) | ((((uint32_t)(l)) & 1) << 21))
#define XTO(op, xop, to) (X ((op), (xop)) | ((((uint32_t)(to)) & 0x1f) << 21))
#define XTLB(op, xop, sh) (X ((op), (xop)) | ((((uint32_t)(sh)) & 0x1f) << 11))
#define XFL(op, xop, rc) \
(OP (op) | ((((uint32_t)(xop)) & 0x3ff) << 1) | (((uint32_t)(rc)) & 1))
#define XL(op, xop) (OP (op) | ((((uint32_t)(xop)) & 0x3ff) << 1))
#define XLLK(op, xop, lk) (XL ((op), (xop)) | ((lk) & 1))
#define XLO(op, bo, xop, lk) \
(XLLK ((op), (xop), (lk)) | ((((uint32_t)(bo)) & 0x1f) << 21))
#define XLYLK(op, xop, y, lk) \
(XLLK ((op), (xop), (lk)) | ((((uint32_t)(y)) & 1) << 21))
#define XLOCB(op, bo, cb, xop, lk) \
(XLO ((op), (bo), (xop), (lk)) | ((((uint32_t)(cb)) & 3) << 16))
#define XO(op, xop, oe, rc) \
(OP (op) | ((((uint32_t)(xop)) & 0x1ff) << 1) | \
((((uint32_t)(oe)) & 1) << 10) | (((uint32_t)(rc)) & 1))
#define XS(op, xop, rc) \
(OP (op) | ((((uint32_t)(xop)) & 0x1ff) << 2) | (((uint32_t)(rc)) & 1))
#define XFXM(op, xop, fxm) \
(X ((op), (xop)) | ((((uint32_t)(fxm)) & 0xff) << 12))
#define XSPR(op, xop, spr) \
(X ((op), (xop)) | ((((uint32_t)(spr)) & 0x1f) << 16) | \
((((uint32_t)(spr)) & 0x3e0) << 6))
#define XDS(op, xop, at) \
(X ((op), (xop)) | ((((uint32_t)(at)) & 1) << 25))
#define XISEL(op, xop) (OP (op) | ((((uint32_t)(xop)) & 0x1f) << 1))
#define XSYNC(op, xop, l) (X ((op), (xop)) | ((((uint32_t)(l)) & 3) << 21))
#define EVSEL(op, xop) (OP (op) | (((uint32_t)(xop)) & 0xff) << 3)
/* The BO encodings used in extended conditional branch mnemonics. */
#define BODNZF (0x0)
#define BODNZFP (0x1)
#define BODZF (0x2)
#define BODZFP (0x3)
#define BOF (0x4)
#define BOFP (0x5)
#define BODNZT (0x8)
#define BODNZTP (0x9)
#define BODZT (0xa)
#define BODZTP (0xb)
#define BOT (0xc)
#define BOTP (0xd)
#define BODNZ (0x10)
#define BODNZP (0x11)
#define BODZ (0x12)
#define BODZP (0x13)
#define BOU (0x14)
/* The BI condition bit encodings used in extended conditional branch
mnemonics. */
#define CBLT (0)
#define CBGT (1)
#define CBEQ (2)
#define CBSO (3)
/* The TO encodings used in extended trap mnemonics. */
#define TOLGT (0x1)
#define TOLLT (0x2)
#define TOEQ (0x4)
#define TOLGE (0x5)
#define TOLNL (0x5)
#define TOLLE (0x6)
#define TOLNG (0x6)
#define TOGT (0x8)
#define TOGE (0xc)
#define TONL (0xc)
#define TOLT (0x10)
#define TOLE (0x14)
#define TONG (0x14)
#define TONE (0x18)
#define TOU (0x1f)
/* Prototypes */
int ppc_data_align(int);
int ppc_data_operand(int);
int ppc_available(int);
int ppc_operand_optional(operand *,int);

View File

@ -0,0 +1,17 @@
"%s",WARNING,
"instruction not supported on selected architecture",ERROR,
"constant integer expression required",ERROR,
"trailing garbage in operand",WARNING,
"illegal operand type",ERROR,
"missing closing parenthesis in load/store addressing mode",ERROR, /* 05 */
"relocation does not allow hi/lo modifier",ERROR,
"multiple relocation attributes",ERROR,
"multiple hi/lo modifiers",ERROR,
"data size %d not supported",ERROR,
"data has illegal type",ERROR, /* 10 */
"relocation attribute not supported by operand",ERROR,
"operand out of range: %ld (allowed: %ld to %ld)",ERROR,
"not a valid register (0-31)",ERROR,
"missing base register in load/store addressing mode",ERROR,
"missing mandatory operand",ERROR, /* 15 */
"ignoring fake operand",WARNING,

2511
vasm-1/cpus/ppc/opcodes.h Normal file

File diff suppressed because it is too large Load Diff

587
vasm-1/cpus/ppc/operands.h Normal file
View File

@ -0,0 +1,587 @@
/* Operand description structure */
struct powerpc_operand
{
int bits;
int shift;
uint32_t (*insert)(uint32_t,int32_t,const char **);
uint32_t flags;
};
/* powerpc_operand flags */
#define OPER_SIGNED (1) /* signed values */
#define OPER_SIGNOPT (2) /* signed values up to 0xffff */
#define OPER_FAKE (4) /* just reuse last read operand */
#define OPER_PARENS (8) /* operand is in parentheses */
#define OPER_CR (0x10) /* CR field */
#define OPER_GPR (0x20) /* GPR field */
#define OPER_FPR (0x40) /* FPR field */
#define OPER_RELATIVE (0x80) /* relative branch displacement */
#define OPER_ABSOLUTE (0x100) /* absolute branch address */
#define OPER_OPTIONAL (0x200) /* optional, zero if omitted */
#define OPER_NEXT (0x400) /* hack for rotate instructions */
#define OPER_NEGATIVE (0x800) /* range check on negative value */
#define OPER_VR (0x1000) /* Altivec register field */
/* Operand types. */
enum {
UNUSED,BA,BAT,BB,BBA,BD,BDA,BDM,BDMA,BDP,BDPA,BF,OBF,BFA,BI,BO,BOE,
BT,CR,D,DS,E,FL1,FL2,FLM,FRA,FRB,FRC,FRS,FXM,L,LEV,LI,LIA,MB,ME,
MBE,MBE_,MB6,NB,NSI,RA,RAL,RAM,RAS,RB,RBS,RS,SH,SH6,SI,SISIGNOPT,
SPR,SPRBAT,SPRG,SR,SV,TBR,TO,U,UI,VA,VB,VC,VD,SIMM,UIMM,SHB,
SLWI,SRWI,EXTLWI,EXTRWI,EXTWIB,INSLWI,INSRWI,ROTRWI,CLRRWI,CLRLSL,
STRM,AT,LS,RSOPT,RAOPT,RBOPT,CT,SHO,CRFS,EVUIMM_2,EVUIMM_4,EVUIMM_8
};
#define FRT FRS
#define ME6 MB6
#define RT RS
#define RTOPT RSOPT
#define VS VD
#define CRB MB
#define PMR SPR
#define TMR SPR
#define CRFD BF
#define EVUIMM SH
#define NEXT (-1) /* use operand_type+1 for next operand */
/* The functions used to insert complex operands. */
static uint32_t insert_bat(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | (((insn >> 21) & 0x1f) << 16);
}
static uint32_t insert_bba(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | (((insn >> 16) & 0x1f) << 11);
}
static uint32_t insert_bd(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | (value & 0xfffc);
}
static uint32_t insert_bdm(uint32_t insn,int32_t value,const char **errmsg)
{
if ((value & 0x8000) != 0)
insn |= 1 << 21;
return insn | (value & 0xfffc);
}
static uint32_t insert_bdp(uint32_t insn,int32_t value,const char **errmsg)
{
if ((value & 0x8000) == 0)
insn |= 1 << 21;
return insn | (value & 0xfffc);
}
static int valid_bo(int32_t value)
{
switch (value & 0x14) {
default:
case 0:
return 1;
case 0x4:
return (value & 0x2) == 0;
case 0x10:
return (value & 0x8) == 0;
case 0x14:
return value == 0x14;
}
}
static uint32_t insert_bo(uint32_t insn,int32_t value,const char **errmsg)
{
if (!valid_bo (value))
*errmsg = "invalid conditional option";
return insn | ((value & 0x1f) << 21);
}
static uint32_t insert_boe(uint32_t insn,int32_t value,const char **errmsg)
{
if (!valid_bo (value))
*errmsg = "invalid conditional option";
else if ((value & 1) != 0)
*errmsg = "attempt to set y bit when using + or - modifier";
return insn | ((value & 0x1f) << 21);
}
static uint32_t insert_ds(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | (value & 0xfffc);
}
static uint32_t insert_li(uint32_t insn,int32_t value,const char **errmsg)
{
if ((value & 3) != 0)
*errmsg = "ignoring least significant bits in branch offset";
return insn | (value & 0x3fffffc);
}
static uint32_t insert_mbe(uint32_t insn,int32_t value,const char **errmsg)
{
uint32_t uval, mask;
int mb, me, mx, count, last;
uval = value;
if (uval == 0) {
*errmsg = "illegal bitmask";
return insn;
}
mb = 0;
me = 32;
if ((uval & 1) != 0)
last = 1;
else
last = 0;
count = 0;
for (mx = 0, mask = (int32_t) 1 << 31; mx < 32; ++mx, mask >>= 1) {
if ((uval & mask) && !last) {
++count;
mb = mx;
last = 1;
}
else if (!(uval & mask) && last) {
++count;
me = mx;
last = 0;
}
}
if (me == 0)
me = 32;
if (count != 2 && (count != 0 || ! last)) {
*errmsg = "illegal bitmask";
}
return insn | (mb << 6) | ((me - 1) << 1);
}
static uint32_t insert_mb6(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | ((value & 0x1f) << 6) | (value & 0x20);
}
static uint32_t insert_nb(uint32_t insn,int32_t value,const char **errmsg)
{
if (value < 0 || value > 32)
*errmsg = "value out of range";
if (value == 32)
value = 0;
return insn | ((value & 0x1f) << 11);
}
static uint32_t insert_nsi(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | ((- value) & 0xffff);
}
static uint32_t insert_ral(uint32_t insn,int32_t value,const char **errmsg)
{
if (value == 0
|| (uint32_t) value == ((insn >> 21) & 0x1f))
*errmsg = "invalid register operand when updating";
return insn | ((value & 0x1f) << 16);
}
static uint32_t insert_ram(uint32_t insn,int32_t value,const char **errmsg)
{
if ((uint32_t) value >= ((insn >> 21) & 0x1f))
*errmsg = "index register in load range";
return insn | ((value & 0x1f) << 16);
}
static uint32_t insert_ras(uint32_t insn,int32_t value,const char **errmsg)
{
if (value == 0)
*errmsg = "invalid register operand when updating";
return insn | ((value & 0x1f) << 16);
}
static uint32_t insert_rbs(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | (((insn >> 21) & 0x1f) << 11);
}
static uint32_t insert_sh6(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | ((value & 0x1f) << 11) | ((value & 0x20) >> 4);
}
static uint32_t insert_spr(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
}
static uint32_t insert_sprg(uint32_t insn,int32_t value,const char **errmsg)
{
/* @@@ only BOOKE, VLE and 405 have 8 SPRGs */
if (value & ~7)
*errmsg = "illegal SPRG number";
if ((insn & 0x100)!=0 || value<=3)
value |= 0x10; /* mfsprg 4..7 use SPR260..263 */
return insn | ((value & 17) << 16);
}
static uint32_t insert_tbr(uint32_t insn,int32_t value,const char **errmsg)
{
if (value == 0)
value = 268;
return insn | ((value & 0x1f) << 16) | ((value & 0x3e0) << 6);
}
static uint32_t insert_slwi(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | ((value&0x1f)<<11) | ((31-(value&0x1f))<<1);
}
static uint32_t insert_srwi(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | (((32-value)&0x1f)<<11) | ((value&0x1f)<<6) | (31<<1);
}
static uint32_t insert_extlwi(uint32_t insn,int32_t value,const char **errmsg)
{
if (value<1 || value>32)
*errmsg = "value out of range (1-32)";
return insn | (((value-1)&0x1f)<<1);
}
static uint32_t insert_extrwi(uint32_t insn,int32_t value,const char **errmsg)
{
if (value<1 || value>32)
*errmsg = "value out of range (1-32)";
return insn | ((value&0x1f)<<11) | (((32-value)&0x1f)<<6) | (31<<1);
}
static uint32_t insert_extwib(uint32_t insn,int32_t value,const char **errmsg)
{
value += (insn>>11) & 0x1f;
if (value > 32)
*errmsg = "sum of last two operands out of range (0-32)";
return (insn&~0xf800) | ((value&0x1f)<<11);
}
static uint32_t insert_inslwi(uint32_t insn,int32_t value,const char **errmsg)
{
int32_t n = ((insn>>1) & 0x1f) + 1;
if (value+n > 32)
*errmsg = "sum of last two operands out of range (1-32)";
return (insn&~0xfffe) | (((32-value)&0x1f)<<11) | ((value&0x1f)<<6)
| ((((value+n)-1)&0x1f)<<1);
}
static uint32_t insert_insrwi(uint32_t insn,int32_t value,const char **errmsg)
{
int32_t n = ((insn>>1) & 0x1f) + 1;
if (value+n > 32)
*errmsg = "sum of last two operands out of range (1-32)";
return (insn&~0xfffe) | (((32-(value+n))&0x1f)<<11) | ((value&0x1f)<<6)
| ((((value+n)-1)&0x1f)<<1);
}
static uint32_t insert_rotrwi(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | (((32-value)&0x1f)<<11);
}
static uint32_t insert_clrrwi(uint32_t insn,int32_t value,const char **errmsg)
{
return insn | (((31-value)&0x1f)<<1);
}
static uint32_t insert_clrlslwi(uint32_t insn,int32_t value,const char **errmsg)
{
int32_t b = (insn>>6) & 0x1f;
if (value > b)
*errmsg = "n (4th oper) must be less or equal to b (3rd oper)";
return (insn&~0x7c0) | ((value&0x1f)<<11) | (((b-value)&0x1f)<<6)
| (((31-value)&0x1f)<<1);
}
static uint32_t insert_ls(uint32_t insn,int32_t value,const char **errmsg)
{
/* @@@ check for POWER4 */
return insn | ((value&3)<<21);
}
/* The operands table.
The fields are: bits, shift, insert, flags. */
const struct powerpc_operand powerpc_operands[] =
{
/* UNUSED */
{ 0, 0, 0, 0 },
/* BA */
{ 5, 16, 0, OPER_CR },
/* BAT */
{ 5, 16, insert_bat, OPER_FAKE },
/* BB */
{ 5, 11, 0, OPER_CR },
/* BBA */
{ 5, 11, insert_bba, OPER_FAKE },
/* BD */
{ 16, 0, insert_bd, OPER_RELATIVE | OPER_SIGNED },
/* BDA */
{ 16, 0, insert_bd, OPER_ABSOLUTE | OPER_SIGNED },
/* BDM */
{ 16, 0, insert_bdm, OPER_RELATIVE | OPER_SIGNED },
/* BDMA */
{ 16, 0, insert_bdm, OPER_ABSOLUTE | OPER_SIGNED },
/* BDP */
{ 16, 0, insert_bdp, OPER_RELATIVE | OPER_SIGNED },
/* BDPA */
{ 16, 0, insert_bdp, OPER_ABSOLUTE | OPER_SIGNED },
/* BF */
{ 3, 23, 0, OPER_CR },
/* OBF */
{ 3, 23, 0, OPER_CR | OPER_OPTIONAL },
/* BFA */
{ 3, 18, 0, OPER_CR },
/* BI */
{ 5, 16, 0, OPER_CR },
/* BO */
{ 5, 21, insert_bo, 0 },
/* BOE */
{ 5, 21, insert_boe, 0 },
/* BT */
{ 5, 21, 0, OPER_CR },
/* CR */
{ 3, 18, 0, OPER_CR | OPER_OPTIONAL },
/* D */
{ 16, 0, 0, OPER_PARENS | OPER_SIGNED },
/* DS */
{ 16, 0, insert_ds, OPER_PARENS | OPER_SIGNED },
/* E */
{ 1, 15, 0, 0 },
/* FL1 */
{ 4, 12, 0, 0 },
/* FL2 */
{ 3, 2, 0, 0 },
/* FLM */
{ 8, 17, 0, 0 },
/* FRA */
{ 5, 16, 0, OPER_FPR },
/* FRB */
{ 5, 11, 0, OPER_FPR },
/* FRC */
{ 5, 6, 0, OPER_FPR },
/* FRS */
{ 5, 21, 0, OPER_FPR },
/* FXM */
{ 8, 12, 0, 0 },
/* L */
{ 1, 21, 0, OPER_OPTIONAL },
/* LEV */
{ 7, 5, 0, 0 },
/* LI */
{ 26, 0, insert_li, OPER_RELATIVE | OPER_SIGNED },
/* LIA */
{ 26, 0, insert_li, OPER_ABSOLUTE | OPER_SIGNED },
/* MB */
{ 5, 6, 0, 0 },
/* ME */
{ 5, 1, 0, 0 },
/* MBE */
{ 5, 6, 0, OPER_OPTIONAL | OPER_NEXT },
/* MBE_ (NEXT) */
{ 31, 1, insert_mbe, 0 },
/* MB6 */
{ 6, 5, insert_mb6, 0 },
/* NB */
{ 6, 11, insert_nb, 0 },
/* NSI */
{ 16, 0, insert_nsi, OPER_NEGATIVE | OPER_SIGNED },
/* RA */
{ 5, 16, 0, OPER_GPR },
/* RAL */
{ 5, 16, insert_ral, OPER_GPR },
/* RAM */
{ 5, 16, insert_ram, OPER_GPR },
/* RAS */
{ 5, 16, insert_ras, OPER_GPR },
/* RB */
{ 5, 11, 0, OPER_GPR },
/* RBS */
{ 5, 1, insert_rbs, OPER_FAKE },
/* RS */
{ 5, 21, 0, OPER_GPR },
/* SH */
{ 5, 11, 0, 0 },
/* SH6 */
{ 6, 1, insert_sh6, 0 },
/* SI */
{ 16, 0, 0, OPER_SIGNED },
/* SISIGNOPT */
{ 16, 0, 0, OPER_SIGNED | OPER_SIGNOPT },
/* SPR */
{ 10, 11, insert_spr, 0 },
/* SPRBAT */
{ 2, 17, 0, 0 },
/* SPRG */
{ 3, 16, insert_sprg, 0 },
/* SR */
{ 4, 16, 0, 0 },
/* SV */
{ 14, 2, 0, 0 },
/* TBR */
{ 10, 11, insert_tbr, OPER_OPTIONAL },
/* TO */
{ 5, 21, 0, 0 },
/* U */
{ 4, 12, 0, 0 },
/* UI */
{ 16, 0, 0, 0 },
/* VA */
{ 5, 16, 0, OPER_VR },
/* VB */
{ 5, 11, 0, OPER_VR },
/* VC */
{ 5, 6, 0, OPER_VR },
/* VD */
{ 5, 21, 0, OPER_VR },
/* SIMM */
{ 5, 16, 0, OPER_SIGNED},
/* UIMM */
{ 5, 16, 0, 0 },
/* SHB */
{ 4, 6, 0, 0 },
/* SLWI */
{ 5, 11, insert_slwi, 0 },
/* SRWI */
{ 5, 11, insert_srwi, 0 },
/* EXTLWI */
{ 31, 1, insert_extlwi, 0 },
/* EXTRWI */
{ 31, 1, insert_extrwi, 0 },
/* EXTWIB */
{ 5, 11, insert_extwib, 0 },
/* INSLWI */
{ 5, 11, insert_inslwi, 0 },
/* INSRWI */
{ 5, 11, insert_insrwi, 0 },
/* ROTRWI */
{ 5, 11, insert_rotrwi, 0 },
/* CLRRWI */
{ 5, 1, insert_clrrwi, 0 },
/* CLRLSL */
{ 5, 11, insert_clrlslwi, 0 },
/* STRM */
{ 2, 21, 0, 0 },
/* AT */
{ 1, 25, 0, OPER_OPTIONAL },
/* LS */
{ 2, 21, insert_ls, OPER_OPTIONAL },
/* RSOPT */
{ 5, 21, 0, OPER_GPR | OPER_OPTIONAL },
/* RAOPT */
{ 5, 16, 0, OPER_GPR | OPER_OPTIONAL },
/* RBOPT */
{ 5, 11, 0, OPER_GPR | OPER_OPTIONAL },
/* CT */
{ 5, 21, 0, OPER_OPTIONAL },
/* SHO */
{ 5, 11, 0, OPER_OPTIONAL },
/* CRFS */
{ 3, 0, 0, OPER_CR },
/* EVUIMM_2 */
{ 5, 10, 0, OPER_PARENS },
/* EVUIMM_4 */
{ 5, 9, 0, OPER_PARENS },
/* EVUIMM_8 */
{ 5, 8, 0, OPER_PARENS },
};

302
vasm-1/cpus/qnice/cpu.c Normal file
View File

@ -0,0 +1,302 @@
/* cpu.c qnice cpu-description file */
/* (c) in 2016 by Volker Barthelmann */
#include "vasm.h"
char *cpu_copyright="vasm qnice cpu backend 0.1 (c) in 2016 Volker Barthelmann";
char *cpuname="qnice";
mnemonic mnemonics[]={
#include "opcodes.h"
};
int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]);
int bitsperbyte=8;
int bytespertaddr=4;
static char *skip_reg(char *s,int *reg)
{
int r=-1;
if(*s!='r'&&*s!='R'){
cpu_error(1);
return s;
}
s++;
if(*s<'0'||*s>'9'){
cpu_error(1);
return s;
}
r=*s++-'0';
if(*s>='0'&&*s<='5')
r=10*r+*s++-'0';
*reg=r;
return s;
}
int parse_operand(char *p,int len,operand *op,int requires)
{
op->type=-1;
p=skip(p);
if(requires==OP_REL){
char *s=p;
op->type=OP_REL;
op->offset=parse_expr(&s);
simplify_expr(op->offset);
if(s==p)
return 0;
else
return 1;
}
if(requires==OP_CC){
static const char ccodes[]="1xcznvim";
int i;
op->type=OP_CC;
if((p[0]=='!'&&len!=2)||(p[0]!='!'&&len!=1))
return 0;
if(*p=='!'){
op->cc=8;
p++;
}else
op->cc=0;
for(i=0;i<sizeof(ccodes);i++){
if(*p==ccodes[i]||tolower(*p)==ccodes[i])
break;
}
if(i>=sizeof(ccodes))
return 0;
op->cc|=i;
return 1;
}
if((p[0]=='r'||p[0]=='R')&&p[1]>='0'&&p[1]<='9'&&len==2){
op->type=OP_REG;
op->reg=p[1]-'0';
}else if((p[0]=='r'||p[0]=='R')&&p[1]=='1'&&p[2]>='0'&&p[2]<='5'&&len==3){
op->type=OP_REG;
op->reg=(p[1]-'0')*10+p[2]-'0';
}else if(*p=='@'){
p=skip(p+1);
if(*p=='-'&&p[1]=='-'){
p=skip(p+2);
p=skip_reg(p,&op->reg);
p=skip(p);
op->type=OP_PREDEC;
}else{
p=skip_reg(p,&op->reg);
p=skip(p);
if(*p=='+'&&p[1]=='+'){
p=skip(p+2);
op->type=OP_POSTINC;
}else{
op->type=OP_REGIND;
}
}
}else{
if(*p=='#'){
op->reg=1;
p=skip(p+1);
}else
op->reg=0;
op->offset=parse_expr(&p);
op->type=OP_ABS;
}
if(requires==op->type)
return 1;
if(requires==OP_GEN&&op->type>=OP_REG&&op->type<=OP_ABS)
return 1;
if(requires==OP_DGEN&&op->type>=OP_REG&&op->type<OP_ABS)
return 1;
return 0;
}
static taddr reloffset(expr *tree,section *sec,taddr pc)
{
symbol *sym;
int btype;
taddr val;
simplify_expr(tree);
if(tree->type==NUM){
/* should we do it like this?? */
val=tree->c.val;
}else{
btype=find_base(tree,&sym,sec,pc);
if(btype!=BASE_OK||!LOCREF(sym)||sym->sec!=sec)
general_error(38);
else{
eval_expr(tree,&val,sec,pc);
val=(val-pc-4)/2;
}
}
return val;
}
static taddr absoffset(expr *tree,section *sec,taddr pc,rlist **relocs,int mode,int roffset,int size)
{
taddr val;
if(!eval_expr(tree,&val,sec,pc)){
taddr addend=val;
symbol *base;
if(find_base(tree,&base,sec,pc)!=BASE_OK){
general_error(38);
return val;
}
add_nreloc_masked(relocs,base,addend,REL_ABS,size,roffset,mode?0x1FFFE:0xFFFF);
return val;
}
if(mode!=0)
val=(val>>1)&0xFFFF;
else if(size==16)
val&=0xffff;
else
val&=((1<<size)-1);
return val;
}
static int translate(instruction *p,section *sec,taddr pc)
{
int c=p->code;
return c;
}
/* Convert an instruction into a DATA atom including relocations,
if necessary. */
dblock *eval_instruction(instruction *p,section *sec,taddr pc)
{
dblock *db=new_dblock();
int opcode,c,osize;
unsigned int code,addr1,addr2,aflag=0;
char *d;
taddr val;
rlist *relocs=0;
c=translate(p,sec,pc);
db->size=osize=instruction_size(p,sec,pc);
db->data=mymalloc(db->size);
opcode=mnemonics[c].ext.opcode;
code=opcode<<12;
if(p->op[0]){
if(p->op[0]->type==OP_ABS){
code|=15<<8;
code|=(OP_POSTINC-1)<<6;
addr1=absoffset(p->op[0]->offset,sec,pc,&relocs,p->op[0]->reg,16,16);
aflag=1;
}else if(p->op[0]->type==OP_REL){
code|=15<<8;
code|=(OP_POSTINC-1)<<6;
addr1=reloffset(p->op[0]->offset,sec,pc);
aflag=1;
}else{
code|=p->op[0]->reg<<8;
code|=(p->op[0]->type-1)<<6;
}
}
if(mnemonics[c].ext.encoding==0){
if(p->op[1]){
if(p->op[1]->type==OP_ABS){
code|=15<<2;
code|=(OP_POSTINC-1)<<0;
addr2=absoffset(p->op[1]->offset,sec,pc,&relocs,p->op[1]->reg,16,16);
aflag|=2;
}else if(p->op[1]->type==OP_REL){
/* case should not exist */
code|=15<<2;
code|=(OP_POSTINC-1)<<0;
addr2=reloffset(p->op[1]->offset,sec,pc);
}else{
code|=p->op[1]->reg<<2;
code|=(p->op[1]->type-1)<<0;
}
}
}else{
code|=(mnemonics[c].ext.encoding-1)<<4;
code|=p->op[1]->cc<<0;
}
d=db->data;
*d++=code;
*d++=code>>8;
if(aflag&1){
*d++=addr1;
*d++=addr1>>8;
}
if(aflag&2){
*d++=addr2;
*d++=addr2>>8;
}
db->relocs=relocs;
return db;
}
/* Create a dblock (with relocs, if necessary) for size bits of data. */
dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
{
dblock *new=new_dblock();
taddr val;
new->size=(bitsize+7)/8;
new->data=mymalloc(new->size);
if(op->type!=OP_ABS)
ierror(0);
if(bitsize!=8&&bitsize!=16&&bitsize!=32)
cpu_error(4);
val=absoffset(op->offset,sec,pc,&new->relocs,op->reg,0,bitsize);
if(bitsize==32){
new->data[3]=val>>24;
new->data[2]=val>>16;
new->data[1]=val>>8;
new->data[0]=val;
}else if(bitsize==16){
new->data[1]=val>>8;
new->data[0]=val;
}else
new->data[0]=val;
return new;
}
/* Calculate the size of the current instruction; must be identical
to the data created by eval_instruction. */
size_t instruction_size(instruction *p,section *sec,taddr pc)
{
int sz=2;
//int c=translate(p,sec,pc),add=0;
if(p->op[0]&&(p->op[0]->type==OP_ABS||p->op[0]->type==OP_REL))
sz+=2;
if(p->op[1]&&(p->op[1]->type==OP_ABS||p->op[1]->type==OP_REL))
sz+=2;
return sz;
}
operand *new_operand()
{
operand *new=mymalloc(sizeof(*new));
new->type=-1;
return new;
}
/* return true, if initialization was successfull */
int init_cpu()
{
return 1;
}
/* return true, if the passed argument is understood */
int cpu_args(char *p)
{
return 0;
}
/* parse cpu-specific directives; return pointer to end of
cpu-specific text */
char *parse_cpu_special(char *s)
{
return s;
}

58
vasm-1/cpus/qnice/cpu.h Normal file
View File

@ -0,0 +1,58 @@
/* cpu.h qnice cpu-description header-file */
/* (c) in 2016 by Volker Barthelmann */
/* maximum number of operands in one mnemonic */
#define MAX_OPERANDS 2
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 0
/* maximum number of additional command-line-flags for this cpu */
/* data type to represent a target-address */
typedef int32_t taddr;
typedef uint32_t utaddr;
#define LITTLEENDIAN 1
#define BIGENDIAN 0
#define VASM_CPU_QNICE 1
/* minimum instruction alignment */
#define INST_ALIGN 2
/* default alignment for n-bit data */
#define DATA_ALIGN(n) ((n)<=8?1:2)
/* operand class for n-bit data definitions */
#define DATA_OPERAND(n) OP_ABS
#define cc reg
/* type to store each operand */
typedef struct {
int type;
int reg; /* also cc */
expr *offset;
} operand;
/* operand-types */
#define OP_REG 1
#define OP_REGIND 2
#define OP_POSTINC 3
#define OP_PREDEC 4
#define OP_ABS 5
#define OP_CC 6
#define OP_REL 7
#define OP_GEN 8
#define OP_DGEN 9
#define OP_PROTECTED 0
/* no derivates yet */
#define CPU_ALL (-1)
typedef struct {
unsigned int opcode;
unsigned int encoding;
} mnemonic_extension;

View File

@ -0,0 +1,6 @@
"illegal operand",ERROR,
"word register expected",ERROR,
"",ERROR,
"value does not find in %d bits",WARNING,
"data size not supported",ERROR,

View File

@ -0,0 +1,18 @@
"move",OP_GEN,OP_DGEN,0,0,
"add",OP_GEN,OP_DGEN,1,0,
"addc",OP_GEN,OP_DGEN,2,0,
"sub",OP_GEN,OP_DGEN,3,0,
"subc",OP_GEN,OP_DGEN,4,0,
"shl",OP_GEN,OP_DGEN,5,0,
"shr",OP_GEN,OP_DGEN,6,0,
"swap",OP_GEN,OP_DGEN,7,0,
"not",OP_GEN,OP_DGEN,8,0,
"and",OP_GEN,OP_DGEN,9,0,
"or",OP_GEN,OP_DGEN,10,0,
"xor",OP_GEN,OP_DGEN,11,0,
"cmp",OP_GEN,OP_GEN,12,0,
"halt",0,0,14,0,
"abra",OP_GEN,OP_CC,15,1,
"asub",OP_GEN,OP_CC,15,2,
"rbra",OP_REL,OP_CC,15,3,
"rsub",OP_REL,OP_CC,15,4,

306
vasm-1/cpus/test/cpu.c Normal file
View File

@ -0,0 +1,306 @@
/* cpu.c example cpu-description file */
/* (c) in 2002 by Volker Barthelmann */
#include "vasm.h"
char *cpu_copyright="vasm test cpu backend (c) in 2002 Volker Barthelmann";
/* example machine.
valid Registers: R0-R3
valid extensions: .b/.w (default .w)
Instruction format:
XCCCCCCC 11112222 [32bit op1] [32bit op2]
X: set if byte-extension
C: instruction code
1/2: operand 1/2 type
0-3 register
4-7 register indirect (32bit offset follows)
8 absolute (32bit value follows)
9 immediate (32bit value follows)
Special case for addq: 1111: immediate 0-15
Special case for bra: 11112222: 0-255 relative offset
*/
char *cpuname="test";
int bitsperbyte=8;
int bytespertaddr=4;
mnemonic mnemonics[]={
"move",{OP_ALL,OP_REG},{CPU_ALL,0x0},
"move",{OP_REG,OP_ALL_DEST},{CPU_ALL,0x1},
"add",{OP_ALL,OP_REG},{CPU_ALL,0x2},
"add",{OP_REG,OP_ALL_DEST},{CPU_ALL,0x3},
"add",{OP_IMM32,OP_MEM},{CPU_ALL,0x4},
"addq",{OP_IMM32,OP_ALL_DEST},{CPU_ALL,0x5},
"jmp",{OP_ABS,0},{CPU_ALL,0x6},
"bra",{OP_ABS,0},{CPU_ALL,0x7},
};
int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]);
char *parse_instruction(char *s,int *inst_len,char **ext,int *ext_len,
int *ext_cnt)
/* parse instruction and save extension locations */
{
char *inst = s;
while (*s && *s!='.' && !isspace((unsigned char)*s))
s++;
*inst_len = s - inst;
if (*s =='.') {
/* extension present */
ext[*ext_cnt] = ++s;
while (*s && *s!='.' && !isspace((unsigned char)*s))
s++;
ext_len[*ext_cnt] = s - ext[*ext_cnt];
*ext_cnt += 1;
}
return s;
}
int set_default_qualifiers(char **q,int *q_len)
/* fill in pointers to default qualifiers, return number of qualifiers */
{
q[0] = "w";
q_len[0] = 1;
return 1;
}
/* Does not do much useful parsing yet. */
int parse_operand(char *p,int len,operand *op,int requires)
{
p=skip(p);
if(len==2&&(p[0]=='r'||p[0]=='R')&&p[1]>='0'&&p[1]<='3'){
op->type=OP_REG;
op->basereg=p[1]-'0';
}else if(p[0]=='#'){
op->type=OP_IMM32;
p=skip(p+1);
op->offset=parse_expr(&p);
}else{
int parent=0;
expr *tree;
op->type=-1;
if(*p=='('){
parent=1;
p=skip(p+1);
}
tree=parse_expr(&p);
if(!tree)
return 0;
p=skip(p);
if(parent){
if(*p==','){
p=skip(p+1);
if((*p!='r'&&*p!='R')||p[1]<'0'||p[1]>'3'){
cpu_error(0);
return 0;
}
op->type=OP_REGIND;
op->basereg=p[1]-'0';
p=skip(p+2);
}
if(*p!=')'){
cpu_error(0);
return 0;
}else
p=skip(p+1);
}
if(op->type!=OP_REGIND)
op->type=OP_ABS;
op->offset=tree;
}
if(requires==op->type)
return 1;
if(requires==OP_ALL_DEST&&op->type!=OP_IMM32)
return 1;
if(requires==OP_MEM&&OP_ISMEM(op->type))
return 1;
if(requires==OP_ALL)
return 1;
return 0;
}
/* Return new instruction code, if instruction can be optimized
to another one. */
static int opt_inst(instruction *p,section *sec,taddr pc)
{
/* Ganz simples Beispiel. */
/* add->addq */
if((p->code==2||p->code==4)&&p->op[0]->type==OP_IMM32){
taddr val;
if(eval_expr(p->op[0]->offset,&val,sec,pc)&&val<16)
return 5;
}
/* jmp->bra */
if(p->code==6){
expr *tree=p->op[0]->offset;
if(tree->type==SYM&&tree->c.sym->sec==sec&&LOCREF(tree->c.sym)&&
tree->c.sym->pc-pc>=-128&&tree->c.sym->pc-pc<=127)
return 7;
}
return p->code;
}
static int operand_code(operand *p)
{
if(!p)
return 0;
if(p->type==OP_REG)
return p->basereg;
if(p->type==OP_REGIND)
return 4+p->basereg;
if(p->type==OP_ABS)
return 8;
if(p->type==OP_IMM32)
return 9;
ierror(0);
}
static char *fill_operand(operand *p,section *sec,taddr pc,char *d,rlist **relocs,int roffset)
{
taddr val;
if(!p||p->type==OP_REG)
return d;
/* FIXME: Test for valid operand, create reloc */
if(!eval_expr(p->offset,&val,sec,pc)){
symbol *base;
if (find_base(p->offset,&base,sec,pc)!=BASE_OK)
general_error(38);
else
add_nreloc(relocs,base,0,REL_ABS,16,roffset*8);
}
*d++=val>>24;
*d++=val>>16;
*d++=val>>8;
*d++=val;
return d;
}
/* Convert an instruction into a DATA atom including relocations,
if necessary. */
dblock *eval_instruction(instruction *p,section *sec,taddr pc)
{
/* Auch simpel. Fehlerchecks fehlen. */
size_t size=instruction_size(p,sec,pc);
dblock *db=new_dblock();
int c=opt_inst(p,sec,pc);
unsigned char *d;
taddr val;
db->size=size;
d=db->data=mymalloc(size);
*d=c;
if(p->qualifiers[0]){
if(c>5)
cpu_error(1,p->qualifiers[0]);
else if(!strcmp(p->qualifiers[0],"b"))
*d|=128;
else if(strcmp(p->qualifiers[0],"w"))
cpu_error(1,p->qualifiers[0]);
}
d++;
if(c==5){
/* addq */
taddr val;
if(!eval_expr(p->op[0]->offset,&val,sec,pc)||val>15)
cpu_error(0);
*d=((val<<4)|operand_code(p->op[1]));
return db;
}
if(c==7){
expr *tree=p->op[0]->offset;
if(!(tree->type==SYM&&tree->c.sym->sec==sec&&LOCREF(tree->c.sym)&&
tree->c.sym->pc-pc>=-128&&tree->c.sym->pc-pc<=127))
cpu_error(0);
else
*d=tree->c.sym->pc-pc;
return db;
}
*d=((operand_code(p->op[0])<<4)|operand_code(p->op[1]));
d++;
d=fill_operand(p->op[0],sec,pc,d,&db->relocs,d-db->data);
d=fill_operand(p->op[1],sec,pc,d,&db->relocs,d-db->data);
return db;
}
/* Create a dblock (with relocs, if necessary) for size bits of data. */
dblock *eval_data(operand *op,size_t bitsize,section *sec,taddr pc)
{
dblock *new=new_dblock();
taddr val;
new->size=(bitsize+7)/8;
new->data=mymalloc(new->size);
if(op->type!=OP_ABS)
ierror(0);
if(bitsize!=8&&bitsize!=16&&bitsize!=32)
cpu_error(2);
if(!eval_expr(op->offset,&val,sec,pc)&&bitsize!=32)
general_error(38);
if(bitsize==8){
new->data[0]=val;
}else if(bitsize==16){
new->data[0]=val>>8;
new->data[1]=val;
}else if(bitsize==32){
fill_operand(op,sec,pc,new->data,&new->relocs,0);
}
return new;
}
static taddr opsize(operand *p)
{
if(!p)
return 0;
if(p->type!=OP_REG)
return 4;
else
return 0;
}
/* Calculate the size of the current instruction; must be identical
to the data created by eval_instruction. */
size_t instruction_size(instruction *p,section *sec,taddr pc)
{
int c;
size_t size=2;
size+=opsize(p->op[0]);
size+=opsize(p->op[1]);
c=opt_inst(p,sec,pc);
if(c==5||c==7){
/* addq/bra */
size-=4;
}
return size;
}
operand *new_operand()
{
operand *new=mymalloc(sizeof(*new));
new->type=-1;
return new;
}
/* return true, if initialization was successfull */
int init_cpu()
{
return 1;
}
/* return true, if the passed argument is understood */
int cpu_args(char *p)
{
/* no args */
return 0;
}
/* parse cpu-specific directives; return pointer to end of
cpu-specific text */
char *parse_cpu_special(char *s)
{
/* no specials */
return s;
}

55
vasm-1/cpus/test/cpu.h Normal file
View File

@ -0,0 +1,55 @@
/* cpu.h example cpu-description header-file */
/* (c) in 2002 by Volker Barthelmann */
#define LITTLEENDIAN 1
#define BIGENDIAN 0
#define VASM_CPU_TEST 1
/* maximum number of operands in one mnemonic */
#define MAX_OPERANDS 2
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 1
/* maximum number of additional command-line-flags for this cpu */
/* data type to represent a target-address */
typedef int32_t taddr;
typedef uint32_t utaddr;
/* minimum instruction alignment */
#define INST_ALIGN 2
/* default alignment for n-bit data */
#define DATA_ALIGN(n) ((n)<=8?1:2)
/* operand class for n-bit data definitions */
#define DATA_OPERAND(n) OP_ABS
/* type to store each operand */
typedef struct {
int type;
int basereg;
expr *offset;
} operand;
/* operand-types (stupid example) */
#define OP_IMM32 1
#define OP_REG 2
#define OP_ABS 3
#define OP_REGIND 4
/* supersets of other operands */
#define OP_MEM 100
#define OP_ALL 200
#define OP_ALL_DEST 300
#define OP_ISMEM(x) ((x)==OP_ABS||(x)==OP_REGIND)
#define CPU_SMALL 1
#define CPU_LARGE 2
#define CPU_ALL (-1)
typedef struct {
unsigned int available;
unsigned int opcode;
} mnemonic_extension;

View File

@ -0,0 +1,3 @@
"illegal operand",ERROR,
"illegal qualifier <%s>",ERROR,
"data size not supported",ERROR,

524
vasm-1/cpus/tr3200/cpu.c Normal file
View File

@ -0,0 +1,524 @@
/* cpu.c tr3200 cpu description file */
/* (c) in 2014,2019 by Luis Panadero Guardeno */
#include "vasm.h"
/*#define CPU_DEBUG (1)*/
#ifdef CPU_DEBUG
#define OPERAND_DEBUG (1)
#define INSTR_DEBUG (1)
#endif
char *cpu_copyright="vasm TR3200 cpu module v0.2 by Luis Panadero Guardeno";
char *cpuname="tr3200";
int bitsperbyte=8;
int bytespertaddr=4;
mnemonic mnemonics[]={
#include "opcodes.h"
};
int mnemonic_cnt=sizeof(mnemonics)/sizeof(mnemonics[0]);
static taddr opsize(operand *p, unsigned char num_operands, section *sec, taddr pc);
/* parse instruction */
char *parse_instruction(char *s, int *inst_len, char **ext, int *ext_len,
int *ext_cnt)
{
char* inst = s;
#ifdef CPU_DEBUG
fprintf(stderr, "parse_inst : \"%.*s\"\n", *inst_len, s);
#endif
/*
while (*s && !isspace((unsigned char)*s))
s++;
*inst_len = s - inst; */
return s;
}
/* Sets op if is a valid register */
static int parse_reg(char **p, int len, operand *op)
{
char *rp = skip(*p);
int reg = -1;
if (len < 2) {
return 0;
}
if (*rp != '%') {
return 0;
}
rp++;
if (tolower((unsigned char)rp[0]) != 'r') {
/* Could be y, bp, sp, ia or flags */
if (len == 2 && tolower((unsigned char)rp[0]) == 'y') {
rp++;
*p = skip(rp);
op->type = OP_GPR;
op->reg = 11;
return 1;
} else if ( len == 3 && (tolower((unsigned char)rp[0]) == 'b')
&& (tolower((unsigned char)rp[1]) == 'p') ) {
rp++; rp++;
*p = skip(rp);
op->type = OP_GPR;
op->reg = 12;
return 1;
} else if ( len == 3 && (tolower((unsigned char)rp[0]) == 's')
&& (tolower((unsigned char)rp[1]) == 'p') ) {
rp++; rp++;
*p = skip(rp);
op->type = OP_GPR;
op->reg = 13;
return 1;
} else if ( len == 3 && (tolower((unsigned char)rp[0]) == 'i')
&& (tolower((unsigned char)rp[1]) == 'a') ) {
rp++; rp++;
*p = skip(rp);
op->type = OP_GPR;
op->reg = 14;
return 1;
} else if ( len == 6
&& (tolower((unsigned char)rp[0]) == 'f')
&& (tolower((unsigned char)rp[1]) == 'l')
&& (tolower((unsigned char)rp[2]) == 'a')
&& (tolower((unsigned char)rp[3]) == 'g')
&& (tolower((unsigned char)rp[4]) == 's')
) {
rp += 5;
*p = skip(rp);
op->type = OP_GPR;
op->reg = 14;
return 1;
}
/* It's not a register */
return 0;
}
rp++;
/* Get number */
if (len < 2 || sscanf(rp, "%u", &reg) != 1) {
return 0;
}
/* "%r0 .. %r15" are valid */
if (reg < 0 || reg > 15) {
return 0;
}
/* skip digits and return new pointer together with register number */
while ( isdigit((unsigned char)*rp) ) {
rp++;
}
*p = skip(rp);
op->type = OP_GPR;
op->reg = reg;
return 1;
}
/* Parses operands and reads expressions
* *p string
* len string length
* *op operand
* requires Type of operand expected
*/
int parse_operand(char *p, int len, operand *op, int requires)
{
op->type = NO_OP;
#ifdef OPERAND_DEBUG
fprintf(stderr, "parse_operand (reqs=%02x): \"%.*s\"\t",
(unsigned)requires, len, p);
#endif
/* Try to grab the register */
if (1 != parse_reg(&p, len, op) ) {
#ifdef OPERAND_DEBUG
fprintf(stderr, "imm\t");
#endif
/* Its not a register, should be a immediate value or a expression */
if(p[0]=='#') { /* Immediate value */
expr *tree;
#ifdef OPERAND_DEBUG
fprintf(stderr, "# ");
#endif
op->type = OP_IMM;
p=skip(p+1);
tree = parse_expr(&p);
if (!tree) { /* It's not a valid expresion */
return PO_NOMATCH;
}
op->value = tree;
} else { /* expresion that would be a immediate value */
#ifdef OPERAND_DEBUG
fprintf(stderr, "expr\t");
#endif
op->type = OP_IMM;
int parent=0;
expr *tree;
/*
if (*p=='(') {
parent=1;
p=skip(p+1);
}
*/
tree = parse_expr(&p);
if (!tree) { /* It's not a valid expresion */
return PO_NOMATCH ;
}
/* Inside of a ( ) */
/*
p=skip(p);
if(parent) {
if(*p!=')'){
cpu_error(0);
return 0;
} else
p=skip(p+1);
}
*/
op->value=tree;
}
}
#ifdef OPERAND_DEBUG
fprintf(stderr, "(type=%02x)\n", (unsigned) op->type);
#endif
if(requires == op->type) { /* Matched type */
return PO_MATCH;
}
return PO_NOMATCH; /* Ops! Not match */
}
/* Convert an instruction into a DATA atom including relocations,
if necessary. */
dblock *eval_instruction (instruction *p, section *sec, taddr pc)
{
/* Calc instruction size */
size_t size = instruction_size(p, sec, pc);
dblock *db = new_dblock();
mnemonic m = mnemonics[p->code];
unsigned char *opcode, *d; /* Data */
taddr val;
unsigned char ml_bits = 0;
unsigned char num_operands = 0;
unsigned char srn = 0; /* Size of Rn */
operand* rn = NULL;
symbol *base = NULL;
int btype;
#ifdef INSTR_DEBUG
fprintf(stderr, "eval_instruction code \"%s\" ", m.name);
#endif
num_operands += (m.operand_type[0] != NO_OP)? 1 : 0;
num_operands += (m.operand_type[1] != NO_OP)? 1 : 0;
num_operands += (m.operand_type[2] != NO_OP)? 1 : 0;
if (num_operands > 0) {
rn = p->op[m.ext.rn_pos];
}
#ifdef INSTR_DEBUG
fprintf(stderr, "P%d ", num_operands);
if (num_operands > 0)
fprintf(stderr, "rn type=%02x ", (unsigned) rn->type);
#endif
/* See if Rn is an immediate to set ML bits*/
if (rn != NULL && rn->type == OP_IMM) {
srn = opsize(rn, num_operands, sec, pc);
ml_bits = 2 | (srn == 4);
}
ml_bits = ml_bits << 6; /* Emplace ML bits */
#ifdef INSTR_DEBUG
fprintf(stderr, "IMM=%d ", srn);
fprintf(stderr, "ml %02x ", ml_bits);
#endif
db->size=size;
db->data = mymalloc(size); /* allocate for the data block */
memset(db->data, 0, db->size);
/* Here to write data ! */
d = db->data;
d[3] = m.ext.opcode; /* Common part */
d[2] = ml_bits;
switch (num_operands) {
case 3: /* format P3 */
/* Rn is always at the LSBytes side */
if( rn->type == OP_GPR) { /* Is a register */
d[0] = (rn->reg) & 0xF;
} else if (ml_bits == 0x80 ) { /* ML are 10 -> immediate */
eval_expr(rn->value, &val, sec, pc);
#ifdef INSTR_DEBUG
fprintf(stderr, "val %04x ", val);
#endif
d[1] = (val >>8) & 0x3F;
d[0] = (val ) & 0xFF;
} else { /* 32 bit immediate */
eval_expr(rn->value, &val, sec, pc);
#ifdef INSTR_DEBUG
fprintf(stderr, "val %08x ", val);
#endif
d[7] = (val >>24) & 0xFF;
d[6] = (val >>16) & 0xFF;
d[5] = (val >>8 ) & 0xFF;
d[4] = (val ) & 0xFF;
}
if (m.ext.rn_pos == 1) { /* Special case of STORE */
d[1] |= (p->op[0]->reg & 0xF) << 6;
d[2] |= (p->op[0]->reg & 0xF) >> 2;
d[2] |= (p->op[2]->reg) << 2; /* rd */
} else {
d[1] |= (p->op[1]->reg & 0xF) << 6;
d[2] |= (p->op[1]->reg & 0xF) >> 2;
d[2] |= (p->op[0]->reg) << 2; /* rd */
}
break;
case 2: /* format P2 */
if( rn->type == OP_GPR) { /* Is a register */
d[0] = (rn->reg) & 0xF;
} else if (ml_bits == 0x80 ) { /* ML are 10 -> immediate */
eval_expr(rn->value, &val, sec, pc);
/* CALL/JUMP stuff */
if (m.ext.opcode == 0x4B || m.ext.opcode == 0x4C ) {
val = val >> 2; /* CALL/JMP does a left shift of two bits */
}
#ifdef INSTR_DEBUG
fprintf(stderr, "val %06x ", val);
#endif
d[2] |= (val >>16) & 0x03;
d[1] = (val >>8) & 0xFF;
d[0] = (val ) & 0xFF;
} else { /* 32 bit immediate */
eval_expr(rn->value, &val, sec, pc);
#ifdef INSTR_DEBUG
fprintf(stderr, "val %08x ", val);
#endif
d[7] = (val >>24) & 0xFF;
d[6] = (val >>16) & 0xFF;
d[5] = (val >>8 ) & 0xFF;
d[4] = (val ) & 0xFF;
}
if (m.ext.rn_pos == 0) { /* Special case of STORE */
d[2] |= (p->op[1]->reg) << 2;
} else {
d[2] |= (p->op[0]->reg) << 2;
}
break;
case 1: /* format P1 */
if( rn->type == OP_GPR) { /* Is a register */
d[0] = (rn->reg) & 0xF;
} else if (ml_bits == 0x80 ) { /* ML are 10 -> immediate */
if (!eval_expr(rn->value, &val, sec, pc))
btype = find_base(rn->value, &base, sec, pc);
/* CALL/JUMP stuff */
if (m.ext.opcode >= 0x27 && m.ext.opcode <= 0x28 ) {
if ((base != NULL && btype == BASE_OK && !is_pc_reloc(base, sec)) ||
base == NULL)
val = val - pc - 4; /* Relative jump/call (%pc has been increased) */
else if (btype == BASE_OK)
add_extnreloc_masked(&db->relocs, base, val-4, REL_PC,
0, 22, 0, 0xfffffc);
else
general_error(38); /* @@@ illegal relocation */
base = NULL;
val = val >> 2; /* CALL/JMP does a left shift of two bits */
} else if (m.ext.opcode >= 0x25 && m.ext.opcode <= 0x26 ) {
if (base != NULL && btype != BASE_ILLEGAL) {
add_extnreloc_masked(&db->relocs, base, val,
btype == BASE_PCREL ? REL_PC : REL_ABS,
0, 22, 0, 0xfffffc);
base = NULL;
}
}
#ifdef INSTR_DEBUG
fprintf(stderr, "val %06x ", val);
#endif
d[2] |= (val >>16) & 0x3F;
d[1] = (val >>8) & 0xFF;
d[0] = (val ) & 0xFF;
} else { /* 32 bit immediate */
eval_expr(rn->value, &val, sec, pc);
/* CALL/JUMP stuff */
if (m.ext.opcode >= 0x27 && m.ext.opcode <= 0x28 ) {
val = val - pc - 4; /* Relative jump/call */
}
#ifdef INSTR_DEBUG
fprintf(stderr, "val %08x ", val);
#endif
d[7] = (val >>24) & 0xFF;
d[6] = (val >>16) & 0xFF;
d[5] = (val >>8 ) & 0xFF;
d[4] = (val ) & 0xFF;
}
break;
case 0: /* format NP */
#ifdef INSTR_DEBUG
fprintf(stderr, "NP ");
#endif
default:
;
}
#ifdef INSTR_DEBUG
{
int i;
for(i= db->size -1; i >= 0; i-- ) {
fprintf(stderr, "%02X ", d[i]);
}
}
fprintf(stderr, "\n");
#endif
return db;
}
/* Create a dblock (with relocs, if necessary) for size bits of data. */
dblock *eval_data(operand *op, size_t bitsize, section *sec, taddr pc)
{
dblock *new=new_dblock();
taddr val;
new->size = bitsize >> 3;
new->data = mymalloc(new->size);
#ifdef CPU_DEBUG
fprintf(stderr, "eval_data ");
#endif
if(op->type != OP_IMM) { /* ??? */
#ifdef CPU_DEBUG
fprintf(stderr, "!= OP_IMM\n");
#endif
ierror(0);
}
if(bitsize!=8 && bitsize!=16 && bitsize!=32) {
#ifdef CPU_DEBUG
fprintf(stderr, "bad data size\n");
#endif
cpu_error(2); /* Invalid data size */
}
if(!eval_expr(op->value, &val, sec, pc) ) {
symbol *base;
int btype;
btype = find_base(op->value, &base, sec, pc);
if (base)
add_extnreloc(&new->relocs, base, val,
btype==BASE_PCREL ? REL_PC : REL_ABS, 0, bitsize, 0);
else if (btype != BASE_NONE)
general_error(38); /* illegal relocation */
}
if(bitsize == 8){
new->data[0] = val & 0xFF;
} else if (bitsize == 16){
new->data[1] = (val>>8) & 0xFF;
new->data[0] = val & 0xFF;
} else if (bitsize == 32){
new->data[3] = (val>>24) & 0xFF;
new->data[2] = (val>>16) & 0xFF;
new->data[1] = (val>>8) & 0xFF;
new->data[0] = val & 0xFF;
}
return new;
}
/* Size of a operand
* *p operand
* num_operand Total number of operands
* */
static taddr opsize(operand *p, unsigned char num_operands, section *sec, taddr pc)
{
taddr val = 0;
if(!p) {
return 0;
} else if (p->type == OP_IMM ) {
eval_expr(p->value, &val, sec, pc);
if (num_operands == 3
&& (val < -8192 || val > 8191) ) { /* 14 bits */
return 4; /* 32 bit immediate */
} else if (num_operands == 2
&& (val < -131072 || val > 131071) ) { /* 18 bits */
return 4; /* 32 bit immediate */
} else if (num_operands == 1
&& (val < -2097152 || val > 2097151) ) { /* 22 bits */
return 4; /* 32 bit immediate */
}
}
return 0;
}
/* Calculate the size of the current instruction; must be identical
to the data created by eval_instruction. */
size_t instruction_size (instruction *p, section *sec, taddr pc)
{
size_t size = 4; /* four bytes */
unsigned char num_operands = 0;
num_operands += (p->op[0] != 0)? 1 : 0;
num_operands += (p->op[1] != 0)? 1 : 0;
num_operands += (p->op[2] != 0)? 1 : 0;
size += opsize(p->op[0], num_operands, sec, pc);
size += opsize(p->op[1], num_operands, sec, pc);
size += opsize(p->op[2], num_operands, sec, pc);
return size;
}
operand *new_operand()
{
operand *new = mymalloc(sizeof(*new));
new->type=-1;
return new;
}
/* return true, if initialization was successfull */
int init_cpu()
{
return 1;
}
/* return true, if the passed argument is understood */
int cpu_args(char *p)
{
/* no args */
return 0;
}
/* parse cpu-specific directives; return pointer to end of
cpu-specific text */
char *parse_cpu_special(char *s)
{
/* no specials */
return s;
}

48
vasm-1/cpus/tr3200/cpu.h Normal file
View File

@ -0,0 +1,48 @@
/* cpu.h TR3200 cpu-description header-file */
/* (c) in 2014 by Luis Panadero Guardeno */
#define LITTLEENDIAN 1
#define BIGENDIAN 0
#define VASM_CPU_TR3200 1
/* maximum number of operands in one mnemonic */
#define MAX_OPERANDS 3
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 0
/* maximum number of additional command-line-flags for this cpu */
/* data type to represent a target-address */
typedef int32_t taddr;
typedef uint32_t utaddr;
/* minimum instruction alignment */
#define INST_ALIGN 4
/* default alignment for n-bit data */
#define DATA_ALIGN(n) ((n)<=8 ? 1 : ((n)<=16 ? 2 : 4))
/* type to store each operand */
typedef struct {
int16_t type; /* type of operand from mnemonic.operand_type */
uint8_t reg; /* Register number if there is one */
expr *value; /* single register, immed. val. or branch loc.*/
} operand;
/* operand types */
#define NO_OP (0)
#define OP_GPR (1) /* %r0 to %r15 or %y, %bp %sp, %ia %flags */
#define OP_IMM (2)
/* operand class for n-bit data definitions */
#define DATA_OPERAND(n) OP_IMM
#define CPU_ALL (-1)
typedef struct {
unsigned char opcode; /* OpCode */
unsigned char rn_pos; /* Position of Rn */
unsigned char available; /* CPU variants were is available */
} mnemonic_extension;

View File

@ -0,0 +1,3 @@
"illegal operand",ERROR,
"illegal qualifier <%s>",ERROR,
"data size not supported",ERROR,

View File

@ -0,0 +1,150 @@
/* name, operand 1, operand 2, operand 3, OpCode, Rn pos, CPU model */
"and", {OP_GPR, OP_GPR, OP_GPR }, {0x80, 2, CPU_ALL},
"and", {OP_GPR, OP_GPR, OP_IMM }, {0x80, 2, CPU_ALL},
"or", {OP_GPR, OP_GPR, OP_GPR }, {0x81, 2, CPU_ALL},
"or", {OP_GPR, OP_GPR, OP_IMM }, {0x81, 2, CPU_ALL},
"xor", {OP_GPR, OP_GPR, OP_GPR }, {0x82, 2, CPU_ALL},
"xor", {OP_GPR, OP_GPR, OP_IMM }, {0x82, 2, CPU_ALL},
"bitc", {OP_GPR, OP_GPR, OP_GPR }, {0x83, 2, CPU_ALL},
"bitc", {OP_GPR, OP_GPR, OP_IMM }, {0x83, 2, CPU_ALL},
"add", {OP_GPR, OP_GPR, OP_GPR }, {0x84, 2, CPU_ALL},
"add", {OP_GPR, OP_GPR, OP_IMM }, {0x84, 2, CPU_ALL},
"addc", {OP_GPR, OP_GPR, OP_GPR }, {0x85, 2, CPU_ALL},
"addc", {OP_GPR, OP_GPR, OP_IMM }, {0x85, 2, CPU_ALL},
"sub", {OP_GPR, OP_GPR, OP_GPR }, {0x86, 2, CPU_ALL},
"sub", {OP_GPR, OP_GPR, OP_IMM }, {0x86, 2, CPU_ALL},
"subb", {OP_GPR, OP_GPR, OP_GPR }, {0x87, 2, CPU_ALL},
"subb", {OP_GPR, OP_GPR, OP_IMM }, {0x87, 2, CPU_ALL},
"rsb", {OP_GPR, OP_GPR, OP_GPR }, {0x88, 2, CPU_ALL},
"rsb", {OP_GPR, OP_GPR, OP_IMM }, {0x88, 2, CPU_ALL},
"rsbb", {OP_GPR, OP_GPR, OP_GPR }, {0x89, 2, CPU_ALL},
"rsbb", {OP_GPR, OP_GPR, OP_IMM }, {0x89, 2, CPU_ALL},
"lls", {OP_GPR, OP_GPR, OP_GPR }, {0x8A, 2, CPU_ALL},
"lls", {OP_GPR, OP_GPR, OP_IMM }, {0x8A, 2, CPU_ALL},
"lrs", {OP_GPR, OP_GPR, OP_GPR }, {0x8B, 2, CPU_ALL},
"lrs", {OP_GPR, OP_GPR, OP_IMM }, {0x8B, 2, CPU_ALL},
"ars", {OP_GPR, OP_GPR, OP_GPR }, {0x8C, 2, CPU_ALL},
"ars", {OP_GPR, OP_GPR, OP_IMM }, {0x8C, 2, CPU_ALL},
"rotl", {OP_GPR, OP_GPR, OP_GPR }, {0x8D, 2, CPU_ALL},
"rotl", {OP_GPR, OP_GPR, OP_IMM }, {0x8D, 2, CPU_ALL},
"rotr", {OP_GPR, OP_GPR, OP_GPR }, {0x8E, 2, CPU_ALL},
"rotr", {OP_GPR, OP_GPR, OP_IMM }, {0x8E, 2, CPU_ALL},
"mul", {OP_GPR, OP_GPR, OP_GPR }, {0x8F, 2, CPU_ALL},
"mul", {OP_GPR, OP_GPR, OP_IMM }, {0x8F, 2, CPU_ALL},
"smul", {OP_GPR, OP_GPR, OP_GPR }, {0x90, 2, CPU_ALL},
"smul", {OP_GPR, OP_GPR, OP_IMM }, {0x90, 2, CPU_ALL},
"div", {OP_GPR, OP_GPR, OP_GPR }, {0x91, 2, CPU_ALL},
"div", {OP_GPR, OP_GPR, OP_IMM }, {0x91, 2, CPU_ALL},
"sdiv", {OP_GPR, OP_GPR, OP_GPR }, {0x92, 2, CPU_ALL},
"sdiv", {OP_GPR, OP_GPR, OP_IMM }, {0x92, 2, CPU_ALL},
/* P2 */
"mov", {OP_GPR, OP_GPR }, {0x40, 1, CPU_ALL},
"mov", {OP_GPR, OP_IMM }, {0x40, 1, CPU_ALL},
"swp", {OP_GPR, OP_GPR }, {0x41, 1, CPU_ALL},
"not", {OP_GPR, OP_GPR }, {0x42, 1, CPU_ALL},
"not", {OP_GPR, OP_IMM }, {0x42, 1, CPU_ALL},
"sigxb", {OP_GPR, OP_GPR }, {0x43, 1, CPU_ALL},
"sigxb", {OP_GPR, OP_IMM }, {0x43, 1, CPU_ALL},
"sigxw", {OP_GPR, OP_GPR }, {0x44, 1, CPU_ALL},
"sigxw", {OP_GPR, OP_IMM }, {0x44, 1, CPU_ALL},
"jmp", {OP_GPR, OP_GPR }, {0x4B, 1, CPU_ALL},
"jmp", {OP_GPR, OP_IMM }, {0x4B, 1, CPU_ALL},
"call", {OP_GPR, OP_GPR }, {0x4C, 1, CPU_ALL},
"call", {OP_GPR, OP_IMM }, {0x4C, 1, CPU_ALL},
/* Branch */
"ifeq", {OP_GPR, OP_GPR }, {0x70, 1, CPU_ALL},
"ifeq", {OP_GPR, OP_IMM }, {0x70, 1, CPU_ALL},
"ifneq", {OP_GPR, OP_GPR }, {0x71, 1, CPU_ALL},
"ifneq", {OP_GPR, OP_IMM }, {0x71, 1, CPU_ALL},
"ifl", {OP_GPR, OP_GPR }, {0x72, 1, CPU_ALL},
"ifl", {OP_GPR, OP_IMM }, {0x72, 1, CPU_ALL},
"ifsl", {OP_GPR, OP_GPR }, {0x73, 1, CPU_ALL},
"ifsl", {OP_GPR, OP_IMM }, {0x73, 1, CPU_ALL},
"ifle", {OP_GPR, OP_GPR }, {0x74, 1, CPU_ALL},
"ifle", {OP_GPR, OP_IMM }, {0x74, 1, CPU_ALL},
"ifsle", {OP_GPR, OP_GPR }, {0x75, 1, CPU_ALL},
"ifsle", {OP_GPR, OP_IMM }, {0x75, 1, CPU_ALL},
"ifg", {OP_GPR, OP_GPR }, {0x76, 1, CPU_ALL},
"ifg", {OP_GPR, OP_IMM }, {0x76, 1, CPU_ALL},
"ifsg", {OP_GPR, OP_GPR }, {0x77, 1, CPU_ALL},
"ifsg", {OP_GPR, OP_IMM }, {0x77, 1, CPU_ALL},
"ifge", {OP_GPR, OP_GPR }, {0x78, 1, CPU_ALL},
"ifge", {OP_GPR, OP_IMM }, {0x78, 1, CPU_ALL},
"ifsge", {OP_GPR, OP_GPR }, {0x79, 1, CPU_ALL},
"ifsge", {OP_GPR, OP_IMM }, {0x79, 1, CPU_ALL},
"ifbits", {OP_GPR, OP_GPR }, {0x7A, 1, CPU_ALL},
"ifbits", {OP_GPR, OP_IMM }, {0x7A, 1, CPU_ALL},
"ifclear", {OP_GPR, OP_GPR }, {0x7B, 1, CPU_ALL},
"ifclear", {OP_GPR, OP_IMM }, {0x7B, 1, CPU_ALL},
/* P1 instructions */
"xchgb", {OP_GPR }, {0x20, 0, CPU_ALL},
"xchgb", {OP_IMM }, {0x20, 0, CPU_ALL},
"xchgw", {OP_GPR }, {0x21, 0, CPU_ALL},
"xchgw", {OP_IMM }, {0x21, 0, CPU_ALL},
"getpc", {OP_GPR }, {0x22, 0, CPU_ALL},
"pop", {OP_GPR }, {0x23, 0, CPU_ALL},
"push", {OP_GPR }, {0x24, 0, CPU_ALL},
"push", {OP_IMM }, {0x24, 0, CPU_ALL},
"jmp", {OP_GPR }, {0x25, 0, CPU_ALL},
"jmp", {OP_IMM }, {0x25, 0, CPU_ALL},
"call", {OP_GPR }, {0x26, 0, CPU_ALL},
"call", {OP_IMM }, {0x26, 0, CPU_ALL},
"rjmp", {OP_GPR }, {0x27, 0, CPU_ALL},
"rjmp", {OP_IMM }, {0x27, 0, CPU_ALL},
"rcall", {OP_GPR }, {0x28, 0, CPU_ALL},
"rcall", {OP_IMM }, {0x28, 0, CPU_ALL},
"int", {OP_GPR }, {0x29, 0, CPU_ALL},
"int", {OP_IMM }, {0x29, 0, CPU_ALL},
/* NP instructions */
"sleep", { }, {0x00, 0, CPU_ALL},
"ret", { }, {0x01, 0, CPU_ALL},
"rfi", { }, {0x02, 0, CPU_ALL},
/* Load / Store*/
/* Register Were to read */
"load", {OP_GPR, OP_GPR, OP_GPR }, {0x93, 2, CPU_ALL},
"load", {OP_GPR, OP_GPR, OP_IMM }, {0x93, 2, CPU_ALL},
"load", {OP_GPR, OP_GPR }, {0x45, 1, CPU_ALL},
"load", {OP_GPR, OP_IMM }, {0x45, 1, CPU_ALL},
"loadw", {OP_GPR, OP_GPR, OP_GPR }, {0x94, 2, CPU_ALL},
"loadw", {OP_GPR, OP_GPR, OP_IMM }, {0x94, 2, CPU_ALL},
"loadw", {OP_GPR, OP_GPR }, {0x46, 1, CPU_ALL},
"loadw", {OP_GPR, OP_IMM }, {0x46, 1, CPU_ALL},
"loadb", {OP_GPR, OP_GPR, OP_GPR }, {0x95, 2, CPU_ALL},
"loadb", {OP_GPR, OP_GPR, OP_IMM }, {0x95, 2, CPU_ALL},
"loadb", {OP_GPR, OP_GPR }, {0x47, 1, CPU_ALL},
"loadb", {OP_GPR, OP_IMM }, {0x47, 1, CPU_ALL},
/* Were to write data to write */
"store", {OP_GPR, OP_GPR, OP_GPR }, {0x96, 1, CPU_ALL},
"store", {OP_GPR, OP_IMM, OP_GPR }, {0x96, 1, CPU_ALL},
"store", {OP_GPR, OP_GPR }, {0x48, 0, CPU_ALL},
"store", {OP_IMM, OP_GPR }, {0x48, 0, CPU_ALL},
"storew", {OP_GPR, OP_GPR, OP_GPR }, {0x97, 1, CPU_ALL},
"storew", {OP_GPR, OP_IMM, OP_GPR }, {0x97, 1, CPU_ALL},
"storew", {OP_GPR, OP_GPR }, {0x49, 0, CPU_ALL},
"storew", {OP_IMM, OP_GPR }, {0x49, 0, CPU_ALL},
"storeb", {OP_GPR, OP_GPR, OP_GPR }, {0x98, 1, CPU_ALL},
"storeb", {OP_GPR, OP_IMM, OP_GPR }, {0x98, 1, CPU_ALL},
"storeb", {OP_GPR, OP_GPR }, {0x4A, 0, CPU_ALL},
"storeb", {OP_IMM, OP_GPR }, {0x4A, 0, CPU_ALL},
/* TODO Others */

1206
vasm-1/cpus/vidcore/cpu.c Normal file

File diff suppressed because it is too large Load Diff

142
vasm-1/cpus/vidcore/cpu.h Normal file
View File

@ -0,0 +1,142 @@
/* cpu.h VideoCore IV cpu-description header-file */
/* (c) in 2013 by Volker Barthelmann */
/* maximum number of operands in one mnemonic */
#define MAX_OPERANDS 4
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 2
/* maximum number of additional command-line-flags for this cpu */
/* data type to represent a target-address */
typedef int32_t taddr;
typedef uint32_t utaddr;
#define LITTLEENDIAN 1
#define BIGENDIAN 0
#define VASM_CPU_VC4 1
/* minimum instruction alignment */
#define INST_ALIGN 2
/* default alignment for n-bit data */
#define DATA_ALIGN(n) ((n)<=8?1:(n<=16?2:4))
/* operand class for n-bit data definitions */
#define DATA_OPERAND(n) OP_ABS
#define cc reg
/* type to store each operand */
typedef struct {
int type;
int reg;
int dreg;
long vecmod;
expr *offset;
} operand;
/* vecmod:
0-15: f_i or add-reg for vload/vstore
16-18: rep
20: setf
for 80-bit 'A' registers, 'dreg' is formatted as
0-5: flags
6-9: ra_x
*/
/* operand-types */
enum {
OP_REG=1,
OP_SREG,
OP_PC,
OP_LR,
OP_MREG,
OP_VREG,
OP_VREGA80,
OP_VREGM,
OP_VREGMM,
OP_ABS,
OP_REL,
OP_IMM4,
OP_IMM5,
OP_IMM6,
OP_IMM32M,
OP_IMM32,
OP_REGIND,
OP_IMMINDPC,
OP_IMMINDSP,
OP_IMMINDSD,
OP_IMMINDR0,
OP_IMMINDS,
OP_IMMIND,
OP_PREDEC,
OP_POSTINC,
OP_IND,
OP_VIND,
OP_DISP5,
OP_DISP12,
OP_DISP16,
OP_DISP27,
};
#define CPU_VC4 1
#define CPU_ALL (-1)
enum {
EN_ARITHR16,
EN_ARITHI16,
EN_FIX16,
EN_LEA16,
EN_IBRANCH16,
EN_RBRANCH16,
EN_TABLE16,
EN_MREG16,
EN_MEMSTACK16,
EN_MEMREG16,
EN_MEMDISP16,
EN_CONDR32,
EN_CONDI32,
EN_RBRANCH32,
EN_ADDCMPB32,
EN_MEMREG32,
EN_MEMDISP32,
EN_MEMPREDEC,
EN_MEMPOSTINC,
EN_MEM12DISP32,
EN_MEM16DISP32,
EN_FUNARY32,
EN_ARITHR32,
EN_ARITHI32,
EN_LEA48,
EN_MEM48,
EN_ARITHI48,
EN_ADD48,
EN_VLOAD48,
EN_VSTORE48,
EN_VREAD48,
EN_VWRITE48,
EN_VREADI48,
EN_VWRITEI48,
EN_VARITHR48,
EN_VARITHI48,
EN_ADDCMPB64,
EN_VLOAD80,
EN_VSTORE80,
EN_VREAD80,
EN_VWRITE80,
EN_VREADI80,
EN_VWRITEI80,
EN_VARITHR80,
EN_VARITHI80,
};
typedef struct {
unsigned int encoding;
unsigned int code;
unsigned int available;
} mnemonic_extension;

View File

@ -0,0 +1,5 @@
"illegal operand",ERROR,
"value does not find in %d bits",WARNING,
"data size not supported",ERROR,
"condition not allowed here",ERROR,
"Invalid increment",ERROR,

File diff suppressed because it is too large Load Diff

1957
vasm-1/cpus/x86/cpu.c Normal file

File diff suppressed because it is too large Load Diff

269
vasm-1/cpus/x86/cpu.h Normal file
View File

@ -0,0 +1,269 @@
/* cpu.h x86 cpu-description header-file */
/* (c) in 2005-2006,2017 by Frank Wille */
#define LITTLEENDIAN 1
#define BIGENDIAN 0
#define VASM_CPU_X86 1
#define MNEMOHTABSIZE 0x8000
/* maximum number of operands in one mnemonic */
#define MAX_OPERANDS 3
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 1
/* data type to represent a target-address */
typedef int64_t taddr;
typedef uint64_t utaddr;
/* minimum instruction alignment */
#define INST_ALIGN 1
/* default alignment for n-bit data */
#define DATA_ALIGN(n) 1
/* default alignment mode for .align directive */
#define CPU_DEF_ALIGN 1 /* alignment in bytes */
/* operand class for n-bit data definitions */
int x86_data_operand(int);
#define DATA_OPERAND(n) x86_data_operand(n)
/* make sure operand is cleared upon first entry into parse_operand() */
#define NEED_CLEARED_OPERANDS 1
/* register symbols */
#define HAVE_REGSYMS
#define REGSYMHTSIZE 64
/* reg_flags: */
#define RegRex 0x1 /* Extended register. */
#define RegRex64 0x2 /* Extended 8 bit register. */
/* type to store each operand */
typedef struct {
int type; /* real type of operand */
int parsed_type; /* type recognized by parser */
unsigned int flags;
expr *value; /* displacement or immediate value */
regsym *basereg; /* base-reg. for SIB or single register */
regsym *indexreg;
expr *scalefactor;
regsym *segoverride;
int log2_scale; /* 0-3 for scale factor 1,2,4,8 */
} operand;
/* register operand types */
#define Reg8 0x1
#define Reg16 0x2
#define Reg32 0x4
#define Reg64 0x8
/* immediate operand types*/
#define Imm8 0x10
#define Imm8S 0x20
#define Imm16 0x40
#define Imm32 0x80
#define Imm32S 0x100
#define Imm64 0x200
#define Imm1 0x400 /* for 1-bit shift-instructions */
/* memory operand types */
#define Disp8 0x800
#define Disp16 0x1000
#define Disp32 0x2000
#define Disp32S 0x4000
#define Disp64 0x8000
#define BaseIndex 0x10000 /* indirect base-register has optional index */
/* special operand types */
#define ShiftCntReg 0x20000 /* Shift-count register (%cl) */
#define IOPortReg 0x40000 /* I/O port register (%dx) */
#define CtrlReg 0x80000
#define DebugReg 0x100000
#define TestReg 0x200000
#define Acc 0x400000 /* Accumulator (%al or %ax or %eax) */
#define SegReg2 0x800000 /* Segment register with 2 bits */
#define SegReg3 0x1000000 /* Segment register with 3 bits */
#define MMXReg 0x2000000
#define XMMReg 0x4000000
#define FloatReg 0x8000000 /* Float register %st(n) */
#define FloatAcc 0x10000000 /* Float stack top %st(0), float-accumulator */
#define EsSeg 0x20000000 /* String instr. oper. with fixed ES seg. */
#define JmpAbs 0x40000000 /* Absolute jump/call instruction */
#define InvMem 0x80000000 /* modrm-byte doesn't support memory form */
/* data operands (@@@ define their own flags?) */
#define FloatData (FloatAcc)
#define Data8 (Disp8)
#define Data16 (Disp16)
#define Data32 (Disp32)
#define Data64 (Disp64)
#define Float32 (Disp32|FloatData)
#define Float64 (Disp64|FloatData)
/* operand type groups */
#define Reg (Reg8|Reg16|Reg32|Reg64)
#define WordReg (Reg16|Reg32|Reg64)
#define AnyReg (Reg|MMXReg|XMMReg|SegReg2|SegReg3|CtrlReg|DebugReg|TestReg)
#define ImpliedReg (IOPortReg|ShiftCntReg|Acc|FloatAcc)
#define Imm (Imm8|Imm8S|Imm16|Imm32S|Imm32|Imm64)
#define EncImm (Imm8|Imm16|Imm32|Imm32S)
#define Disp (Disp8|Disp16|Disp32|Disp32S|Disp64)
#define AnyMem (Disp8|Disp16|Disp32|Disp32S|BaseIndex|InvMem)
/* currently we do not differentiate between those memory types, */
/* but the opcode table is prepared for it */
#define LLongMem AnyMem
#define LongMem AnyMem
#define ShortMem AnyMem
#define WordMem AnyMem
#define ByteMem AnyMem
/* flags */
#define OPER_REG 1 /* operand is a direct register */
#define OPER_PCREL 2 /* PC-relative operand */
/* x86 opcode prefixes */
#define WAIT_PREFIX 0
#define LOCKREP_PREFIX 1
#define ADDR_PREFIX 2
#define DATA_PREFIX 3
#define SEG_PREFIX 4
#define REX_PREFIX 5 /* must be the last one */
#define MAX_PREFIXES 6 /* maximum number of prefixes */
/* x86 segment register numbers */
#define ESEG_REGNUM 0
#define CSEG_REGNUM 1
#define SSEG_REGNUM 2
#define DSEG_REGNUM 3
#define FSEG_REGNUM 4
#define GSEG_REGNUM 5
/* Mod-R/M byte, which follows the opcode */
typedef struct {
unsigned char mode; /* how to interpret regmem & reg */
unsigned char reg; /* register operand or extended opcode */
unsigned char regmem; /* register or memory operand (addr.mode) */
} modrm_byte;
/* SIB (scale, index, base) byte, which follows modrm_byte in some
i386 addressing modes */
typedef struct {
unsigned char scale; /* scale-factor (1, 2, 4 or 8) */
unsigned char index; /* index register */
unsigned char base; /* base register */
} sib_byte;
#define EBP_REGNUM 5
#define ESP_REGNUM 4
/* modrm_byte.regmem for 2-byte opcode escape */
#define TWO_BYTE_ESCAPE (ESP_REGNUM)
/* sib_byte.index for no index register */
#define NO_INDEXREG (ESP_REGNUM)
/* sib_byte.base for no base register */
#define NO_BASEREG (EBP_REGNUM)
#define NO_BASEREG16 6
/* instruction extension */
#define HAVE_INSTRUCTION_EXTENSION 1
typedef struct {
uint32_t base_opcode;
unsigned char flags;
unsigned char num_prefixes;
unsigned char prefix[MAX_PREFIXES];
modrm_byte rm;
sib_byte sib;
short last_size;
} instruction_ext;
/* flags: */
#define HAS_REG_OPER 0x1 /* inst. has direct-register operands */
#define SUFFIX_CHECKED 0x2 /* suffix assigned and checked */
#define MODRM_BYTE 0x4 /* needs mod/rm byte */
#define SIB_BYTE 0x8 /* needs sib byte */
#define NEGOPT 0x40 /* negatively optimized, bytes gained */
#define POSOPT 0x80 /* positively optimized, bytes gained */
#define OPTFAILED (POSOPT|NEGOPT) /* no longer try to optimize this */
/* max_opt_tries:
An instruction optimized more frequent than that is been considered
'oscillating' (e.g. by effects of alignment-directives) and should
no longer be optimized! */
#define MAX_OPT_TRIES 10
/* additional mnemonic data */
typedef struct {
uint32_t base_opcode;
uint32_t extension_opcode;
uint32_t opcode_modifier;
uint32_t available;
} mnemonic_extension;
/* extension_opcode */
#define NO_EXTOPCODE 0xffff
/* cpu available flags: */
#define CPU086 0x1
#define CPU186 0x2
#define CPU286 0x4
#define CPU386 0x8
#define CPU486 0x10
#define CPU586 0x20
#define CPU686 0x40
#define CPUP4 0x80
#define CPUK6 0x100
#define CPUAthlon 0x200
#define CPUSledgehammer 0x400
#define CPUMMX 0x800
#define CPUSSE 0x1000
#define CPUSSE2 0x2000
#define CPU3dnow 0x4000
#define CPUPNI 0x8000
#define CPUPadLock 0x10000
#define CPU64 0x4000000
#define CPUNo64 0x8000000
#define CPUAny (CPU086|CPU186|CPU286|CPU386|CPU486|CPU586|CPU686|CPUP4|CPUSledgehammer|CPUMMX|CPUSSE|CPUSSE2|CPUPNI|CPU3dnow|CPUK6|CPUAthlon|CPUPadLock)
/* opcode_modifier: */
#define W 0x1 /* operands can be words or dwords */
#define M 0x4 /* has Modrm byte */
#define FloatR 0x8 /* swapped src/dest for floats: MUST BE 0x8 */
#define ShortForm 0x10 /* reg. enc. in 3 low-order bits of opcode */
#define FloatMF 0x20 /* FP insn memory format bit, sized by 0x4 */
#define Jmp 0x40 /* relative conditional and uncond. branches */
#define JmpDword 0x80 /* relative 16/32 bit calls */
#define JmpByte 0x100 /* loop and jecxz */
#define JmpInterSeg 0x200 /* inter segment calls and branches */
#define FloatD 0x400 /* direction for FP insns: MUST BE 0x400 */
#define Seg2ShortForm 0x800 /* 2-bit segment reg. encoded in opcode */
#define Seg3ShortForm 0x1000 /* 3-bit segment reg. encoded in opcode */
#define Size16 0x2000 /* needs a size prefix in 32-bit mode */
#define Size32 0x4000 /* needs a size prefix in 16-bit mode */
#define Size64 0x8000 /* needs a size prefix in 16-bit mode */
#define IgnoreSize 0x10000 /* operand size prefix is ignored */
#define DefaultSize 0x20000 /* default instruction size depends on mode */
#define b_Illegal 0x40000 /* b suffix is illegal */
#define w_Illegal 0x80000 /* w suffix is illegal */
#define l_Illegal 0x100000 /* l suffix is illegal */
#define s_Illegal 0x200000 /* s suffix is illegal */
#define q_Illegal 0x400000 /* q suffix is illegal */
#define x_Illegal 0x800000 /* x suffix is illegal */
#define FWait 0x1000000 /* needs an FWAIT prefix */
#define StrInst 0x2000000 /* string instructions */
#define FakeLastReg 0x4000000 /* duplicate last reg. for clr and imul */
#define IsPrefix 0x8000000 /* opcode is a prefix */
#define ImmExt 0x10000000 /* has extension in 8 bit immediate */
#define NoRex64 0x20000000 /* doesn't require REX64 prefix */
#define Rex64 0x40000000 /* requires REX64 prefix */
#define Deprecated 0x80000000 /* deprecated FPU instruction */

View File

@ -0,0 +1,26 @@
"instruction not supported on selected architecture",ERROR,
"trailing garbage in operand",WARNING,
"same type of prefix used twice",WARNING,
"immediate operand illegal with absolute jump",ERROR,
"base register expected",ERROR,
"scale factor without index register",ERROR, /* 5 */
"missing ')' in baseindex addressing mode",ERROR,
"redundant %s prefix ignored",WARNING,
"unknown register specified",ERROR,
"using register %%%s instead of %%%s due to '%c' suffix",WARNING,
"%%%s not allowed with '%c' suffix",ERROR, /* 10 */
"illegal suffix '%c'",ERROR,
"instruction has no suffix and no register operands - size is unknown",ERROR,
"UNUSED",ERROR,
"memory operand expected",ERROR,
"you cannot pop %%%s",ERROR, /* 15 */
"translating to %s %%%s,%%%s",WARNING,
"translating to %s %%%s",WARNING,
"absolute scale factor required",ERROR,
"illegal scale factor (valid: 1,2,4,8)",ERROR,
"data objects with %d bits size are not supported",ERROR, /* 20 */
"need at least %d bits for a relocatable symbol",ERROR,
"pc-relative jump destination out of range (%lld)",ERROR,
"instruction doesn't support these operand sizes",ERROR,
"cannot determine immediate operand size without a suffix",ERROR,
"displacement doesn't fit into %d bits",ERROR, /* 25 */

1062
vasm-1/cpus/x86/opcodes.h Normal file

File diff suppressed because it is too large Load Diff

180
vasm-1/cpus/x86/registers.h Normal file
View File

@ -0,0 +1,180 @@
{"st", FloatReg|FloatAcc, 0, 0},
/* 8 bit regs */
#define AL_INDEX 1
{"al", Reg8|Acc, 0, 0},
{"cl", Reg8|ShiftCntReg, 0, 1},
{"dl", Reg8, 0, 2},
{"bl", Reg8, 0, 3},
{"ah", Reg8, 0, 4},
{"ch", Reg8, 0, 5},
{"dh", Reg8, 0, 6},
{"bh", Reg8, 0, 7},
{"axl", Reg8|Acc, RegRex64, 0},
{"cxl", Reg8, RegRex64, 1},
{"dxl", Reg8, RegRex64, 2},
{"bxl", Reg8, RegRex64, 3},
{"spl", Reg8, RegRex64, 4},
{"bpl", Reg8, RegRex64, 5},
{"sil", Reg8, RegRex64, 6},
{"dil", Reg8, RegRex64, 7},
{"r8b", Reg8, RegRex64|RegRex, 0},
{"r9b", Reg8, RegRex64|RegRex, 1},
{"r10b", Reg8, RegRex64|RegRex, 2},
{"r11b", Reg8, RegRex64|RegRex, 3},
{"r12b", Reg8, RegRex64|RegRex, 4},
{"r13b", Reg8, RegRex64|RegRex, 5},
{"r14b", Reg8, RegRex64|RegRex, 6},
{"r15b", Reg8, RegRex64|RegRex, 7},
/* 16 bit regs */
#define AX_INDEX 25
{"ax", Reg16|Acc, 0, 0},
{"cx", Reg16, 0, 1},
{"dx", Reg16|IOPortReg, 0, 2},
{"bx", Reg16|BaseIndex, 0, 3},
{"sp", Reg16, 0, 4},
{"bp", Reg16|BaseIndex, 0, 5},
{"si", Reg16|BaseIndex, 0, 6},
{"di", Reg16|BaseIndex, 0, 7},
{"r8w", Reg16, RegRex, 0},
{"r9w", Reg16, RegRex, 1},
{"r10w", Reg16, RegRex, 2},
{"r11w", Reg16, RegRex, 3},
{"r12w", Reg16, RegRex, 4},
{"r13w", Reg16, RegRex, 5},
{"r14w", Reg16, RegRex, 6},
{"r15w", Reg16, RegRex, 7},
/* 32 bit regs */
#define EAX_INDEX 41
{"eax", Reg32|BaseIndex|Acc, 0, 0},
{"ecx", Reg32|BaseIndex, 0, 1},
{"edx", Reg32|BaseIndex, 0, 2},
{"ebx", Reg32|BaseIndex, 0, 3},
{"esp", Reg32, 0, 4},
{"ebp", Reg32|BaseIndex, 0, 5},
{"esi", Reg32|BaseIndex, 0, 6},
{"edi", Reg32|BaseIndex, 0, 7},
{"r8d", Reg32|BaseIndex, RegRex, 0},
{"r9d", Reg32|BaseIndex, RegRex, 1},
{"r10d", Reg32|BaseIndex, RegRex, 2},
{"r11d", Reg32|BaseIndex, RegRex, 3},
{"r12d", Reg32|BaseIndex, RegRex, 4},
{"r13d", Reg32|BaseIndex, RegRex, 5},
{"r14d", Reg32|BaseIndex, RegRex, 6},
{"r15d", Reg32|BaseIndex, RegRex, 7},
{"rax", Reg64|BaseIndex|Acc, 0, 0},
{"rcx", Reg64|BaseIndex, 0, 1},
{"rdx", Reg64|BaseIndex, 0, 2},
{"rbx", Reg64|BaseIndex, 0, 3},
{"rsp", Reg64, 0, 4},
{"rbp", Reg64|BaseIndex, 0, 5},
{"rsi", Reg64|BaseIndex, 0, 6},
{"rdi", Reg64|BaseIndex, 0, 7},
{"r8", Reg64|BaseIndex, RegRex, 0},
{"r9", Reg64|BaseIndex, RegRex, 1},
{"r10", Reg64|BaseIndex, RegRex, 2},
{"r11", Reg64|BaseIndex, RegRex, 3},
{"r12", Reg64|BaseIndex, RegRex, 4},
{"r13", Reg64|BaseIndex, RegRex, 5},
{"r14", Reg64|BaseIndex, RegRex, 6},
{"r15", Reg64|BaseIndex, RegRex, 7},
/* segment registers */
{"es", SegReg2, 0, 0},
{"cs", SegReg2, 0, 1},
{"ss", SegReg2, 0, 2},
{"ds", SegReg2, 0, 3},
{"fs", SegReg3, 0, 4},
{"gs", SegReg3, 0, 5},
/* control registers */
{"cr0", CtrlReg, 0, 0},
{"cr1", CtrlReg, 0, 1},
{"cr2", CtrlReg, 0, 2},
{"cr3", CtrlReg, 0, 3},
{"cr4", CtrlReg, 0, 4},
{"cr5", CtrlReg, 0, 5},
{"cr6", CtrlReg, 0, 6},
{"cr7", CtrlReg, 0, 7},
{"cr8", CtrlReg, RegRex, 0},
{"cr9", CtrlReg, RegRex, 1},
{"cr10", CtrlReg, RegRex, 2},
{"cr11", CtrlReg, RegRex, 3},
{"cr12", CtrlReg, RegRex, 4},
{"cr13", CtrlReg, RegRex, 5},
{"cr14", CtrlReg, RegRex, 6},
{"cr15", CtrlReg, RegRex, 7},
/* debug registers */
{"db0", DebugReg, 0, 0},
{"db1", DebugReg, 0, 1},
{"db2", DebugReg, 0, 2},
{"db3", DebugReg, 0, 3},
{"db4", DebugReg, 0, 4},
{"db5", DebugReg, 0, 5},
{"db6", DebugReg, 0, 6},
{"db7", DebugReg, 0, 7},
{"db8", DebugReg, RegRex, 0},
{"db9", DebugReg, RegRex, 1},
{"db10", DebugReg, RegRex, 2},
{"db11", DebugReg, RegRex, 3},
{"db12", DebugReg, RegRex, 4},
{"db13", DebugReg, RegRex, 5},
{"db14", DebugReg, RegRex, 6},
{"db15", DebugReg, RegRex, 7},
{"dr0", DebugReg, 0, 0},
{"dr1", DebugReg, 0, 1},
{"dr2", DebugReg, 0, 2},
{"dr3", DebugReg, 0, 3},
{"dr4", DebugReg, 0, 4},
{"dr5", DebugReg, 0, 5},
{"dr6", DebugReg, 0, 6},
{"dr7", DebugReg, 0, 7},
{"dr8", DebugReg, RegRex, 0},
{"dr9", DebugReg, RegRex, 1},
{"dr10", DebugReg, RegRex, 2},
{"dr11", DebugReg, RegRex, 3},
{"dr12", DebugReg, RegRex, 4},
{"dr13", DebugReg, RegRex, 5},
{"dr14", DebugReg, RegRex, 6},
{"dr15", DebugReg, RegRex, 7},
/* test registers */
{"tr0", TestReg, 0, 0},
{"tr1", TestReg, 0, 1},
{"tr2", TestReg, 0, 2},
{"tr3", TestReg, 0, 3},
{"tr4", TestReg, 0, 4},
{"tr5", TestReg, 0, 5},
{"tr6", TestReg, 0, 6},
{"tr7", TestReg, 0, 7},
/* mmx and simd registers */
{"mm0", MMXReg, 0, 0},
{"mm1", MMXReg, 0, 1},
{"mm2", MMXReg, 0, 2},
{"mm3", MMXReg, 0, 3},
{"mm4", MMXReg, 0, 4},
{"mm5", MMXReg, 0, 5},
{"mm6", MMXReg, 0, 6},
{"mm7", MMXReg, 0, 7},
{"xmm0", XMMReg, 0, 0},
{"xmm1", XMMReg, 0, 1},
{"xmm2", XMMReg, 0, 2},
{"xmm3", XMMReg, 0, 3},
{"xmm4", XMMReg, 0, 4},
{"xmm5", XMMReg, 0, 5},
{"xmm6", XMMReg, 0, 6},
{"xmm7", XMMReg, 0, 7},
{"xmm8", XMMReg, RegRex, 0},
{"xmm9", XMMReg, RegRex, 1},
{"xmm10", XMMReg, RegRex, 2},
{"xmm11", XMMReg, RegRex, 3},
{"xmm12", XMMReg, RegRex, 4},
{"xmm13", XMMReg, RegRex, 5},
{"xmm14", XMMReg, RegRex, 6},
{"xmm15", XMMReg, RegRex, 7},
{"st(0)", FloatReg|FloatAcc, 0, 0},
{"st(1)", FloatReg, 0, 1},
{"st(2)", FloatReg, 0, 2},
{"st(3)", FloatReg, 0, 3},
{"st(4)", FloatReg, 0, 4},
{"st(5)", FloatReg, 0, 5},
{"st(6)", FloatReg, 0, 6},
{"st(7)", FloatReg, 0, 7},
{"rip", BaseIndex, 0, 0},
{NULL, 0, 0, 0}

2265
vasm-1/cpus/z80/cpu.c Normal file

File diff suppressed because it is too large Load Diff

273
vasm-1/cpus/z80/cpu.h Normal file
View File

@ -0,0 +1,273 @@
/*
* Copyright (c) 2007-2009 Dominic Morris <dom /at/ suborbital.org.uk>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* z80 backend for vasm */
#include <stdint.h>
#define BIGENDIAN 0
#define LITTLEENDIAN 1
#define VASM_CPU_Z80 1
/* maximum number of operands for one mnemonic */
#define MAX_OPERANDS 2
/* maximum number of mnemonic-qualifiers per mnemonic */
#define MAX_QUALIFIERS 0
/* maximum number of additional command-line-flags for this cpu */
/* data type to represent a target-address */
typedef int32_t taddr;
typedef uint32_t utaddr;
#define HAVE_INSTRUCTION_EXTENSION 1
typedef struct {
int altd;
int ioi;
int ioe;
} instruction_ext;
/* minimum instruction alignment */
#define INST_ALIGN 1
/* default alignment for n-bit data */
#define DATA_ALIGN(n) 1
/* operand class for n-bit data definitions */
#define DATA_OPERAND(n) OP_DATA
/* we define two additional unary operations, '<' and '>' */
int ext_unary_eval(int,taddr,taddr *,int);
int ext_find_base(symbol **,expr *,section *,taddr);
#define LOBYTE (LAST_EXP_TYPE+1)
#define HIBYTE (LAST_EXP_TYPE+2)
#define EXT_UNARY_NAME(s) (*s=='<'||*s=='>')
#define EXT_UNARY_TYPE(s) (*s=='<'?LOBYTE:HIBYTE)
#define EXT_UNARY_EVAL(t,v,r,c) ext_unary_eval(t,v,r,c)
#define EXT_FIND_BASE(b,e,s,p) ext_find_base(b,e,s,p)
/* Z80 allows ':' as a statement delimiter in oldstyle-syntax */
#define STATEMENT_DELIMITER ':'
/* type to store each operand */
typedef struct {
int reg;
int type;
int flags;
int bit;
expr *value;
} operand;
#define CPU_8080 1
#define CPU_Z80 2
#define CPU_RCM2000 4
#define CPU_RCM3000 8
#define CPU_RCM4000 16
#define CPU_Z180 32
#define CPU_EZ80 64
#define CPU_GB80 128
#define CPU_80OS 256
#define CPU_RABBIT (CPU_RCM2000|CPU_RCM3000|CPU_RCM4000)
#define CPU_ZILOG (CPU_Z80|CPU_Z180|CPU_EZ80)
#define CPU_ALL ( CPU_ZILOG | CPU_8080 | CPU_RABBIT | CPU_GB80 )
#define CPU_NOT8080 ( CPU_ALL ^ CPU_8080 )
#define CPU_NOTGB80 ( CPU_ALL ^ CPU_GB80 )
#define RCM_EMU_NONE 0
#define RCM_EMU_INCREMENT 1 /* Move to next instruction */
#define RCM_EMU_LIBRARY 2 /* Call a library routine */
/* Flags for altd */
#define F_IO 1 /* ioe/ioi valid */
#define F_ALTD 2 /* altd valid */
#define F_ALTDW 4 /* warn about altw use */
#define F_ALTDWHL 8 /* Warn about HLREF use with altd */
#define F_80OS_CHECK 16 /* When both 8080 and 80OS are specified, jp = "jump on plus" else jp = jump (jmp) */
#define F_ALL ( F_IO|F_ALTD)
/* additional mnemonic data */
typedef struct {
int mode; /* Opcode mode */
uint32_t opcode; /* Opcode */
unsigned short cpus;
int modifier_flags; /* Modifier flags for altd/ioi etc */
int rabbit2000_action; /* Action to take on a rabbit */
int rabbit3000_action; /* Action to take on a rabbit */
int rabbit4000_action; /* Action to take on a rabbit */
int gb80_action; /* Action to take for a GBz80 */
} mnemonic_extension;
/* These values are significant - opcodes derived using them */
#define FLAGS_NZ 0
#define FLAGS_Z 1
#define FLAGS_NC 2
#define FLAGS_C 3
#define FLAGS_PO 4
#define FLAGS_PE 5
#define FLAGS_P 6
#define FLAGS_M 7
/* These values are significant - RCM4000 flags */
#define FLAGS_GT 0
#define FLAGS_GTU 1
#define FLAGS_LT 2
#define FLAGS_V 3
/* Theses values are significant */
#define REG_BC 0x00
#define REG_DE 0x01
#define REG_HL 0x02
#define REG_SP 0x03
#define REG_AF 0x04
/* These values are signifcant - opcodes are derived using them */
#define REG_B 0x00
#define REG_C 0x01
#define REG_D 0x02
#define REG_E 0x03
#define REG_H 0x04
#define REG_L 0x05
#define REG_HLREF 0x06
#define REG_M 0x06
#define REG_A 0x07
/* Extra ones - values from here onwards aren't significant */
#define REG_I 0x08
#define REG_R 0x09
#define REG_F 0x0a
#define REG_PORT 0x0b
/* Rabbit extras */
#define REG_IP 0x0c
#define REG_XPC 0x0d
/* Rabbit 4000 extras */
#define REG_JK 0x0d
#define REG_BCDE 0x0e
#define REG_JKHL 0x0f
/* PW...PZ should be defined in this order */
#define REG_PW 0x10
#define REG_PX 0x11
#define REG_PY 0x12
#define REG_PZ 0x13
#define REG_SU 0x14
#define REG_HTR 0x15
#define REG_PLAIN 0x1f /* Mask to get the register out */
/* Modifiers */
#define REG_IX 0x20 /* h,l modified by ix */
#define REG_IY 0x40 /* h,l modified by iy */
#define REG_ALT 0x80 /* alternate registers */
#define REG_INDEX 0x100 /* (ix + ) */
/* Operand types */
#define OP_NONE 0x00
#define OP_ABS 0x01
#define OP_ABS16 0x02
#define OP_REG16 0x03
#define OP_REG8 0x04
#define OP_AF 0x05 /* af */
#define OP_SP 0x06 /* sp */
#define OP_HL 0x07 /* hl */
#define OP_DE 0x08 /* de */
#define OP_BC 0x09 /* bc */
#define OP_JK 0x0a
#define OP_BCDE 0x0b
#define OP_JKHL 0x0c
#define OP_A 0x0d /* a register */
#define OP_R 0x0e /* r register */
#define OP_I 0x0f /* i register */
#define OP_F 0x10 /* f - for in f,(c) */
#define OP_PORT 0x11
#define OP_FLAGS 0x12 /* nz, z, nc, c, (po, pe) */
#define OP_FLAGS_RCM 0x13 /* gt, lt, ge, le */
#define OP_ADDR 0x14 /* (xx) - an address */
#define OP_NUMBER 0x15 /* for bit, im, res, set, rst */
#define OP_ADDR8 0x16
#define OP_IP 0x17 /* ip (RCM) */
#define OP_XPC 0x18
#define OP_ABS24 0x19
#define OP_ABS32 0x20
#define OP_ADDR24 0x21
#define OP_ADDR32 0x22
#define OP_IX 0x23
#define OP_IY 0x24
#define OP_IDX32 0x25
#define OP_SU 0x26
#define OP_HTR 0x27
#define OP_DATA 0x3e
#define OP_MASK 0x3f /* Gets the basic operation out */
/* Modifiers */
#define OP_INDIR 0x40 /* ( x ) */
#define OP_INDEX 0x80 /* Modifier for 8 bit operations with ixh, ixl */
#define OP_ALT 0x100
#define OP_OFFSET 0x200 /* Has an offset as well (always optional) - maybe from ix,iy or sp,hl (rabbit) */
#define OP_ARITH16 0x400
#define OP_PUSHABLE 0x800
#define OP_STD16BIT 0x1000
#define OP_RALT 0x2000 /* Accept an alt register on a rabbit (only used mnemonics) - except (hl) */
#define OP_RALTHL 0x4000 /* Accept an alt (hl) register on a rabbit (only used mnemonics) */
#define OP_OFFSA 0x8000 /* Have +a as offset */
#define OP_OFFSHL 0x10000 /* Have +hl as offset */
#define OP_OFFSBC 0x20000 /* Have +bc as offset */
#define OP_OFFSDE 0x40000 /* Have +de as offset */
#define OP_OFFSIX 0x80000 /* Have +ix as offset */
#define OP_OFFSIY 0x100000 /* Have +iy as offset */
#define OP_RP 0x200000 /* Reg Pair (BC, DE, HL, and SP) */
#define OP_RP_PUSHABLE 0x400000 /* Pushable reg pair (BC, DE, HL, and PSW) */
#define OP_B 0x800000 /* Reg Pair B (for ldax and stax) */
#define OP_D 0x1000000 /* Reg Pair D (for ldax and stax) */
/* Opcode types - we can group them together to calculate offsets etc */
#define TYPE_NONE 0x00 /* No modifiers */
#define TYPE_ARITH8 0x01 /* + reg1 index or + reg2 index*/
#define TYPE_MISC8 0x02 /* + reg1 * 8 or + reg 2 * 8*/
#define TYPE_LD8 0x03 /* + reg1 * 8 + reg 2 */
#define TYPE_ARITH16 0x04 /* reg * 16 */
#define TYPE_FLAGS 0x05 /* flags * 8 */
#define TYPE_RELJUMP 0x06 /* jr/djnz/jre (flags *8 if necessary */
#define TYPE_BIT 0x07 /* Bit setting etc */
#define TYPE_RST 0x08 /* rst XX */
#define TYPE_IM 0x09 /* im */
#define TYPE_EDPREF 0x0a /* Has a 0xed prefix by default (RCM opcodes) */
#define TYPE_IPSET 0x0b /* ipset X (RCM) */
#define TYPE_IDX32 0x0c /* p? * 16 */
#define TYPE_NOPREFIX 0x0d /* Don't add on an indexing prefix (RCM) */
#define TYPE_IDX32R 0x0e /* p? * 16 + p? * 64*/
#define TYPE_OUT_C_0 0x0f /* for out (c), number, number can only be 0 */
#define TYPE_RP 0x10 /* Register pair instructions */

View File

@ -0,0 +1,27 @@
"index offset out of bounds (%d)",ERROR,
"Opcode not supported by %s (%s)",ERROR,
"Index registers not available on %s",ERROR,
"out of range for 8 bit expression (%d)",ERROR,
"invalid bit number (%d) should be in range 0..7",ERROR,
"rst value out of range (%d/0x%02x)",ERROR, /* 5 */
"%s value out of range (%d)",ERROR,
"index offset should be a constant",ERROR,
"invalid branch type for %s",ERROR,
"Rabbit target doesn't support rst %d",ERROR,
"Rabbit target doesn't support 8 bit index registers",ERROR, /* 10 */
"z180 target doesn't support 8 bit index registers",ERROR,
"altd specifier cannot be used with index registers",WARNING,
"Opcode not supported by %s (%s) but it can be emulated (-rcmemu)",ERROR,
"%s specifier is only valid for Rabbit processors",ERROR,
"Only one of ioi and ioe can be specified at a time",ERROR, /* 15 */
"%s specifier is not valid for the opcode %s",ERROR,
"%s specifier redundant for the opcode %s",WARNING,
"%s specifier has no effect on the opcode %s",WARNING,
"Operand value must evaluate to a constant for opcode %s",ERROR,
"Unhandled operand type wanted 0x%x got 0x%x",ERROR, /* 20 */
"Missed matched index registers on %s",ERROR,
"Only out (c),0 is supported for the opcode %s",ERROR,
"Operations between different index registers are forbidden",ERROR,
"Operations between ix/iy/hl are forbidden", ERROR,
"Double indirection forbidden", ERROR, /* 25 */
"Instruction %s will be assembled as '%s'", WARNING,

131
vasm-1/doc/cpu_6502.texi Normal file
View File

@ -0,0 +1,131 @@
This chapter documents the backend for the MOS/Rockwell 6502
microprocessor family. It also supports the Rockwell/WDC 65C02 and the
Hudson Soft HuC6280 instruction sets.
@section Legal
This module is written in 2002,2006,2008-2012,2014-2020 by Frank Wille
and is covered by the vasm copyright without modifications.
@section Additional options for this module
This module provides the following additional options:
@table @option
@item -6280
Recognize all HuC6280 instructions.
@item -bbcade
Swap meaning of @code{<} and @code{>} unary operators for compatibility
with the BBC ADE assembler.
@item -c02
Recognize all 65C02 instructions. This excludes DTV (@option{-dtv})
and illegal (@option{-illegal}) instructions.
@item -dtv
Recognize the three additional C64-DTV instructions.
@item -illegal
Allow 'illegal' 6502 instructions to be recognized.
@item -opt-branch
Enables 'optimization' of B<cc> branches into
"B<!cc> *+3 ; JMP label" sequences when necessary.
@item -wdc02
Recognize all 65C02 instructions and the WDC65C02 extensions
(RMB,SMB,BBR,BBS,STP,WAI).
@end table
@section General
This backend accepts 6502 family instructions as described in
the instruction set reference manuals from MOS and Rockwell, which are valid
for the following CPUs: 6502 - 6518, 6570, 6571, 6702, 7501, 8500, 8502.
Optionally accepts 65C02 family instructions as decribed in the
instruction set reference manuals from Rockwell and WDC. Also supports
the WDC extensions in the W65C02 and W65C134.
Optionally accepts 65CE02 family instructions as decribed in the
instruction set reference manuals from Commodore Semiconductor Group.
Optionally accepts HuC6280 instructions as described in the instruction
set reference manuals from Hudson Soft.
The target address type is 16 bit.
Instructions consist of one up to three bytes for the standard 6502 family
(up to 7 bytes for the 6280) and require no alignment.
There is also no alignment requirement for sections and data.
All known mnemonics for illegal instructions are optionally recognized (e.g.
@code{dcm} and @code{dcp} refer to the same instruction). Some illegal
insructions (e.g. @code{$ab}) are known to show unpredictable behaviour,
or do not always work the same on different CPUs.
@section Extensions
This backend provides the following specific extensions:
@itemize @minus
@item The parser understands a lo/hi-modifier to select low- or high-byte
of a 16-bit word. The character @code{<} is used to select the low-byte
and @code{>} for the high-byte. It has to be the first character before
an expression.
@item When applying the operation @code{/256}, @code{%256} or @code{&256}
on a label, an appropriate lo/hi-byte relocation will automatically be
generated.
@end itemize
This backend extends the selected syntax module by the following
directives:
@table @code
@item setdp <expr>
Set the current base address of the zero/direct page for
optimizations from absolute to zero-page addressing modes.
Example: set it to @code{$2000} for the HuC6280/PC-Engine.
@item zpage <symbol>
Mark <symbol> as zero page and use zero page addressing for
expressions based on this symbol.
@end table
@section Optimizations
This backend performs the following operand optimizations:
@itemize @minus
@item Branches, where the destination is out of range, are translated
into @code{B<!cc> *+3} and an absolute @code{JMP} instruction.
@end itemize
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item None.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 2001: instruction not supported on selected architecture
@item 2002: trailing garbage in operand
@item 2003: missing closing parenthesis in addressing mode
@item 2004: data size %d not supported
@item 2005: relocation does not allow hi/lo modifier
@item 2006: operand doesn't fit into %d bits
@item 2007: branch destination out of range
@item 2008: illegal bit number
@item 2009: identifier expected
@end itemize

85
vasm-1/doc/cpu_6800.texi Normal file
View File

@ -0,0 +1,85 @@
This chapter documents the backend for the Motorola 6800
microprocessor family.
@section Legal
This module is written in 2013-2016 by Esben Norby and Frank Wille
and is covered by the vasm copyright without modifications.
@section Additional options for this module
This module provides the following additional options:
@table @option
@item -m6800
Generate code for the 6800 CPU (default setting).
@item -m6801
Generate code for the 6801 CPU.
@item -m68hc11
Generate code for the 68HC11 CPU.
@end table
@section General
This backend accepts 6800 family instructions for the following CPUs:
@itemize
@item 6800 code generation: 6800, 6802, 6808.
@item 6801 code generation: 6801, 6803.
@item 68HC11.
@end itemize
The 6804, 6805, 68HC08 and 6809 are not supported, they use a similar
instruction set, but are not opcode compatible.
The target address type is 16 bit.
Instructions consist of one up to five bytes and require no alignment.
There is also no alignment requirement for sections and data.
@section Extensions
This backend provides the following specific extensions:
@itemize @minus
@item When an instruction supports direct and extended addressing mode
the @code{<} character can be used to force direct mode and the
@code{>} character forces extended mode. Otherwise the assembler selects
the best mode automatically, which defaults to extended mode for external
symbols.
@item When applying the operation @code{/256}, @code{%256} or @code{&256}
on a label, an appropriate lo/hi-byte relocation will automatically be
generated.
@end itemize
@section Optimizations
None.
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item None?
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 2001: data size %d not supported
@item 2002: operand doesn't fit into 8-bits
@item 2003: branch destination out of range
@end itemize

248
vasm-1/doc/cpu_arm.texi Normal file
View File

@ -0,0 +1,248 @@
This chapter documents the backend for the Advanced RISC Machine (ARM)
microprocessor family.
@section Legal
This module is written in 2004,2006,2010-2015 by Frank Wille and
is covered by the vasm copyright without modifications.
@section Additional options for this module
This module provides the following additional options:
@table @option
@item -a2
Generate code compatible with ARM V2 architecture.
@item -a3
Generate code compatible with ARM V3 architecture.
@item -a3m
Generate code compatible with ARM V3m architecture.
@item -a4
Generate code compatible with ARM V4 architecture.
@item -a4t
Generate code compatible with ARM V4t architecture.
@item -big
Output big-endian code and data.
@item -little
Output little-endian code and data (default).
@item -m2
Generate code for the ARM2 CPU.
@item -m250
Generate code for the ARM250 CPU.
@item -m3
Generate code for the ARM3 CPU.
@item -m6
Generate code for the ARM6 CPU.
@item -m600
Generate code for the ARM600 CPU.
@item -m610
Generate code for the ARM610 CPU.
@item -m7
Generate code for the ARM7 CPU.
@item -m710
Generate code for the ARM710 CPU.
@item -m7500
Generate code for the ARM7500 CPU.
@item -m7d
Generate code for the ARM7d CPU.
@item -m7di
Generate code for the ARM7di CPU.
@item -m7dm
Generate code for the ARM7dm CPU.
@item -m7dmi
Generate code for the ARM7dmi CPU.
@item -m7tdmi
Generate code for the ARM7tdmi CPU.
@item -m8
Generate code for the ARM8 CPU.
@item -m810
Generate code for the ARM810 CPU.
@item -m9
Generate code for the ARM9 CPU.
@item -m9
Generate code for the ARM9 CPU.
@item -m920
Generate code for the ARM920 CPU.
@item -m920t
Generate code for the ARM920t CPU.
@item -m9tdmi
Generate code for the ARM9tdmi CPU.
@item -msa1
Generate code for the SA1 CPU.
@item -mstrongarm
Generate code for the STRONGARM CPU.
@item -mstrongarm110
Generate code for the STRONGARM110 CPU.
@item -mstrongarm1100
Generate code for the STRONGARM1100 CPU.
@item -opt-adr
The @code{ADR} directive will be automatically converted into
@code{ADRL} if required (which inserts an additional
@code{ADD}/@code{SUB} to calculate an address).
@item -opt-ldrpc
The maximum range in which PC-relative symbols can be accessed
through @code{LDR} and @code{STR} is extended from +/-4KB to +/-1MB
(or +/-256 Bytes to +/-65536 Bytes when accessing half-words).
This is done by automatically inserting an additional @code{ADD}
or @code{SUB} instruction before the @code{LDR}/@code{STR}.
@item -thumb
Start assembling in Thumb mode.
@end table
@section General
This backend accepts ARM instructions as described in various ARM CPU
data sheets. Additionally some architectures support a second, more
dense, instruction set, called THUMB. There are special directives
to switch between those two instruction sets.
The target address type is 32bit.
Default alignment for instructions is 4 bytes for ARM and 2 bytes for
THUMB. Sections will be aligned to 4 bytes by default. Data is
aligned to its natural alignment by default.
@section Extensions
This backend extends the selected syntax module by the following
directives:
@table @code
@item .arm
Generate 32-bit ARM code.
@item .thumb
Generate 16-bit THUMB code.
@end table
@section Optimizations
This backend performs the following optimizations and translations for
the ARM instruction set:
@itemize @minus
@item @code{LDR/STR Rd,symbol}, with a distance between symbol and PC larger
than 4KB, is translated to
@code{ADD/SUB Rd,PC,#offset&0xff000} +
@code{LDR/STR Rd,[Rd,#offset&0xfff]}, when allowed by the option
@code{-opt-ldrpc}.
@item @code{ADR Rd,symbol} is translated to
@code{ADD/SUB Rd,PC,#rotated_offset8}.
@item @code{ADRL Rd,symbol} is translated to
@code{ADD/SUB Rd,PC,#hi_rotated8} + @code{ADD/SUB Rd,Rd,#lo_rotated8}.
@code{ADR} will be automatically treated as @code{ADRL} when required
and when allowed by the option @code{-opt-adr}.
@item The immediate operand of ALU-instructions will be translated into
the appropriate 8-bit-rotated value. When rotation alone doesn't
succeed the backed will try it with inverted and negated values
(inverting/negating the ALU-instruction too).
Optionally you may specify the rotate constant yourself, as an
additional operand.
@end itemize
For the THUMB instruction set the following optimizations and translations
are done:
@itemize @minus
@item A conditional branch with a branch-destination being out of range is
translated into @code{B<!cc> .+4} + @code{B label}.
@item The @code{BL} instruction is translated into two sub-instructions combining
the high- and low 22 bit of the branch displacement.
@end itemize
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item Only instruction sets up to ARM architecture V4t are supported.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 2001: instruction not supported on selected architecture
@item 2002: trailing garbage in operand
@item 2003: label from current section required
@item 2004: branch offset (%ld) is out of range
@item 2005: PC-relative load/store (offset %ld) out of range
@item 2006: cannot make rotated immediate from PC-relative offset (0x%lx)
@item 2007: constant integer expression required
@item 2008: constant (0x%lx) not suitable for 8-bit rotated immediate
@item 2009: branch to an unaligned address (offset %ld)
@item 2010: not a valid ARM register
@item 2011: PC (r15) not allowed in this mode
@item 2012: PC (r15) not allowed for offset register Rm
@item 2013: PC (r15) not allowed with write-back
@item 2014: register r%ld was used multiple times
@item 2015: illegal immediate shift count (%ld)
@item 2016: not a valid shift register
@item 2017: 24-bit unsigned immediate expected
@item 2018: data size %d not supported
@item 2019: illegal addressing mode: %s
@item 2020: signed/halfword ldr/str doesn't support shifts
@item 2021: %d-bit immediate offset out of range (%ld)
@item 2022: post-indexed addressing mode exptected
@item 2023: operation not allowed on external symbols
@item 2024: ldc/stc offset has to be a multiple of 4
@item 2025: illegal coprocessor operation mode or type: %ld\n
@item 2026: %d-bit unsigned immediate offset out of range (%ld)
@item 2027: offset has to be a multiple of %d
@item 2028: instruction at unaligned address
@item 2029: TSTP/TEQP/CMNP/CMPP deprecated on 32-bit architectures
@item 2030: rotate constant must be an even number between 0 and 30: %ld
@item 2031: %d-bit unsigned constant required: %ld
@end itemize

124
vasm-1/doc/cpu_c16x.texi Normal file
View File

@ -0,0 +1,124 @@
This chapter documents the Backend for the c16x/st10 microcontroller family.
Note that this module is not yet fully completed!
@section Legal
This module is written in 2002-2004 by Volker Barthelmann and
is covered by the vasm copyright without modifications.
@section Additional options for this module
This module provides the following additional options:
@table @option
@item -no-translations
Do not translate between jump instructions.
If the offset of a @code{jmpr}
instruction is too large, it will not be translated to
@code{jmps} but an error will be emitted.
Also, @code{jmpa} will not be optimized to @code{jmpr}.
The pseudo-instruction @code{jmp} will still be translated.
@item -jmpa
A @code{jmp} or @code{jmpr} instruction that is translated due to
its offset being larger than 8 bits will be translated to a
@code{jmpa} rather than a @code{jmps}, if possible.
@end table
@section General
This backend accepts c16x/st10 instructions as described in the
Infineon instruction set manuals.
The target address type is 32bit.
Default alignment for sections and instructions is 2 bytes.
@section Extensions
This backend provides the following specific extensions:
@itemize @minus
@item
There is a pseudo instruction @code{jmp} that will be translated
either to a @code{jmpr} or @code{jmpa} instruction, depending on
the offset.
@item
The @code{sfr} pseudo opcode can be used to declare special function
registers. It has two, three of four arguments. The first argument
is the identifier to be declared as special function register.
The second argument is either the 16bit sfr address or its 8bit base
address (0xfe for normal sfrs and
0xf0 for extended special function registers). In the latter case,
the third argument is
the 8bit sfr number. If another argument is given, it specifies the
bit-number in the sfr (i.e. the declaration declares a single bit).
Example:
@example
.sfr zeros,0xfe,0x8e
@end example
@item
@code{SEG} and @code{SOF} can be used to obtain the segment or
segment offset of a full address.
Example:
@example
mov r3,#SEG farfunc
@end example
@end itemize
@section Optimizations
This backend performs the following optimizations:
@itemize @minus
@item
@code{jmp} is translated to @code{jmpr}, if possible. Also, if
@option{-no-translations} was not specified, @code{jmpr} and
@code{jmpa} are translated.
@item
Relative jump instructions with an offset that does not fit into
8 bits are translated to a @code{jmps} instruction or an inverted
jump around a @code{jmps} instruction.
@item
For instruction that have two forms @code{gpr,#IMM3/4} and
@code{reg,#IMM16} the smaller form is used, if possible.
@end itemize
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item Lots...
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 2001: illegal operand
@item 2002: word register expected
@item 2004: value does not find in %d bits
@item 2005: data size not supported
@item 2006: illegal use of SOF
@item 2007: illegal use of SEG
@item 2008: illegal use of DPP prefix
@end itemize

124
vasm-1/doc/cpu_jagrisc.texi Normal file
View File

@ -0,0 +1,124 @@
This chapter documents the backend for the Atari Jaguar GPU/DSP RISC processor.
@section Legal
This module is written in 2014-2015 by Frank Wille and
is covered by the vasm copyright without modifications.
@section Additional options for this module
This module provides the following additional options:
@table @option
@item -big
Output big-endian code and data (default).
@item -little
Output little-endian code and data.
@item -many
Generate code for GPU or DSP RISC. All instructions are accepted
(default).
@item -mdsp
@itemx -mjerry
Generate code for the DSP RISC (part of Jerry).
@item -mgpu
@itemx -mtom
Generate code for the GPU RISC (part of Tom).
@end table
@section General
This backend accepts RISC instructions for the GPU or DSP in Atari's
Jaguar custom chip set according to the "Jaguar Technical Reference Manual
for Tom & Jerry", Revision 8. Documentation bugs were fixed by using
various sources on the net.
The target address type is 32 bits.
Default alignment for instructions is 2 bytes.
Data is aligned to its natural alignment by default.
@section Optimizations
This backend performs the following optimizations and translations for
the GPU/DSP RISC instruction set:
@itemize @minus
@item @code{load (Rn+0),Rm} is optimized to @code{load (Rn),Rm}.
@item @code{store Rn,(Rm+0)} is optimized to @code{store Rn,(Rm)}.
@end itemize
@section Extensions
This backend extends the selected syntax module by the following
directives (note that a leading dot is optional):
@table @code
@item <symbol> ccdef <expression>
Allows defining a symbol for the condition codes used in @code{jump}
and @code{jr} instructions. Must be constant number in the range of
0 to 31 or another condition code symbol.
@item ccundef <symbol>
Undefine a condition code symbol previously defined via @code{ccdef}.
@item dsp
Select DSP instruction set.
@item <symbol> equr <Rn>
Define a new symbol named <symbol> and assign the address register
@code{Rn} to it. <Rn> may also be another register symbol.
Note that a register symbol must be defined before it can be used.
@item equrundef <symbol>
Undefine a register symbol previously defined via @code{equr}.
@item gpu
Select GPU instruction set.
@item <symbol> regequ <Rn>
Equivalent to @code{equr}.
@item regundef <symbol>
Undefine a register symbol previously defined via @code{regequ}.
@end table
All directives may be optionally preceded by a dot (@code{.}), for
compatibility with various syntax modules.
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item Encoding of @code{MOVEI} instruction in little-endian mode is unkown.
@item The developer has to provide the necessary @code{NOP} instructions
after jumps, or @code{OR} instructions to work around hardware bugs,
her/himself.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 2001: data size %d not supported
@item 2002: value from %ld to %ld required
@end itemize

1090
vasm-1/doc/cpu_m68k.texi Normal file

File diff suppressed because it is too large Load Diff

172
vasm-1/doc/cpu_ppc.texi Normal file
View File

@ -0,0 +1,172 @@
This chapter documents the Backend for the PowerPC microprocessor family.
@section Legal
This module is written in 2002-2016 by Frank Wille and
is covered by the vasm copyright without modifications.
@section Additional options for this module
This module provides the following additional options:
@table @option
@item -big
Select big-endian mode.
@item -little
Select little-endian mode.
@item -many
Allow both, 32- and 64-bit instructions.
@item -mavec, -maltivec
Generate code for the Altivec unit.
@item -mcom
Allow only common PPC instructions.
@item -m601
Generate code for the PPC 601.
@item -mppc32, -mppc, -m603, -m604
Generate code for the 32-bit PowerPC 6xx family.
@item -mppc64, -m620
Generate code for the 64-bit PowerPC 600 family.
@item -m7400, -m7410, -m7455
Generate code for the 32-bit PowerPC 74xx (G4) family.
@item -m7450
Generate code for the 32-bit PowerPC 7450.
@item -m403, -m405
Generate code for the IBM/AMCC 32-bit embedded 40x family.
@item -m440, -m460
Generate code for the AMCC 32-bit embedded 440/460 family.
@item -m821, -m850, -m860
Generate code for the 32-bit MPC8xx PowerQUICC I family.
@item -mbooke
Generate code for the 32-bit Book-E architecture.
@item -me300
Generate code for the 32-bit e300 core (MPC51xx, MPC52xx, MPC83xx).
@item -me500
Generate code for the 32-bit e500 core (MPC85xx), including SPE,
EFS and PMR.
@item -mpwr
Generate code for the POWER family.
@item -mpwrx, -mpwr2
Generate code for the POWER2 family.
@item -no-regnames
Don't predefine any register-name symbols.
@item -opt-branch
Enables translation of 16-bit branches into
"B<!cc> $+8 ; B label" sequences when destination is out of range.
@item -sd2reg=<n>
Sets the 2nd small data base register to @code{Rn}.
@item -sdreg=<n>
Sets small data base register to @code{Rn}.
@end table
The default setting is to generate code for a 32-bit PPC G2, G3, G4 CPU
with Altivec support.
@section General
This backend accepts PowerPC instructions as described in the
instruction set manuals from IBM, Motorola, Freescale and AMCC.
The full instruction set of the following families is supported:
POWER, POWER2, 40x, 44x, 46x, 60x, 620, 750, 74xx, 860, Book-E,
e300 and e500.
The target address type is 32 or 64 bits, depending on the selected
CPU model.
Default alignment for sections and instructions is 4 bytes. Data is
aligned to its natural alignment by default.
@section Extensions
This backend provides the following specific extensions:
@itemize @minus
@item When not disabled by the option @code{-no-regnames}, the registers r0 - r31,
f0 - f31, v0 - v31, cr0 - cr7, vrsave, sp, rtoc, fp, fpscr, xer, lr, ctr,
and the symbols lt, gt, so and un will be predefined on startup and may
be referenced by the program.
@end itemize
This backend extends the selected syntax module by the following
directives:
@table @code
@item .sdreg <n>
Sets the small data base register to @code{Rn}.
@item .sd2reg <n>
Sets the 2nd small data base register to @code{Rn}.
@end table
@section Optimizations
This backend performs the following optimizations:
@itemize @minus
@item 16-bit branches, where the destination is out of range, are translated
into @code{B<!cc> $+8} and a 26-bit unconditional branch.
@end itemize
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item No real differentiation between 403, 750, 860 instructions
at the moment.
@item There may still be some unsupported PPC models.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 2002: instruction not supported on selected architecture
@item 2003: constant integer expression required
@item 2004: trailing garbage in operand
@item 2005: illegal operand type
@item 2006: missing closing parenthesis in load/store addressing mode
@item 2007: relocation does not allow hi/lo modifier
@item 2008: multiple relocation attributes
@item 2009: multiple hi/lo modifiers
@item 2010: data size %d not supported
@item 2011: data has illegal type
@item 2012: relocation attribute not supported by operand
@item 2013: operand out of range: %ld (allowed: %ld to %ld)
@item 2014: not a valid register (0-31)
@item 2015: missing base register in load/store addressing mode
@item 2016: missing mandatory operand
@item 2017: ignoring fake operand
@end itemize

127
vasm-1/doc/cpu_tr3200.texi Normal file
View File

@ -0,0 +1,127 @@
This chapter documents the Backend for the TR3200 cpu.
@section Legal
This module is written in 2014 by Luis Panadero Guarde@~no and
is covered by the vasm copyright without modifications.
@section General
This backend accepts TR3200 instructions as described in the
@uref{https://github.com/trillek-team/trillek-computer, TR3200 specification}
The target address type is 32 bits.
Default alignment for sections is 4 bytes. Instructions alignment is 4 bytes.
Data is aligned to its natural alignment by default, i.e. 2 byte wide data
alignment is 2 bytes and 4 byte wide data alignment is 4 byte.
The backend uses TR3200 syntax! This means the left operands are always the
destination and the right operand is the source (except for single operand
instructions). Register names have to be prefixed by a '@code{%}'
(@code{%bp}, @code{%r0}, etc.)
This means that it should accept WaveAsm assembly files if oldstyle syntax module
is being used. The instructions are lowercase, @option{-dotdir} option is being used
and directives are not in the first column.
@section Extensions
Predefined register symbols in this backend:
@itemize @minus
@item register by number: @code{r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 r13 r14 r15}
@item special registers by name: @code{bp sp y ia flags}
@end itemize
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item This module need to be fully checked, but has been tested building a full
program that could be found here : @uref{https://github.com/Zardoz89/trillek-firmware}
@item Instruction relocations are missing.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 2001: illegal operand
@item 2002: illegal qualifier <%s>
@item 2003: data size not supported
@end itemize
@section Example
It follows a little example to illustrate TR3200 assembly using
the oldstyle syntax module (option @option{-dotdir} required):
@example
const .equ 0xBEBACAFE ; A constant
an_addr .equ 0x100 ; Other constant
; ROM code
.org 0x100000
.text
_start ; Label with or without a ending ":"
mov %sp, 0x1000 ; Set the initial stack
mov %r0, 0
mov %r1, 0xA5
mov %r2, 0
storeb %r0, an_addr, %r1
add %r0, %r2, %bp
add %r0, %r2, 0
add %r0, %r0, 10
add %r0, %r0, 10h
add %r0, %r0, 0x100010
add %r0, %r0, (256 + 100) ; vasm parses math expressions
mov %r2, 0
mov %r3, 0x10200
loadb %r6, 0x100200
loadb %r1, %r2, 0x100200
loadb %r1, %r2, %r3
loadb %r4, var1
push %r0
.repeat 2 ; directives to repeat stuff!
push const
.endrepeat
.repeat 2
pop %r5
.endrepeat
pop %r0
rcall foo ; Relative call/jump!
sleep
foo: ; Subrutine
ifneq %r5, 0
mul %r5, %r5, 2
sub %r5, %r5, 1
ret
; ROM data
.org 0x100500
var1 .db 0x20 ; A byte size variable
.even ; Enforce to align to even address
var3 .dw 0x1020 ; A word size variable
var4 .dd 0x0A0B0C20 ; A double word size variable
str1 .asciiz "Hello world!" ; ASCII string with null termination
str2 .string "Hello world!" ; ASCII string with null termination
.fill 5, 0xFF ; Fill 5 bytes with 0xFF
.reserve 5 ; Reserves space for 5 byte
@end example

168
vasm-1/doc/cpu_x86.texi Normal file
View File

@ -0,0 +1,168 @@
This chapter documents the Backend for the 80x86 microprocessor family.
@section Legal
This module is written in 2005-2006,2011,2015-2016 by Frank Wille and
is covered by the vasm copyright without modifications.
@section Additional options for this module
This module provides the following additional options:
@table @option
@item -cpudebug=<n>
Enables debugging output.
@item -m8086
Generate code for the 8086 CPU.
@item -mi186
Generate code for the 80186 CPU.
@item -mi286
Generate code for the 80286 CPU.
@item -mi386
Generate code for the 80386 CPU.
@item -mi486
Generate code for the 80486 CPU.
@item -mi586
Generate code for the Pentium.
@item -mi686
Generate code for the PentiumPro.
@item -mpentium
Generate code for the Pentium.
@item -mpentiumpro
Generate code for the PentiumPro.
@item -mk6
Generate code for the AMD K6.
@item -mathlon
Generate code for the AMD Athlon.
@item -msledgehammer
Generate code for the Sledgehammer CPU.
@item -m64
Generate code for 64-bit architectures (x86_64).
@end table
@section General
This backend accepts 80x86 instructions as described in the
Intel Architecture Software Developer's Manual.
The target address type is 32 bits. It is 64 bits when the x86_64
architecture was selected (@option{-m64}).
Instructions do not need any alignment. Data is aligned to its natural
alignment by default.
The backend uses MIT-syntax! This means the left operands are always the
source and the right operand is the destination. Register names have to
be prefixed by a '%'.
The operation size is indicated by a 'b', 'w', 'l', etc. suffix directly
appended to the mnemonic. The assembler can also determine the operation
size from the size of the registers being used.
@section Extensions
Predefined register symbols in this backend:
@itemize @minus
@item 8-bit registers: @code{al cl dl bl ah ch dh bh axl cxl dxl spl bpl sil dil r8b r9b r10b r11b r12b r13b r14b r15b}
@item 16-bit registers: @code{ax cx dx bx sp bp si di r8w r9w r10w r11w r12w r13w r14w r15w}
@item 32-bit registers: @code{eax ecx edx ebx esp ebp esi edi r8d r9d r10d r11d r12d r13d r14d r15d}
@item 64-bit registers: @code{rax rcx rdx rbx rsp ebp rsi rdi r8 r9 r10 r11 r12 r13 r14 r15}
@item segment registers: @code{es cs ss ds fs gs}
@item control registers: @code{cr0 cr1 cr2 cr3 cr4 cr5 cr6 cr7 cr8 cr9 cr10 cr11 cr12 cr13 cr14 cr15}
@item debug registers: @code{dr0 dr1 dr2 dr3 dr4 dr5 dr6 dr7 dr8 dr9 dr10 dr11 dr12 dr13 dr14 dr15}
@item test registers: @code{tr0 tr1 tr2 tr3 tr4 tr5 tr6 tr7}
@item MMX and SIMD registers: @code{mm0 mm1 mm2 mm3 mm4 mm5 mm6 mm7 xmm0 xmm1 xmm2 xmm3 xmm4 xmm5 xmm6 xmm7 xmm8 xmm9 xmm10 xmm11 xmm12 xmm13 xmm14 xmm15}
@item FPU registers: @code{st st(0) st(1) st(2) st(3) st(4) st(5) st(6) st(7)}
@end itemize
This backend extends the selected syntax module by the following
directives:
@table @code
@item .code16
Sets the assembler to 16-bit addressing mode.
@item .code32
Sets the assembler to 32-bit addressing mode, which is the default.
@item .code64
Sets the assembler to 64-bit addressing mode.
@end table
@section Optimizations
This backend performs the following optimizations:
@itemize @minus
@item Immediate operands are optimized to the smallest size which can
still represent the absolute value.
@item Displacement operands are optimized to the smallest size which
can still represent the absolute value.
@item Jump instructions are optimized to 8-bit displacements, when possible.
@end itemize
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item 64-bit operations are incomplete and experimental.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 2001: instruction not supported on selected architecture
@item 2002: trailing garbage in operand
@item 2003: same type of prefix used twice
@item 2004: immediate operand illegal with absolute jump
@item 2005: base register expected
@item 2006: scale factor without index register
@item 2007: missing ')' in baseindex addressing mode
@item 2008: redundant %s prefix ignored
@item 2009: unknown register specified
@item 2010: using register %%%s instead of %%%s due to '%c' suffix
@item 2011: %%%s not allowed with '%c' suffix
@item 2012: illegal suffix '%c'
@item 2013: instruction has no suffix and no register operands - size is unknown
@item 2015: memory operand expected
@item 2016: you cannot pop %%%s
@item 2017: translating to %s %%%s,%%%s
@item 2018: translating to %s %%%s
@item 2019: absolute scale factor required
@item 2020: illegal scale factor (valid: 1,2,4,8)
@item 2021: data objects with %d bits size are not supported
@item 2022: need at least %d bits for a relocatable symbol
@item 2023: pc-relative jump destination out of range (%lld)
@item 2024: instruction doesn't support these operand sizes
@item 2025: cannot determine immediate operand size without a suffix
@item 2026: displacement doesn't fit into %d bits
@end itemize

165
vasm-1/doc/cpu_z80.texi Normal file
View File

@ -0,0 +1,165 @@
This chapter documents the backend for the 8080/z80/gbz80/64180/RCMx000
microprocessor family.
@section Legal
This module is copyright in 2009 by Dominic Morris.
@example
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@end example
@section Additional options for this module
This module provides the following additional options:
@table @option
@item -8080
Turns on 8080 compatibility mode. Any use of z80 (or higher)
opcodes will result in an error being generated.
@item -gbz80
Turns on gbz80 compatibility mode. Any use of non-supported
opcodes will result in an error being generated.
@item -hd64180
Turns on 64180 mode supporting additional 64180 opcodes.
@item -intel-syntax
Turns on the older Intel 8080 syntax mode. When this mode is
activated, mnemonics and oprand types from the Intel 8080 syntax
instead of the Zilog Z80 syntax (such as @code{STA 1234h}
instead of @code{ld (1234h),a}) will be valid. This option can
be used in parallel with -8080 to use both sets of mnemonics,
although this is discouraged, as two instructions (@code{jp} and
@code{cp}) mean different things in each syntax. In this case,
these instructions will be assembled as the Intel syntax, and a
warning will be emitted.
@item -rcm2000
@item -rcm3000
@item -rcm4000
Turns on Rabbit compatibility mode, generating the correct
codes for moved opcodes and supporting the additional Rabbit
instructions. In this mode, 8 bit access to the 16 bit index
registers is not permitted.
@item -rcmemu
Turns on emulation of some instructions which aren't available
on the Rabbit processors.
@item -swapixiy
Swaps the usage of ix and iy registers. This is useful
for compiling generic code that uses an index register that
is reserved on the target machine.
@item -z80asm
Switches on z80asm mode. This translates ASMPC to $ and accepts
some pseudo opcodes that z80asm supports. Most emulation of
z80asm directives is provided by the oldsyntax syntax module.
@end table
@section General
This backend accepts z80 family instructions in standard
Zilog syntax. Rabbit opcodes are accepted as defined in the
publically available reference material from Rabbit Semiconductor,
with the exception that the @code{ljp} and @code{lcall} opcodes need
to be supplied with a 24 bit number rather than an 8 bit @code{xpc} and a
16 bit address.
The target address type is 16 bit.
Instructions consist of one up to six bytes and require no alignment.
There is also no alignment requirement for sections and data.
@section Extensions
This backend provides the following specific extensions:
@itemize @minus
@item Certain Rabbit opcodes can be prefixed by the @code{altd} and/or the
@code{ioi}/@code{ioe} modifier.
For details of which instructions these are valid for please
see the documentation from Rabbit.
@item The parser understands a lo/hi-modifier to select low- or high-byte
of a 16-bit word. The character @code{<} is used to select the low-byte
and @code{>} for the high-byte. It has to be the first character before
an expression.
@item When applying the operation @code{/256}, @code{%256} or @code{&256}
on a label, an appropriate lo/hi-byte relocation will automatically be
generated.
@end itemize
@section Optimisations
This backend supports the emulation of certain z80 instructions on the
Rabbit/gbz80 processor. These instructions are @code{rld}, @code{rrd},
@code{cpi}, @code{cpir}, @code{cpd} and @code{cpdr}.
The link stage should provide routines with the opcode name prefixed with
@code{rcmx_} (eg @code{rcmx_rld}) which implements the same functionality.
Example implementations are available within the z88dk CVS tree.
Additionally, for the Rabbit targets the missing call @code{cc}, opcodes
will be emulated.
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item Not all RCM4000 opcodes are supported (@code{llcall}, @code{lljp}
are not available).
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 2001: index offset out of bounds (%d)
@item 2002: Opcode not supported by %s (%s)
@item 2003: Index registers not available on 8080
@item 2004: out of range for 8 bit expression (%d)
@item 2005: invalid bit number (%d) should be in range 0..7
@item 2006: rst value out of range (%d/0x%02x)
@item 2007: %s value out of range (%d)
@item 2008: index offset should be a constant
@item 2009: invalid branch type for jr
@item 2010: Rabbit target doesn't support rst %d
@item 2011: Rabbit target doesn't support 8 bit index registers
@item 2012: z180 target doesn't support 8 bit index registers
@item 2013: invalid branch type for jre
@item 2014: Opcode not supported by %s (%s) but it can be emulated (-rcmemu)
@item 2015: %s specifier is only valid for Rabbit processors
@item 2016: Only one of ioi and ioe can be specified at a time
@item 2017: %s specifier is not valid for the opcode %s
@item 2018: %s specifier redundant for the opcode %s
@item 2019: %s specifier has no effect on the opcode %s
@item 2020: Operand value must evaluate to a constant for opcode %s
@item 2021: Unhandled operand type wanted 0x%x got 0x%x
@item 2022: Missed matched index registers on %s
@item 2023: Only out (c),0 is supported for the opcode %s
@item 2024: Operations between different index registers are forbidden
@item 2025: Operations between ix/iy/hl are forbidden
@item 2026: Double indirection forbidden
@item 2027: Instruction %s will be assembled as '%s'
@end itemize

1458
vasm-1/doc/interface.texi Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,62 @@
This chapter describes the a.out output module which can be
selected with the @option{-Faout} option.
@section Legal
This module is written in 2008-2012 by Frank Wille and
is covered by the vasm copyright without modifications.
@section Additional options for this module
@table @option
@item -mid=<machine id>
Sets the MID field of the a.out header to the specified value.
The MID defaults to 2 (Sun020 big-endian) for M68k and to 100
(PC386 little-endian) for x86.
@end table
@section General
This output module outputs the @code{a.out} (assembler output)
format, which is an older 32-bit format for Unix-like operating systems,
originally invented by AT&T.
@section Restrictions
The @code{a.out} output format, as implemented in vasm, currently supports
the following architectures:
@itemize @minus
@item M68k
@item i386
@end itemize
The following standard relocations are supported by default:
@itemize @minus
@item absolute, 8, 16, 32 bits
@item pc-relative, 8, 16, 32 bits
@item base-relative
@end itemize
Standard relocations occupy 8 bytes and don't include an addend, so they
are not suitable for most RISC CPUs. The extended relocations format occupies
12 bytes and also allows more relocation types.
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item Support for stab debugging symbols is still missing.
@item The extended relocation format is not supported.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 3004: section attributes <attr> not supported
@item 3008: output module doesn't allow multiple sections of the same type
@item 3010: section <%s>: alignment padding (%lu) not a multiple of %lu at 0x%llx
@end itemize

View File

@ -0,0 +1,49 @@
This chapter describes the simple binary output module which can be
selected with the @option{-Fbin} option.
@section Legal
This module is written in 2002-2009,2013 by Volker Barthelmann and
is covered by the vasm copyright without modifications.
@section Additional options for this module
@table @option
@item -cbm-prg
Writes a Commodore PRG header in front of the output file, which
consists of two bytes in little-endian order, defining the load
address of the program.
@item -atari-com
Writes a Atari DOS COM header in front of the output file, which
consists of standard header (0xFFFF) followed by each section,
starting with four bytes in little-endian order, defining the load
address begin and end of each section.
@end table
@section General
This output module outputs the contents of all sections as simple
binary data without any header or additional information. When there
are multiple sections, they must not overlap. Gaps between sections
are filled with zero bytes when not using Atari COM format. Undefined
symbols are not allowed.
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item None.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 3001: sections must not overlap
@item 3007: undefined symbol <%s>
@item 3010: section <%s>: alignment padding (%lu) not a multiple of %lu at 0x%llx
@end itemize

View File

@ -0,0 +1,59 @@
This chapter describes the ELF output module which can be
selected with the @option{-Felf} option.
@section Legal
This module is written in 2002-2016 by Frank Wille and
is covered by the vasm copyright without modifications.
@section Additional options for this module
@table @option
@item -keepempty
Do not delete empty sections without any symbol definition.
@end table
@section General
This output module outputs the @code{ELF} (Executable and Linkable Format)
format, which is a portable object file format which works for a variety
of 32- and 64-bit operating systems.
@section Restrictions
The @code{ELF} output format, as implemented in vasm, currently supports
the following architectures:
@itemize @minus
@item PowerPC
@item M68k
@item ARM
@item i386
@item x86_64
@item Jaguar RISC
@end itemize
The supported relocation types depend on the selected architecture.
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item None.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 3002: output module doesn't support cpu <name>
@item 3003: write error
@item 3005: reloc type <m>, size <n>, mask <mask> (symbol <sym> + <offset>) not supported
@item 3006: reloc type <n> not supported
@item 3010: section <%s>: alignment padding (%lu) not a multiple of %lu at 0x%llx
@end itemize

115
vasm-1/doc/output_hunk.texi Normal file
View File

@ -0,0 +1,115 @@
This chapter describes the AmigaOS hunk-format output module which can be
selected with the @option{-Fhunk} option to generate objects and with the
@option{-Fhunkexe} option to generate executable files.
@section Legal
This module is written in 2002-2019 by Frank Wille and
is covered by the vasm copyright without modifications.
@section Additional options for this module
@table @option
@item -hunkpad=<code>
Sets a two-byte code used for aligning a code hunk to the
next 32-bit border. Defaults to 0x4e71 on M68k to allow linking
of functions which extend over two object files.
@item -keepempty
Do not delete empty sections without any symbol definition.
@item -kick1hunks
Use only those hunk types and external reference types which have
been valid at the time of Kickstart 1.x for compatibility with
old assembler sources and old linkers. For example: no longer
differentiate between absolute and relative references.
In executables it will prevent the assembler from using
16-bit relocation offsets in hunks and rejects 32-bit PC-relative
relocations.
@item -linedebug
Automatically generate an SAS/C-compatible LINE DEBUG hunk for
the input source. Overrides any line debugging directives from
the source.
@end table
These options are valid for the @code{hunkexe} module only:
@table @option
@item -databss
Try to shorten sections in the output file by removing zero words
without relocation from the end. This technique is only supported
by AmigaOS 2.0 and higher.
@end table
@section General
This output module outputs the @code{hunk} object (standard for @code{M68k}
and extended for @code{PowerPC}) and @code{hunkexe} executable format, which
is a proprietary file format used by AmigaOS and WarpOS.
The @code{hunkexe} module will generate directly executable files, without
the need for another linker run. But you have to make sure that there are
no undefined symbols, common symbols, or unusual relocations (e.g. small
data) left.
It is allowed to define sections with the same name but different
attributes. They will be regarded as different entities.
@section Restrictions
The @code{hunk}/@code{hunkexe} output format is only intended for @code{M68k}
and @code{PowerPC} cpu modules and will abort when used otherwise.
The @code{hunk} module supports the following relocation types:
@itemize @minus
@item absolute, 32-bit
@item absolute, 16-bit
@item absolute, 8-bit
@item relative, 8-bit
@item relative, 14-bit (mask 0xfffc) for PPC branch instructions.
@item relative, 16-bit
@item relative, 24-bit (mask 0x3fffffc) for PPC branch instructions.
@item relative, 32-bit
@item base-relative, 16-bit
@item common symbols are supported as 32-bit absolute and relative
references
@end itemize
The @code{hunkexe} module supports absolute 32-bit relocations only.
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item The @code{hunkexe} module won't process common symbols and allocate
them in a @code{BSS} section. Use a real linker for that.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 3001: multiple sections not supported by this format
@item 3002: output module doesn't support cpu <name>
@item 3003: write error
@item 3004: section attributes <attr> not supported
@item 3005: reloc type <m>, size <n>, mask <mask> (symbol <sym> + <offset>) not supported
@item 3006: reloc type <n> not supported
@item 3009: undefined symbol <%s> at %s+0x%lx, reloc type %d
@item 3010: section <%s>: alignment padding (%lu) not a multiple of %lu at 0x%llx
@item 3011: weak symbol <%s> not supported by output format, treating as global
@item 3014: data definition following a databss space directive
@end itemize

View File

@ -0,0 +1,54 @@
This chapter describes the Motorola srecord output module which can be
selected with the @option{-Fsrec} option.
@section Legal
This module is written in 2015 by Joseph Zatarski and
is covered by the vasm copyright without modifications.
@section Additional options for this module
@table @option
@item -s19
Writes S1 data records and S9 trailers with 16-bit addresses.
@item -s28
Writes S2 data records and S8 trailers with 24-bit addresses.
@item -s37
Writes S3 data records and S7 trailers with 32-bit addresses.
This is the default setting.
@item -exec[=<symbol>]
Use the given symbol <symbol> as entry point of the program.
This start address will be written into the trailer record,
which is otherwise zero.
When the symbol assignment is omitted, then the default symbol
@code{start} will be used.
@end table
@section General
This output module outputs the contents of all sections in Motorola srecord
format, which is a simple ASCII output of hexadecimal digits. Each record
starts with '@code{S}' and a one-digit ID. It is followed by the data
and terminated by a checksum and a newline character.
Every section starts with a new header record.
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item A new header is written for every new section. This may cause
compatibility issues.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 3007: undefined symbol <%s>
@item 3010: section <%s>: alignment padding (%lu) not a multiple of %lu at 0x%llx
@item 3012: address 0x%llx out of range for selected format
@end itemize

View File

@ -0,0 +1,38 @@
This chapter describes the test output module which can be
selected with the @option{-Ftest} option.
@section Legal
This module is written in 2002 by Volker Barthelmann and
is covered by the vasm copyright without modifications.
@section Additional options for this module
This output module provides no additional options.
@section General
This output module outputs a textual description of the contents of
all sections. It is mainly intended for debugging.
@section Restrictions
None.
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item None.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item None.
@end itemize

View File

@ -0,0 +1,54 @@
This chapter describes the TOS output module which can be
selected with the @option{-Ftos} option.
@section Legal
This module is written in 2009-2014 by Frank Wille and
is covered by the vasm copyright without modifications.
@section Additional options for this module
@table @option
@item -monst
Write Devpac "MonST"-compatible symbols.
@item -tos-flags=<flags>
Sets the flags field in the TOS file header. Defaults to 0.
Overwrites a TOS flags definition in the assembler source.
@end table
@section General
This module outputs the TOS executable file format, which is used
on Atari 16/32-bit computers with 68000 up to 68060 CPU. The symbol
table uses the DRI format.
@section Restrictions
@itemize @minus
@item All symbols must be defined, otherwise the generation of the executable
fails. Unknown symbols are listed by vasm.
@item The only relocations allowed in this format are 32-bit absolute.
@end itemize
Those are restrictions of the output format, not of vasm.
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item None.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 3004: section attributes <attr> not supported
@item 3005: reloc type %d, size %d, mask 0x%lx (symbol %s + 0x%lx) not supported
@item 3006: reloc type %d not supported
@item 3007: undefined symbol <%s>
@item 3008: output module doesn't allow multiple sections of the same type
@item 3010: section <%s>: alignment padding (%lu) not a multiple of %lu at 0x%llx
@item 3011: weak symbol <%s> not supported by output format, treating as global
@end itemize

View File

@ -0,0 +1,38 @@
This chapter describes the simple binary output module which can be
selected with the @option{-Fvobj} option.
@section Legal
This module is written in 2002-2014 by Volker Barthelmann and
is covered by the vasm copyright without modifications.
@section Additional options for this module
None.
@section General
This output module outputs the @code{vobj} object format, a simple
portable proprietary object file format of @code{vasm}.
As this format is not yet fixed, it is not described here.
@section Restrictions
None.
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item None.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 3010: section <%s>: alignment padding (%lu) not a multiple of %lu at 0x%llx
@end itemize

View File

@ -0,0 +1,49 @@
This chapter describes the Xfile output module which can be
selected with the @option{-Fxfile} option.
@section Legal
This module is written in 2018 by Frank Wille and
is covered by the vasm copyright without modifications.
@section Additional options for this module
None.
@section General
This module outputs the Xfile executable file format, which is used
on Sharp X68000 16/32-bit computer with 68000 up to 68040 CPU.
@section Restrictions
@itemize @minus
@item The source must not define more than one code, data and bss section
each. More complex sources with @code{.rdata} or @code{.stack} sections
require a linker.
@item All symbols must be defined, otherwise the generation of the executable
fails. Unknown symbols are listed by vasm.
@item The only relocations allowed in this format are 32-bit absolute.
@end itemize
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item None.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 3004: section attributes <attr> not supported
@item 3005: reloc type %d, size %d, mask 0x%lx (symbol %s + 0x%lx) not supported
@item 3006: reloc type %d not supported
@item 3007: undefined symbol <%s>
@item 3008: output module doesn't allow multiple sections of the same type
@item 3011: weak symbol <%s> not supported by output format, treating as global
@item 3013: reloc type %d, mask 0x%lx to symbol %s + 0x%lx does not fit into %u bits
@end itemize

View File

@ -0,0 +1,330 @@
This chapter describes the madmac syntax module, which is compatible
to the MadMac assembler syntax, written by Landon Dyer for Atari and
improved later to support Jaguar and JRISC.
It is mainly intended for Atari's 6502, 68000 and Jaguar systems.
@section Legal
This module is written in 2015 by Frank Wille and
is covered by the vasm copyright without modifications.
@section General Syntax
A statement may contain up to four fields which are identified by order
of appearance and terminating characters. The general form is:
@example
label: operator operand(s) ; comment
@end example
Labels must not start at the first column, as they are identified by the
mandatory terminating colon (@code{:}) character. A double colon (@code{::})
automatically makes the label externally visible.
Labels preceded by '@code{.}' have local scope and are only valid between
two global labels.
Equate directives, starting in the operator field, have a symbol without
terminating colon in the first field, left of the operator.
The equals-character (@code{=}) can be used as an alias for @code{equ}.
A double-equals (@code{==}) automatically makes the symbol externally
visible.
@example
symbol equate expression ; comment
@end example
Identifiers, like symbols or labels, may start with any upper- or lower-case
character, a dot (@code{.}), question-mark (@code{?}) or underscore
(@code{_}). The remaining characters may be any alphanumeric character,
a dollar-sign (@code{$}), question-mark (@code{?}) or underscore (@code{_}).
The operands are separated from the operator by whitespace. Multiple
operands are separated by comma (@code{,}).
Comments are introduced by the comment character @code{;}. The asterisk
(@code{*}) can be used at the first column to start a comment.
The rest of the line will be ignored.
In expressions, numbers starting with @code{$} are hexadecimal (e.g.
@code{$fb2c}). @code{%} introduces binary numbers (e.g. @code{%1100101}).
Numbers starting with @code{@@} are assumed to be octal numbers, e.g.
@code{@@237}.
All other numbers starting with a digit are decimal, e.g. @code{1239}.
NOTE: Unlike the original Madmac assembler all expressions are evaluated
following the usual mathematical operator priorities.
C-like escape characters are supported in strings.
@section Directives
The following directives are supported by this syntax module (if the
CPU- and output-module allow it). Note that all directives, besides the
equals-character, may be optionally preceded by a dot (@code{.}).
@table @code
@item <symbol> = <expression>
Equivalent to @code{<symbol> equ <expression>}.
@item <symbol> == <expression>
Equivalent to @code{<symbol> equ <expression>}, but declare <symbol>
as externally visible.
@item assert <expresion>[,<expression>...]
Assert that all conditions are true (non-zero), otherwise issue a
warning.
@item bss
The following data (space definitions) are going into the BSS section.
The BSS section cannot contain any initialized data.
@item data
The following data are going into the data section, which usually
contains pre-initialized data and no executable code.
@item dc <exp1>[,<exp2>...]
Equivalent to @code{dc.w}.
@item dc.b <exp1>[,<exp2>,"<string1>",'<string2>'...]
Assign the integer or string constant operands into successive
bytes of memory in the current section. Any combination of integer
and character string constant operands is permitted.
@item dc.i <exp1>[,<exp2>...]
Assign the values of the operands into successive 32-bit words
of memory in the current section. In contrast to @code{dc.l} the
high and low half-words will be swapped as with the Jaguar-RISC
@code{movei} instruction.
@item dc.l <exp1>[,<exp2>...]
Assign the values of the operands into successive 32-bit words
of memory in the current section.
@item dc.w <exp1>[,<exp2>...]
Assign the values of the operands into successive 16-bit words
of memory in the current section.
@item dcb
Equivalent to @code{dcb.w}.
@item dcb.b <exp>[,<fill>]
Insert <exp> zero or <fill> bytes into the current section.
@item dcb.l <exp>[,<fill>]
Insert <exp> zero or <fill> 32-bit words into the current section.
@item dcb.w <exp>[,<fill>]
Insert <exp> zero or <fill> 16-bit words into the current section.
@item dphrase
Align the program counter to the next integral double phrase
boundary (16 bytes).
@item ds <exp>
Equivalent to @code{dcb.w <exp>,0}.
@item ds.b <exp>
Equivalent to @code{dcb.b <exp>,0}.
@item ds.l <exp>
Equivalent to @code{dcb.l <exp>,0}.
@item ds.w <exp>
Equivalent to @code{dcb.w <exp>,0}.
@item else
Else-part of a conditional-assembly block. Refer to '@code{if}'.
@item end
End the assembly of the current file. Parsing of an include file is
terminated here and assembling of the parent source commences. It
also works to break the current conditional block, repetition or macro.
@item endif
Ends a block of conditional assembly.
@item endm
Ends a macro definition.
@item endr
Ends a repetition block.
@item <symbol> equ <expression>
Define a new program symbol with the name <symbol> and assign to it
the value of <expression>. Defining <symbol> twice will cause
an error.
@item even
Align the program counter to an even value, by inserting a zero-byte
when it is odd.
@item exitm
Exit the current macro (proceed to @code{endm}) at this point and
continue assembling the parent context.
Note that this directive also resets the level of conditional
assembly to a state before the macro was invoked (which means that
it works as a 'break' command on all new @code{if} directives).
@item extern <symbol>[,<symbol>...]
Declare the given symbols as externally defined. Internally there is
no difference to @code{globl}, as both declare the symbols, no
matter if defined or not, as externally visible.
@item globl <symbol>[,<symbol>...]
Declare the given symbols as externally visible in the object file
for the linker. Note that you can have the same effect by using
a double-colon (@code{::}) on labels or a double-equal (@code{==})
on equate-symbols.
@item if <expression>
Start of block of conditional assembly. If <expression> is true, the
block between '@code{if}' and the matching '@code{endif}' or
'@code{else}' will be assembled. When false, ignore all lines until
and '@code{else}' or '@code{endif}' directive is encountered.
It is possible to leave such a block early from within an include
file (with @code{end}) or a macro (with @code{endm}).
@item iif <expression>, <statement>
A single-line conditional assembly. The <statement> will be parsed
when <expression> evaluates to true (non-zero).
<statement> may be a normal source line, including labels, operators
and operands.
@item incbin "<file>"
Inserts the binary contents of <file> into the object code at
this position. The file will be searched first in the current
directory, then in all paths defined by @option{-I} in the order
of occurence.
@item include "<file>"
Include source text of <file> at this position. The include file
will be searched first in the current directory, then in all
paths defined by @option{-I} in the order of occurence.
@item list
The following lines will appear in the listing file, if it was
requested.
@item long
Align the program counter to the next integral longword boundary
(4 bytes), by inserting as many zero-bytes as needed.
@item macro <name> [<argname>[,<argname>...]]
Defines a macro which can be referenced by <name> (case-sensitive).
The macro definition is terminated by an @code{endm} directive
and may be exited by @code{exitm}.
When calling a macro you may pass up to 64 arguments, separated by
comma. The first ten arguments are referenced within the macro
context as @code{\1} to @code{\9} and @code{\0} for the tenth.
Optionally you can specify a list of argument names, which are
referenced with a leading backslash character (@code{\}) within the macro.
The special code @code{\~} inserts a unique id, useful for
defining labels. @code{\#} is replaced by the number of arguments.
@code{\!} writes the the size-qualifier (M68k) including the dot.
@code{\?argname} expands to @code{1} when the named argument is
specified and non-empty, otherwise it expands to @code{0}.
It is also allowed to enclose argument names in curly braces, which
is useful in situations where the argument name is followed by
another valid identifier character.
@item macundef <name>[,<name>...]
Undefine one or more already defined macros, making them unknown for
the following source to assemble.
@item nlist
The following lines will not be visible in a listing file.
@item nolist
The following lines will not be visible in a listing file.
@item org <expression>
Sets the base address for the subsequent code and switch into
absolute mode. Such a block is terminated by any section directive
or by @code{.68000} (Jaguar only).
@item phrase
Align the program counter to the next integral phrase
boundary (8 bytes).
@item print <expression>[,<expression>...]
Prints strings and formatted expressions to the assembler's console.
<expression> is either a string in quotes or an expression, which
is optionally preceded by special format flags:
Several flags can be used to format the output of expressions.
The default is a 16-bit signed decimal.
@table @code
@item /x
hexadecimal
@item /d
signed decimal
@item /u
unsigned decimal
@item /w
16-bit word
@item /l
32-bit longword
@end table
For example:
@example
.print "Value: ", /d/l xyz
@end example
@item qphrase
Align the program counter to the next integral quad phrase
boundary (32 bytes).
@item rept <expression>
The block between @code{rept} and @code{endr} will be repeated
<expression> times, which has to be positive.
@item <symbol> set <expression>
Create a new symbol with the name <symbol> and assign
the value of <expression>. If <symbol> is already assigned, it will
contain a new value from now on.
@item text
The following code and data is going into the text section, which
usually is the first program section, containing the executable code.
@end table
@section Known Problems
Some known problems of this module at the moment:
@itemize @minus
@item Not all Madmac, smac and extended Jaguar-Madmac directives are
supported.
@item Expressions are not evaluated left-to-right, but mathematically
correct.
@item Square-brackets (@code{[]}) are currently not supported to
prioritize terms, as an alternative for parentheses.
@item Functions (@code{^^func}) are currently not supported.
@end itemize
@section Error Messages
This module has the following error messages:
@itemize @minus
@item 1001: malformed immediate-if
@item 1003: cannot export local symbol
@item 1004: no space before operands
@item 1005: too many closing parentheses
@item 1006: missing closing parentheses
@item 1007: missing operand
@item 1008: garbage at end of line
@item 1009: unknown print format flag '%c'
@item 1010: invalid data operand
@item 1011: print format corrupted
@item 1012: identifier expected
@item 1014: unexpected "%s" without "%s"
@end itemize

Some files were not shown because too many files have changed in this diff Show More