Up to trying out hello-world.s for my 20x4 LCD

main
Paul Warren 3 years ago
parent 5e42e2a80c
commit daa48611c0
  1. 45
      6502-monitor/6502-monitor.ino
  2. 168
      hello-world.s
  3. 25
      makecounter.py
  4. 14
      mult.s
  5. 26
      rom-counter.s
  6. 11
      template.s
  7. 18
      vasm/Makefile
  8. 18
      vasm/Makefile.68k
  9. 18
      vasm/Makefile.Cygwin
  10. 18
      vasm/Makefile.Haiku
  11. 18
      vasm/Makefile.MOS
  12. 18
      vasm/Makefile.MiNT
  13. 18
      vasm/Makefile.OS4
  14. 18
      vasm/Makefile.PUp
  15. 18
      vasm/Makefile.TOS
  16. 18
      vasm/Makefile.WOS
  17. 30
      vasm/Makefile.Win32
  18. 22
      vasm/Makefile.Win32FromLinux
  19. 661
      vasm/atom.c
  20. 145
      vasm/atom.h
  21. 85
      vasm/cond.c
  22. 25
      vasm/cond.h
  23. 574
      vasm/cpus/6502/cpu.c
  24. 91
      vasm/cpus/6502/cpu.h
  25. 8
      vasm/cpus/6502/cpu_errors.h
  26. 287
      vasm/cpus/6502/opcodes.h
  27. 392
      vasm/cpus/6800/cpu.c
  28. 80
      vasm/cpus/6800/cpu.h
  29. 3
      vasm/cpus/6800/cpu_errors.h
  30. 339
      vasm/cpus/6800/opcodes.h
  31. 1755
      vasm/cpus/arm/cpu.c
  32. 214
      vasm/cpus/arm/cpu.h
  33. 31
      vasm/cpus/arm/cpu_errors.h
  34. 201
      vasm/cpus/arm/opcodes.h
  35. 786
      vasm/cpus/c16x/cpu.c
  36. 88
      vasm/cpus/c16x/cpu.h
  37. 8
      vasm/cpus/c16x/cpu_errors.h
  38. 233
      vasm/cpus/c16x/opcodes.h
  39. 617
      vasm/cpus/jagrisc/cpu.c
  40. 86
      vasm/cpus/jagrisc/cpu.h
  41. 3
      vasm/cpus/jagrisc/cpu_errors.h
  42. 72
      vasm/cpus/jagrisc/opcodes.h
  43. 5819
      vasm/cpus/m68k/cpu.c
  44. 432
      vasm/cpus/m68k/cpu.h
  45. 68
      vasm/cpus/m68k/cpu_errors.h
  46. 129
      vasm/cpus/m68k/cpu_models.h
  47. 2273
      vasm/cpus/m68k/opcodes.h
  48. 631
      vasm/cpus/m68k/operands.h
  49. 151
      vasm/cpus/m68k/specregs.h
  50. 907
      vasm/cpus/ppc/cpu.c
  51. 264
      vasm/cpus/ppc/cpu.h
  52. 17
      vasm/cpus/ppc/cpu_errors.h
  53. 2511
      vasm/cpus/ppc/opcodes.h
  54. 587
      vasm/cpus/ppc/operands.h
  55. 302
      vasm/cpus/qnice/cpu.c
  56. 58
      vasm/cpus/qnice/cpu.h
  57. 6
      vasm/cpus/qnice/cpu_errors.h
  58. 18
      vasm/cpus/qnice/opcodes.h
  59. 306
      vasm/cpus/test/cpu.c
  60. 55
      vasm/cpus/test/cpu.h
  61. 3
      vasm/cpus/test/cpu_errors.h
  62. 526
      vasm/cpus/tr3200/cpu.c
  63. 48
      vasm/cpus/tr3200/cpu.h
  64. 3
      vasm/cpus/tr3200/cpu_errors.h
  65. 150
      vasm/cpus/tr3200/opcodes.h
  66. 1206
      vasm/cpus/vidcore/cpu.c
  67. 142
      vasm/cpus/vidcore/cpu.h
  68. 5
      vasm/cpus/vidcore/cpu_errors.h
  69. 1041
      vasm/cpus/vidcore/opcodes.h
  70. 1950
      vasm/cpus/x86/cpu.c
  71. 269
      vasm/cpus/x86/cpu.h
  72. 26
      vasm/cpus/x86/cpu_errors.h
  73. 1062
      vasm/cpus/x86/opcodes.h
  74. 180
      vasm/cpus/x86/registers.h
  75. 2102
      vasm/cpus/z80/cpu.c
  76. 268
      vasm/cpus/z80/cpu.h
  77. 26
      vasm/cpus/z80/cpu_errors.h
  78. 123
      vasm/doc/cpu_6502.texi
  79. 85
      vasm/doc/cpu_6800.texi
  80. 248
      vasm/doc/cpu_arm.texi
  81. 124
      vasm/doc/cpu_c16x.texi
  82. 124
      vasm/doc/cpu_jagrisc.texi
  83. 1033
      vasm/doc/cpu_m68k.texi
  84. 172
      vasm/doc/cpu_ppc.texi
  85. 127
      vasm/doc/cpu_tr3200.texi
  86. 168
      vasm/doc/cpu_x86.texi
  87. 154
      vasm/doc/cpu_z80.texi
  88. 1455
      vasm/doc/interface.texi
  89. 62
      vasm/doc/output_aout.texi
  90. 43
      vasm/doc/output_bin.texi
  91. 59
      vasm/doc/output_elf.texi
  92. 115
      vasm/doc/output_hunk.texi
  93. 54
      vasm/doc/output_srec.texi
  94. 38
      vasm/doc/output_test.texi
  95. 54
      vasm/doc/output_tos.texi
  96. 38
      vasm/doc/output_vobj.texi
  97. 49
      vasm/doc/output_xfile.texi
  98. 330
      vasm/doc/syntax_madmac.texi
  99. 786
      vasm/doc/syntax_mot.texi
  100. 616
      vasm/doc/syntax_oldstyle.texi
  101. Some files were not shown because too many files have changed in this diff Show More

@ -0,0 +1,45 @@
const char ADDR[] = {22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52};
const char DATA[] = {39, 41, 43, 45, 47, 49, 51, 53};
#define CLOCK 2
#define READ_WRITE 3
void setup() {
for (int n = 0; n < 16; n += 1) {
pinMode(ADDR[n], INPUT);
}
for (int n = 0; n < 8; n += 1) {
pinMode(DATA[n], INPUT);
}
pinMode(CLOCK, INPUT);
pinMode(READ_WRITE, INPUT);
attachInterrupt(digitalPinToInterrupt(CLOCK), onClock, RISING);
Serial.begin(115200);sx
}
void onClock() {
char output[15];
unsigned int address = 0;
for (int n = 0; n < 16; n += 1) {
int bit = digitalRead(ADDR[n]) ? 1 : 0;
Serial.print(bit);
address = (address << 1) + bit;
}
Serial.print(" ");
unsigned int data = 0;
for (int n = 0; n < 8; n += 1) {
int bit = digitalRead(DATA[n]) ? 1 : 0;
Serial.print(bit);
data = (data << 1) + bit;
}
sprintf(output, " %04x %c %02x", address, digitalRead(READ_WRITE) ? 'r' : 'W', data);
Serial.println(output);
}
void loop() {
}

@ -0,0 +1,168 @@
PORTB = $6000
PORTA = $6001
DDRB = $6002
DDRA = $6003
E = %10000000
RW = %01000000
RS = %00100000
.org $8000
reset:
lda #%11111111 ; Set all pins on port B to output
sta DDRB
lda #%11100000 ; Set top 3 pins on port A to output
sta DDRA
lda #%00111000 ; Set 8-bit mode; 2-line display; 5x8 font
sta PORTB
lda #0 ; Clear RS/RW/E bits
sta PORTA
lda #E ; Set E bit to send instruction
sta PORTA
lda #0 ; Clear RS/RW/E bits
sta PORTA
lda #%00001110 ; Display on; cursor on; blink off
sta PORTB
lda #0 ; Clear RS/RW/E bits
sta PORTA
lda #E ; Set E bit to send instruction
sta PORTA
lda #0 ; Clear RS/RW/E bits
sta PORTA
lda #%00000110 ; Increment and shift cursor; don't shift display
sta PORTB
lda #0 ; Clear RS/RW/E bits
sta PORTA
lda #E ; Set E bit to send instruction
sta PORTA
lda #0 ; Clear RS/RW/E bits
sta PORTA
lda #"H"
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #"e"
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #"l"
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #"l"
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #"o"
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #","
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #" "
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #"w"
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #"o"
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #"r"
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #"l"
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #"d"
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
lda #"!"
sta PORTB
lda #RS ; Set RS; Clear RW/E bits
sta PORTA
lda #(RS | E) ; Set E bit to send instruction
sta PORTA
lda #RS ; Clear E bits
sta PORTA
loop:
jmp loop
.org $fffc
.word reset
.word $0000

@ -0,0 +1,25 @@
#
# Please see this video for details:
# https://www.youtube.com/watch?v=yl8vPW5hydQ
#
code = bytearray([
0xa9, 0xff, # lda #$ff # set output register B
0x8d, 0x02, 0x60, # sta $6002
0xa9, 0x00, # lda #$00 # Start at 0
0x8d, 0x00, 0x60, # sta $6000 # Latch out
0x69, 0x01, # add #$1
0x4c, 0x07, 0x80, # jmp $8005 # go back to first output
])
rom = code + bytearray([0xea] * (32768 - len(code)))
# Reset Vector
rom[0x7ffc] = 0x00
rom[0x7ffd] = 0x80
with open("rom-counter.bin", "wb") as out_file:
out_file.write(rom)

@ -0,0 +1,14 @@
.org $8000
reset:
lda $9000
.org $9000
.byte 18
.byte 03
.org $fffc
.word reset
.word $0000

@ -0,0 +1,26 @@
.org $8000
reset:
;; set output register
lda #$ff
sta $6002
;; flash the lights
;; lda #$50
;; sta $6000
;; start at 0
lda #$00
loop:
sta $6000
;; increment
adc #$1
jmp loop
.org $fffc
.word reset
.word $0000

@ -0,0 +1,11 @@
.org $8000
reset:
;; main program goes here
.org $fffc
.word reset
.word $0000

@ -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

@ -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

@ -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 -D_WIN32 $(OUTFMTS)
LD = $(CC)
LDOUT = $(CCOUT)
LDFLAGS = -lm
RM = rm -f
include make.rules

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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

@ -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 /Zp1 /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

@ -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

@ -0,0 +1,661 @@
/* atom.c - atomic objects from source */
/* (c) in 2010-2019 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(expr *offsexp,section *sec,taddr pc)
{
taddr offs;
eval_expr(offsexp,&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 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 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);
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;
}
static 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)
{
atom *new = new_atom(ROFFS,1);
new->content.roffs = offs;
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;
}

@ -0,0 +1,145 @@
/* atom.h - atomic objects from source */
/* (c) in 2010-2019 by Volker Barthelmann and Frank Wille */
#ifndef ATOM_H
#define ATOM_H
/* types of atoms */
#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 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;
expr *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 *);
void add_atom(section *,atom *);
size_t atom_size(atom *,section *,taddr);
void print_atom(FILE *,atom *);
void atom_printexpr