Implement addition expressions, critical expressions, proper modrm
This commit is contained in:
parent
6f8a24927a
commit
61d3688581
127
host/asm.awk
127
host/asm.awk
@ -42,6 +42,7 @@ BEGIN {
|
|||||||
modstr["dibp"]=3
|
modstr["dibp"]=3
|
||||||
modstr["si"]=4
|
modstr["si"]=4
|
||||||
modstr["di"]=5
|
modstr["di"]=5
|
||||||
|
modstr["bp"]=6
|
||||||
modstr["bx"]=7
|
modstr["bx"]=7
|
||||||
# ALU operations
|
# ALU operations
|
||||||
alu["add"]=0
|
alu["add"]=0
|
||||||
@ -119,6 +120,7 @@ function err(str) {
|
|||||||
}
|
}
|
||||||
# submit a assembling result to output
|
# submit a assembling result to output
|
||||||
# set label of current line to off
|
# set label of current line to off
|
||||||
|
# this outputs a listing line
|
||||||
function submit(off) {
|
function submit(off) {
|
||||||
if (of=="lst") printf("%04X %-18s %s\n", off, hex, $0)
|
if (of=="lst") printf("%04X %-18s %s\n", off, hex, $0)
|
||||||
if (of=="hex" && hex) printf("%s", hex)
|
if (of=="hex" && hex) printf("%s", hex)
|
||||||
@ -132,23 +134,61 @@ function submit(off) {
|
|||||||
pos=pos+length(hex)/2
|
pos=pos+length(hex)/2
|
||||||
hex=""
|
hex=""
|
||||||
}
|
}
|
||||||
# gets a symbol's values
|
# evaluate an expression
|
||||||
function getsym(name) {
|
# globals set:
|
||||||
if (substr(name,1,1)=="0" || int(name)) {
|
# ecrit: value known after first pass, 1=yes, 0=no
|
||||||
return int(name)
|
# eregs: concatenated list of registers that add to this expr (for modrm)
|
||||||
|
function expr(str) {
|
||||||
|
val=0
|
||||||
|
sign=1
|
||||||
|
ecrit=1
|
||||||
|
eregs=""
|
||||||
|
gsub(/-/, "+-", str)
|
||||||
|
split(str, ep,"+")
|
||||||
|
for (k in ep) {
|
||||||
|
if (substr(ep[k],1,1)=="-") {
|
||||||
|
gsub(/^-/, "", ep[k])
|
||||||
|
sign = -1
|
||||||
|
} else {
|
||||||
|
sign = 1
|
||||||
}
|
}
|
||||||
if (name in r8 || name in r16 || name in sreg) {
|
if (substr(ep[k],1,1)==".") ep[k] = plabel ep[k]
|
||||||
err("Register name " name " is not a valid immediate")
|
if (ep[k] in r8 || ep[k] in r16 || ep[k] in sreg) {
|
||||||
return 0
|
if (sign > 0) {
|
||||||
|
eregs=eregs ep[k]
|
||||||
|
} else {
|
||||||
|
err("Registers cannot be subtractive in expressions")
|
||||||
}
|
}
|
||||||
if (substr(name,1,1)==".") name = plabel name
|
} else if (match(ep[k], /^[0-9]/)) {
|
||||||
if (name in prevsym) {
|
if (match(ep[k], /h$/)) {
|
||||||
return prevsym[name]
|
ep[i]="0x" ep[k]
|
||||||
} else if (name in sym) {
|
|
||||||
return sym[name]
|
|
||||||
}
|
}
|
||||||
return 0
|
val = val + sign*int(ep[k])
|
||||||
|
} else if (ep[k] in sym) {
|
||||||
|
val = val + sign*sym[ep[k]]
|
||||||
|
} else if (ep[k] in prevsym) {
|
||||||
|
val = val + sign*prevsym[ep[k]]
|
||||||
|
ecrit=0
|
||||||
|
} else {
|
||||||
|
err("Undefined label " ep[k])
|
||||||
|
ecrit=0
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
function imm(str) {
|
||||||
|
val = expr(str)
|
||||||
|
if (eregs) err("Registers not allowed here")
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
function crit(str) {
|
||||||
|
val = imm(str)
|
||||||
|
if (!ecrit) err("Labels from below not allowed here")
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
function push_byte(val) {
|
function push_byte(val) {
|
||||||
#print("; pushb " val)
|
#print("; pushb " val)
|
||||||
if (val<0 || val>=256) err("Value " val " does not fit in byte")
|
if (val<0 || val>=256) err("Value " val " does not fit in byte")
|
||||||
@ -165,29 +205,27 @@ function push_word(val) {
|
|||||||
}
|
}
|
||||||
# rs is the register set (r8, r16) that can show up in str
|
# rs is the register set (r8, r16) that can show up in str
|
||||||
function push_modrm(str, spare, rs) {
|
function push_modrm(str, spare, rs) {
|
||||||
mod=3
|
mod=0
|
||||||
rm=0
|
rm=0
|
||||||
if (str in rs) {
|
if (str in rs) {
|
||||||
mod=3
|
mod=3
|
||||||
rm=rs[str]
|
rm=rs[str]
|
||||||
} else if (substr(str,1,1)=="[") {
|
} else if (substr(str,1,1)=="[") {
|
||||||
rmap=""
|
|
||||||
gsub(/^\[|\]$/, "", str)
|
gsub(/^\[|\]$/, "", str)
|
||||||
split(str,rmp,"+")
|
disp=expr(str)
|
||||||
disp=0
|
if (!ecrit || disp) {
|
||||||
for (i in rmp) {
|
|
||||||
if (rmp[i] in r16) {
|
|
||||||
rmap=rmap rmp[i]
|
|
||||||
} else {
|
|
||||||
disp = disp + getsym(rmp[i])
|
|
||||||
mod=2
|
mod=2
|
||||||
}
|
}
|
||||||
}
|
if (!eregs) {
|
||||||
if (!rmap) {
|
|
||||||
mod=0
|
mod=0
|
||||||
rm=6
|
rm=6
|
||||||
} else if (rmap in modstr) {
|
} else if (eregs in modstr) {
|
||||||
rm=modstr[rmap]
|
rm=modstr[eregs]
|
||||||
|
# [BP] is unencodable, this combination is read as [0000]
|
||||||
|
# so we upgrade [BP] to [BP+00]
|
||||||
|
if (mod==0 && rm==6) {
|
||||||
|
mod=1
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
err("Bad modR/M")
|
err("Bad modR/M")
|
||||||
}
|
}
|
||||||
@ -333,11 +371,11 @@ op=="cpu" {
|
|||||||
next
|
next
|
||||||
}
|
}
|
||||||
op=="org" {
|
op=="org" {
|
||||||
pos=getsym(a[1])
|
pos=crit(a[1])
|
||||||
submit(pos);next
|
submit(pos);next
|
||||||
}
|
}
|
||||||
op=="equ" {
|
op=="equ" {
|
||||||
val=getsym(a[1])
|
val=crit(a[1])
|
||||||
submit(val);next
|
submit(val);next
|
||||||
}
|
}
|
||||||
op=="db" {
|
op=="db" {
|
||||||
@ -346,11 +384,11 @@ op=="db" {
|
|||||||
for(j=2;j<length(a[i]);j++) {
|
for(j=2;j<length(a[i]);j++) {
|
||||||
push_byte(_ord_[substr(a[i],j,1)])
|
push_byte(_ord_[substr(a[i],j,1)])
|
||||||
}
|
}
|
||||||
} else push_byte(getsym(a[i]))
|
} else push_byte(imm(a[i]))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
op=="dw" {
|
op=="dw" {
|
||||||
for(i=1;i<=c;i++) push_word(getsym(a[i]))
|
for(i=1;i<=c;i++) push_word(imm(a[i]))
|
||||||
}
|
}
|
||||||
# arithmetics: ADD, SUB, XOR etc
|
# arithmetics: ADD, SUB, XOR etc
|
||||||
op in alu {
|
op in alu {
|
||||||
@ -358,9 +396,9 @@ op in alu {
|
|||||||
if (!hex) {
|
if (!hex) {
|
||||||
size=push_op_fixed_spare(0x80, alu[op])
|
size=push_op_fixed_spare(0x80, alu[op])
|
||||||
if (size==1) {
|
if (size==1) {
|
||||||
push_byte(getsym(op2))
|
push_byte(imm(op2))
|
||||||
} else if (size==2) {
|
} else if (size==2) {
|
||||||
push_word(getsym(op2))
|
push_word(imm(op2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -370,9 +408,9 @@ op=="test" {
|
|||||||
if (!hex) {
|
if (!hex) {
|
||||||
size=push_op_fixed_spare(246, 0)
|
size=push_op_fixed_spare(246, 0)
|
||||||
if (size==1) {
|
if (size==1) {
|
||||||
push_byte(getsym(op2))
|
push_byte(imm(op2))
|
||||||
} else if (size==2) {
|
} else if (size==2) {
|
||||||
push_word(getsym(op2))
|
push_word(imm(op2))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -407,10 +445,10 @@ op=="mov" {
|
|||||||
# reg <- imm
|
# reg <- imm
|
||||||
} else if (op1 in r8) {
|
} else if (op1 in r8) {
|
||||||
push_byte(176+r8[op1])
|
push_byte(176+r8[op1])
|
||||||
push_byte(getsym(op2))
|
push_byte(imm(op2))
|
||||||
} else if (op1 in r16) {
|
} else if (op1 in r16) {
|
||||||
push_byte(184+r16[op1])
|
push_byte(184+r16[op1])
|
||||||
push_word(getsym(op2))
|
push_word(imm(op2))
|
||||||
# modrm <- imm
|
# modrm <- imm
|
||||||
} else if (byteop && rm1) {
|
} else if (byteop && rm1) {
|
||||||
push_byte(198)
|
push_byte(198)
|
||||||
@ -431,15 +469,22 @@ op=="int" && op1=="3" { # CC breakpoint
|
|||||||
}
|
}
|
||||||
op=="int" { # CD
|
op=="int" { # CD
|
||||||
push_byte(205)
|
push_byte(205)
|
||||||
push_byte(getsym(op1))
|
push_byte(imm(op1))
|
||||||
}
|
}
|
||||||
op=="jmp" && wordop {
|
op=="jmp" {
|
||||||
|
val=imm(op1)-(pos+2)
|
||||||
|
if (val>-127 && val<128 && ecrit) {
|
||||||
|
push_byte(235)
|
||||||
|
push_signed_byte(val)
|
||||||
|
} else {
|
||||||
push_byte(233)
|
push_byte(233)
|
||||||
push_word(getsym(op1)-(pos+3))
|
push_word(val-1)
|
||||||
|
}
|
||||||
|
submit(pos);next
|
||||||
}
|
}
|
||||||
op=="call" && wordop {
|
op=="call" && wordop {
|
||||||
push_byte(232)
|
push_byte(232)
|
||||||
push_word(getsym(op1)-(pos+3))
|
push_word(imm(op1)-(pos+3))
|
||||||
}
|
}
|
||||||
op=="neg" {
|
op=="neg" {
|
||||||
push_op_fixed_spare(246, 3)
|
push_op_fixed_spare(246, 3)
|
||||||
@ -447,7 +492,7 @@ op=="neg" {
|
|||||||
# opcodes with rel8 encoding
|
# opcodes with rel8 encoding
|
||||||
op in ops_rel8 && byteop && c==1 {
|
op in ops_rel8 && byteop && c==1 {
|
||||||
push_byte(ops_rel8[op])
|
push_byte(ops_rel8[op])
|
||||||
push_signed_byte(getsym(op1)-(pos+2))
|
push_signed_byte(imm(op1)-(pos+2))
|
||||||
}
|
}
|
||||||
# opcodes without arguments
|
# opcodes without arguments
|
||||||
op in ops_sb { push_byte(ops_sb[op]) }
|
op in ops_sb { push_byte(ops_sb[op]) }
|
||||||
|
Loading…
Reference in New Issue
Block a user