ulisp/builder/assembler.lisp

210 lines
5.3 KiB
Common Lisp

;;;-*- Mode: Lisp; Package: cl-user -*-
(in-package :cl-user)
(defparameter *assembler*
'(
#+avr
#"
// Assembler
#if defined(CPU_ATmega1284P)
#define CODE_ADDRESS 0x1bb00
#elif defined(CPU_AVR128DX48)
#define CODE_ADDRESS 0x1be00
#endif
object *call (int entry, int nargs, object *args, object *env) {
#if defined(CODESIZE)
(void) env;
int param[4];
for (int i=0; i<nargs; i++) {
object *arg = first(args);
if (integerp(arg)) param[i] = arg->integer;
else param[i] = (uintptr_t)arg;
args = cdr(args);
}
uint32_t address = (CODE_ADDRESS + entry)>>1; // Code addresses are word addresses on AVR
int w = ((intfn_ptr_type)address)(param[0], param[1], param[2], param[3]);
return number(w);
#else
return nil;
#endif
}"#
#+arm
#"
// Assembler
object *call (int entry, int nargs, object *args, object *env) {
#if defined(CODESIZE)
(void) env;
int param[4];
for (int i=0; i<nargs; i++) {
object *arg = first(args);
if (integerp(arg)) param[i] = arg->integer;
else param[i] = (uintptr_t)arg;
args = cdr(args);
}
int w = ((intfn_ptr_type)&MyCode[entry])(param[0], param[1], param[2], param[3]);
return number(w);
#else
return nil;
#endif
}"#
#+riscv
#"
// Assembler
object *call (int entry, int nargs, object *args, object *env) {
#if defined(CODESIZE)
(void) env;
int param[4];
for (int i=0; i<nargs; i++) {
object *arg = first(args);
if (integerp(arg)) param[i] = arg->integer;
else param[i] = (uintptr_t)arg;
args = cdr(args);
}
asm("fence.i");
int w = ((intfn_ptr_type)&MyCode[entry])(param[0], param[1], param[2], param[3]);
return number(w);
#else
return nil;
#endif
}"#
#+avr
#"
void putcode (object *arg, int origin, int pc) {
#if defined(CODESIZE)
int code = checkinteger(arg);
uint8_t hi = (code>>8) & 0xff;
uint8_t lo = code & 0xff;
MyCode[origin+pc] = lo; // Little-endian
MyCode[origin+pc+1] = hi;
#if defined(assemblerlist)
printhex2(pc>>8, pserial); printhex2(pc, pserial); pserial(' ');
printhex2(lo, pserial); pserial(' '); printhex2(hi, pserial); pserial(' ');
#endif
#endif
}"#
#+(or arm riscv)
#"
void putcode (object *arg, int origin, int pc) {
#if defined(CODESIZE)
int code = checkinteger(arg);
MyCode[origin+pc] = code & 0xff;
MyCode[origin+pc+1] = (code>>8) & 0xff;
#if defined(assemblerlist)
printhex4(pc, pserial);
printhex4(code, pserial);
#endif
#endif
}"#
#+avr
#"
int assemble (int pass, int origin, object *entries, object *env, object *pcpair) {
int pc = 0; cdr(pcpair) = number(pc);
while (entries != NULL) {
object *arg = first(entries);
if (symbolp(arg)) {
if (pass == 2) {
#if defined(assemblerlist)
printhex2(pc>>8, pserial); printhex2(pc, pserial);
indent(7, ' ', pserial);
printobject(arg, pserial); pln(pserial);
#endif
} else {
object *pair = findvalue(arg, env);
cdr(pair) = number(pc);
}
} else {
object *argval = eval(arg, env);
if (listp(argval)) {
object *arglist = argval;
while (arglist != NULL) {
if (pass == 2) {
putcode(first(arglist), origin, pc);
#if defined(assemblerlist)
if (arglist == argval) superprint(arg, 0, pserial);
pln(pserial);
#endif
}
pc = pc + 2;
cdr(pcpair) = number(pc);
arglist = cdr(arglist);
}
} else if (integerp(argval)) {
if (pass == 2) {
putcode(argval, origin, pc);
#if defined(assemblerlist)
superprint(arg, 0, pserial); pln(pserial);
#endif
}
pc = pc + 2;
cdr(pcpair) = number(pc);
} else error(PSTR("illegal entry"), arg);
}
entries = cdr(entries);
}
// Round up to multiple of 2 to give code size
if (pc%2 != 0) pc = pc + 2 - pc%2;
return pc;
}"#
#+(or arm riscv)
#"
int assemble (int pass, int origin, object *entries, object *env, object *pcpair) {
int pc = 0; cdr(pcpair) = number(pc);
while (entries != NULL) {
object *arg = first(entries);
if (symbolp(arg)) {
if (pass == 2) {
#if defined(assemblerlist)
printhex4(pc, pserial);
indent(5, ' ', pserial);
printobject(arg, pserial); pln(pserial);
#endif
} else {
object *pair = findvalue(arg, env);
cdr(pair) = number(pc);
}
} else {
object *argval = eval(arg, env);
if (listp(argval)) {
object *arglist = argval;
while (arglist != NULL) {
if (pass == 2) {
putcode(first(arglist), origin, pc);
#if defined(assemblerlist)
if (arglist == argval) superprint(arg, 0, pserial);
pln(pserial);
#endif
}
pc = pc + 2;
cdr(pcpair) = number(pc);
arglist = cdr(arglist);
}
} else if (integerp(argval)) {
if (pass == 2) {
putcode(argval, origin, pc);
#if defined(assemblerlist)
superprint(arg, 0, pserial); pln(pserial);
#endif
}
pc = pc + 2;
cdr(pcpair) = number(pc);
} else error(PSTR("illegal entry"), arg);
}
entries = cdr(entries);
}
// Round up to multiple of 4 to give code size
if (pc%4 != 0) pc = pc + 4 - pc%4;
return pc;
}"#))